Cleaned up map data storage (#3347)

Follow up to a942853.
Fixes #3336.
Moved map_data storage to std::map container.
Created map_getmapdata to obtain pointer to map_data.
Got rid of MAX_MAP_PER_SERVER define.
Resolved deletion of instances causing other instances to lose their intended map ID.
Refactored warp suggestions

Thanks to @teededung, @anacondaqq, @cydh and @Lemongrass3110!
This commit is contained in:
Aleos 2018-07-25 19:06:59 -04:00 committed by Lemongrass3110
parent 62ac5be447
commit 584fcac43a
26 changed files with 916 additions and 741 deletions

View File

@ -4,6 +4,8 @@
#ifndef _CHAR_HPP_
#define _CHAR_HPP_
#include <vector>
#include "../common/core.hpp" // CORE_ST_LAST
#include "../common/mmo.hpp"
#include "../common/msg_conf.hpp"
@ -197,7 +199,7 @@ struct mmo_map_server {
uint32 ip;
uint16 port;
int users;
unsigned short map[MAX_MAP_PER_SERVER];
std::vector<uint16> map;
};
extern struct mmo_map_server map_server[MAX_MAP_SERVERS];

View File

@ -676,7 +676,7 @@ int chclif_parse_maplogin(int fd){
map_server[i].ip = ntohl(RFIFOL(fd,54));
map_server[i].port = ntohs(RFIFOW(fd,58));
map_server[i].users = 0;
memset(map_server[i].map, 0, sizeof(map_server[i].map));
map_server[i].map = {};
session[fd]->func_parse = chmapif_parse;
session[fd]->flag.server = 1;
realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);

View File

@ -239,29 +239,27 @@ void chmapif_send_maps(int fd, int map_id, int count, unsigned char *mapbuf) {
* @return : 0 not enough data received, 1 success
*/
int chmapif_parse_getmapname(int fd, int id){
int i = 0, j = 0;
int i = 0;
unsigned char *mapbuf;
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
//Retain what map-index that map-serv contains
memset(map_server[id].map, 0, sizeof(map_server[id].map));
for(i = 4; i < RFIFOW(fd,2); i += 4) {
map_server[id].map[j] = RFIFOW(fd,i);
j++;
}
map_server[id].map = {};
for(i = 4; i < RFIFOW(fd,2); i += 4)
map_server[id].map.push_back(RFIFOW(fd, i));
mapbuf = RFIFOP(fd,4);
RFIFOSKIP(fd,RFIFOW(fd,2));
ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n",
id, j, CONVIP(map_server[id].ip), map_server[id].port);
id, map_server[id].map.size(), CONVIP(map_server[id].ip), map_server[id].port);
ShowStatus("Map-server %d loading complete.\n", id);
chmapif_send_misc(fd);
chmapif_send_fame_list(fd); //Send fame list.
chmapif_send_maps(fd, id, j, mapbuf);
chmapif_send_maps(fd, id, map_server[id].map.size(), mapbuf);
return 1;
}
@ -1515,7 +1513,7 @@ void do_init_chmapif(void){
* @param id: id of map-serv (should be >0, FIXME)
*/
void chmapif_server_reset(int id){
int i,j;
int j = 0;
unsigned char buf[16384];
int fd = map_server[id].fd;
DBMap* online_char_db = char_get_onlinedb();
@ -1524,8 +1522,7 @@ void chmapif_server_reset(int id){
WBUFW(buf,0) = 0x2b20;
WBUFL(buf,4) = htonl(map_server[id].ip);
WBUFW(buf,8) = htons(map_server[id].port);
j = 0;
for(i = 0; i < MAX_MAP_PER_SERVER; i++)
for(uint16 i = 0; i < map_server[id].map.size(); i++)
if (map_server[id].map[i])
WBUFW(buf,10+(j++)*4) = map_server[id].map[i];
if (j > 0) {

View File

@ -32,7 +32,6 @@
#define MAX_HOTKEYS 38
#endif
#define MAX_MAP_PER_SERVER 1500 /// Increased to allow creation of Instance Maps
#define MAX_INVENTORY 100 ///Maximum items in player inventory
/** Max number of characters per account. Note that changing this setting alone is not enough if the client is not hexed to support more characters as well.
* Max value tested was 265 */

View File

@ -387,62 +387,95 @@ ACMD_FUNC(send)
* @author Euphy
*/
static void warp_get_suggestions(struct map_session_data* sd, const char *name) {
char buffer[512];
int i, count = 0;
if (strlen(name) < 2)
// Minimum length for suggestions is 2 characters
if( strlen( name ) < 2 ){
return;
}
std::vector<const char*> suggestions;
suggestions.reserve( MAX_SUGGESTIONS );
// check for maps that contain string
for( auto& pair : map ){
struct map_data *mapdata = &pair.second;
// Prevent suggestion of instance mapnames
if( mapdata->instance_id != 0 ){
continue;
}
if( strstr( mapdata->name, name ) != nullptr ){
suggestions.push_back( mapdata->name );
if( suggestions.size() == MAX_SUGGESTIONS ){
break;
}
}
}
// if no maps found, search by edit distance
if( suggestions.empty() ){
// Levenshtein > 4 is bad
const int LEVENSHTEIN_MAX = 4;
std::map<int, std::vector<const char*>> maps;
for( auto& pair : map ){
// Prevent suggestion of instance mapnames
if( pair.second.instance_id != 0 ){
continue;
}
// Calculate the levenshtein distance of the two strings
int distance = levenshtein( pair.second.name, name );
// Check if it is above the maximum defined distance
if( distance > LEVENSHTEIN_MAX ){
continue;
}
std::vector<const char*>& vector = maps[distance];
// Do not add more entries than required
if( vector.size() == MAX_SUGGESTIONS ){
continue;
}
vector.push_back( pair.second.name );
}
for( int distance = 0; distance <= LEVENSHTEIN_MAX; distance++ ){
std::vector<const char*>& vector = maps[distance];
for( const char* found_map : vector ){
suggestions.push_back( found_map );
if( suggestions.size() == MAX_SUGGESTIONS ){
break;
}
}
if( suggestions.size() == MAX_SUGGESTIONS ){
break;
}
}
}
// If no suggestion could be made, do not output anything at all
if( suggestions.empty() ){
return;
}
char buffer[CHAT_SIZE_MAX];
// build the suggestion string
strcpy(buffer, msg_txt(sd, 205)); // Maybe you meant:
strcat(buffer, "\n");
// check for maps that contain string
for (i = 0; i < MAX_MAP_PER_SERVER; i++) {
if (count < MAX_SUGGESTIONS && strstr(map[i].name, name) != NULL) {
strcat(buffer, map[i].name);
strcat(buffer, " ");
if (++count >= MAX_SUGGESTIONS)
break;
}
}
// if no maps found, search by edit distance
if (!count) {
unsigned int distance[MAX_MAP_PER_SERVER][2];
int j;
// calculate Levenshtein distance for all maps
for (i = 0; i < MAX_MAP_PER_SERVER; i++) {
if (strlen(map[i].name) < 4) // invalid map name?
distance[i][0] = INT_MAX;
else {
distance[i][0] = levenshtein(map[i].name, name);
distance[i][1] = i;
}
}
// selection sort elements as needed
count = min(MAX_SUGGESTIONS, 5); // results past 5 aren't worth showing
for (i = 0; i < count; i++) {
int min = i;
for (j = i+1; j < MAX_MAP_PER_SERVER; j++) {
if (distance[j][0] < distance[min][0])
min = j;
}
// print map name
if (distance[min][0] > 4) { // awful results, don't bother
if (!i) return;
break;
}
strcat(buffer, map[distance[min][1]].name);
strcat(buffer, " ");
// swap elements
SWAP(distance[i][0], distance[min][0]);
SWAP(distance[i][1], distance[min][1]);
}
for( const char* suggestion : suggestions ){
strcat(buffer, suggestion);
strcat(buffer, " ");
}
clif_displaymessage(sd->fd, buffer);
@ -709,12 +742,14 @@ ACMD_FUNC(who) {
else
StringBuf_Printf(&buf, msg_txt(sd,30), count); // %d players found.
} else {
struct map_data *mapdata = map_getmapdata(map_id);
if (count == 0)
StringBuf_Printf(&buf, msg_txt(sd,54), map[map_id].name); // No player found in map '%s'.
StringBuf_Printf(&buf, msg_txt(sd,54), mapdata->name); // No player found in map '%s'.
else if (count == 1)
StringBuf_Printf(&buf, msg_txt(sd,55), map[map_id].name); // 1 player found in map '%s'.
StringBuf_Printf(&buf, msg_txt(sd,55), mapdata->name); // 1 player found in map '%s'.
else
StringBuf_Printf(&buf, msg_txt(sd,56), count, map[map_id].name); // %d players found in map '%s'.
StringBuf_Printf(&buf, msg_txt(sd,56), count, mapdata->name); // %d players found in map '%s'.
}
clif_displaymessage(fd, StringBuf_Value(&buf));
StringBuf_Destroy(&buf);
@ -814,7 +849,7 @@ ACMD_FUNC(save)
{
nullpo_retr(-1, sd);
if( map[sd->bl.m].instance_id ) {
if( map_getmapdata(sd->bl.m)->instance_id ) {
clif_displaymessage(fd, msg_txt(sd,383)); // You cannot create a savepoint in an instance.
return 1;
}
@ -995,7 +1030,7 @@ ACMD_FUNC(hide)
clif_displaymessage(fd, msg_txt(sd,10)); // Invisible: Off
// increment the number of pvp players on the map
map[sd->bl.m].users_pvp++;
map_getmapdata(sd->bl.m)->users_pvp++;
if( !battle_config.pk_mode && map_getmapflag(sd->bl.m, MF_PVP) && !map_getmapflag(sd->bl.m, MF_PVP_NOCALCRANK) )
{// register the player for ranking calculations
@ -1009,7 +1044,7 @@ ACMD_FUNC(hide)
clif_displaymessage(fd, msg_txt(sd,11)); // Invisible: On
// decrement the number of pvp players on the map
map[sd->bl.m].users_pvp--;
map_getmapdata(sd->bl.m)->users_pvp--;
if( map_getmapflag(sd->bl.m, MF_PVP) && !map_getmapflag(sd->bl.m, MF_PVP_NOCALCRANK) && sd->pvp_timer != INVALID_TIMER )
{// unregister the player for ranking
@ -2411,7 +2446,7 @@ ACMD_FUNC(gat)
for (y = 2; y >= -2; y--) {
sprintf(atcmd_output, "%s (x= %d, y= %d) %02X %02X %02X %02X %02X",
map[sd->bl.m].name, sd->bl.x - 2, sd->bl.y + y,
map_getmapdata(sd->bl.m)->name, sd->bl.x - 2, sd->bl.y + y,
map_getcell(sd->bl.m, sd->bl.x - 2, sd->bl.y + y, CELL_GETTYPE),
map_getcell(sd->bl.m, sd->bl.x - 1, sd->bl.y + y, CELL_GETTYPE),
map_getcell(sd->bl.m, sd->bl.x, sd->bl.y + y, CELL_GETTYPE),
@ -4033,13 +4068,15 @@ ACMD_FUNC(mapinfo) {
}
mapit_free(iter);
sprintf(atcmd_output, msg_txt(sd,1040), mapname, map[m_id].users, map[m_id].npc_num, chat_num, vend_num); // Map: %s | Players: %d | NPCs: %d | Chats: %d | Vendings: %d
struct map_data *mapdata = map_getmapdata(m_id);
sprintf(atcmd_output, msg_txt(sd,1040), mapname, mapdata->users, mapdata->npc_num, chat_num, vend_num); // Map: %s | Players: %d | NPCs: %d | Chats: %d | Vendings: %d
clif_displaymessage(fd, atcmd_output);
clif_displaymessage(fd, msg_txt(sd,1041)); // ------ Map Flags ------
if (map_getmapflag(m_id, MF_TOWN))
clif_displaymessage(fd, msg_txt(sd,1042)); // Town Map
if (map_getmapflag(m_id, MF_RESTRICTED)){
sprintf(atcmd_output, " Restricted (zone %d)",map[m_id].zone);
sprintf(atcmd_output, " Restricted (zone %d)",mapdata->zone);
clif_displaymessage(fd, atcmd_output);
}
@ -4066,17 +4103,17 @@ ACMD_FUNC(mapinfo) {
,(args.flag_val = SKILLDMG_OTHER && map_getmapflag_sub(m_id, MF_SKILL_DAMAGE, &args))
,(args.flag_val = SKILLDMG_CASTER && map_getmapflag_sub(m_id, MF_SKILL_DAMAGE, &args)));
clif_displaymessage(fd, atcmd_output);
if (map[m_id].skill_damage.size()) {
if (mapdata->skill_damage.size()) {
clif_displaymessage(fd," > [Map Skill] Name : Player, Monster, Boss Monster, Other | Caster");
for (int j = 0; j < map[m_id].skill_damage.size(); j++) {
for (int j = 0; j < mapdata->skill_damage.size(); j++) {
sprintf(atcmd_output," %d. %s : %d%%, %d%%, %d%%, %d%% | %d"
,j+1
,skill_get_name(map[m_id].skill_damage[j].skill_id)
,map[m_id].skill_damage[j].rate[SKILLDMG_PC]
,map[m_id].skill_damage[j].rate[SKILLDMG_MOB]
,map[m_id].skill_damage[j].rate[SKILLDMG_BOSS]
,map[m_id].skill_damage[j].rate[SKILLDMG_OTHER]
,map[m_id].skill_damage[j].caster);
,skill_get_name(mapdata->skill_damage[j].skill_id)
,mapdata->skill_damage[j].rate[SKILLDMG_PC]
,mapdata->skill_damage[j].rate[SKILLDMG_MOB]
,mapdata->skill_damage[j].rate[SKILLDMG_BOSS]
,mapdata->skill_damage[j].rate[SKILLDMG_OTHER]
,mapdata->skill_damage[j].caster);
clif_displaymessage(fd,atcmd_output);
}
}
@ -4132,15 +4169,15 @@ ACMD_FUNC(mapinfo) {
clif_displaymessage(fd, atcmd_output);
if (map_getmapflag(m_id, MF_NOSAVE)) {
if (!map[m_id].save.map)
if (!mapdata->save.map)
clif_displaymessage(fd, msg_txt(sd,1068)); // No Save (Return to last Save Point)
else if (map[m_id].save.x == -1 || map[m_id].save.y == -1 ) {
sprintf(atcmd_output, msg_txt(sd,1069), mapindex_id2name(map[m_id].save.map)); // No Save, Save Point: %s,Random
else if (mapdata->save.x == -1 || mapdata->save.y == -1 ) {
sprintf(atcmd_output, msg_txt(sd,1069), mapindex_id2name(mapdata->save.map)); // No Save, Save Point: %s,Random
clif_displaymessage(fd, atcmd_output);
}
else {
sprintf(atcmd_output, msg_txt(sd,1070), // No Save, Save Point: %s,%d,%d
mapindex_id2name(map[m_id].save.map),map[m_id].save.x,map[m_id].save.y);
mapindex_id2name(mapdata->save.map),mapdata->save.x,mapdata->save.y);
clif_displaymessage(fd, atcmd_output);
}
}
@ -4239,9 +4276,9 @@ ACMD_FUNC(mapinfo) {
break;
case 2:
clif_displaymessage(fd, msg_txt(sd,482)); // ----- NPCs in Map -----
for (i = 0; i < map[m_id].npc_num;)
for (i = 0; i < mapdata->npc_num;)
{
struct npc_data *nd = map[m_id].npc[i];
struct npc_data *nd = mapdata->npc[i];
switch(nd->ud.dir) {
case DIR_NORTH: strcpy(direction, msg_txt(sd,491)); break; // North
case DIR_NORTHWEST: strcpy(direction, msg_txt(sd,492)); break; // North West
@ -7861,7 +7898,7 @@ ACMD_FUNC(whereis)
int16 mapid = map_mapindex2mapid(spawn.mapindex);
if (mapid < 0)
continue;
snprintf(atcmd_output, sizeof atcmd_output, "%s (%d)", map[mapid].name, spawn.qty);
snprintf(atcmd_output, sizeof atcmd_output, "%s (%d)", map_getmapdata(mapid)->name, spawn.qty);
clif_displaymessage(fd, atcmd_output);
}
}

View File

@ -2199,7 +2199,7 @@ static int battle_skill_damage_skill(struct block_list *src, struct block_list *
(damage->map&4 && map_flag_gvg2(m)) ||
(damage->map&8 && map_getmapflag(m, MF_BATTLEGROUND)) ||
(damage->map&16 && map_getmapflag_sub(m, MF_SKILL_DAMAGE, &args)) ||
(map_getmapflag(m, MF_RESTRICTED) && damage->map&(8*map[m].zone)))
(map_getmapflag(m, MF_RESTRICTED) && damage->map&(8*map_getmapdata(m)->zone)))
{
return damage->rate[battle_skill_damage_type(target)];
}
@ -2216,24 +2216,24 @@ static int battle_skill_damage_skill(struct block_list *src, struct block_list *
*/
static int battle_skill_damage_map(struct block_list *src, struct block_list *target, uint16 skill_id) {
int rate = 0;
struct map_data *mapd = &map[src->m];
struct map_data *mapdata = map_getmapdata(src->m);
union u_mapflag_args args = {};
args.flag_val = SKILLDMG_MAX; // Check if it's enabled first
if (!mapd || !map_getmapflag_sub(src->m, MF_SKILL_DAMAGE, &args))
if (!mapdata || !map_getmapflag_sub(src->m, MF_SKILL_DAMAGE, &args))
return 0;
// Damage rate for all skills at this map
if (mapd->damage_adjust.caster&src->type)
rate = mapd->damage_adjust.rate[battle_skill_damage_type(target)];
if (mapdata->damage_adjust.caster&src->type)
rate = mapdata->damage_adjust.rate[battle_skill_damage_type(target)];
if (mapd->skill_damage.empty())
if (mapdata->skill_damage.empty())
return rate;
// Damage rate for specified skill at this map
for (int i = 0; i < mapd->skill_damage.size(); i++) {
if (mapd->skill_damage[i].skill_id == skill_id && mapd->skill_damage[i].caster&src->type)
rate += mapd->skill_damage[i].rate[battle_skill_damage_type(target)];
for (int i = 0; i < mapdata->skill_damage.size(); i++) {
if (mapdata->skill_damage[i].skill_id == skill_id && mapdata->skill_damage[i].caster&src->type)
rate += mapdata->skill_damage[i].rate[battle_skill_damage_type(target)];
}
return rate;
}

View File

@ -232,7 +232,7 @@ int8 buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`id`, `account_id`, `char_id`, `sex`, `map`, `x`, `y`, `title`, `limit`, `autotrade`, `body_direction`, `head_direction`, `sit`) "
"VALUES( %d, %d, %d, '%c', '%s', %d, %d, '%s', %d, %d, '%d', '%d', '%d' );",
buyingstores_table, sd->buyer_id, sd->status.account_id, sd->status.char_id, sd->status.sex == 0 ? 'F' : 'M', map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->buyingstore.zenylimit, sd->state.autotrade, at ? at->dir : sd->ud.dir, at ? at->head_dir : sd->head_dir, at ? at->sit : pc_issit(sd) ) != SQL_SUCCESS ){
buyingstores_table, sd->buyer_id, sd->status.account_id, sd->status.char_id, sd->status.sex == 0 ? 'F' : 'M', map_getmapdata(sd->bl.m)->name, sd->bl.x, sd->bl.y, message_sql, sd->buyingstore.zenylimit, sd->state.autotrade, at ? at->dir : sd->ud.dir, at ? at->head_dir : sd->head_dir, at ? at->sit : pc_issit(sd) ) != SQL_SUCCESS ){
Sql_ShowDebug(mmysql_handle);
}

View File

@ -163,7 +163,7 @@ int channel_delete(struct Channel *channel, bool force) {
channel->group_count = 0;
switch(channel->type){
case CHAN_TYPE_MAP:
map[channel->m].channel = NULL;
map_getmapdata(channel->m)->channel = NULL;
aFree(channel);
break;
case CHAN_TYPE_ALLY: {
@ -251,16 +251,18 @@ int channel_mjoin(struct map_session_data *sd) {
char mout[60];
if(!sd) return -1;
if( !map[sd->bl.m].channel ) {
map[sd->bl.m].channel = channel_create_simple(NULL,NULL,CHAN_TYPE_MAP,sd->bl.m);
struct map_data *mapdata = map_getmapdata(sd->bl.m);
if( !mapdata->channel ) {
mapdata->channel = channel_create_simple(NULL,NULL,CHAN_TYPE_MAP,sd->bl.m);
}
if( map[sd->bl.m].channel->opt & CHAN_OPT_ANNOUNCE_SELF ) {
sprintf(mout, msg_txt(sd,1435),map[sd->bl.m].channel->name,map[sd->bl.m].name); // You're now in the '#%s' channel for '%s'.
if( mapdata->channel->opt & CHAN_OPT_ANNOUNCE_SELF ) {
sprintf(mout, msg_txt(sd,1435),mapdata->channel->name,mapdata->name); // You're now in the '#%s' channel for '%s'.
clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], mout, false, SELF);
}
return channel_join(map[sd->bl.m].channel,sd);
return channel_join(mapdata->channel,sd);
}
/**
@ -410,8 +412,11 @@ int channel_pcquit(struct map_session_data *sd, int type){
}
}
}
if(type&4 && channel_config.map_tmpl.name[0] && channel_haspc(map[sd->bl.m].channel,sd)==1){ //quit map chan
channel_clean(map[sd->bl.m].channel,sd,0);
struct map_data *mapdata = map_getmapdata(sd->bl.m);
if(type&4 && channel_config.map_tmpl.name[0] && channel_haspc(mapdata->channel,sd)==1){ //quit map chan
channel_clean(mapdata->channel,sd,0);
}
if(type&8 && sd->channel_count ) { //quit all chan
uint8 count = sd->channel_count;
@ -498,17 +503,20 @@ int channel_chk(char *chname, char *chpass, int type){
struct Channel* channel_name2channel(char *chname, struct map_session_data *sd, int flag){
if(channel_chk(chname, NULL, 1))
return NULL;
struct map_data *mapdata = map_getmapdata(sd->bl.m);
if(sd && strcmpi(chname + 1,channel_config.map_tmpl.name) == 0){
if(flag&1 && !map[sd->bl.m].channel)
map[sd->bl.m].channel = channel_create_simple(NULL,NULL,CHAN_TYPE_MAP,sd->bl.m);
if(flag&2 && channel_pc_haschan(sd,map[sd->bl.m].channel) < 1)
if(flag&1 && !mapdata->channel)
mapdata->channel = channel_create_simple(NULL,NULL,CHAN_TYPE_MAP,sd->bl.m);
if(flag&2 && channel_pc_haschan(sd,mapdata->channel) < 1)
channel_mjoin(sd);
return map[sd->bl.m].channel;
return mapdata->channel;
}
else if(sd && (strcmpi(chname + 1,channel_config.ally_tmpl.name) == 0) && sd->guild){
if(flag&1 && !sd->guild->channel)
sd->guild->channel = channel_create_simple(NULL,NULL,CHAN_TYPE_ALLY,sd->guild->guild_id);
if(flag&2 && channel_pc_haschan(sd,map[sd->bl.m].channel) < 1)
if(flag&2 && channel_pc_haschan(sd,mapdata->channel) < 1)
channel_gjoin(sd,3);
return sd->guild->channel;
}
@ -610,10 +618,11 @@ int channel_display_list(struct map_session_data *sd, const char *options){
bool has_perm = pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ? true : false;
struct Channel *channel;
char output[CHAT_SIZE_MAX];
struct map_data *mapdata = map_getmapdata(sd->bl.m);
clif_displaymessage(sd->fd, msg_txt(sd,1410)); // ---- Public Channels ----
if( channel_config.map_tmpl.name[0] && map[sd->bl.m].channel ) {
sprintf(output, msg_txt(sd,1409), map[sd->bl.m].channel->name, db_size(map[sd->bl.m].channel->users));// - #%s (%d users)
if( channel_config.map_tmpl.name[0] && mapdata->channel ) {
sprintf(output, msg_txt(sd,1409), mapdata->channel->name, db_size(mapdata->channel->users));// - #%s (%d users)
clif_displaymessage(sd->fd, output);
}
if( channel_config.ally_tmpl.name[0] && sd->status.guild_id ) {

View File

@ -341,7 +341,7 @@ int chrif_save(struct map_session_data *sd, int flag) {
WFIFOB(char_fd,12) = (flag&CSAVE_QUIT) ? 1 : 0; //Flag to tell char-server this character is quitting.
// If the user is on a instance map, we have to fake his current position
if( map[sd->bl.m].instance_id ){
if( map_getmapdata(sd->bl.m)->instance_id ){
struct mmo_charstatus status;
// Copy the whole status
@ -395,17 +395,18 @@ int chrif_connect(int fd) {
// sends maps to char-server
int chrif_sendmap(int fd) {
int i;
int i = 0, size = 4 + map.size() * 4;
ShowStatus("Sending maps to char server...\n");
// Sending normal maps, not instances
WFIFOHEAD(fd, 4 + map.size() * 4);
WFIFOHEAD(fd, size);
WFIFOW(fd,0) = 0x2afa;
for(i = 0; i < map.size(); i++)
WFIFOW(fd,4+i*4) = map[i].index;
WFIFOW(fd,2) = 4 + i * 4;
WFIFOSET(fd,WFIFOW(fd,2));
WFIFOW(fd,2) = size;
for( auto& pair : map ){
WFIFOW(fd,4+i*4) = pair.second.index;
i++;
}
WFIFOSET(fd,size);
return 0;
}

View File

@ -3404,7 +3404,7 @@ void clif_updatestatus(struct map_session_data *sd,int type)
}
break;
case SP_HP:
if( map[sd->bl.m].hpmeter_visible ){
if( map_getmapdata(sd->bl.m)->hpmeter_visible ){
clif_hpmeter(sd);
}
if( !battle_config.party_hp_mode && sd->status.party_id ){
@ -10324,10 +10324,12 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
pc_setinvincibletimer(sd,battle_config.pc_invincible_time);
}
if( map[sd->bl.m].users++ == 0 && battle_config.dynamic_mobs )
struct map_data *mapdata = map_getmapdata(sd->bl.m);
if( mapdata->users++ == 0 && battle_config.dynamic_mobs )
map_spawnmobs(sd->bl.m);
if( !pc_isinvisible(sd) ) { // increment the number of pvp players on the map
map[sd->bl.m].users_pvp++;
mapdata->users_pvp++;
}
sd->state.debug_remove_map = 0; // temporary state to track double remove_map's [FlavioJS]
@ -10515,9 +10517,10 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
guild_notice = false; // Do not display it twice
}
if( (battle_config.bg_flee_penalty != 100 || battle_config.gvg_flee_penalty != 100) &&
(map_flag_gvg(sd->state.pmap) || map_flag_gvg(sd->bl.m) || map_getmapflag(sd->state.pmap, MF_BATTLEGROUND) || map_getmapflag(sd->bl.m, MF_BATTLEGROUND)) )
status_calc_bl(&sd->bl, SCB_FLEE); //Refresh flee penalty
if (battle_config.bg_flee_penalty != 100 || battle_config.gvg_flee_penalty != 100) {
if ((sd->state.pmap != 0 && map_getmapdata(sd->state.pmap) != nullptr && (map_flag_gvg(sd->state.pmap) || map_getmapflag(sd->state.pmap, MF_BATTLEGROUND))) || (mapdata != nullptr && (map_flag_gvg(sd->bl.m) || map_getmapflag(sd->bl.m, MF_BATTLEGROUND))))
status_calc_bl(&sd->bl, SCB_FLEE); //Refresh flee penalty
}
if( night_flag && map_getmapflag(sd->bl.m, MF_NIGHTENABLED) )
{ //Display night.
@ -10548,7 +10551,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
}
if( pc_has_permission(sd,PC_PERM_VIEW_HPMETER) ) {
map[sd->bl.m].hpmeter_visible++;
mapdata->hpmeter_visible++;
sd->state.hpmeter_visible = 1;
}
@ -10569,7 +10572,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
#endif
// Instances do not need their own channels
if( channel_config.map_tmpl.name[0] && (channel_config.map_tmpl.opt&CHAN_OPT_AUTOJOIN) && !map_getmapflag(sd->bl.m,MF_NOMAPCHANNELAUTOJOIN) && !map[sd->bl.m].instance_id )
if( channel_config.map_tmpl.name[0] && (channel_config.map_tmpl.opt&CHAN_OPT_AUTOJOIN) && !map_getmapflag(sd->bl.m,MF_NOMAPCHANNELAUTOJOIN) && !mapdata->instance_id )
channel_mjoin(sd); //join new map
clif_pk_mode_message(sd);
@ -17299,14 +17302,15 @@ void clif_bg_updatescore(int16 m)
{
struct block_list bl;
unsigned char buf[6];
struct map_data *mapdata = map_getmapdata(m);
bl.id = 0;
bl.type = BL_NUL;
bl.m = m;
WBUFW(buf,0) = 0x2de;
WBUFW(buf,2) = map[m].bgscore_lion;
WBUFW(buf,4) = map[m].bgscore_eagle;
WBUFW(buf,2) = mapdata->bgscore_lion;
WBUFW(buf,4) = mapdata->bgscore_eagle;
clif_send(buf,packet_len(0x2de),&bl,ALL_SAMEMAP);
}
@ -17316,10 +17320,12 @@ void clif_bg_updatescore_single(struct map_session_data *sd)
nullpo_retv(sd);
fd = sd->fd;
struct map_data *mapdata = map_getmapdata(sd->bl.m);
WFIFOHEAD(fd,packet_len(0x2de));
WFIFOW(fd,0) = 0x2de;
WFIFOW(fd,2) = map[sd->bl.m].bgscore_lion;
WFIFOW(fd,4) = map[sd->bl.m].bgscore_eagle;
WFIFOW(fd,2) = mapdata->bgscore_lion;
WFIFOW(fd,4) = mapdata->bgscore_eagle;
WFIFOSET(fd,packet_len(0x2de));
}

View File

@ -879,11 +879,11 @@ int guild_member_withdraw(int guild_id, uint32 account_id, uint32 char_id, int f
sd->guild_emblem_id = 0;
if (g->instance_id) {
int16 m = sd->bl.m;
struct map_data *mapdata = map_getmapdata(sd->bl.m);
if (map[m].instance_id) { // User was on the instance map
if (map[m].save.map)
pc_setpos(sd, map[m].save.map, map[m].save.x, map[m].save.y, CLR_TELEPORT);
if (mapdata->instance_id) { // User was on the instance map
if (mapdata->save.map)
pc_setpos(sd, mapdata->save.map, mapdata->save.x, mapdata->save.y, CLR_TELEPORT);
else
pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT);
}

View File

@ -343,12 +343,18 @@ void instance_addnpc(struct instance_data *im)
int i;
// First add the NPCs
for(i = 0; i < im->cnt_map; i++)
map_foreachinallarea(instance_addnpc_sub, im->map[i]->src_m, 0, 0, map[im->map[i]->src_m].xs, map[im->map[i]->src_m].ys, BL_NPC, im->map[i]->m);
for (i = 0; i < im->cnt_map; i++) {
struct map_data *mapdata = map_getmapdata(im->map[i]->src_m);
map_foreachinallarea(instance_addnpc_sub, im->map[i]->src_m, 0, 0, mapdata->xs, mapdata->ys, BL_NPC, im->map[i]->m);
}
// Now run their OnInstanceInit
for(i = 0; i < im->cnt_map; i++)
map_foreachinallarea(instance_npcinit, im->map[i]->m, 0, 0, map[im->map[i]->m].xs, map[im->map[i]->m].ys, BL_NPC, im->map[i]->m);
for (i = 0; i < im->cnt_map; i++) {
struct map_data *mapdata = map_getmapdata(im->map[i]->m);
map_foreachinallarea(instance_npcinit, im->map[i]->m, 0, 0, mapdata->xs, mapdata->ys, BL_NPC, im->map[i]->m);
}
}
@ -653,7 +659,9 @@ int instance_destroy(unsigned short instance_id)
// Run OnInstanceDestroy on all NPCs in the instance
for(i = 0; i < im->cnt_map; i++){
map_foreachinallarea(instance_npcdestroy, im->map[i]->m, 0, 0, map[im->map[i]->m].xs, map[im->map[i]->m].ys, BL_NPC, im->map[i]->m);
struct map_data *mapdata = map_getmapdata(im->map[i]->m);
map_foreachinallarea(instance_npcdestroy, im->map[i]->m, 0, 0, mapdata->xs, mapdata->ys, BL_NPC, im->map[i]->m);
}
for(i = 0; i < im->cnt_map; i++) {
@ -875,7 +883,7 @@ int instance_delusers(unsigned short instance_id)
// If no one is in the instance, start the idle timer
for(i = 0; i < im->cnt_map && im->map[i]->m; i++)
users += max(map[im->map[i]->m].users,0);
users += max(map_getmapdata(im->map[i]->m)->users,0);
// We check the actual map.users before being updated, hence the 1
// The instance should be empty if users are now <= 1
@ -1078,39 +1086,41 @@ void do_reload_instance(void)
// Reset player to instance beginning
iter = mapit_getallusers();
for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) )
if(sd && map[sd->bl.m].instance_id) {
for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) {
struct map_data *mapdata = map_getmapdata(sd->bl.m);
if(sd && mapdata->instance_id) {
struct party_data *pd = NULL;
struct guild *gd = NULL;
struct clan *cd = NULL;
unsigned short instance_id;
im = &instance_data[map[sd->bl.m].instance_id];
im = &instance_data[mapdata->instance_id];
switch (im->mode) {
case IM_NONE:
continue;
case IM_CHAR:
if (sd->instance_id != map[sd->bl.m].instance_id) // Someone who is not instance owner is on instance map
if (sd->instance_id != mapdata->instance_id) // Someone who is not instance owner is on instance map
continue;
instance_id = sd->instance_id;
break;
case IM_PARTY:
if ((!(pd = party_search(sd->status.party_id)) || pd->instance_id != map[sd->bl.m].instance_id)) // Someone not in party is on instance map
if ((!(pd = party_search(sd->status.party_id)) || pd->instance_id != mapdata->instance_id)) // Someone not in party is on instance map
continue;
instance_id = pd->instance_id;
break;
case IM_GUILD:
if (!(gd = guild_search(sd->status.guild_id)) || gd->instance_id != map[sd->bl.m].instance_id) // Someone not in guild is on instance map
if (!(gd = guild_search(sd->status.guild_id)) || gd->instance_id != mapdata->instance_id) // Someone not in guild is on instance map
continue;
instance_id = gd->instance_id;
break;
case IM_CLAN:
if (!(cd = clan_search(sd->status.clan_id)) || cd->instance_id != map[sd->bl.m].instance_id) // Someone not in clan is on instance map
if (!(cd = clan_search(sd->status.clan_id)) || cd->instance_id != mapdata->instance_id) // Someone not in clan is on instance map
continue;
instance_id = cd->instance_id;
break;
default:
ShowError("do_reload_instance: Unexpected instance mode for instance %s (id=%u, mode=%u).\n", (db) ? StringBuf_Value(db->name) : "Unknown", map[sd->bl.m].instance_id, (unsigned short)im->mode);
ShowError("do_reload_instance: Unexpected instance mode for instance %s (id=%u, mode=%u).\n", (db) ? StringBuf_Value(db->name) : "Unknown", mapdata->instance_id, (unsigned short)im->mode);
continue;
}
if((db = instance_searchtype_db(im->type)) != NULL && !instance_enter(sd, instance_id, StringBuf_Value(db->name), -1, -1)) { // All good
@ -1119,6 +1129,7 @@ void do_reload_instance(void)
} else // Something went wrong
ShowError("do_reload_instance: Error setting character at instance start: character_id=%d instance=%s.\n",sd->status.char_id,StringBuf_Value(db->name));
}
}
mapit_free(iter);
}

View File

@ -690,8 +690,8 @@ int intif_party_changemap(struct map_session_data *sd,int online)
if(!sd)
return 0;
if( (m=map_mapindex2mapid(sd->mapindex)) >= 0 && map[m].instance_id )
mapindex = map[map[m].instance_src_map].index;
if( (m=map_mapindex2mapid(sd->mapindex)) >= 0 && map_getmapdata(m)->instance_id )
mapindex = map_getmapdata(map_getmapdata(m)->instance_src_map)->index;
else
mapindex = sd->mapindex;

View File

@ -1586,7 +1586,7 @@ bool itemdb_isNoEquip(struct item_data *id, uint16 m) {
(map_flag_gvg2_no_te(m) && id->flag.no_equip&4) || // GVG
(map_getmapflag(m, MF_BATTLEGROUND) && id->flag.no_equip&8) || // Battleground
(map_flag_gvg2_te(m) && id->flag.no_equip&16) || // WOE:TE
(map_getmapflag(m, MF_RESTRICTED) && id->flag.no_equip&(8*map[m].zone)) // Zone restriction
(map_getmapflag(m, MF_RESTRICTED) && id->flag.no_equip&(8*map_getmapdata(m)->zone)) // Zone restriction
)
return true;
return false;

View File

@ -226,7 +226,7 @@ void log_pick(int id, int16 m, e_log_pick_type type, int amount, struct item* it
StringBuf_Printf(&buf, ", `option_parm%d`", i);
}
StringBuf_Printf(&buf, ") VALUES(NOW(),'%u','%c','%d','%d','%d','%s','%" PRIu64 "','%d'",
id, log_picktype2char(type), itm->nameid, amount, itm->refine, map[m].name[0] ? map[m].name : "", itm->unique_id, itm->bound);
id, log_picktype2char(type), itm->nameid, amount, itm->refine, map_getmapdata(m)->name[0] ? map_getmapdata(m)->name : "", itm->unique_id, itm->bound);
for (i = 0; i < MAX_SLOTS; i++)
StringBuf_Printf(&buf, ",'%d'", itm->card[i]);
@ -250,7 +250,7 @@ void log_pick(int id, int16 m, e_log_pick_type type, int amount, struct item* it
return;
time(&curtime);
strftime(timestring, sizeof(timestring), log_timestamp_format, localtime(&curtime));
fprintf(logfp,"%s - %d\t%c\t%hu,%d,%d,%hu,%hu,%hu,%hu,%s,'%" PRIu64 "',%d\n", timestring, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name[0]?map[m].name:"", itm->unique_id, itm->bound);
fprintf(logfp,"%s - %d\t%c\t%hu,%d,%d,%hu,%hu,%hu,%hu,%s,'%" PRIu64 "',%d\n", timestring, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map_getmapdata(m)->name[0]?map_getmapdata(m)->name:"", itm->unique_id, itm->bound);
fclose(logfp);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -29,6 +29,7 @@ enum E_MAPSERVER_ST {
MAPSERVER_ST_LAST
};
struct map_data *map_getmapdata(int16 m);
#define msg_config_read(cfgName,isnew) map_msg_config_read(cfgName,isnew)
#define msg_txt(sd,msg_number) map_msg_txt(sd,msg_number)
#define do_final_msg() map_do_final_msg()
@ -773,7 +774,7 @@ int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk);
void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag);
void map_setgatcell(int16 m, int16 x, int16 y, int gat);
extern std::vector<map_data> map;
extern std::map<int16, map_data> map;
extern int autosave_interval;
extern int minsave_interval;

View File

@ -270,15 +270,17 @@ void mvptomb_destroy(struct mob_data *md) {
struct npc_data *nd;
if ( (nd = map_id2nd(md->tomb_nid)) ) {
int16 m = nd->bl.m, i;
int16 i;
struct map_data *mapdata = map_getmapdata(nd->bl.m);
clif_clearunit_area(&nd->bl,CLR_OUTSIGHT);
map_delblock(&nd->bl);
ARR_FIND( 0, map[m].npc_num, i, map[m].npc[i] == nd );
if( !(i == map[m].npc_num) ) {
map[m].npc_num--;
map[m].npc[i] = map[m].npc[map[m].npc_num];
map[m].npc[map[m].npc_num] = NULL;
ARR_FIND( 0, mapdata->npc_num, i, mapdata->npc[i] == nd );
if( !(i == mapdata->npc_num) ) {
mapdata->npc_num--;
mapdata->npc[i] = mapdata->npc[mapdata->npc_num];
mapdata->npc[mapdata->npc_num] = NULL;
}
map_deliddb(&nd->bl);
aFree(nd);
@ -646,8 +648,9 @@ struct mob_data *mob_once_spawn_sub(struct block_list *bl, int16 m, int16 x, int
if (bl && (x < 0 || y < 0))
map_search_freecell(bl, m, &x, &y, 1, 1, 0);
struct map_data *mapdata = map_getmapdata(m);
// if none found, pick random position on map
if (x <= 0 || x >= map[m].xs || y <= 0 || y >= map[m].ys)
if (x <= 0 || x >= mapdata->xs || y <= 0 || y >= mapdata->ys)
map_search_freecell(NULL, m, &x, &y, -1, -1, 1);
data.x = x;
@ -682,7 +685,7 @@ int mob_once_spawn(struct map_session_data* sd, int16 m, int16 x, int16 y, const
if (mob_id == MOBID_EMPERIUM)
{
struct guild_castle* gc = guild_mapindex2gc(map[m].index);
struct guild_castle* gc = guild_mapindex2gc(map_getmapdata(m)->index);
struct guild* g = (gc) ? guild_search(gc->guild_id) : nullptr;
if (gc)
{
@ -835,6 +838,9 @@ int mob_spawn_guardian(const char* mapname, int16 x, int16 y, const char* mobnam
ShowWarning("mob_spawn_guardian: Map [%s] not found.\n", mapname);
return 0;
}
struct map_data *mapdata = map_getmapdata(m);
data.m = m;
data.num = 1;
if(mob_id<=0) {
@ -850,13 +856,13 @@ int mob_spawn_guardian(const char* mapname, int16 x, int16 y, const char* mobnam
}
else if( guardian < 0 || guardian >= MAX_GUARDIANS )
{
ShowError("mob_spawn_guardian: Invalid guardian index %d for guardian %d (castle map %s)\n", guardian, mob_id, map[m].name);
ShowError("mob_spawn_guardian: Invalid guardian index %d for guardian %d (castle map %s)\n", guardian, mob_id, mapdata->name);
return 0;
}
if((x<=0 || y<=0) && !map_search_freecell(NULL, m, &x, &y, -1,-1, 1))
{
ShowWarning("mob_spawn_guardian: Couldn't locate a spawn cell for guardian class %d (index %d) at castle map %s\n",mob_id, guardian, map[m].name);
ShowWarning("mob_spawn_guardian: Couldn't locate a spawn cell for guardian class %d (index %d) at castle map %s\n",mob_id, guardian, mapdata->name);
return 0;
}
data.x = x;
@ -866,14 +872,14 @@ int mob_spawn_guardian(const char* mapname, int16 x, int16 y, const char* mobnam
if (!mob_parse_dataset(&data))
return 0;
gc=guild_mapname2gc(map[m].name);
gc=guild_mapname2gc(mapdata->name);
if (gc == NULL)
{
ShowError("mob_spawn_guardian: No castle set at map %s\n", map[m].name);
ShowError("mob_spawn_guardian: No castle set at map %s\n", mapdata->name);
return 0;
}
if (!gc->guild_id)
ShowWarning("mob_spawn_guardian: Spawning guardian %d on a castle with no guild (castle map %s)\n", mob_id, map[m].name);
ShowWarning("mob_spawn_guardian: Spawning guardian %d on a castle with no guild (castle map %s)\n", mob_id, mapdata->name);
else
g = guild_search(gc->guild_id);
@ -883,7 +889,7 @@ int mob_spawn_guardian(const char* mapname, int16 x, int16 y, const char* mobnam
if (md2 && md2->bl.type == BL_MOB &&
md2->guardian_data && md2->guardian_data->number == guardian)
{
ShowError("mob_spawn_guardian: Attempted to spawn guardian in position %d which already has a guardian (castle map %s)\n", guardian, map[m].name);
ShowError("mob_spawn_guardian: Attempted to spawn guardian in position %d which already has a guardian (castle map %s)\n", guardian, mapdata->name);
return 0;
}
}
@ -947,7 +953,7 @@ int mob_spawn_bg(const char* mapname, int16 x, int16 y, const char* mobname, int
data.id = mob_id;
if( (x <= 0 || y <= 0) && !map_search_freecell(NULL, m, &x, &y, -1,-1, 1) )
{
ShowWarning("mob_spawn_bg: Couldn't locate a spawn cell for guardian class %d (bg_id %d) at map %s\n",mob_id, bg_id, map[m].name);
ShowWarning("mob_spawn_bg: Couldn't locate a spawn cell for guardian class %d (bg_id %d) at map %s\n",mob_id, bg_id, map_getmapdata(m)->name);
return 0;
}
@ -1186,7 +1192,7 @@ int mob_spawn (struct mob_data *md)
if(map_addblock(&md->bl))
return 2;
if( map[md->bl.m].users )
if( map_getmapdata(md->bl.m)->users )
clif_spawn(&md->bl);
skill_unit_move(&md->bl,tick,1);
mobskill_use(md, tick, MSC_SPAWN);
@ -1404,7 +1410,7 @@ static int mob_warpchase_sub(struct block_list *bl,va_list ap) {
if(nd->subtype != NPCTYPE_WARP)
return 0; //Not a warp
if(nd->u.warp.mapindex != map[target->m].index)
if(nd->u.warp.mapindex != map_getmapdata(target->m)->index)
return 0; //Does not lead to the same map.
cur_distance = distance_blxy(target, nd->u.warp.x, nd->u.warp.y);
@ -1629,7 +1635,7 @@ int mob_randomwalk(struct mob_data *md,unsigned int tick)
if(battle_config.mob_stuck_warning) {
md->move_fail_count++;
if(md->move_fail_count>1000){
ShowWarning("MOB can't move. random spawn %d, class = %d, at %s (%d,%d)\n",md->bl.id,md->mob_id,map[md->bl.m].name, md->bl.x, md->bl.y);
ShowWarning("MOB can't move. random spawn %d, class = %d, at %s (%d,%d)\n",md->bl.id,md->mob_id,map_getmapdata(md->bl.m)->name, md->bl.x, md->bl.y);
md->move_fail_count=0;
mob_spawn(md);
}
@ -2005,7 +2011,7 @@ static int mob_ai_sub_lazy(struct mob_data *md, va_list args)
tick = va_arg(args,unsigned int);
if (battle_config.mob_ai&0x20 && map[md->bl.m].users>0)
if (battle_config.mob_ai&0x20 && map_getmapdata(md->bl.m)->users>0)
return (int)mob_ai_sub_hard(md, tick);
if (md->bl.prev==NULL || md->status.hp == 0)

View File

@ -350,7 +350,7 @@ static int npc_event_export(struct npc_data *nd, int i)
struct event_data *ev;
char buf[EVENT_NAME_LENGTH];
if (nd->bl.m > -1 && map[nd->bl.m].instance_id > 0) { // Block script events in instances
if (nd->bl.m > -1 && map_getmapdata(nd->bl.m)->instance_id > 0) { // Block script events in instances
int j;
for (j = 0; j < NPCE_MAX; j++) {
@ -981,59 +981,61 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
//if(sd->npc_id)
// return 1;
for(i=0;i<map[m].npc_num;i++)
struct map_data *mapdata = map_getmapdata(m);
for(i=0;i<mapdata->npc_num;i++)
{
if (map[m].npc[i]->sc.option&OPTION_INVISIBLE) {
if (mapdata->npc[i]->sc.option&OPTION_INVISIBLE) {
f=0; // a npc was found, but it is disabled; don't print warning
continue;
}
switch(map[m].npc[i]->subtype) {
switch(mapdata->npc[i]->subtype) {
case NPCTYPE_WARP:
xs=map[m].npc[i]->u.warp.xs;
ys=map[m].npc[i]->u.warp.ys;
xs=mapdata->npc[i]->u.warp.xs;
ys=mapdata->npc[i]->u.warp.ys;
break;
case NPCTYPE_SCRIPT:
xs=map[m].npc[i]->u.scr.xs;
ys=map[m].npc[i]->u.scr.ys;
xs=mapdata->npc[i]->u.scr.xs;
ys=mapdata->npc[i]->u.scr.ys;
break;
default:
continue;
}
if( x >= map[m].npc[i]->bl.x-xs && x <= map[m].npc[i]->bl.x+xs
&& y >= map[m].npc[i]->bl.y-ys && y <= map[m].npc[i]->bl.y+ys )
if( x >= mapdata->npc[i]->bl.x-xs && x <= mapdata->npc[i]->bl.x+xs
&& y >= mapdata->npc[i]->bl.y-ys && y <= mapdata->npc[i]->bl.y+ys )
break;
}
if( i == map[m].npc_num )
if( i == mapdata->npc_num )
{
if( f == 1 ) // no npc found
ShowError("npc_touch_areanpc : stray NPC cell/NPC not found in the block on coordinates '%s',%d,%d\n", map[m].name, x, y);
ShowError("npc_touch_areanpc : stray NPC cell/NPC not found in the block on coordinates '%s',%d,%d\n", mapdata->name, x, y);
return 1;
}
switch(map[m].npc[i]->subtype) {
switch(mapdata->npc[i]->subtype) {
case NPCTYPE_WARP:
if ((!map[m].npc[i]->trigger_on_hidden && (pc_ishiding(sd) || (sd->sc.count && sd->sc.data[SC_CAMOUFLAGE]))) || pc_isdead(sd))
if ((!mapdata->npc[i]->trigger_on_hidden && (pc_ishiding(sd) || (sd->sc.count && sd->sc.data[SC_CAMOUFLAGE]))) || pc_isdead(sd))
break; // hidden or dead chars cannot use warps
if (!pc_job_can_entermap((enum e_job)sd->status.class_, map_mapindex2mapid(map[m].npc[i]->u.warp.mapindex), sd->group_level))
if (!pc_job_can_entermap((enum e_job)sd->status.class_, map_mapindex2mapid(mapdata->npc[i]->u.warp.mapindex), sd->group_level))
break;
if(sd->count_rewarp > 10){
ShowWarning("Prevented infinite warp loop for player (%d:%d). Please fix NPC: '%s', path: '%s'\n", sd->status.account_id, sd->status.char_id, map[m].npc[i]->exname, map[m].npc[i]->path);
ShowWarning("Prevented infinite warp loop for player (%d:%d). Please fix NPC: '%s', path: '%s'\n", sd->status.account_id, sd->status.char_id, mapdata->npc[i]->exname, mapdata->npc[i]->path);
sd->count_rewarp=0;
break;
}
pc_setpos(sd,map[m].npc[i]->u.warp.mapindex,map[m].npc[i]->u.warp.x,map[m].npc[i]->u.warp.y,CLR_OUTSIGHT);
pc_setpos(sd,mapdata->npc[i]->u.warp.mapindex,mapdata->npc[i]->u.warp.x,mapdata->npc[i]->u.warp.y,CLR_OUTSIGHT);
break;
case NPCTYPE_SCRIPT:
for (j = i; j < map[m].npc_num; j++) {
if (map[m].npc[j]->subtype != NPCTYPE_WARP) {
for (j = i; j < mapdata->npc_num; j++) {
if (mapdata->npc[j]->subtype != NPCTYPE_WARP) {
continue;
}
if ((sd->bl.x >= (map[m].npc[j]->bl.x - map[m].npc[j]->u.warp.xs) && sd->bl.x <= (map[m].npc[j]->bl.x + map[m].npc[j]->u.warp.xs)) &&
(sd->bl.y >= (map[m].npc[j]->bl.y - map[m].npc[j]->u.warp.ys) && sd->bl.y <= (map[m].npc[j]->bl.y + map[m].npc[j]->u.warp.ys))) {
if ((!map[m].npc[i]->trigger_on_hidden && (pc_ishiding(sd) || (sd->sc.count && sd->sc.data[SC_CAMOUFLAGE]))) || pc_isdead(sd))
if ((sd->bl.x >= (mapdata->npc[j]->bl.x - mapdata->npc[j]->u.warp.xs) && sd->bl.x <= (mapdata->npc[j]->bl.x + mapdata->npc[j]->u.warp.xs)) &&
(sd->bl.y >= (mapdata->npc[j]->bl.y - mapdata->npc[j]->u.warp.ys) && sd->bl.y <= (mapdata->npc[j]->bl.y + mapdata->npc[j]->u.warp.ys))) {
if ((!mapdata->npc[i]->trigger_on_hidden && (pc_ishiding(sd) || (sd->sc.count && sd->sc.data[SC_CAMOUFLAGE]))) || pc_isdead(sd))
break; // hidden or dead chars cannot use warps
pc_setpos(sd,map[m].npc[j]->u.warp.mapindex,map[m].npc[j]->u.warp.x,map[m].npc[j]->u.warp.y,CLR_OUTSIGHT);
pc_setpos(sd,mapdata->npc[j]->u.warp.mapindex,mapdata->npc[j]->u.warp.x,mapdata->npc[j]->u.warp.y,CLR_OUTSIGHT);
found_warp = 1;
break;
}
@ -1043,7 +1045,7 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
break;
}
if( npc_ontouch_event(sd,map[m].npc[i]) > 0 && npc_ontouch2_event(sd,map[m].npc[i]) > 0 )
if( npc_ontouch_event(sd,mapdata->npc[i]) > 0 && npc_ontouch2_event(sd,mapdata->npc[i]) > 0 )
{ // failed to run OnTouch event, so just click the npc
struct unit_data *ud = unit_bl2ud(&sd->bl);
if( ud && ud->walkpath.path_pos < ud->walkpath.path_len )
@ -1051,8 +1053,8 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
clif_fixpos(&sd->bl);
ud->walkpath.path_pos = ud->walkpath.path_len;
}
sd->areanpc_id = map[m].npc[i]->bl.id;
npc_click(sd,map[m].npc[i]);
sd->areanpc_id = mapdata->npc[i]->bl.id;
npc_click(sd,mapdata->npc[i]);
}
break;
}
@ -1063,50 +1065,51 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
// Return 1 if Warped
int npc_touch_areanpc2(struct mob_data *md)
{
int i, m = md->bl.m, x = md->bl.x, y = md->bl.y, id;
int i, x = md->bl.x, y = md->bl.y, id;
char eventname[EVENT_NAME_LENGTH];
struct event_data* ev;
int xs, ys;
struct map_data *mapdata = map_getmapdata(md->bl.m);
for( i = 0; i < map[m].npc_num; i++ )
for( i = 0; i < mapdata->npc_num; i++ )
{
if( map[m].npc[i]->sc.option&OPTION_INVISIBLE )
if( mapdata->npc[i]->sc.option&OPTION_INVISIBLE )
continue;
switch( map[m].npc[i]->subtype )
switch( mapdata->npc[i]->subtype )
{
case NPCTYPE_WARP:
if( !( battle_config.mob_warp&1 ) )
continue;
xs = map[m].npc[i]->u.warp.xs;
ys = map[m].npc[i]->u.warp.ys;
xs = mapdata->npc[i]->u.warp.xs;
ys = mapdata->npc[i]->u.warp.ys;
break;
case NPCTYPE_SCRIPT:
xs = map[m].npc[i]->u.scr.xs;
ys = map[m].npc[i]->u.scr.ys;
xs = mapdata->npc[i]->u.scr.xs;
ys = mapdata->npc[i]->u.scr.ys;
break;
default:
continue; // Keep Searching
}
if( x >= map[m].npc[i]->bl.x-xs && x <= map[m].npc[i]->bl.x+xs && y >= map[m].npc[i]->bl.y-ys && y <= map[m].npc[i]->bl.y+ys )
if( x >= mapdata->npc[i]->bl.x-xs && x <= mapdata->npc[i]->bl.x+xs && y >= mapdata->npc[i]->bl.y-ys && y <= mapdata->npc[i]->bl.y+ys )
{ // In the npc touch area
switch( map[m].npc[i]->subtype )
switch( mapdata->npc[i]->subtype )
{
case NPCTYPE_WARP:
xs = map_mapindex2mapid(map[m].npc[i]->u.warp.mapindex);
if( m < 0 )
xs = map_mapindex2mapid(mapdata->npc[i]->u.warp.mapindex);
if( md->bl.m < 0 )
break; // Cannot Warp between map servers
if( unit_warp(&md->bl, xs, map[m].npc[i]->u.warp.x, map[m].npc[i]->u.warp.y, CLR_OUTSIGHT) == 0 )
if( unit_warp(&md->bl, xs, mapdata->npc[i]->u.warp.x, mapdata->npc[i]->u.warp.y, CLR_OUTSIGHT) == 0 )
return 1; // Warped
break;
case NPCTYPE_SCRIPT:
if( map[m].npc[i]->bl.id == md->areanpc_id )
if( mapdata->npc[i]->bl.id == md->areanpc_id )
break; // Already touch this NPC
safesnprintf(eventname, ARRAYLENGTH(eventname), "%s::%s", map[m].npc[i]->exname, script_config.ontouchnpc_event_name);
safesnprintf(eventname, ARRAYLENGTH(eventname), "%s::%s", mapdata->npc[i]->exname, script_config.ontouchnpc_event_name);
if( (ev = (struct event_data*)strdb_get(ev_db, eventname)) == NULL || ev->nd == NULL )
break; // No OnTouchNPC Event
md->areanpc_id = map[m].npc[i]->bl.id;
md->areanpc_id = mapdata->npc[i]->bl.id;
id = md->bl.id; // Stores Unique ID
run_script(ev->nd->u.scr.script, ev->pos, md->bl.id, ev->nd->bl.id);
if( map_id2md(id) == NULL ) return 1; // Not Warped, but killed
@ -1138,10 +1141,13 @@ int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range)
int xs,ys;
if (range < 0) return 0;
struct map_data *mapdata = map_getmapdata(m);
x0 = i16max(x-range, 0);
y0 = i16max(y-range, 0);
x1 = i16min(x+range, map[m].xs-1);
y1 = i16min(y+range, map[m].ys-1);
x1 = i16min(x+range, mapdata->xs-1);
y1 = i16min(y+range, mapdata->ys-1);
//First check for npc_cells on the range given
i = 0;
@ -1154,37 +1160,37 @@ int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range)
if (!i) return 0; //No NPC_CELLs.
//Now check for the actual NPC on said range.
for(i=0;i<map[m].npc_num;i++)
for(i=0;i<mapdata->npc_num;i++)
{
if (map[m].npc[i]->sc.option&OPTION_INVISIBLE)
if (mapdata->npc[i]->sc.option&OPTION_INVISIBLE)
continue;
switch(map[m].npc[i]->subtype)
switch(mapdata->npc[i]->subtype)
{
case NPCTYPE_WARP:
if (!(flag&1))
continue;
xs=map[m].npc[i]->u.warp.xs;
ys=map[m].npc[i]->u.warp.ys;
xs=mapdata->npc[i]->u.warp.xs;
ys=mapdata->npc[i]->u.warp.ys;
break;
case NPCTYPE_SCRIPT:
if (!(flag&2))
continue;
xs=map[m].npc[i]->u.scr.xs;
ys=map[m].npc[i]->u.scr.ys;
xs=mapdata->npc[i]->u.scr.xs;
ys=mapdata->npc[i]->u.scr.ys;
break;
default:
continue;
}
if( x1 >= map[m].npc[i]->bl.x-xs && x0 <= map[m].npc[i]->bl.x+xs
&& y1 >= map[m].npc[i]->bl.y-ys && y0 <= map[m].npc[i]->bl.y+ys )
if( x1 >= mapdata->npc[i]->bl.x-xs && x0 <= mapdata->npc[i]->bl.x+xs
&& y1 >= mapdata->npc[i]->bl.y-ys && y0 <= mapdata->npc[i]->bl.y+ys )
break; // found a npc
}
if (i==map[m].npc_num)
if (i==mapdata->npc_num)
return 0;
return (map[m].npc[i]->bl.id);
return (mapdata->npc[i]->bl.id);
}
/*==========================================
@ -1418,9 +1424,10 @@ static enum e_CASHSHOP_ACK npc_cashshop_process_payment(struct npc_data *nd, int
case NPCTYPE_ITEMSHOP:
{
struct item_data *id = itemdb_exists(nd->u.shop.itemshop_nameid);
struct map_data *mapdata = map_getmapdata(nd->bl.m);
if (!id) { // Item Data is checked at script parsing but in case of item_db reload, check again.
ShowWarning("Failed to find sellitem %hu for itemshop NPC '%s' (%s, %d, %d)!\n", nd->u.shop.itemshop_nameid, nd->exname, map[nd->bl.m].name, nd->bl.x, nd->bl.y);
ShowWarning("Failed to find sellitem %hu for itemshop NPC '%s' (%s, %d, %d)!\n", nd->u.shop.itemshop_nameid, nd->exname, mapdata->name, nd->bl.x, nd->bl.y);
return ERROR_TYPE_PURCHASE_FAIL;
}
if (cost[0] < (price - points)) {
@ -1433,7 +1440,7 @@ static enum e_CASHSHOP_ACK npc_cashshop_process_payment(struct npc_data *nd, int
return ERROR_TYPE_PURCHASE_FAIL;
}
if (pc_delitem(sd, pc_search_inventory(sd, nd->u.shop.itemshop_nameid), price - points, 0, 0, LOG_TYPE_NPC)) {
ShowWarning("Failed to delete item %hu from '%s' at itemshop NPC '%s' (%s, %d, %d)!\n", nd->u.shop.itemshop_nameid, sd->status.name, nd->exname, map[nd->bl.m].name, nd->bl.x, nd->bl.y);
ShowWarning("Failed to delete item %hu from '%s' at itemshop NPC '%s' (%s, %d, %d)!\n", nd->u.shop.itemshop_nameid, sd->status.name, nd->exname, mapdata->name, nd->bl.x, nd->bl.y);
return ERROR_TYPE_PURCHASE_FAIL;
}
}
@ -1673,7 +1680,7 @@ int npc_cashshop_buy(struct map_session_data *sd, unsigned short nameid, int amo
{
ShowWarning("npc_cashshop_buy: Item '%s' (%hu) price overflow attempt!\n", item->name, nameid);
ShowDebug("(NPC:'%s' (%s,%d,%d), player:'%s' (%d/%d), value:%d, amount:%d)\n",
nd->exname, map[nd->bl.m].name, nd->bl.x, nd->bl.y, sd->status.name, sd->status.account_id, sd->status.char_id, nd->u.shop.shop_item[i].value, amount);
nd->exname, map_getmapdata(nd->bl.m)->name, nd->bl.x, nd->bl.y, sd->status.name, sd->status.account_id, sd->status.char_id, nd->u.shop.shop_item[i].value, amount);
return ERROR_TYPE_ITEM_ID;
}
@ -2064,24 +2071,26 @@ uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list
//This doesn't remove it from map_db
int npc_remove_map(struct npc_data* nd)
{
int16 m,i;
int16 i;
nullpo_retr(1, nd);
if(nd->bl.prev == NULL || nd->bl.m < 0)
return 1; //Not assigned to a map.
m = nd->bl.m;
struct map_data *mapdata = map_getmapdata(nd->bl.m);
if (nd->subtype == NPCTYPE_SCRIPT)
skill_clear_unitgroup(&nd->bl);
clif_clearunit_area(&nd->bl,CLR_RESPAWN);
npc_unsetcells(nd);
map_delblock(&nd->bl);
//Remove npc from map[].npc list. [Skotlex]
ARR_FIND( 0, map[m].npc_num, i, map[m].npc[i] == nd );
if( i == map[m].npc_num ) return 2; //failed to find it?
ARR_FIND( 0, mapdata->npc_num, i, mapdata->npc[i] == nd );
if( i == mapdata->npc_num ) return 2; //failed to find it?
map[m].npc_num--;
map[m].npc[i] = map[m].npc[map[m].npc_num];
map[m].npc[map[m].npc_num] = NULL;
mapdata->npc_num--;
mapdata->npc[i] = mapdata->npc[mapdata->npc_num];
mapdata->npc[mapdata->npc_num] = NULL;
return 0;
}
@ -2361,8 +2370,8 @@ static void npc_parsename(struct npc_data* nd, const char* name, const char* sta
snprintf(newname, ARRAYLENGTH(newname), "%d_%d_%d_%d", i, nd->bl.m, nd->bl.x, nd->bl.y);
} while( npc_name2id(newname) != NULL );
strcpy(this_mapname, (nd->bl.m==-1?"(not on a map)":mapindex_id2name(map[nd->bl.m].index)));
strcpy(other_mapname, (dnd->bl.m==-1?"(not on a map)":mapindex_id2name(map[dnd->bl.m].index)));
strcpy(this_mapname, (nd->bl.m==-1?"(not on a map)":mapindex_id2name(map_getmapdata(nd->bl.m)->index)));
strcpy(other_mapname, (dnd->bl.m==-1?"(not on a map)":mapindex_id2name(map_getmapdata(dnd->bl.m)->index)));
ShowWarning("npc_parsename: Duplicate unique name in file '%s', line'%d'. Renaming '%s' to '%s'.\n", filepath, strline(buffer,start-buffer), nd->exname, newname);
ShowDebug("this npc:\n display name '%s'\n unique name '%s'\n map=%s, x=%d, y=%d\n", nd->name, nd->exname, this_mapname, nd->bl.x, nd->bl.y);
@ -2519,7 +2528,7 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short
status_set_viewdata(&nd->bl, nd->class_);
status_change_init(&nd->bl);
unit_dataset(&nd->bl);
if( map[nd->bl.m].users )
if( map_getmapdata(nd->bl.m)->users )
clif_spawn(&nd->bl);
strdb_put(npcname_db, nd->exname, nd);
@ -2563,8 +2572,10 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const
return strchr(start,'\n');// skip and continue
}
if( m != -1 && ( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) ) {
ShowWarning("npc_parse_warp: coordinates %d/%d are out of bounds in map %s(%dx%d), in file '%s', line '%d'\n", x, y, map[m].name, map[m].xs, map[m].ys,filepath,strline(buffer,start-buffer));
struct map_data *mapdata = map_getmapdata(m);
if( m != -1 && ( x < 0 || x >= mapdata->xs || y < 0 || y >= mapdata->ys ) ) {
ShowWarning("npc_parse_warp: coordinates %d/%d are out of bounds in map %s(%dx%d), in file '%s', line '%d'\n", x, y, mapdata->name, mapdata->xs, mapdata->ys,filepath,strline(buffer,start-buffer));
}
nd = npc_create_npc(m, x, y);
@ -2595,7 +2606,7 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const
status_set_viewdata(&nd->bl, nd->class_);
status_change_init(&nd->bl);
unit_dataset(&nd->bl);
if( map[nd->bl.m].users )
if( map_getmapdata(nd->bl.m)->users )
clif_spawn(&nd->bl);
strdb_put(npcname_db, nd->exname, nd);
@ -2647,8 +2658,10 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
m = map_mapname2mapid(mapname);
}
if( m != -1 && ( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) ) {
ShowWarning("npc_parse_shop: coordinates %d/%d are out of bounds in map %s(%dx%d), in file '%s', line '%d'\n", x, y, map[m].name, map[m].xs, map[m].ys,filepath,strline(buffer,start-buffer));
struct map_data *mapdata = map_getmapdata(m);
if( m != -1 && ( x < 0 || x >= mapdata->xs || y < 0 || y >= mapdata->ys ) ) {
ShowWarning("npc_parse_shop: coordinates %d/%d are out of bounds in map %s(%dx%d), in file '%s', line '%d'\n", x, y, mapdata->name, mapdata->xs, mapdata->ys,filepath,strline(buffer,start-buffer));
}
if( !strcasecmp(w2,"cashshop") )
@ -2830,7 +2843,7 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
nd->ud.dir = (uint8)dir;
if( nd->class_ != JT_FAKENPC ){
status_set_viewdata(&nd->bl, nd->class_);
if( map[nd->bl.m].users )
if( map_getmapdata(nd->bl.m)->users )
clif_spawn(&nd->bl);
}
} else
@ -3065,7 +3078,7 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons
if( nd->class_ != JT_FAKENPC )
{
status_set_viewdata(&nd->bl, nd->class_);
if( map[nd->bl.m].users )
if( map_getmapdata(nd->bl.m)->users )
clif_spawn(&nd->bl);
}
}
@ -3158,8 +3171,10 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
m = map_mapname2mapid(mapname);
}
if( m != -1 && ( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) ) {
ShowError("npc_parse_duplicate: coordinates %d/%d are out of bounds in map %s(%dx%d), in file '%s', line '%d'\n", x, y, map[m].name, map[m].xs, map[m].ys,filepath,strline(buffer,start-buffer));
struct map_data *mapdata = map_getmapdata(m);
if( m != -1 && ( x < 0 || x >= mapdata->xs || y < 0 || y >= mapdata->ys ) ) {
ShowError("npc_parse_duplicate: coordinates %d/%d are out of bounds in map %s(%dx%d), in file '%s', line '%d'\n", x, y, mapdata->name, mapdata->xs, mapdata->ys,filepath,strline(buffer,start-buffer));
}
if( type == NPCTYPE_WARP && sscanf(w4, "%6hd,%6hd", &xs, &ys) == 2 );// <spanx>,<spany>
@ -3222,7 +3237,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
return end;
if( nd->class_ != JT_FAKENPC ) {
status_set_viewdata(&nd->bl, nd->class_);
if( map[nd->bl.m].users )
if( map_getmapdata(nd->bl.m)->users )
clif_spawn(&nd->bl);
}
} else {
@ -3245,7 +3260,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
}
if(!strcmp(filepath,"INSTANCING")) //Instance NPCs will use this for commands
nd->instance_id = map[m].instance_id;
nd->instance_id = mapdata->instance_id;
nd->u.scr.timerid = INVALID_TIMER;
@ -3254,33 +3269,34 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
int npc_duplicate4instance(struct npc_data *snd, int16 m) {
char newname[NPC_NAME_LENGTH+1];
struct map_data *mapdata = map_getmapdata(m);
if( map[m].instance_id == 0 )
if( mapdata->instance_id == 0 )
return 1;
snprintf(newname, ARRAYLENGTH(newname), "dup_%d_%d", map[m].instance_id, snd->bl.id);
snprintf(newname, ARRAYLENGTH(newname), "dup_%d_%d", mapdata->instance_id, snd->bl.id);
if( npc_name2id(newname) != NULL ) { // Name already in use
ShowError("npc_duplicate4instance: the npcname (%s) is already in use while trying to duplicate npc %s in instance %d.\n", newname, snd->exname, map[m].instance_id);
ShowError("npc_duplicate4instance: the npcname (%s) is already in use while trying to duplicate npc %s in instance %d.\n", newname, snd->exname, mapdata->instance_id);
return 1;
}
if( snd->subtype == NPCTYPE_WARP ) { // Adjust destination, if instanced
struct npc_data *wnd = NULL; // New NPC
struct instance_data *im = &instance_data[map[m].instance_id];
struct instance_data *im = &instance_data[mapdata->instance_id];
int dm = map_mapindex2mapid(snd->u.warp.mapindex), imap = 0, i;
if( dm < 0 ) return 1;
for(i = 0; i < im->cnt_map; i++)
if(im->map[i]->m && map_mapname2mapid(map[im->map[i]->src_m].name) == dm) {
imap = map_mapname2mapid(map[im->map[i]->m].name);
if(im->map[i]->m && map_mapname2mapid(map_getmapdata(im->map[i]->src_m)->name) == dm) {
imap = map_mapname2mapid(map_getmapdata(im->map[i]->m)->name);
break; // Instance map matches destination, update to instance map
}
if(!imap)
imap = map_mapname2mapid(map[dm].name);
imap = map_mapname2mapid(map_getmapdata(dm)->name);
if( imap == -1 ) {
ShowError("npc_duplicate4instance: warp (%s) leading to instanced map (%s), but instance map is not attached to current instance.\n", map[dm].name, snd->exname);
ShowError("npc_duplicate4instance: warp (%s) leading to instanced map (%s), but instance map is not attached to current instance.\n", map_getmapdata(dm)->name, snd->exname);
return 1;
}
@ -3305,14 +3321,14 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) {
status_set_viewdata(&wnd->bl, wnd->class_);
status_change_init(&wnd->bl);
unit_dataset(&wnd->bl);
if( map[wnd->bl.m].users )
if( map_getmapdata(wnd->bl.m)->users )
clif_spawn(&wnd->bl);
strdb_put(npcname_db, wnd->exname, wnd);
} else {
static char w1[50], w2[50], w3[50], w4[50];
const char* stat_buf = "- call from instancing subsystem -\n";
snprintf(w1, sizeof(w1), "%s,%d,%d,%d", map[m].name, snd->bl.x, snd->bl.y, snd->ud.dir);
snprintf(w1, sizeof(w1), "%s,%d,%d,%d", mapdata->name, snd->bl.x, snd->bl.y, snd->ud.dir);
snprintf(w2, sizeof(w2), "duplicate(%s)", snd->exname);
snprintf(w3, sizeof(w3), "%s::%s", snd->name, newname);
@ -3580,12 +3596,14 @@ void npc_unsetcells(struct npc_data* nd)
if (m < 0 || xs < 0 || ys < 0)
return;
struct map_data *mapdata = map_getmapdata(m);
//Locate max range on which we can locate npc cells
//FIXME: does this really do what it's supposed to do? [ultramage]
for(x0 = x-xs; x0 > 0 && map_getcell(m, x0, y, CELL_CHKNPC); x0--);
for(x1 = x+xs; x1 < map[m].xs-1 && map_getcell(m, x1, y, CELL_CHKNPC); x1++);
for(x1 = x+xs; x1 < mapdata->xs-1 && map_getcell(m, x1, y, CELL_CHKNPC); x1++);
for(y0 = y-ys; y0 > 0 && map_getcell(m, x, y0, CELL_CHKNPC); y0--);
for(y1 = y+ys; y1 < map[m].ys-1 && map_getcell(m, x, y1, CELL_CHKNPC); y1++);
for(y1 = y+ys; y1 < mapdata->ys-1 && map_getcell(m, x, y1, CELL_CHKNPC); y1++);
//Erase this npc's cells
for (i = y-ys; i <= y+ys; i++)
@ -3598,12 +3616,13 @@ void npc_unsetcells(struct npc_data* nd)
bool npc_movenpc(struct npc_data* nd, int16 x, int16 y)
{
const int16 m = nd->bl.m;
if (m < 0 || nd->bl.prev == NULL)
if (nd->bl.m < 0 || nd->bl.prev == NULL)
return false; //Not on a map.
x = cap_value(x, 0, map[m].xs-1);
y = cap_value(y, 0, map[m].ys-1);
struct map_data *mapdata = map_getmapdata(nd->bl.m);
x = cap_value(x, 0, mapdata->xs-1);
y = cap_value(y, 0, mapdata->ys-1);
map_foreachinallrange(clif_outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl);
map_moveblock(&nd->bl, x, y, gettick());
@ -3620,7 +3639,7 @@ void npc_setdisplayname(struct npc_data* nd, const char* newname)
nullpo_retv(nd);
safestrncpy(nd->name, newname, sizeof(nd->name));
if( map[nd->bl.m].users )
if( map_getmapdata(nd->bl.m)->users )
clif_name_area(&nd->bl);
}
@ -3635,11 +3654,13 @@ void npc_setclass(struct npc_data* nd, short class_)
if( nd->class_ == class_ )
return;
if( map[nd->bl.m].users )
struct map_data *mapdata = map_getmapdata(nd->bl.m);
if( mapdata->users )
clif_clearunit_area(&nd->bl, CLR_OUTSIGHT);// fade out
nd->class_ = class_;
status_set_viewdata(&nd->bl, class_);
if( map[nd->bl.m].users )
if( mapdata->users )
clif_spawn(&nd->bl);// fade in
}
@ -3797,9 +3818,11 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c
return strchr(start,'\n');// skip and continue
mob.m = (unsigned short)m;
if( x < 0 || x >= map[mob.m].xs || y < 0 || y >= map[mob.m].ys )
struct map_data *mapdata = map_getmapdata(m);
if( x < 0 || x >= mapdata->xs || y < 0 || y >= mapdata->ys )
{
ShowError("npc_parse_mob: Spawn coordinates out of range: %s (%d,%d), map size is (%d,%d) - %s %s (file '%s', line '%d').\n", map[mob.m].name, x, y, (map[mob.m].xs-1), (map[mob.m].ys-1), w1, w3, filepath, strline(buffer,start-buffer));
ShowError("npc_parse_mob: Spawn coordinates out of range: %s (%d,%d), map size is (%d,%d) - %s %s (file '%s', line '%d').\n", mapdata->name, x, y, (mapdata->xs-1), (mapdata->ys-1), w1, w3, filepath, strline(buffer,start-buffer));
return strchr(start,'\n');// skip and continue
}
@ -3894,7 +3917,7 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c
}
//Update mob spawn lookup database
struct spawn_info spawn = { map[mob.m].index, mob.num };
struct spawn_info spawn = { mapdata->index, mob.num };
mob_add_spawn(mob_id, spawn);
//Now that all has been validated. We allocate the actual memory that the re-spawn data will use.
@ -3910,7 +3933,7 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c
// check if target map has players
// (usually shouldn't occur when map server is just starting,
// but not the case when we do @reloadscript
if( map[data->m].users > 0 )
if( map_getmapdata(data->m)->users > 0 )
npc_parse_mob2(data);
}
else
@ -4035,7 +4058,7 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con
if (sscanf(w4, "%11d", &args.flag_val) == 1)
map_setmapflag_sub(m, MF_RESTRICTED, true, &args);
else // Could not be read, no value defined; don't remove as other restrictions may be set on the map
ShowWarning("npc_parse_mapflag: Zone value not set for the restricted mapflag! Skipped flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
ShowWarning("npc_parse_mapflag: Zone value not set for the restricted mapflag! Skipped flag from %s (file '%s', line '%d').\n", map_getmapdata(m)->name, filepath, strline(buffer,start-buffer));
} else
map_setmapflag(m, MF_RESTRICTED, false);
break;
@ -4088,7 +4111,7 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con
else { // Adjusted damage for specified skill
args.flag_val = 1;
map_setmapflag_sub(m, MF_SKILL_DAMAGE, true, &args);
map_skill_damage_add(&map[m], skill_name2id(skill_name), args.skill_damage.rate, args.skill_damage.caster);
map_skill_damage_add(map_getmapdata(m), skill_name2id(skill_name), args.skill_damage.rate, args.skill_damage.caster);
}
}
}
@ -4254,7 +4277,10 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit)
p = strchr(p,'\n');// next line
continue;
}
if (x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys) {
struct map_data *mapdata = map_getmapdata(m);
if (x < 0 || x >= mapdata->xs || y < 0 || y >= mapdata->ys) {
ShowError("npc_parsesrcfile: Unknown coordinates ('%d', '%d') for map '%s' in file '%s', line '%d'. Skipping line...\n", x, y, mapname, filepath, strline(buffer,p-buffer));
if( strcasecmp(w2,"script") == 0 && count > 3 )
{
@ -4430,20 +4456,22 @@ int npc_reload(void) {
// dynamic check by [random]
if( battle_config.dynamic_mobs ){
for( int16 m = 0; m < map.size(); m++ ){
for( auto& pair : map ){
for( int16 i = 0; i < MAX_MOB_LIST_PER_MAP; i++ ){
if (map[m].moblist[i] != NULL) {
aFree(map[m].moblist[i]);
map[m].moblist[i] = NULL;
struct map_data *mapdata = &pair.second;
if (mapdata->moblist[i] != NULL) {
aFree(mapdata->moblist[i]);
mapdata->moblist[i] = NULL;
}
if( map[m].mob_delete_timer != INVALID_TIMER )
if( mapdata->mob_delete_timer != INVALID_TIMER )
{ // Mobs were removed anyway,so delete the timer [Inkfish]
delete_timer(map[m].mob_delete_timer, map_removemobs_timer);
map[m].mob_delete_timer = INVALID_TIMER;
delete_timer(mapdata->mob_delete_timer, map_removemobs_timer);
mapdata->mob_delete_timer = INVALID_TIMER;
}
if( map[m].npc_num > 0 ){
ShowWarning( "npc_reload: %d npcs weren't removed at map %s!\n", map[m].npc_num, map[m].name );
if( mapdata->npc_num > 0 ){
ShowWarning( "npc_reload: %d npcs weren't removed at map %s!\n", mapdata->npc_num, mapdata->name );
}
}
}
@ -4553,28 +4581,31 @@ static void npc_debug_warps_sub(struct npc_data* nd)
if (m < 0) return; //Warps to another map, nothing to do about it.
if (nd->u.warp.x == 0 && nd->u.warp.y == 0) return; // random warp
struct map_data *mapdata = map_getmapdata(m);
struct map_data *mapdata_nd = map_getmapdata(nd->bl.m);
if (map_getcell(m, nd->u.warp.x, nd->u.warp.y, CELL_CHKNPC)) {
ShowWarning("Warp %s at %s(%d,%d) warps directly on top of an area npc at %s(%d,%d)\n",
nd->name,
map[nd->bl.m].name, nd->bl.x, nd->bl.y,
map[m].name, nd->u.warp.x, nd->u.warp.y
mapdata_nd->name, nd->bl.x, nd->bl.y,
mapdata->name, nd->u.warp.x, nd->u.warp.y
);
}
if (map_getcell(m, nd->u.warp.x, nd->u.warp.y, CELL_CHKNOPASS)) {
ShowWarning("Warp %s at %s(%d,%d) warps to a non-walkable tile at %s(%d,%d)\n",
nd->name,
map[nd->bl.m].name, nd->bl.x, nd->bl.y,
map[m].name, nd->u.warp.x, nd->u.warp.y
mapdata_nd->name, nd->bl.x, nd->bl.y,
mapdata->name, nd->u.warp.x, nd->u.warp.y
);
}
}
static void npc_debug_warps(void)
{
int16 m, i;
for (m = 0; m < map.size(); m++)
for (i = 0; i < map[m].npc_num; i++)
npc_debug_warps_sub(map[m].npc[i]);
static void npc_debug_warps(void){
for( auto& pair : map ){
for( int i = 0; i < pair.second.npc_num; i++ ){
npc_debug_warps_sub( pair.second.npc[i] );
}
}
}
/*==========================================

View File

@ -675,11 +675,11 @@ int party_member_withdraw(int party_id, uint32 account_id, uint32 char_id, char
//TODO: hp bars should be cleared too
if( p->instance_id ) {
int16 m = sd->bl.m;
struct map_data *mapdata = map_getmapdata(sd->bl.m);
if( map[m].instance_id ) { // User was on the instance map
if( map[m].save.map )
pc_setpos(sd, map[m].save.map, map[m].save.x, map[m].save.y, CLR_TELEPORT);
if( mapdata->instance_id ) { // User was on the instance map
if( mapdata->save.map )
pc_setpos(sd, mapdata->save.map, mapdata->save.x, mapdata->save.y, CLR_TELEPORT);
else
pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT);
}

View File

@ -79,11 +79,10 @@ void do_final_path(){
*------------------------------------------*/
int path_blownpos(int16 m,int16 x0,int16 y0,int16 dx,int16 dy,int count)
{
struct map_data *md;
struct map_data *mapdata = map_getmapdata(m);
if( !map[m].cell )
if( !mapdata->cell )
return -1;
md = &map[m];
if( count>25 ){ //Cap to prevent too much processing...?
ShowWarning("path_blownpos: count too many %d !\n",count);
@ -97,14 +96,14 @@ int path_blownpos(int16 m,int16 x0,int16 y0,int16 dx,int16 dy,int count)
while( count > 0 && (dx != 0 || dy != 0) )
{
if( !map_getcellp(md,x0+dx,y0+dy,CELL_CHKPASS) )
if( !map_getcellp(mapdata,x0+dx,y0+dy,CELL_CHKPASS) )
{
if (battle_config.path_blown_halt)
break;
else
{// attempt partial movement
int fx = ( dx != 0 && map_getcellp(md,x0+dx,y0,CELL_CHKPASS) );
int fy = ( dy != 0 && map_getcellp(md,x0,y0+dy,CELL_CHKPASS) );
int fx = ( dx != 0 && map_getcellp(mapdata,x0+dx,y0,CELL_CHKPASS) );
int fy = ( dy != 0 && map_getcellp(mapdata,x0,y0+dy,CELL_CHKPASS) );
if( fx && fy )
{
if(rnd()&1)
@ -135,15 +134,14 @@ bool path_search_long(struct shootpath_data *spd,int16 m,int16 x0,int16 y0,int16
int dx, dy;
int wx = 0, wy = 0;
int weight;
struct map_data *md;
struct map_data *mapdata = map_getmapdata(m);
struct shootpath_data s_spd;
if( spd == NULL )
spd = &s_spd; // use dummy output variable
if (!map[m].cell)
if (!mapdata->cell)
return false;
md = &map[m];
dx = (x1 - x0);
if (dx < 0) {
@ -187,7 +185,7 @@ bool path_search_long(struct shootpath_data *spd,int16 m,int16 x0,int16 y0,int16
spd->y[spd->len] = y0;
spd->len++;
}
if ((x0 != x1 || y0 != y1) && map_getcellp(md,x0,y0,cell))
if ((x0 != x1 || y0 != y1) && map_getcellp(mapdata,x0,y0,cell))
return false;
}
@ -273,7 +271,7 @@ static int add_path(struct node_heap *heap, struct path_node *tp, int16 x, int16
bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int flag, cell_chk cell)
{
register int i, x, y, dx = 0, dy = 0;
struct map_data *md;
struct map_data *mapdata = map_getmapdata(m);
struct walkpath_data s_wpd;
if (flag&2)
@ -282,17 +280,15 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
if (wpd == NULL)
wpd = &s_wpd; // use dummy output variable
if (!map[m].cell)
if (!mapdata->cell)
return false;
md = &map[m];
//Do not check starting cell as that would get you stuck.
if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys /*|| map_getcellp(md,x0,y0,cell)*/)
if (x0 < 0 || x0 >= mapdata->xs || y0 < 0 || y0 >= mapdata->ys /*|| map_getcellp(mapdata,x0,y0,cell)*/)
return false;
// Check destination cell
if (x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || map_getcellp(md,x1,y1,cell))
if (x1 < 0 || x1 >= mapdata->xs || y1 < 0 || y1 >= mapdata->ys || map_getcellp(mapdata,x1,y1,cell))
return false;
if (flag&1) {
@ -318,7 +314,7 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
if( dx == 0 && dy == 0 )
break; // success
if( map_getcellp(md,x,y,cell) )
if( map_getcellp(mapdata,x,y,cell) )
break; // obstacle = failure
}
@ -335,8 +331,8 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
// Figure out more proper size or another way to keep track of known nodes.
struct path_node tp[MAX_WALKPATH * MAX_WALKPATH];
struct path_node *current, *it;
int xs = md->xs - 1;
int ys = md->ys - 1;
int xs = mapdata->xs - 1;
int ys = mapdata->ys - 1;
int len = 0;
int j;
@ -388,26 +384,26 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
break;
}
if (y < ys && !map_getcellp(md, x, y+1, cell)) allowed_dirs |= PATH_DIR_NORTH;
if (y > 0 && !map_getcellp(md, x, y-1, cell)) allowed_dirs |= PATH_DIR_SOUTH;
if (x < xs && !map_getcellp(md, x+1, y, cell)) allowed_dirs |= PATH_DIR_EAST;
if (x > 0 && !map_getcellp(md, x-1, y, cell)) allowed_dirs |= PATH_DIR_WEST;
if (y < ys && !map_getcellp(mapdata, x, y+1, cell)) allowed_dirs |= PATH_DIR_NORTH;
if (y > 0 && !map_getcellp(mapdata, x, y-1, cell)) allowed_dirs |= PATH_DIR_SOUTH;
if (x < xs && !map_getcellp(mapdata, x+1, y, cell)) allowed_dirs |= PATH_DIR_EAST;
if (x > 0 && !map_getcellp(mapdata, x-1, y, cell)) allowed_dirs |= PATH_DIR_WEST;
#define chk_dir(d) ((allowed_dirs & (d)) == (d))
// Process neighbors of current node
if (chk_dir(PATH_DIR_SOUTH|PATH_DIR_EAST) && !map_getcellp(md, x+1, y-1, cell))
if (chk_dir(PATH_DIR_SOUTH|PATH_DIR_EAST) && !map_getcellp(mapdata, x+1, y-1, cell))
e += add_path(&g_open_set, tp, x+1, y-1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x+1, y-1, x1, y1)); // (x+1, y-1) 5
if (chk_dir(PATH_DIR_EAST))
e += add_path(&g_open_set, tp, x+1, y, g_cost + MOVE_COST, current, heuristic(x+1, y, x1, y1)); // (x+1, y) 6
if (chk_dir(PATH_DIR_NORTH|PATH_DIR_EAST) && !map_getcellp(md, x+1, y+1, cell))
if (chk_dir(PATH_DIR_NORTH|PATH_DIR_EAST) && !map_getcellp(mapdata, x+1, y+1, cell))
e += add_path(&g_open_set, tp, x+1, y+1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x+1, y+1, x1, y1)); // (x+1, y+1) 7
if (chk_dir(PATH_DIR_NORTH))
e += add_path(&g_open_set, tp, x, y+1, g_cost + MOVE_COST, current, heuristic(x, y+1, x1, y1)); // (x, y+1) 0
if (chk_dir(PATH_DIR_NORTH|PATH_DIR_WEST) && !map_getcellp(md, x-1, y+1, cell))
if (chk_dir(PATH_DIR_NORTH|PATH_DIR_WEST) && !map_getcellp(mapdata, x-1, y+1, cell))
e += add_path(&g_open_set, tp, x-1, y+1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x-1, y+1, x1, y1)); // (x-1, y+1) 1
if (chk_dir(PATH_DIR_WEST))
e += add_path(&g_open_set, tp, x-1, y, g_cost + MOVE_COST, current, heuristic(x-1, y, x1, y1)); // (x-1, y) 2
if (chk_dir(PATH_DIR_SOUTH|PATH_DIR_WEST) && !map_getcellp(md, x-1, y-1, cell))
if (chk_dir(PATH_DIR_SOUTH|PATH_DIR_WEST) && !map_getcellp(mapdata, x-1, y-1, cell))
e += add_path(&g_open_set, tp, x-1, y-1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x-1, y-1, x1, y1)); // (x-1, y-1) 3
if (chk_dir(PATH_DIR_SOUTH))
e += add_path(&g_open_set, tp, x, y-1, g_cost + MOVE_COST, current, heuristic(x, y-1, x1, y1)); // (x, y-1) 4

View File

@ -4,7 +4,6 @@
#include "pc.hpp"
#include <map>
#include <vector>
#include <math.h>
#include <stdlib.h>
@ -713,9 +712,10 @@ void pc_makesavestatus(struct map_session_data *sd) {
}
if(map_getmapflag(sd->bl.m, MF_NOSAVE)) {
struct map_data *m=&map[sd->bl.m];
if(m->save.map)
memcpy(&sd->status.last_point,&m->save,sizeof(sd->status.last_point));
struct map_data *mapdata = map_getmapdata(sd->bl.m);
if(mapdata->save.map)
memcpy(&sd->status.last_point,&mapdata->save,sizeof(sd->status.last_point));
else
memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point));
}
@ -1568,7 +1568,7 @@ void pc_reg_received(struct map_session_data *sd)
sd->vd.class_ = JT_INVISIBLE;
clif_displaymessage( sd->fd, msg_txt( sd, 11 ) ); // Invisible: On
// decrement the number of pvp players on the map
map[sd->bl.m].users_pvp--;
map_getmapdata(sd->bl.m)->users_pvp--;
if( map_getmapflag(sd->bl.m, MF_PVP) && !map_getmapflag(sd->bl.m, MF_PVP_NOCALCRANK) && sd->pvp_timer != INVALID_TIMER ){
// unregister the player for ranking
@ -5496,6 +5496,8 @@ enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, in
m = map_mapindex2mapid(mapindex);
struct map_data *mapdata = map_getmapdata(m);
sd->state.changemap = (sd->mapindex != mapindex);
sd->state.warping = 1;
sd->state.workinprogress = WIP_DISABLE_NONE;
@ -5503,7 +5505,7 @@ enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, in
if( sd->state.changemap ) { // Misc map-changing settings
int i;
if(map[sd->bl.m].instance_id && !map[m].instance_id) {
if(map_getmapdata(sd->bl.m)->instance_id && !mapdata->instance_id) {
bool instance_found = false;
struct party_data *p = NULL;
struct guild *g = NULL;
@ -5599,7 +5601,7 @@ enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, in
return SETPOS_OK;
}
if( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys )
if( x < 0 || x >= mapdata->xs || y < 0 || y >= mapdata->ys )
{
ShowError("pc_setpos: attempt to place player '%s' (%d:%d) on invalid coordinates (%s-%d,%d)\n", sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(mapindex),x,y);
x = y = 0; // make it random
@ -5608,11 +5610,11 @@ enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, in
if( x == 0 && y == 0 ) { // pick a random walkable cell
int c=0;
do {
x = rnd()%(map[m].xs-2)+1;
y = rnd()%(map[m].ys-2)+1;
x = rnd()%(mapdata->xs-2)+1;
y = rnd()%(mapdata->ys-2)+1;
c++;
if(c > (map[m].xs * map[m].ys)*3){ //force out
if(c > (mapdata->xs * mapdata->ys)*3){ //force out
ShowError("pc_setpos: couldn't found a valid coordinates for player '%s' (%d:%d) on (%s), preventing warp\n", sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(mapindex));
return SETPOS_OK; //preventing warp
//break; //allow warp anyway
@ -5696,22 +5698,21 @@ enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, in
char pc_randomwarp(struct map_session_data *sd, clr_type type)
{
int x,y,i=0;
int16 m;
nullpo_ret(sd);
m=sd->bl.m;
if (map_getmapflag(sd->bl.m, MF_NOTELEPORT)) //Teleport forbidden
return 3;
struct map_data *mapdata = map_getmapdata(sd->bl.m);
do {
x = rnd()%(map[m].xs-2)+1;
y = rnd()%(map[m].ys-2)+1;
} while((map_getcell(m,x,y,CELL_CHKNOPASS) || (!battle_config.teleport_on_portal && npc_check_areanpc(1,m,x,y,1))) && (i++) < 1000);
x = rnd()%(mapdata->xs-2)+1;
y = rnd()%(mapdata->ys-2)+1;
} while((map_getcell(sd->bl.m,x,y,CELL_CHKNOPASS) || (!battle_config.teleport_on_portal && npc_check_areanpc(1,sd->bl.m,x,y,1))) && (i++) < 1000);
if (i < 1000)
return pc_setpos(sd,map[sd->bl.m].index,x,y,type);
return pc_setpos(sd,mapdata->index,x,y,type);
return 3;
}
@ -5756,7 +5757,7 @@ bool pc_memo(struct map_session_data* sd, int pos)
pos = 0;
}
if( map[sd->bl.m].instance_id ) {
if( map_getmapdata(sd->bl.m)->instance_id ) {
clif_displaymessage( sd->fd, msg_txt(sd,384) ); // You cannot create a memo in an instance.
return false;
}
@ -7972,9 +7973,9 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
if( map_getmapflag( sd->bl.m, MF_PVP_NIGHTMAREDROP ) ) { // Moved this outside so it works when PVP isn't enabled and during pk mode [Ancyker]
for(int j=0;j<MAX_DROP_PER_MAP;j++){
int id = map[sd->bl.m].drop_list[j].drop_id;
int per = map[sd->bl.m].drop_list[j].drop_per;
enum e_nightmare_drop_type type = map[sd->bl.m].drop_list[j].drop_type;
int id = map_getmapdata(sd->bl.m)->drop_list[j].drop_id;
int per = map_getmapdata(sd->bl.m)->drop_list[j].drop_per;
enum e_nightmare_drop_type type = map_getmapdata(sd->bl.m)->drop_list[j].drop_type;
if(id == 0)
continue;
@ -10301,12 +10302,12 @@ static int pc_calc_pvprank_sub(struct block_list *bl,va_list ap)
int pc_calc_pvprank(struct map_session_data *sd)
{
int old = sd->pvp_rank;
struct map_data *m = &map[sd->bl.m];
struct map_data *mapdata = map_getmapdata(sd->bl.m);
sd->pvp_rank=1;
map_foreachinmap(pc_calc_pvprank_sub,sd->bl.m,BL_PC,sd);
if(old!=sd->pvp_rank || sd->pvp_lastusers!=m->users_pvp)
clif_pvpset(sd,sd->pvp_rank,sd->pvp_lastusers=m->users_pvp,0);
if(old!=sd->pvp_rank || sd->pvp_lastusers!=mapdata->users_pvp)
clif_pvpset(sd,sd->pvp_rank,sd->pvp_lastusers=mapdata->users_pvp,0);
return sd->pvp_rank;
}
/*==========================================
@ -12374,13 +12375,16 @@ void pc_show_questinfo(struct map_session_data *sd) {
if (sd->bl.m < 0 || sd->bl.m >= MAX_MAPINDEX)
return;
if (!map[sd->bl.m].qi_count || !map[sd->bl.m].qi_data)
struct map_data *mapdata = map_getmapdata(sd->bl.m);
if (!mapdata->qi_count || !mapdata->qi_data)
return;
if (map[sd->bl.m].qi_count != sd->qi_count)
if (mapdata->qi_count != sd->qi_count)
return; // init was not called yet
for(i = 0; i < map[sd->bl.m].qi_count; i++) {
qi = &map[sd->bl.m].qi_data[i];
for(i = 0; i < mapdata->qi_count; i++) {
qi = &mapdata->qi_data[i];
if (!qi)
continue;
@ -12450,9 +12454,12 @@ void pc_show_questinfo_reinit(struct map_session_data *sd) {
if (sd->bl.m < 0 || sd->bl.m >= MAX_MAPINDEX)
return;
if (!map[sd->bl.m].qi_count || !map[sd->bl.m].qi_data)
struct map_data *mapdata = map_getmapdata(sd->bl.m);
if (!mapdata->qi_count || !mapdata->qi_data)
return;
CREATE(sd->qi_display, bool, (sd->qi_count = map[sd->bl.m].qi_count));
CREATE(sd->qi_display, bool, (sd->qi_count = mapdata->qi_count));
#endif
}
@ -12470,7 +12477,9 @@ bool pc_job_can_entermap(enum e_job jobid, int m, int group_lv) {
if (m < 0)
return true;
if (m >= MAX_MAP_PER_SERVER || !map[m].cell)
struct map_data *mapdata = map_getmapdata(m);
if (!mapdata->cell)
return false;
if (!pcdb_checkid(jobid))
@ -12485,7 +12494,7 @@ bool pc_job_can_entermap(enum e_job jobid, int m, int group_lv) {
(map_flag_gvg2_no_te(m) && job_info[idx].noenter_map.zone&4) || // GVG
(map_getmapflag(m, MF_BATTLEGROUND) && job_info[idx].noenter_map.zone&8) || // Battleground
(map_flag_gvg2_te(m) && job_info[idx].noenter_map.zone&16) || // WOE:TE
(map_getmapflag(m, MF_RESTRICTED) && job_info[idx].noenter_map.zone&(8*map[m].zone)) // Zone restriction
(map_getmapflag(m, MF_RESTRICTED) && job_info[idx].noenter_map.zone&(8*mapdata->zone)) // Zone restriction
)
return false;

View File

@ -490,16 +490,18 @@ static void script_reportsrc(struct script_state *st)
if( bl == NULL )
return;
struct map_data *mapdata = map_getmapdata(bl->m);
switch( bl->type ) {
case BL_NPC:
if( bl->m >= 0 )
ShowDebug("Source (NPC): %s at %s (%d,%d)\n", ((struct npc_data *)bl)->name, map[bl->m].name, bl->x, bl->y);
ShowDebug("Source (NPC): %s at %s (%d,%d)\n", ((struct npc_data *)bl)->name, mapdata->name, bl->x, bl->y);
else
ShowDebug("Source (NPC): %s (invisible/not on a map)\n", ((struct npc_data *)bl)->name);
break;
default:
if( bl->m >= 0 )
ShowDebug("Source (Non-NPC type %d): name %s at %s (%d,%d)\n", bl->type, status_get_name(bl), map[bl->m].name, bl->x, bl->y);
ShowDebug("Source (Non-NPC type %d): name %s at %s (%d,%d)\n", bl->type, status_get_name(bl), mapdata->name, bl->x, bl->y);
else
ShowDebug("Source (Non-NPC type %d): name %s (invisible/not on a map)\n", bl->type, status_get_name(bl));
break;
@ -5604,7 +5606,7 @@ BUILDIN_FUNC(warpparty)
if( !(pl_sd = p->data[i].sd) || pl_sd->status.party_id != p_id )
continue;
if( str2 && strcmp(str2, map[pl_sd->bl.m].name) != 0 )
if( str2 && strcmp(str2, map_getmapdata(pl_sd->bl.m)->name) != 0 )
continue;
if( pc_isdead(pl_sd) )
@ -8437,7 +8439,7 @@ BUILDIN_FUNC(strcharinfo)
}
break;
case 3:
script_pushconststr(st,map[sd->bl.m].name);
script_pushconststr(st,map_getmapdata(sd->bl.m)->name);
break;
default:
ShowWarning("buildin_strcharinfo: unknown parameter.\n");
@ -8491,7 +8493,7 @@ BUILDIN_FUNC(strnpcinfo)
break;
case 4: // map name
if (nd->bl.m >= 0)
name = aStrdup(map[nd->bl.m].name);
name = aStrdup(map_getmapdata(nd->bl.m)->name);
break;
}
@ -10970,7 +10972,7 @@ BUILDIN_FUNC(getusers)
if(bl)
{
val = map[bl->m].users;
val = map_getmapdata(bl->m)->users;
}
break;
case 1:
@ -11028,7 +11030,7 @@ BUILDIN_FUNC(getmapusers)
script_pushint(st,-1);
return SCRIPT_CMD_SUCCESS;
}
script_pushint(st,map[m].users);
script_pushint(st,map_getmapdata(m)->users);
return SCRIPT_CMD_SUCCESS;
}
/*==========================================
@ -14931,7 +14933,7 @@ BUILDIN_FUNC(getmapxy)
x= bl->x;
y= bl->y;
safestrncpy(mapname, map[bl->m].name, MAP_NAME_LENGTH);
safestrncpy(mapname, map_getmapdata(bl->m)->name, MAP_NAME_LENGTH);
//Set MapName$
num=st->stack->stack_data[st->start+2].u.num;
@ -14987,7 +14989,7 @@ BUILDIN_FUNC(mapid2name)
{
uint16 m = script_getnum(st, 2);
if (m < 0 || m >= MAX_MAP_PER_SERVER) {
if (m < 0) {
script_pushconststr(st, "");
return SCRIPT_CMD_FAILURE;
}
@ -19506,8 +19508,10 @@ BUILDIN_FUNC(bg_updatescore)
if( (m = map_mapname2mapid(str)) < 0 )
return SCRIPT_CMD_SUCCESS;
map[m].bgscore_lion = script_getnum(st,3);
map[m].bgscore_eagle = script_getnum(st,4);
struct map_data *mapdata = map_getmapdata(m);
mapdata->bgscore_lion = script_getnum(st,3);
mapdata->bgscore_eagle = script_getnum(st,4);
clif_bg_updatescore(m);
return SCRIPT_CMD_SUCCESS;
@ -19643,7 +19647,7 @@ BUILDIN_FUNC(instance_destroy)
else
instance_id = script_instancegetid(st);
if( instance_id == 0 || instance_id >= MAX_MAP_PER_SERVER ) {
if( instance_id == 0 ) {
ShowError("buildin_instance_destroy: Trying to destroy invalid instance %hu.\n", instance_id);
return SCRIPT_CMD_FAILURE;
}
@ -19733,7 +19737,7 @@ BUILDIN_FUNC(instance_mapname)
if(!instance_id || (m = instance_mapname2mapid(str,instance_id)) < 0)
script_pushconststr(st, "");
else
script_pushconststr(st, map[m].name);
script_pushconststr(st, map_getmapdata(m)->name);
return SCRIPT_CMD_SUCCESS;
}
@ -19807,7 +19811,7 @@ BUILDIN_FUNC(instance_warpall)
else
instance_id = script_instancegetid(st);
if( !instance_id || (m = map_mapname2mapid(mapn)) < 0 || (m = instance_mapname2mapid(map[m].name,instance_id)) < 0)
if( !instance_id || (m = map_mapname2mapid(mapn)) < 0 || (m = instance_mapname2mapid(map_getmapdata(m)->name,instance_id)) < 0)
return SCRIPT_CMD_FAILURE;
for(i = 0; i < instance_data[instance_id].cnt_map; i++)
@ -22964,7 +22968,7 @@ BUILDIN_FUNC(channel_chat) {
script_pushint(st,0);
return SCRIPT_CMD_FAILURE;
}
if (!(ch = map[m].channel)) {
if (!(ch = map_getmapdata(m)->channel)) {
ShowDebug("buildin_channel_chat: Map '%s' doesn't have local channel yet.\n", chname);
script_pushint(st,0);
return SCRIPT_CMD_SUCCESS;
@ -22977,7 +22981,7 @@ BUILDIN_FUNC(channel_chat) {
script_pushint(st,0);
return SCRIPT_CMD_FAILURE;
}
if (!(ch = map[nd->bl.m].channel)) {
if (!(ch = map_getmapdata(nd->bl.m)->channel)) {
ShowDebug("buildin_channel_chat: Map '%s' doesn't have local channel yet.\n", chname);
script_pushint(st,0);
return SCRIPT_CMD_SUCCESS;

View File

@ -700,7 +700,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
(map_flag_gvg2_no_te(m) && skill_nocast&4) ||
(map_getmapflag(m, MF_BATTLEGROUND) && skill_nocast&8) ||
(map_flag_gvg2_te(m) && skill_nocast&16) || // WOE:TE
(map_getmapflag(m, MF_RESTRICTED) && map[m].zone && skill_nocast&(8*map[m].zone)) ){
(map_getmapflag(m, MF_RESTRICTED) && map_getmapdata(m)->zone && skill_nocast&(8*map_getmapdata(m)->zone)) ){
clif_msg(sd, SKILL_CANT_USE_AREA); // This skill cannot be used within this area
return true;
}
@ -13076,9 +13076,10 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
int unit_val1 = skill_lv;
int unit_val2 = 0;
int alive = 1;
struct map_data *mapdata = map_getmapdata(src->m);
// are the coordinates out of range?
if( ux <= 0 || uy <= 0 || ux >= map[src->m].xs || uy >= map[src->m].ys ){
if( ux <= 0 || uy <= 0 || ux >= mapdata->xs || uy >= mapdata->ys ){
continue;
}

View File

@ -113,7 +113,7 @@ static unsigned int status_calc_maxhpsp_pc(struct map_session_data* sd, unsigned
static int status_get_sc_interval(enum sc_type type);
static bool status_change_isDisabledOnMap_(sc_type type, bool mapIsVS, bool mapIsPVP, bool mapIsGVG, bool mapIsBG, unsigned int mapZone, bool mapIsTE);
#define status_change_isDisabledOnMap(type, m) ( status_change_isDisabledOnMap_((type), map_flag_vs2((m)), map_getmapflag((m), MF_PVP) != 0, map_flag_gvg2_no_te((m)), map_getmapflag((m), MF_BATTLEGROUND) != 0, (map[(m)].zone << 3) != 0, map_flag_gvg2_te((m))) )
#define status_change_isDisabledOnMap(type, m) ( status_change_isDisabledOnMap_((type), map_flag_vs2((m)), map_getmapflag((m), MF_PVP) != 0, map_flag_gvg2_no_te((m)), map_getmapflag((m), MF_BATTLEGROUND) != 0, (map_getmapdata(m)->zone << 3) != 0, map_flag_gvg2_te((m))) )
/**
* Returns the status change associated with a skill.
@ -2801,10 +2801,11 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt)
if(flag&4) { // Strengthen Guardians - custom value +10% / lv
struct guild_castle *gc;
struct map_data *mapdata = map_getmapdata(md->bl.m);
gc=guild_mapname2gc(map[md->bl.m].name);
gc=guild_mapname2gc(mapdata->name);
if (!gc)
ShowError("status_calc_mob: No castle set at map %s\n", map[md->bl.m].name);
ShowError("status_calc_mob: No castle set at map %s\n", mapdata->name);
else if(gc->castle_id < 24 || md->mob_id == MOBID_EMPERIUM) {
#ifdef RENEWAL
status->max_hp += 50 * (gc->defense / 5);
@ -14373,7 +14374,7 @@ void status_change_clear_onChangeMap(struct block_list *bl, struct status_change
bool mapIsGVG = map_flag_gvg2_no_te(bl->m);
bool mapIsBG = map_getmapflag(bl->m, MF_BATTLEGROUND) != 0;
bool mapIsTE = map_flag_gvg2_te(bl->m);
unsigned int mapZone = map[bl->m].zone << 3;
unsigned int mapZone = map_getmapdata(bl->m)->zone << 3;
for (i = 0; i < SC_MAX; i++) {
if (!sc->data[i] || !SCDisabled[i])

View File

@ -369,7 +369,7 @@ int8 vending_openvending(struct map_session_data* sd, const char* message, const
if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`id`, `account_id`, `char_id`, `sex`, `map`, `x`, `y`, `title`, `autotrade`, `body_direction`, `head_direction`, `sit`) "
"VALUES( %d, %d, %d, '%c', '%s', %d, %d, '%s', %d, '%d', '%d', '%d' );",
vendings_table, sd->vender_id, sd->status.account_id, sd->status.char_id, sd->status.sex == SEX_FEMALE ? 'F' : 'M', map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->state.autotrade, at ? at->dir : sd->ud.dir, at ? at->head_dir : sd->head_dir, at ? at->sit : pc_issit(sd) ) != SQL_SUCCESS ) {
vendings_table, sd->vender_id, sd->status.account_id, sd->status.char_id, sd->status.sex == SEX_FEMALE ? 'F' : 'M', map_getmapdata(sd->bl.m)->name, sd->bl.x, sd->bl.y, message_sql, sd->state.autotrade, at ? at->dir : sd->ud.dir, at ? at->head_dir : sd->head_dir, at ? at->sit : pc_issit(sd) ) != SQL_SUCCESS ) {
Sql_ShowDebug(mmysql_handle);
}