From 584fcac43a13381d74374cf8835b2d2b077913b6 Mon Sep 17 00:00:00 2001 From: Aleos Date: Wed, 25 Jul 2018 19:06:59 -0400 Subject: [PATCH] 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! --- src/char/char.hpp | 4 +- src/char/char_clif.cpp | 2 +- src/char/char_mapif.cpp | 19 +- src/common/mmo.hpp | 1 - src/map/atcommand.cpp | 185 ++++++---- src/map/battle.cpp | 18 +- src/map/buyingstore.cpp | 2 +- src/map/channel.cpp | 39 +- src/map/chrif.cpp | 17 +- src/map/clif.cpp | 30 +- src/map/guild.cpp | 8 +- src/map/instance.cpp | 39 +- src/map/intif.cpp | 4 +- src/map/itemdb.cpp | 2 +- src/map/log.cpp | 4 +- src/map/map.cpp | 774 ++++++++++++++++++++++------------------ src/map/map.hpp | 3 +- src/map/mob.cpp | 44 ++- src/map/npc.cpp | 279 ++++++++------- src/map/party.cpp | 8 +- src/map/path.cpp | 50 ++- src/map/pc.cpp | 73 ++-- src/map/script.cpp | 36 +- src/map/skill.cpp | 5 +- src/map/status.cpp | 9 +- src/map/vending.cpp | 2 +- 26 files changed, 916 insertions(+), 741 deletions(-) diff --git a/src/char/char.hpp b/src/char/char.hpp index bf5553a818..6921f0db40 100644 --- a/src/char/char.hpp +++ b/src/char/char.hpp @@ -4,6 +4,8 @@ #ifndef _CHAR_HPP_ #define _CHAR_HPP_ +#include + #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 map; }; extern struct mmo_map_server map_server[MAX_MAP_SERVERS]; diff --git a/src/char/char_clif.cpp b/src/char/char_clif.cpp index 514fdb429d..1806ebf820 100644 --- a/src/char/char_clif.cpp +++ b/src/char/char_clif.cpp @@ -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); diff --git a/src/char/char_mapif.cpp b/src/char/char_mapif.cpp index 4062b046a7..16b6ee6bf6 100644 --- a/src/char/char_mapif.cpp +++ b/src/char/char_mapif.cpp @@ -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) { diff --git a/src/common/mmo.hpp b/src/common/mmo.hpp index 2c36488434..5240a4ed92 100644 --- a/src/common/mmo.hpp +++ b/src/common/mmo.hpp @@ -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 */ diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index 5d815727bf..8d4e5a93f7 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -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 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> 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& 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& 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); } } diff --git a/src/map/battle.cpp b/src/map/battle.cpp index ee4401d9ad..642924d446 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -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; } diff --git a/src/map/buyingstore.cpp b/src/map/buyingstore.cpp index 173997a80c..8a92aded9c 100644 --- a/src/map/buyingstore.cpp +++ b/src/map/buyingstore.cpp @@ -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); } diff --git a/src/map/channel.cpp b/src/map/channel.cpp index deee27ef02..5b91e3ce1f 100644 --- a/src/map/channel.cpp +++ b/src/map/channel.cpp @@ -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 ) { diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp index 6bd913fe26..e570b4b3c2 100644 --- a/src/map/chrif.cpp +++ b/src/map/chrif.cpp @@ -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; } diff --git a/src/map/clif.cpp b/src/map/clif.cpp index 8fb30b0294..fb011687b1 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -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)); } diff --git a/src/map/guild.cpp b/src/map/guild.cpp index 98efb8dfac..7b4b1bbcb2 100644 --- a/src/map/guild.cpp +++ b/src/map/guild.cpp @@ -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); } diff --git a/src/map/instance.cpp b/src/map/instance.cpp index 85885378f6..86131bd1b4 100644 --- a/src/map/instance.cpp +++ b/src/map/instance.cpp @@ -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); } diff --git a/src/map/intif.cpp b/src/map/intif.cpp index fceb509ee0..f1871a2559 100644 --- a/src/map/intif.cpp +++ b/src/map/intif.cpp @@ -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; diff --git a/src/map/itemdb.cpp b/src/map/itemdb.cpp index 61ba8f4267..d791292b8f 100644 --- a/src/map/itemdb.cpp +++ b/src/map/itemdb.cpp @@ -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; diff --git a/src/map/log.cpp b/src/map/log.cpp index cd5950f52e..a41e937b43 100644 --- a/src/map/log.cpp +++ b/src/map/log.cpp @@ -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); } } diff --git a/src/map/map.cpp b/src/map/map.cpp index 0de12514a1..8c554b1212 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -122,7 +122,8 @@ static int bl_list_count = 0; #define MAP_MAX_MSG 1550 #endif -std::vector map; +std::map map; + int map_port=0; int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; @@ -180,6 +181,16 @@ int console = 0; int enable_spy = 0; //To enable/disable @spy commands, which consume too much cpu time when sending packets. [Skotlex] int enable_grf = 0; //To enable/disable reading maps from GRF files, bypassing mapcache [blackhole89] +/** + * Get the map data + * @param mapid: Map ID to lookup + * @return map_data on success or nullptr on failure + */ +struct map_data *map_getmapdata(int16 mapid) +{ + return util::map_find(map, mapid); +} + /*========================================== * server player count (of all mapservers) *------------------------------------------*/ @@ -276,17 +287,21 @@ static struct block_list bl_head; *------------------------------------------*/ static void map_addblcell(struct block_list *bl) { - if( bl->m<0 || bl->x<0 || bl->x>=map[bl->m].xs || bl->y<0 || bl->y>=map[bl->m].ys || !(bl->type&BL_CHAR) ) + struct map_data *mapdata = map_getmapdata(bl->m); + + if( bl->m<0 || bl->x<0 || bl->x>=mapdata->xs || bl->y<0 || bl->y>=mapdata->ys || !(bl->type&BL_CHAR) ) return; - map[bl->m].cell[bl->x+bl->y*map[bl->m].xs].cell_bl++; + mapdata->cell[bl->x+bl->y*mapdata->cell_bl++; return; } static void map_delblcell(struct block_list *bl) { - if( bl->m <0 || bl->x<0 || bl->x>=map[bl->m].xs || bl->y<0 || bl->y>=map[bl->m].ys || !(bl->type&BL_CHAR) ) + struct map_data *mapdata = map_getmapdata(bl->m); + + if( bl->m <0 || bl->x<0 || bl->x>=mapdata->xs || bl->y<0 || bl->y>=mapdata->ys || !(bl->type&BL_CHAR) ) return; - map[bl->m].cell[bl->x+bl->y*map[bl->m].xs].cell_bl--; + mapdata->cell[bl->x+bl->y*mapdata->cell_bl--; } #endif @@ -298,6 +313,7 @@ int map_addblock(struct block_list* bl) { int16 m, x, y; int pos; + struct map_data *mapdata; nullpo_ret(bl); @@ -309,29 +325,33 @@ int map_addblock(struct block_list* bl) m = bl->m; x = bl->x; y = bl->y; - if( m < 0 || m >= map.size() ) + + if( m < 0 ) { ShowError("map_addblock: invalid map id (%d), only %d are loaded.\n", m, map.size()); return 1; } - if( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) + + mapdata = map_getmapdata(m); + + if( x < 0 || x >= mapdata->xs || y < 0 || y >= mapdata->ys ) { - ShowError("map_addblock: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d\n", map[m].name, x, y, map[m].xs, map[m].ys); + ShowError("map_addblock: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d\n", mapdata->name, x, y, mapdata->xs, mapdata->ys); return 1; } - pos = x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs; + pos = x/BLOCK_SIZE+(y/BLOCK_SIZE)*mapdata->bxs; if (bl->type == BL_MOB) { - bl->next = map[m].block_mob[pos]; + bl->next = mapdata->block_mob[pos]; bl->prev = &bl_head; if (bl->next) bl->next->prev = bl; - map[m].block_mob[pos] = bl; + mapdata->block_mob[pos] = bl; } else { - bl->next = map[m].block[pos]; + bl->next = mapdata->block[pos]; bl->prev = &bl_head; if (bl->next) bl->next->prev = bl; - map[m].block[pos] = bl; + mapdata->block[pos] = bl; } #ifdef CELL_NOSTACK @@ -362,16 +382,18 @@ int map_delblock(struct block_list* bl) map_delblcell(bl); #endif - pos = bl->x/BLOCK_SIZE+(bl->y/BLOCK_SIZE)*map[bl->m].bxs; + struct map_data *mapdata = map_getmapdata(bl->m); + + pos = bl->x/BLOCK_SIZE+(bl->y/BLOCK_SIZE)*mapdata->bxs; if (bl->next) bl->next->prev = bl->prev; if (bl->prev == &bl_head) { //Since the head of the list, update the block_list map of [] if (bl->type == BL_MOB) { - map[bl->m].block_mob[pos] = bl->next; + mapdata->block_mob[pos] = bl->next; } else { - map[bl->m].block[pos] = bl->next; + mapdata->block[pos] = bl->next; } } else { bl->prev->next = bl->next; @@ -516,15 +538,16 @@ int map_count_oncell(int16 m, int16 x, int16 y, int type, int flag) int bx,by; struct block_list *bl; int count = 0; + struct map_data *mapdata = map_getmapdata(m); - if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys)) + if (x < 0 || y < 0 || (x >= mapdata->xs) || (y >= mapdata->ys)) return 0; bx = x/BLOCK_SIZE; by = y/BLOCK_SIZE; if (type&~BL_MOB) - for( bl = map[m].block[bx+by*map[m].bxs] ; bl != NULL ; bl = bl->next ) + for( bl = mapdata->block[bx+by*mapdata->bxs] ; bl != NULL ; bl = bl->next ) if(bl->x == x && bl->y == y && bl->type&type) { if(flag&1) { struct unit_data *ud = unit_bl2ud(bl); @@ -536,7 +559,7 @@ int map_count_oncell(int16 m, int16 x, int16 y, int type, int flag) } if (type&BL_MOB) - for( bl = map[m].block_mob[bx+by*map[m].bxs] ; bl != NULL ; bl = bl->next ) + for( bl = mapdata->block_mob[bx+by*mapdata->bxs] ; bl != NULL ; bl = bl->next ) if(bl->x == x && bl->y == y) { if(flag&1) { struct unit_data *ud = unit_bl2ud(bl); @@ -555,18 +578,20 @@ int map_count_oncell(int16 m, int16 x, int16 y, int type, int flag) * flag&1: runs battle_check_target check based on unit->group->target_flag */ struct skill_unit* map_find_skill_unit_oncell(struct block_list* target,int16 x,int16 y,uint16 skill_id,struct skill_unit* out_unit, int flag) { - int16 m,bx,by; + int16 bx,by; struct block_list *bl; struct skill_unit *unit; - m = target->m; + struct map_data *mapdata; - if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys)) + mapdata = map_getmapdata(target->m); + + if (x < 0 || y < 0 || (x >= mapdata->xs) || (y >= mapdata->ys)) return NULL; bx = x/BLOCK_SIZE; by = y/BLOCK_SIZE; - for( bl = map[m].block[bx+by*map[m].bxs] ; bl != NULL ; bl = bl->next ) + for( bl = mapdata->block[bx+by*mapdata->bxs] ; bl != NULL ; bl = bl->next ) { if (bl->x != x || bl->y != y || bl->type != BL_SKILL) continue; @@ -590,21 +615,23 @@ int map_foreachinrangeV(int (*func)(struct block_list*,va_list),struct block_lis struct block_list *bl; int blockcount = bl_list_count, i; int x0, x1, y0, y1; + struct map_data *mapdata; va_list ap_copy; - + m = center->m; if( m < 0 ) return 0; + mapdata = map_getmapdata(m); x0 = i16max(center->x - range, 0); y0 = i16max(center->y - range, 0); - x1 = i16min(center->x + range, map[m].xs - 1); - y1 = i16min(center->y + range, map[m].ys - 1); + x1 = i16min(center->x + range, mapdata->xs - 1); + y1 = i16min(center->y + range, mapdata->ys - 1); if ( type&~BL_MOB ) { for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) { for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) { - for(bl = map[m].block[ bx + by * map[m].bxs ]; bl != NULL; bl = bl->next ) { + for(bl = mapdata->block[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) { if( bl->type&type && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 #ifdef CIRCULAR_AREA @@ -621,7 +648,7 @@ int map_foreachinrangeV(int (*func)(struct block_list*,va_list),struct block_lis if ( type&BL_MOB ) { for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) { for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) { - for(bl = map[m].block_mob[ bx + by * map[m].bxs ]; bl != NULL; bl = bl->next ) { + for(bl = mapdata->block_mob[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) { if( bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 #ifdef CIRCULAR_AREA && check_distance_bl(center, bl, range) @@ -703,9 +730,10 @@ int map_foreachinareaV(int(*func)(struct block_list*, va_list), int16 m, int16 x int returnCount = 0; //total sum of returned values of func() struct block_list *bl; int blockcount = bl_list_count, i; + struct map_data *mapdata; va_list ap_copy; - if (m < 0 || m >= map.size()) + if (m < 0) return 0; if (x1 < x0) @@ -713,10 +741,11 @@ int map_foreachinareaV(int(*func)(struct block_list*, va_list), int16 m, int16 x if (y1 < y0) SWAP(y0, y1); + mapdata = map_getmapdata(m); x0 = i16max(x0, 0); y0 = i16max(y0, 0); - x1 = i16min(x1, map[m].xs - 1); - y1 = i16min(y1, map[m].ys - 1); + x1 = i16min(x1, mapdata->xs - 1); + y1 = i16min(y1, mapdata->ys - 1); if( wall_check ) { cx = x0 + (x1 - x0) / 2; @@ -726,7 +755,7 @@ int map_foreachinareaV(int(*func)(struct block_list*, va_list), int16 m, int16 x if( type&~BL_MOB ) { for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) { for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) { - for(bl = map[m].block[bx + by * map[m].bxs]; bl != NULL; bl = bl->next) { + for(bl = mapdata->block[bx + by * mapdata->bxs]; bl != NULL; bl = bl->next) { if ( bl->type&type && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && ( !wall_check || path_search_long(NULL, m, cx, cy, bl->x, bl->y, CELL_CHKWALL) ) @@ -740,7 +769,7 @@ int map_foreachinareaV(int(*func)(struct block_list*, va_list), int16 m, int16 x if( type&BL_MOB ) { for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) { for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) { - for(bl = map[m].block_mob[bx + by * map[m].bxs]; bl != NULL; bl = bl->next) { + for(bl = mapdata->block_mob[bx + by * mapdata->bxs]; bl != NULL; bl = bl->next) { if ( bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && ( !wall_check || path_search_long(NULL, m, cx, cy, bl->x, bl->y, CELL_CHKWALL) ) && bl_list_count < BL_LIST_MAX ) @@ -808,18 +837,20 @@ int map_forcountinrange(int (*func)(struct block_list*,va_list), struct block_li struct block_list *bl; int blockcount = bl_list_count, i; int x0, x1, y0, y1; + struct map_data *mapdata; va_list ap; m = center->m; + mapdata = map_getmapdata(m); x0 = i16max(center->x - range, 0); y0 = i16max(center->y - range, 0); - x1 = i16min(center->x + range, map[ m ].xs - 1); - y1 = i16min(center->y + range, map[ m ].ys - 1); + x1 = i16min(center->x + range, mapdata->xs - 1); + y1 = i16min(center->y + range, mapdata->ys - 1); if ( type&~BL_MOB ) for ( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) { for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) { - for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + for( bl = mapdata->block[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) { if( bl->type&type && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 #ifdef CIRCULAR_AREA @@ -833,7 +864,7 @@ int map_forcountinrange(int (*func)(struct block_list*,va_list), struct block_li if( type&BL_MOB ) for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) { for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ){ - for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + for( bl = mapdata->block_mob[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) { if( bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 #ifdef CIRCULAR_AREA && check_distance_bl(center, bl, range) @@ -869,6 +900,7 @@ int map_forcountinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x int returnCount = 0; //total sum of returned values of func() [Skotlex] struct block_list *bl; int blockcount = bl_list_count, i; + struct map_data *mapdata; va_list ap; if ( m < 0 ) @@ -879,22 +911,23 @@ int map_forcountinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x if ( y1 < y0 ) SWAP(y0, y1); + mapdata = map_getmapdata(m); x0 = i16max(x0, 0); y0 = i16max(y0, 0); - x1 = i16min(x1, map[ m ].xs - 1); - y1 = i16min(y1, map[ m ].ys - 1); + x1 = i16min(x1, mapdata->xs - 1); + y1 = i16min(y1, mapdata->ys - 1); if ( type&~BL_MOB ) for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) - for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) + for( bl = mapdata->block[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) if( bl->type&type && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && bl_list_count < BL_LIST_MAX ) bl_list[ bl_list_count++ ] = bl; if( type&BL_MOB ) for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) - for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) + for( bl = mapdata->block_mob[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) if( bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && bl_list_count < BL_LIST_MAX ) bl_list[ bl_list_count++ ] = bl; @@ -929,13 +962,14 @@ int map_foreachinmovearea(int (*func)(struct block_list*,va_list), struct block_ struct block_list *bl; int blockcount = bl_list_count, i; int16 x0, x1, y0, y1; + struct map_data *mapdata; va_list ap; if ( !range ) return 0; if ( !dx && !dy ) return 0; //No movement. m = center->m; - + mapdata = map_getmapdata(m); x0 = center->x - range; x1 = center->x + range; y0 = center->y - range; @@ -962,13 +996,13 @@ int map_foreachinmovearea(int (*func)(struct block_list*,va_list), struct block_ x0 = i16max(x0, 0); y0 = i16max(y0, 0); - x1 = i16min(x1, map[ m ].xs - 1); - y1 = i16min(y1, map[ m ].ys - 1); + x1 = i16min(x1, mapdata->xs - 1); + y1 = i16min(y1, mapdata->ys - 1); for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) { for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) { if ( type&~BL_MOB ) { - for( bl = map[m].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + for( bl = mapdata->block[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) { if( bl->type&type && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && @@ -977,7 +1011,7 @@ int map_foreachinmovearea(int (*func)(struct block_list*,va_list), struct block_ } } if ( type&BL_MOB ) { - for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + for( bl = mapdata->block_mob[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) { if( bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && bl_list_count < BL_LIST_MAX ) @@ -989,13 +1023,13 @@ int map_foreachinmovearea(int (*func)(struct block_list*,va_list), struct block_ } else { // Diagonal movement x0 = i16max(x0, 0); y0 = i16max(y0, 0); - x1 = i16min(x1, map[ m ].xs - 1); - y1 = i16min(y1, map[ m ].ys - 1); + x1 = i16min(x1, mapdata->xs - 1); + y1 = i16min(y1, mapdata->ys - 1); for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) { for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) { if ( type & ~BL_MOB ) { - for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + for( bl = mapdata->block[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) { if( bl->type&type && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && @@ -1008,7 +1042,7 @@ int map_foreachinmovearea(int (*func)(struct block_list*,va_list), struct block_ } } if ( type&BL_MOB ) { - for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + for( bl = mapdata->block_mob[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) { if( bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && bl_list_count < BL_LIST_MAX) @@ -1052,19 +1086,20 @@ int map_foreachincell(int (*func)(struct block_list*,va_list), int16 m, int16 x, int returnCount = 0; //total sum of returned values of func() [Skotlex] struct block_list *bl; int blockcount = bl_list_count, i; + struct map_data *mapdata = map_getmapdata(m); va_list ap; - if ( x < 0 || y < 0 || x >= map[ m ].xs || y >= map[ m ].ys ) return 0; + if ( x < 0 || y < 0 || x >= mapdata->xs || y >= mapdata->ys ) return 0; by = y / BLOCK_SIZE; bx = x / BLOCK_SIZE; if( type&~BL_MOB ) - for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) + for( bl = mapdata->block[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) if( bl->type&type && bl->x == x && bl->y == y && bl_list_count < BL_LIST_MAX ) bl_list[ bl_list_count++ ] = bl; if( type&BL_MOB ) - for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs]; bl != NULL; bl = bl->next ) + for( bl = mapdata->block_mob[ bx + by * mapdata->bxs]; bl != NULL; bl = bl->next ) if( bl->x == x && bl->y == y && bl_list_count < BL_LIST_MAX) bl_list[ bl_list_count++ ] = bl; @@ -1133,6 +1168,7 @@ int map_foreachinpath(int (*func)(struct block_list*,va_list),int16 m,int16 x0,i int magnitude2, len_limit; //The square of the magnitude int k, xi, yi, xu, yu; int mx0 = x0, mx1 = x1, my0 = y0, my1 = y1; + struct map_data *mapdata; va_list ap; //Avoid needless calculations by not getting the sqrt right away. @@ -1174,17 +1210,18 @@ int map_foreachinpath(int (*func)(struct block_list*,va_list),int16 m,int16 x0,i if ( my0 > my1 ) SWAP(my0, my1); + mapdata = map_getmapdata(m); mx0 = max(mx0, 0); my0 = max(my0, 0); - mx1 = min(mx1, map[ m ].xs - 1); - my1 = min(my1, map[ m ].ys - 1); + mx1 = min(mx1, mapdata->xs - 1); + my1 = min(my1, mapdata->ys - 1); range *= range << 8; //Values are shifted later on for higher precision using int math. if ( type&~BL_MOB ) for ( by = my0 / BLOCK_SIZE; by <= my1 / BLOCK_SIZE; by++ ) { for( bx = mx0 / BLOCK_SIZE; bx <= mx1 / BLOCK_SIZE; bx++ ) { - for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + for( bl = mapdata->block[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) { if( bl->prev && bl->type&type && bl_list_count < BL_LIST_MAX ) { xi = bl->x; yi = bl->y; @@ -1218,7 +1255,7 @@ int map_foreachinpath(int (*func)(struct block_list*,va_list),int16 m,int16 x0,i if( type&BL_MOB ) for( by = my0 / BLOCK_SIZE; by <= my1 / BLOCK_SIZE; by++ ) { for( bx = mx0 / BLOCK_SIZE; bx <= mx1 / BLOCK_SIZE; bx++ ) { - for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + for( bl = mapdata->block_mob[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) { if( bl->prev && bl_list_count < BL_LIST_MAX ) { xi = bl->x; yi = bl->y; @@ -1292,6 +1329,7 @@ int map_foreachindir(int(*func)(struct block_list*, va_list), int16 m, int16 x0, uint8 dir = map_calc_dir_xy(x0, y0, x1, y1, 6); short dx = dirx[dir]; short dy = diry[dir]; + struct map_data *mapdata; va_list ap; if (m < 0) @@ -1312,6 +1350,7 @@ int map_foreachindir(int(*func)(struct block_list*, va_list), int16 m, int16 x0, length++; } + mapdata = map_getmapdata(m); //Get area that needs to be checked mx0 = x0 + dx*(offset / ((dir % 2) + 1)); my0 = y0 + dy*(offset / ((dir % 2) + 1)); @@ -1332,13 +1371,13 @@ int map_foreachindir(int(*func)(struct block_list*, va_list), int16 m, int16 x0, mx0 = max(mx0, 0); my0 = max(my0, 0); - mx1 = min(mx1, map[m].xs - 1); - my1 = min(my1, map[m].ys - 1); + mx1 = min(mx1, mapdata->xs - 1); + my1 = min(my1, mapdata->ys - 1); if (type&~BL_MOB) { for (by = my0 / BLOCK_SIZE; by <= my1 / BLOCK_SIZE; by++) { for (bx = mx0 / BLOCK_SIZE; bx <= mx1 / BLOCK_SIZE; bx++) { - for (bl = map[m].block[bx + by * map[m].bxs]; bl != NULL; bl = bl->next) { + for (bl = mapdata->block[bx + by * mapdata->bxs]; bl != NULL; bl = bl->next) { if (bl->prev && bl->type&type && bl_list_count < BL_LIST_MAX) { //Check if inside search area if (bl->x < mx0 || bl->x > mx1 || bl->y < my0 || bl->y > my1) @@ -1374,7 +1413,7 @@ int map_foreachindir(int(*func)(struct block_list*, va_list), int16 m, int16 x0, if (type&BL_MOB) { for (by = my0 / BLOCK_SIZE; by <= my1 / BLOCK_SIZE; by++) { for (bx = mx0 / BLOCK_SIZE; bx <= mx1 / BLOCK_SIZE; bx++) { - for (bl = map[m].block_mob[bx + by * map[m].bxs]; bl != NULL; bl = bl->next) { + for (bl = mapdata->block_mob[bx + by * mapdata->bxs]; bl != NULL; bl = bl->next) { if (bl->prev && bl_list_count < BL_LIST_MAX) { //Check if inside search area if (bl->x < mx0 || bl->x > mx1 || bl->y < my0 || bl->y > my1) @@ -1433,19 +1472,20 @@ int map_foreachinmap(int (*func)(struct block_list*,va_list), int16 m, int type, int returnCount = 0; //total sum of returned values of func() [Skotlex] struct block_list *bl; int blockcount = bl_list_count, i; + struct map_data *mapdata = map_getmapdata(m); va_list ap; - bsize = map[ m ].bxs * map[ m ].bys; + bsize = mapdata->bxs * mapdata->bys; if( type&~BL_MOB ) for( b = 0; b < bsize; b++ ) - for( bl = map[ m ].block[ b ]; bl != NULL; bl = bl->next ) + for( bl = mapdata->block[ b ]; bl != NULL; bl = bl->next ) if( bl->type&type && bl_list_count < BL_LIST_MAX ) bl_list[ bl_list_count++ ] = bl; if( type&BL_MOB ) for( b = 0; b < bsize; b++ ) - for( bl = map[ m ].block_mob[ b ]; bl != NULL; bl = bl->next ) + for( bl = mapdata->block_mob[ b ]; bl != NULL; bl = bl->next ) if( bl_list_count < BL_LIST_MAX ) bl_list[ bl_list_count++ ] = bl; @@ -1545,12 +1585,13 @@ void map_clearflooritem(struct block_list *bl) { int map_searchrandfreecell(int16 m,int16 *x,int16 *y,int stack) { int free_cell,i,j; int free_cells[9][2]; + struct map_data *mapdata = map_getmapdata(m); for(free_cell=0,i=-1;i<=1;i++){ - if(i+*y<0 || i+*y>=map[m].ys) + if(i+*y<0 || i+*y>=mapdata->ys) continue; for(j=-1;j<=1;j++){ - if(j+*x<0 || j+*x>=map[m].xs) + if(j+*x<0 || j+*x>=mapdata->xs) continue; if(map_getcell(m,j+*x,i+*y,CELL_CHKNOPASS) && !map_getcell(m,j+*x,i+*y,CELL_CHKICEWALL)) continue; @@ -1615,17 +1656,19 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1 return map_getcell(m,*x,*y,CELL_CHKREACH); } + struct map_data *mapdata = map_getmapdata(m); + if (rx >= 0 && ry >= 0) { tries = rx2*ry2; if (tries > 100) tries = 100; } else { - tries = map[m].xs*map[m].ys; + tries = mapdata->xs*mapdata->ys; if (tries > 500) tries = 500; } while(tries--) { - *x = (rx >= 0)?(rnd()%rx2-rx+bx):(rnd()%(map[m].xs-2)+1); - *y = (ry >= 0)?(rnd()%ry2-ry+by):(rnd()%(map[m].ys-2)+1); + *x = (rx >= 0)?(rnd()%rx2-rx+bx):(rnd()%(mapdata->xs-2)+1); + *y = (ry >= 0)?(rnd()%ry2-ry+by):(rnd()%(mapdata->ys-2)+1); if (*x == bx && *y == by) continue; //Avoid picking the same target tile. @@ -2073,16 +2116,18 @@ int map_quit(struct map_session_data *sd) { if (sd->state.permanent_speed == 1) sd->state.permanent_speed = 0; // Remove lock so speed is set back to normal at login. - if( map[sd->bl.m].instance_id ) - instance_delusers(map[sd->bl.m].instance_id); + struct map_data *mapdata = map_getmapdata(sd->bl.m); + + if( mapdata->instance_id ) + instance_delusers(mapdata->instance_id); unit_remove_map_pc(sd,CLR_RESPAWN); - if( map[sd->bl.m].instance_id ) { // Avoid map conflicts and warnings on next login + if( mapdata->instance_id ) { // Avoid map conflicts and warnings on next login int16 m; struct point *pt; - if( map[sd->bl.m].save.map ) - pt = &map[sd->bl.m].save; + if( mapdata->save.map ) + pt = &mapdata->save; else pt = &sd->status.save_point; @@ -2540,17 +2585,19 @@ bool map_addnpc(int16 m,struct npc_data *nd) { nullpo_ret(nd); - if( m < 0 || m >= map.size() ) + if( m < 0 ) return false; - if( map[m].npc_num == MAX_NPC_PER_MAP ) + struct map_data *mapdata = map_getmapdata(m); + + if( mapdata->npc_num == MAX_NPC_PER_MAP ) { - ShowWarning("too many NPCs in one map %s\n",map[m].name); + ShowWarning("too many NPCs in one map %s\n",mapdata->name); return false; } - map[m].npc[map[m].npc_num]=nd; - map[m].npc_num++; + mapdata->npc[mapdata->npc_num]=nd; + mapdata->npc_num++; idb_put(id_db,nd->bl.id,nd); return true; } @@ -2560,7 +2607,7 @@ bool map_addnpc(int16 m,struct npc_data *nd) *------------------------------------------*/ int map_addinstancemap(const char *name, unsigned short instance_id) { - int src_m = map_mapname2mapid(name); + int16 src_m = map_mapname2mapid(name); char iname[MAP_NAME_LENGTH]; size_t num_cell, size; @@ -2573,14 +2620,15 @@ int map_addinstancemap(const char *name, unsigned short instance_id) return -2; } - if(map.size() >= MAX_MAP_PER_SERVER) { // Out of bounds - ShowError("map_addinstancemap: Failed to add map. Map size (%d) > max maps (%d)\n", map.size(), MAX_MAP_PER_SERVER); - return -3; - } - // Copy the map - int dst_m = map.size(); - map.push_back(map[src_m]); + int16 dst_m = static_cast(map.size()); + struct map_data *src_map = map_getmapdata(src_m); + + map.insert({ dst_m, *src_map }); + + // Retrieve new map data + struct map_data *dst_map = map_getmapdata(dst_m); + strcpy(iname, name); // Alter the name @@ -2588,40 +2636,40 @@ int map_addinstancemap(const char *name, unsigned short instance_id) // This also allows us to maintain complete independence with main map functions if((strchr(iname,'@') == NULL) && strlen(iname) > 8) { memmove(iname, iname+(strlen(iname)-9), strlen(iname)); - snprintf(map[dst_m].name, sizeof(map[dst_m].name),"%hu#%s", instance_id, iname); + snprintf(dst_map->name, sizeof(dst_map->name),"%hu#%s", instance_id, iname); } else - snprintf(map[dst_m].name, sizeof(map[dst_m].name),"%.3hu%s", instance_id, iname); - map[dst_m].name[MAP_NAME_LENGTH-1] = '\0'; + snprintf(dst_map->name, sizeof(dst_map->name),"%.3hu%s", instance_id, iname); + dst_map->name[MAP_NAME_LENGTH-1] = '\0'; // Mimic questinfo - if( map[src_m].qi_count ) { - map[dst_m].qi_count = map[src_m].qi_count; - CREATE( map[dst_m].qi_data, struct questinfo, map[dst_m].qi_count ); - memcpy( map[dst_m].qi_data, map[src_m].qi_data, map[dst_m].qi_count * sizeof(struct questinfo) ); + if( src_map->qi_count ) { + dst_map->qi_count = src_map->qi_count; + CREATE( dst_map->qi_data, struct questinfo, dst_map->qi_count ); + memcpy( dst_map->qi_data, src_map->qi_data, dst_map->qi_count * sizeof(struct questinfo) ); } - map[dst_m].m = dst_m; - map[dst_m].instance_id = instance_id; - map[dst_m].instance_src_map = src_m; - map[dst_m].users = 0; + dst_map->m = dst_m; + dst_map->instance_id = instance_id; + dst_map->instance_src_map = src_m; + dst_map->users = 0; - memset(map[dst_m].npc, 0, sizeof(map[dst_m].npc)); - map[dst_m].npc_num = 0; + memset(dst_map->npc, 0, sizeof(dst_map->npc)); + dst_map->npc_num = 0; // Reallocate cells - num_cell = map[dst_m].xs * map[dst_m].ys; - CREATE( map[dst_m].cell, struct mapcell, num_cell ); - memcpy( map[dst_m].cell, map[src_m].cell, num_cell * sizeof(struct mapcell) ); + num_cell = dst_map->xs * dst_map->ys; + CREATE( dst_map->cell, struct mapcell, num_cell ); + memcpy( dst_map->cell, src_map->cell, num_cell * sizeof(struct mapcell) ); - size = map[dst_m].bxs * map[dst_m].bys * sizeof(struct block_list*); - map[dst_m].block = (struct block_list **)aCalloc(1,size); - map[dst_m].block_mob = (struct block_list **)aCalloc(1,size); + size = dst_map->bxs * dst_map->bys * sizeof(struct block_list*); + dst_map->block = (struct block_list **)aCalloc(1,size); + dst_map->block_mob = (struct block_list **)aCalloc(1,size); - map[dst_m].index = mapindex_addmap(-1, map[dst_m].name); - map[dst_m].channel = NULL; - map[dst_m].mob_delete_timer = INVALID_TIMER; + dst_map->index = mapindex_addmap(-1, dst_map->name); + dst_map->channel = NULL; + dst_map->mob_delete_timer = INVALID_TIMER; - map_addmap2db(&map[dst_m]); + map_addmap2db(dst_map); return dst_m; } @@ -2676,7 +2724,9 @@ static void map_free_questinfo(int m); *------------------------------------------*/ int map_delinstancemap(int m) { - if(m < 0 || !map[m].instance_id) + struct map_data *mapdata = map_getmapdata(m); + + if(m < 0 || !mapdata->instance_id) return 0; // Kick everyone out @@ -2685,19 +2735,19 @@ int map_delinstancemap(int m) // Do the unit cleanup map_foreachinmap(map_instancemap_clean, m, BL_ALL); - if( map[m].mob_delete_timer != INVALID_TIMER ) - delete_timer(map[m].mob_delete_timer, map_removemobs_timer); + if( mapdata->mob_delete_timer != INVALID_TIMER ) + delete_timer(mapdata->mob_delete_timer, map_removemobs_timer); // Free memory - aFree(map[m].cell); - aFree(map[m].block); - aFree(map[m].block_mob); + aFree(mapdata->cell); + aFree(mapdata->block); + aFree(mapdata->block_mob); map_free_questinfo(m); + mapdata->damage_adjust = {}; - mapindex_removemap( map[m].index ); - map_removemapdb(&map[m]); - memset(&map[m], 0x00, sizeof(map[0])); - map[m].mob_delete_timer = INVALID_TIMER; + mapindex_removemap( mapdata->index ); + map_removemapdb(mapdata); + map.erase(m); return 1; } @@ -2709,10 +2759,12 @@ int map_delinstancemap(int m) int map_addmobtolist(unsigned short m, struct spawn_data *spawn) { size_t i; - ARR_FIND( 0, MAX_MOB_LIST_PER_MAP, i, map[m].moblist[i] == NULL ); + struct map_data *mapdata = map_getmapdata(m); + + ARR_FIND( 0, MAX_MOB_LIST_PER_MAP, i, mapdata->moblist[i] == NULL ); if( i < MAX_MOB_LIST_PER_MAP ) { - map[m].moblist[i] = spawn; + mapdata->moblist[i] = spawn; return static_cast(i); } return -1; @@ -2721,22 +2773,24 @@ int map_addmobtolist(unsigned short m, struct spawn_data *spawn) void map_spawnmobs(int16 m) { int i, k=0; - if (map[m].mob_delete_timer != INVALID_TIMER) + struct map_data *mapdata = map_getmapdata(m); + + if (mapdata->mob_delete_timer != INVALID_TIMER) { //Mobs have not been removed yet [Skotlex] - 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; return; } for(i=0; imoblist[i]!=NULL) { - k+=map[m].moblist[i]->num; - npc_parse_mob2(map[m].moblist[i]); + k+=mapdata->moblist[i]->num; + npc_parse_mob2(mapdata->moblist[i]); } if (battle_config.etc_log && k > 0) { - ShowStatus("Map %s: Spawned '" CL_WHITE "%d" CL_RESET "' mobs.\n",map[m].name, k); + ShowStatus("Map %s: Spawned '" CL_WHITE "%d" CL_RESET "' mobs.\n",mapdata->name, k); } } @@ -2771,38 +2825,43 @@ TIMER_FUNC(map_removemobs_timer){ int count; const int16 m = id; - if (m < 0 || m >= MAX_MAP_PER_SERVER) + if (m < 0) { //Incorrect map id! ShowError("map_removemobs_timer error: timer %d points to invalid map %d\n",tid, m); return 0; } - if (map[m].mob_delete_timer != tid) + + struct map_data *mapdata = map_getmapdata(m); + + if (mapdata->mob_delete_timer != tid) { //Incorrect timer call! - ShowError("map_removemobs_timer mismatch: %d != %d (map %s)\n",map[m].mob_delete_timer, tid, map[m].name); + ShowError("map_removemobs_timer mismatch: %d != %d (map %s)\n",mapdata->mob_delete_timer, tid, mapdata->name); return 0; } - map[m].mob_delete_timer = INVALID_TIMER; - if (map[m].users > 0) //Map not empty! + mapdata->mob_delete_timer = INVALID_TIMER; + if (mapdata->users > 0) //Map not empty! return 1; count = map_foreachinmap(map_removemobs_sub, m, BL_MOB); if (battle_config.etc_log && count > 0) - ShowStatus("Map %s: Removed '" CL_WHITE "%d" CL_RESET "' mobs.\n",map[m].name, count); + ShowStatus("Map %s: Removed '" CL_WHITE "%d" CL_RESET "' mobs.\n",mapdata->name, count); return 1; } void map_removemobs(int16 m) { - if (map[m].mob_delete_timer != INVALID_TIMER) // should never happen + struct map_data *mapdata = map_getmapdata(m); + + if (mapdata->mob_delete_timer != INVALID_TIMER) // should never happen return; //Mobs are already scheduled for removal // Don't remove mobs on instance map - if (map[m].instance_id) + if (mapdata->instance_id) return; - map[m].mob_delete_timer = add_timer(gettick()+battle_config.mob_remove_delay, map_removemobs_timer, m, 0); + mapdata->mob_delete_timer = add_timer(gettick()+battle_config.mob_remove_delay, map_removemobs_timer, m, 0); } /*========================================== @@ -2810,11 +2869,13 @@ void map_removemobs(int16 m) *------------------------------------------*/ const char* map_mapid2mapname(int m) { - if (map[m].instance_id) { // Instance map check - struct instance_data *im = &instance_data[map[m].instance_id]; + struct map_data *mapdata = map_getmapdata(m); + + if (mapdata->instance_id) { // Instance map check + struct instance_data *im = &instance_data[mapdata->instance_id]; if (!im) // This shouldn't happen but if it does give them the map we intended to give - return map[m].name; + return mapdata->name; else { uint8 i; @@ -2825,7 +2886,7 @@ const char* map_mapid2mapname(int m) } } - return map[m].name; + return mapdata->name; } /*========================================== @@ -3018,7 +3079,10 @@ static int map_cell2gat(struct mapcell cell) *------------------------------------------*/ int map_getcell(int16 m,int16 x,int16 y,cell_chk cellchk) { - return (m < 0 || m >= MAX_MAP_PER_SERVER) ? 0 : map_getcellp(&map[m],x,y,cellchk); + if (m < 0) + return 0; + else + return map_getcellp(map_getmapdata(m), x, y, cellchk); } int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) @@ -3101,24 +3165,25 @@ 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) { int j; + struct map_data *mapdata = map_getmapdata(m); - if( m < 0 || m >= map.size() || x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) + if( m < 0 || x < 0 || x >= mapdata->xs || y < 0 || y >= mapdata->ys ) return; - j = x + y*map[m].xs; + j = x + y*mapdata->xs; switch( cell ) { - case CELL_WALKABLE: map[m].cell[j].walkable = flag; break; - case CELL_SHOOTABLE: map[m].cell[j].shootable = flag; break; - case CELL_WATER: map[m].cell[j].water = flag; break; + case CELL_WALKABLE: mapdata->cell[j].walkable = flag; break; + case CELL_SHOOTABLE: mapdata->cell[j].shootable = flag; break; + case CELL_WATER: mapdata->cell[j].water = flag; break; - case CELL_NPC: map[m].cell[j].npc = flag; break; - case CELL_BASILICA: map[m].cell[j].basilica = flag; break; - case CELL_LANDPROTECTOR: map[m].cell[j].landprotector = flag; break; - case CELL_NOVENDING: map[m].cell[j].novending = flag; break; - case CELL_NOCHAT: map[m].cell[j].nochat = flag; break; - case CELL_MAELSTROM: map[m].cell[j].maelstrom = flag; break; - case CELL_ICEWALL: map[m].cell[j].icewall = flag; break; + case CELL_NPC: mapdata->cell[j].npc = flag; break; + case CELL_BASILICA: mapdata->cell[j].basilica = flag; break; + case CELL_LANDPROTECTOR: mapdata->cell[j].landprotector = flag; break; + case CELL_NOVENDING: mapdata->cell[j].novending = flag; break; + case CELL_NOCHAT: mapdata->cell[j].nochat = flag; break; + case CELL_MAELSTROM: mapdata->cell[j].maelstrom = flag; break; + case CELL_ICEWALL: mapdata->cell[j].icewall = flag; break; default: ShowWarning("map_setcell: invalid cell type '%d'\n", (int)cell); break; @@ -3129,16 +3194,17 @@ void map_setgatcell(int16 m, int16 x, int16 y, int gat) { int j; struct mapcell cell; + struct map_data *mapdata = map_getmapdata(m); - if( m < 0 || m >= map.size() || x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) + if( m < 0 || x < 0 || x >= mapdata->xs || y < 0 || y >= mapdata->ys ) return; - j = x + y*map[m].xs; + j = x + y*mapdata->xs; cell = map_gat2cell(gat); - map[m].cell[j].walkable = cell.walkable; - map[m].cell[j].shootable = cell.shootable; - map[m].cell[j].water = cell.water; + mapdata->cell[j].walkable = cell.walkable; + mapdata->cell[j].shootable = cell.shootable; + mapdata->cell[j].water = cell.water; } /*========================================== @@ -3202,8 +3268,10 @@ bool map_iwall_set(int16 m, int16 x, int16 y, int size, int8 dir, bool shootable iwall->size = i; + struct map_data *mapdata = map_getmapdata(m); + strdb_put(iwall_db, iwall->wall_name, iwall); - map[m].iwall_num++; + mapdata->iwall_num++; return true; } @@ -3213,8 +3281,9 @@ void map_iwall_get(struct map_session_data *sd) { DBIterator* iter; int16 x1, y1; int i; + struct map_data *mapdata = map_getmapdata(sd->bl.m); - if( map[sd->bl.m].iwall_num < 1 ) + if( mapdata->iwall_num < 1 ) return; iter = db_iterator(iwall_db); @@ -3247,7 +3316,7 @@ bool map_iwall_remove(const char *wall_name) clif_changemapcell(0, iwall->m, x1, y1, map_getcell(iwall->m, x1, y1, CELL_GETTYPE), ALL_SAMEMAP); } - map[iwall->m].iwall_num--; + map_getmapdata(iwall->m)->iwall_num--; strdb_remove(iwall_db, iwall->wall_name); return true; } @@ -3415,28 +3484,20 @@ int map_addmap(char* mapname) return 0; } - if( map.size() >= MAX_MAP_PER_SERVER ) - { - ShowError("Could not add map '" CL_WHITE "%s" CL_RESET "', the limit of maps has been reached.\n",mapname); - return 1; - } - struct map_data entry = {}; mapindex_getmapname(mapname, entry.name); - map.push_back(entry); + map.insert({ static_cast(map.size()), entry }); return 0; } static void map_delmapid(int id) { - ShowNotice("Removing map [ %s ] from maplist" CL_CLL "\n",map[id].name); - map.erase(map.begin() + id); + ShowNotice("Removing map [ %s ] from maplist" CL_CLL "\n",map_getmapdata(id)->name); + map.erase(id); } -int map_delmap(char* mapname) -{ - int i; +int map_delmap(char* mapname){ char map_name[MAP_NAME_LENGTH]; if (strcmpi(mapname, "all") == 0) { @@ -3445,38 +3506,38 @@ int map_delmap(char* mapname) } mapindex_getmapname(mapname, map_name); - for(i = 0; i < map.size(); i++) { - if (strcmp(map[i].name, map_name) == 0) { - map_delmapid(i); + for( auto& pair : map ){ + if (strcmp(pair.second.name, map_name) == 0) { + map_delmapid(pair.first); return 1; } } + return 0; } /// Initializes map flags and adjusts them depending on configuration. -void map_flags_init(void) -{ - for( int i = 0; i < map.size(); i++ ) - { +void map_flags_init(void){ + for( auto& pair : map ){ + struct map_data *mapdata = &pair.second; union u_mapflag_args args = {}; args.flag_val = 100; // additional mapflag data - map[i].zone = 0; // restricted mapflag zone - map_setmapflag(i, MF_NOCOMMAND, false); // nocommand mapflag level - map_setmapflag_sub(i, MF_BEXP, true, &args); // per map base exp multiplicator - map_setmapflag_sub(i, MF_JEXP, true, &args); // per map job exp multiplicator + mapdata->zone = 0; // restricted mapflag zone + map_setmapflag(pair.first, MF_NOCOMMAND, false); // nocommand mapflag level + map_setmapflag_sub(pair.first, MF_BEXP, true, &args); // per map base exp multiplicator + map_setmapflag_sub(pair.first, MF_JEXP, true, &args); // per map job exp multiplicator // skill damage - map[i].damage_adjust = {}; + mapdata->damage_adjust = {}; // adjustments if( battle_config.pk_mode ) - map_setmapflag(i, MF_PVP, true); // make all maps pvp for pk_mode [Valaris] + map_setmapflag(pair.first, MF_PVP, true); // make all maps pvp for pk_mode [Valaris] - map_free_questinfo(i); + map_free_questinfo(pair.first); } } @@ -3572,9 +3633,7 @@ void map_removemapdb(struct map_data *m) *--------------------------------------*/ int map_readallmaps (void) { - int i; FILE* fp=NULL; - int maps_removed = 0; // Has the uncompressed gat data of all maps, so just one allocation has to be made char *map_cache_buffer[2] = { NULL, @@ -3590,7 +3649,7 @@ int map_readallmaps (void) "db/import/map_cache.dat" }; - for( i = 0; i < 2; i++ ){ + for( int i = 0; i < 2; i++ ){ ShowStatus( "Loading maps (using %s as map cache)...\n", mapcachefilepath[i] ); if( ( fp = fopen(mapcachefilepath[i], "rb") ) == NULL ){ @@ -3615,65 +3674,61 @@ int map_readallmaps (void) } } - for(i = 0; i < map.size(); i++) { + int i = 0; + std::vector maps_removed; + + for( auto &pair : map ){ size_t size; bool success = false; unsigned short idx = 0; + struct map_data *mapdata = &pair.second; + + // show progress + ShowStatus("Loading maps [%i/%i]: %s" CL_CLL "\r", i++, map.size(), mapdata->name); if( enable_grf ){ - // show progress - ShowStatus("Loading maps [%i/%i]: %s" CL_CLL "\r", i, map.size(), map[i].name); - // try to load the map - success = map_readgat(&map[i]) != 0; + success = map_readgat(mapdata) != 0; }else{ // try to load the map // Read from import first, in case of override if( map_cache_buffer[1] != NULL ){ - success = map_readfromcache( &map[i], map_cache_buffer[1], map_cache_decode_buffer ) != 0; + success = map_readfromcache( mapdata, map_cache_buffer[1], map_cache_decode_buffer ) != 0; } // Nothing was found in import - try to find it in the main file if( !success ){ - success = map_readfromcache( &map[i], map_cache_buffer[0], map_cache_decode_buffer ) != 0; + success = map_readfromcache( mapdata, map_cache_buffer[0], map_cache_decode_buffer ) != 0; } } // The map was not found - remove it - if( !(idx = mapindex_name2id(map[i].name)) || !success ){ - map_delmapid(i); - maps_removed++; - i--; + if( !(idx = mapindex_name2id(mapdata->name)) || !success ){ + maps_removed.push_back(pair.first); continue; } - map[i].index = idx; + mapdata->index = idx; - if (uidb_get(map_db,(unsigned int)map[i].index) != NULL) + if (uidb_get(map_db,(unsigned int)mapdata->index) != NULL) { - ShowWarning("Map %s already loaded!" CL_CLL "\n", map[i].name); - if (map[i].cell) { - aFree(map[i].cell); - map[i].cell = NULL; - } - map_delmapid(i); - maps_removed++; - i--; + ShowWarning("Map %s already loaded!" CL_CLL "\n", mapdata->name); + maps_removed.push_back(pair.first); continue; } - map_addmap2db(&map[i]); + map_addmap2db(mapdata); - map[i].m = i; - memset(map[i].moblist, 0, sizeof(map[i].moblist)); //Initialize moblist [Skotlex] - map[i].mob_delete_timer = INVALID_TIMER; //Initialize timer [Skotlex] + mapdata->m = pair.first; + memset(mapdata->moblist, 0, sizeof(mapdata->moblist)); //Initialize moblist [Skotlex] + mapdata->mob_delete_timer = INVALID_TIMER; //Initialize timer [Skotlex] - map[i].bxs = (map[i].xs + BLOCK_SIZE - 1) / BLOCK_SIZE; - map[i].bys = (map[i].ys + BLOCK_SIZE - 1) / BLOCK_SIZE; + mapdata->bxs = (mapdata->xs + BLOCK_SIZE - 1) / BLOCK_SIZE; + mapdata->bys = (mapdata->ys + BLOCK_SIZE - 1) / BLOCK_SIZE; - size = map[i].bxs * map[i].bys * sizeof(struct block_list*); - map[i].block = (struct block_list**)aCalloc(size, 1); - map[i].block_mob = (struct block_list**)aCalloc(size, 1); + size = mapdata->bxs * mapdata->bys * sizeof(struct block_list*); + mapdata->block = (struct block_list**)aCalloc(size, 1); + mapdata->block_mob = (struct block_list**)aCalloc(size, 1); } // intialization and configuration-dependent adjustments of mapflags @@ -3687,12 +3742,17 @@ int map_readallmaps (void) aFree(map_cache_buffer[0]); } + if( !maps_removed.empty() ){ + for( auto& id : maps_removed ){ + map_delmapid( id ); + } + + ShowNotice("Maps removed: '" CL_WHITE "%d" CL_RESET "'\n",maps_removed.size()); + } + // finished map loading ShowInfo("Successfully loaded '" CL_WHITE "%d" CL_RESET "' maps." CL_CLL "\n",map.size()); - if (maps_removed) - ShowNotice("Maps removed: '" CL_WHITE "%d" CL_RESET "'\n",maps_removed); - return 0; } @@ -4119,35 +4179,37 @@ int log_sql_init(void) struct questinfo *map_add_questinfo(int m, struct questinfo *qi) { unsigned short i; + struct map_data *mapdata = map_getmapdata(m); /* duplicate, override */ - for(i = 0; i < map[m].qi_count; i++) { - if( &map[m].qi_data[i] && map[m].qi_data[i].nd == qi->nd && map[m].qi_data[i].quest_id == qi->quest_id) + for(i = 0; i < mapdata->qi_count; i++) { + if( &mapdata->qi_data[i] && mapdata->qi_data[i].nd == qi->nd && mapdata->qi_data[i].quest_id == qi->quest_id) break; } - if( i == map[m].qi_count ) - RECREATE(map[m].qi_data, struct questinfo, ++map[m].qi_count); + if( i == mapdata->qi_count ) + RECREATE(mapdata->qi_data, struct questinfo, ++mapdata->qi_count); else { // clear previous criteria on override - if (map[m].qi_data[i].jobid) - aFree(map[m].qi_data[i].jobid); - map[m].qi_data[i].jobid = NULL; - map[m].qi_data[i].jobid_count = 0; - if (map[m].qi_data[i].req) - aFree(map[m].qi_data[i].req); - map[m].qi_data[i].req = NULL; - map[m].qi_data[i].req_count = 0; + if (mapdata->qi_data[i].jobid) + aFree(mapdata->qi_data[i].jobid); + mapdata->qi_data[i].jobid = NULL; + mapdata->qi_data[i].jobid_count = 0; + if (mapdata->qi_data[i].req) + aFree(mapdata->qi_data[i].req); + mapdata->qi_data[i].req = NULL; + mapdata->qi_data[i].req_count = 0; } - memcpy(&map[m].qi_data[i], qi, sizeof(struct questinfo)); - return &map[m].qi_data[i]; + memcpy(&mapdata->qi_data[i], qi, sizeof(struct questinfo)); + return &mapdata->qi_data[i]; } bool map_remove_questinfo(int m, struct npc_data *nd) { unsigned short i, c; + struct map_data *mapdata = map_getmapdata(m); - for(i = 0; i < map[m].qi_count; i++) { - struct questinfo *qi = &map[m].qi_data[i]; + for(i = 0; i < mapdata->qi_count; i++) { + struct questinfo *qi = &mapdata->qi_data[i]; if( qi->nd == nd ) { if (qi->jobid) aFree(qi->jobid); @@ -4159,57 +4221,59 @@ bool map_remove_questinfo(int m, struct npc_data *nd) { qi->req = NULL; qi->req_count = 0; - memset(&map[m].qi_data[i], 0, sizeof(map[m].qi_data[i])); + memset(&mapdata->qi_data[i], 0, sizeof(mapdata->qi_data[i])); } } // Move next data to empty slot - for(i = 0, c = 0; i < map[m].qi_count; i++) { - struct questinfo *qi = &map[m].qi_data[i]; + for(i = 0, c = 0; i < mapdata->qi_count; i++) { + struct questinfo *qi = &mapdata->qi_data[i]; if (!qi || !qi->nd) continue; if (i != c) { - map[m].qi_data[c] = map[m].qi_data[i]; - memset(&map[m].qi_data[i], 0, sizeof(map[m].qi_data[i])); + mapdata->qi_data[c] = mapdata->qi_data[i]; + memset(&mapdata->qi_data[i], 0, sizeof(mapdata->qi_data[i])); } c++; } - if (!(map[m].qi_count = c)) { - aFree(map[m].qi_data); - map[m].qi_data = NULL; + if (!(mapdata->qi_count = c)) { + aFree(mapdata->qi_data); + mapdata->qi_data = NULL; } else - RECREATE(map[m].qi_data, struct questinfo, map[m].qi_count); + RECREATE(mapdata->qi_data, struct questinfo, mapdata->qi_count); return true; } static void map_free_questinfo(int m) { unsigned short i; + struct map_data *mapdata = map_getmapdata(m); - for(i = 0; i < map[m].qi_count; i++) { - if (map[m].qi_data[i].jobid) - aFree(map[m].qi_data[i].jobid); - map[m].qi_data[i].jobid = NULL; - map[m].qi_data[i].jobid_count = 0; - if (map[m].qi_data[i].req) - aFree(map[m].qi_data[i].req); - map[m].qi_data[i].req = NULL; - map[m].qi_data[i].req_count = 0; + for(i = 0; i < mapdata->qi_count; i++) { + if (mapdata->qi_data[i].jobid) + aFree(mapdata->qi_data[i].jobid); + mapdata->qi_data[i].jobid = NULL; + mapdata->qi_data[i].jobid_count = 0; + if (mapdata->qi_data[i].req) + aFree(mapdata->qi_data[i].req); + mapdata->qi_data[i].req = NULL; + mapdata->qi_data[i].req_count = 0; } - aFree(map[m].qi_data); - map[m].qi_data = NULL; - map[m].qi_count = 0; + aFree(mapdata->qi_data); + mapdata->qi_data = NULL; + mapdata->qi_count = 0; } struct questinfo *map_has_questinfo(int m, struct npc_data *nd, int quest_id) { unsigned short i; + struct map_data *mapdata = map_getmapdata(m); - for (i = 0; i < map[m].qi_count; i++) { - struct questinfo *qi = &map[m].qi_data[i]; + for (i = 0; i < mapdata->qi_count; i++) { + struct questinfo *qi = &mapdata->qi_data[i]; if (qi->nd == nd && qi->quest_id == quest_id) { return qi; } @@ -4388,23 +4452,25 @@ bool map_getmapflag_name( enum e_mapflag mapflag, char* output ){ */ int map_getmapflag_sub(int16 m, enum e_mapflag mapflag, union u_mapflag_args *args) { - if (m < 0 || m >= map.size()) { + if (m < 0) { ShowWarning("map_getmapflag: Invalid map ID %d.\n", m); return -1; } + struct map_data *mapdata = map_getmapdata(m); + if (mapflag < MF_MIN || mapflag >= MF_MAX) { - ShowWarning("map_getmapflag: Invalid mapflag %d on map %s.\n", mapflag, map[m].name); + ShowWarning("map_getmapflag: Invalid mapflag %d on map %s.\n", mapflag, mapdata->name); return -1; } switch(mapflag) { case MF_NOLOOT: - return util::map_get(map[m].flag, MF_NOMOBLOOT, 0) && util::map_get(map[m].flag, MF_NOMVPLOOT, 0); + return util::map_get(mapdata->flag, MF_NOMOBLOOT, 0) && util::map_get(mapdata->flag, MF_NOMVPLOOT, 0); case MF_NOPENALTY: - return util::map_get(map[m].flag, MF_NOEXPPENALTY, 0) && util::map_get(map[m].flag, MF_NOZENYPENALTY, 0); + return util::map_get(mapdata->flag, MF_NOEXPPENALTY, 0) && util::map_get(mapdata->flag, MF_NOZENYPENALTY, 0); case MF_NOEXP: - return util::map_get(map[m].flag, MF_NOBASEEXP, 0) && util::map_get(map[m].flag, MF_NOJOBEXP, 0); + return util::map_get(mapdata->flag, MF_NOBASEEXP, 0) && util::map_get(mapdata->flag, MF_NOJOBEXP, 0); case MF_SKILL_DAMAGE: nullpo_retr(-1, args); @@ -4413,14 +4479,14 @@ int map_getmapflag_sub(int16 m, enum e_mapflag mapflag, union u_mapflag_args *ar case SKILLDMG_MOB: case SKILLDMG_BOSS: case SKILLDMG_OTHER: - return map[m].damage_adjust.rate[args->flag_val]; + return mapdata->damage_adjust.rate[args->flag_val]; case SKILLDMG_CASTER: - return map[m].damage_adjust.caster; + return mapdata->damage_adjust.caster; default: - return util::map_get(map[m].flag, mapflag, 0); + return util::map_get(mapdata->flag, mapflag, 0); } default: - return util::map_get(map[m].flag, mapflag, 0); + return util::map_get(mapdata->flag, mapflag, 0); } } @@ -4434,13 +4500,15 @@ int map_getmapflag_sub(int16 m, enum e_mapflag mapflag, union u_mapflag_args *ar */ bool map_setmapflag_sub(int16 m, enum e_mapflag mapflag, bool status, union u_mapflag_args *args) { - if (m < 0 || m >= map.size()) { + if (m < 0) { ShowWarning("map_setmapflag: Invalid map ID %d.\n", m); return false; } + struct map_data *mapdata = map_getmapdata(m); + if (mapflag < MF_MIN || mapflag >= MF_MAX) { - ShowWarning("map_setmapflag: Invalid mapflag %d on map %s.\n", mapflag, map[m].name); + ShowWarning("map_setmapflag: Invalid mapflag %d on map %s.\n", mapflag, mapdata->name); return false; } @@ -4449,11 +4517,11 @@ bool map_setmapflag_sub(int16 m, enum e_mapflag mapflag, bool status, union u_ma if (status) { nullpo_retr(false, args); - map[m].save.map = args->nosave.map; - map[m].save.x = args->nosave.x; - map[m].save.y = args->nosave.y; + mapdata->save.map = args->nosave.map; + mapdata->save.x = args->nosave.x; + mapdata->save.y = args->nosave.y; } - map[m].flag[mapflag] = status; + mapdata->flag[mapflag] = status; break; case MF_PVP: if (!status) @@ -4463,30 +4531,30 @@ bool map_setmapflag_sub(int16 m, enum e_mapflag mapflag, bool status, union u_ma map_foreachinmap(map_mapflag_pvp_sub, m, BL_PC); if (map_getmapflag(m, MF_GVG)) { map_setmapflag(m, MF_GVG, false); - ShowWarning("map_setmapflag: Unable to set GvG and PvP flags for the same map! Removing GvG flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set GvG and PvP flags for the same map! Removing GvG flag from %s.\n", mapdata->name); } if (map_getmapflag(m, MF_GVG_TE)) { map_setmapflag(m, MF_GVG_TE, false); - ShowWarning("map_setmapflag: Unable to set GvG TE and PvP flags for the same map! Removing GvG TE flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set GvG TE and PvP flags for the same map! Removing GvG TE flag from %s.\n", mapdata->name); } if (map_getmapflag(m, MF_GVG_DUNGEON)) { map_setmapflag(m, MF_GVG_DUNGEON, false); - ShowWarning("map_setmapflag: Unable to set GvG Dungeon and PvP flags for the same map! Removing GvG Dungeon flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set GvG Dungeon and PvP flags for the same map! Removing GvG Dungeon flag from %s.\n", mapdata->name); } if (map_getmapflag(m, MF_GVG_CASTLE)) { map_setmapflag(m, MF_GVG_CASTLE, false); - ShowWarning("map_setmapflag: Unable to set GvG Castle and PvP flags for the same map! Removing GvG Castle flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set GvG Castle and PvP flags for the same map! Removing GvG Castle flag from %s.\n", mapdata->name); } if (map_getmapflag(m, MF_GVG_TE_CASTLE)) { map_setmapflag(m, MF_GVG_TE_CASTLE, false); - ShowWarning("map_setmapflag: Unable to set GvG TE Castle and PvP flags for the same map! Removing GvG TE Castle flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set GvG TE Castle and PvP flags for the same map! Removing GvG TE Castle flag from %s.\n", mapdata->name); } if (map_getmapflag(m, MF_BATTLEGROUND)) { map_setmapflag(m, MF_BATTLEGROUND, false); - ShowWarning("map_setmapflag: Unable to set Battleground and PvP flags for the same map! Removing Battleground flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set Battleground and PvP flags for the same map! Removing Battleground flag from %s.\n", mapdata->name); } } - map[m].flag[mapflag] = status; + mapdata->flag[mapflag] = status; break; case MF_GVG: case MF_GVG_TE: @@ -4496,60 +4564,60 @@ bool map_setmapflag_sub(int16 m, enum e_mapflag mapflag, bool status, union u_ma clif_map_property_mapall(m, MAPPROPERTY_AGITZONE); if (map_getmapflag(m, MF_PVP)) { map_setmapflag(m, MF_PVP, false); - ShowWarning("map_setmapflag: Unable to set PvP and GvG flags for the same map! Removing PvP flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set PvP and GvG flags for the same map! Removing PvP flag from %s.\n", mapdata->name); } if (map_getmapflag(m, MF_BATTLEGROUND)) { map_setmapflag(m, MF_BATTLEGROUND, false); - ShowWarning("map_setmapflag: Unable to set Battleground and GvG flags for the same map! Removing Battleground flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set Battleground and GvG flags for the same map! Removing Battleground flag from %s.\n", mapdata->name); } } - map[m].flag[mapflag] = status; + mapdata->flag[mapflag] = status; break; case MF_GVG_CASTLE: case MF_GVG_TE_CASTLE: if (status) { if (mapflag == MF_GVG_CASTLE && map_getmapflag(m, MF_GVG_TE_CASTLE)) { map_setmapflag(m, MF_GVG_TE_CASTLE, false); - ShowWarning("map_setmapflag: Unable to set GvG TE Castle and GvG Castle flags for the same map! Removing GvG TE Castle flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set GvG TE Castle and GvG Castle flags for the same map! Removing GvG TE Castle flag from %s.\n", mapdata->name); } if (mapflag == MF_GVG_TE_CASTLE && map_getmapflag(m, MF_GVG_CASTLE)) { map_setmapflag(m, MF_GVG_CASTLE, false); - ShowWarning("map_setmapflag: Unable to set GvG Castle and GvG TE Castle flags for the same map! Removing GvG Castle flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set GvG Castle and GvG TE Castle flags for the same map! Removing GvG Castle flag from %s.\n", mapdata->name); } if (map_getmapflag(m, MF_PVP)) { map_setmapflag(m, MF_PVP, false); - ShowWarning("npc_parse_mapflag: Unable to set PvP and GvG%s Castle flags for the same map! Removing PvP flag from %s.\n", (mapflag == MF_GVG_CASTLE ? NULL : " TE"), map[m].name); + ShowWarning("npc_parse_mapflag: Unable to set PvP and GvG%s Castle flags for the same map! Removing PvP flag from %s.\n", (mapflag == MF_GVG_CASTLE ? NULL : " TE"), mapdata->name); } } - map[m].flag[mapflag] = status; + mapdata->flag[mapflag] = status; break; case MF_GVG_DUNGEON: if (status && map_getmapflag(m, MF_PVP)) { map_setmapflag(m, MF_PVP, false); - ShowWarning("map_setmapflag: Unable to set PvP and GvG Dungeon flags for the same map! Removing PvP flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set PvP and GvG Dungeon flags for the same map! Removing PvP flag from %s.\n", mapdata->name); } - map[m].flag[mapflag] = status; + mapdata->flag[mapflag] = status; break; case MF_NOBASEEXP: case MF_NOJOBEXP: if (status) { if (mapflag == MF_NOBASEEXP && map_getmapflag(m, MF_BEXP) != 100) { map_setmapflag(m, MF_BEXP, false); - ShowWarning("map_setmapflag: Unable to set BEXP and No Base EXP flags for the same map! Removing BEXP flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set BEXP and No Base EXP flags for the same map! Removing BEXP flag from %s.\n", mapdata->name); } if (mapflag == MF_NOJOBEXP && map_getmapflag(m, MF_JEXP) != 100) { map_setmapflag(m, MF_JEXP, false); - ShowWarning("map_setmapflag: Unable to set JEXP and No Job EXP flags for the same map! Removing JEXP flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set JEXP and No Job EXP flags for the same map! Removing JEXP flag from %s.\n", mapdata->name); } } - map[m].flag[mapflag] = status; + mapdata->flag[mapflag] = status; break; case MF_PVP_NIGHTMAREDROP: if (status) { nullpo_retr(false, args); - if (map[m].drop_list.size() == MAX_DROP_PER_MAP) { - ShowWarning("map_setmapflag: Reached the maximum number of drop list items for mapflag pvp_nightmaredrop on %s. Skipping.\n", map[m].name); + if (mapdata->drop_list.size() == MAX_DROP_PER_MAP) { + ShowWarning("map_setmapflag: Reached the maximum number of drop list items for mapflag pvp_nightmaredrop on %s. Skipping.\n", mapdata->name); break; } @@ -4558,26 +4626,26 @@ bool map_setmapflag_sub(int16 m, enum e_mapflag mapflag, bool status, union u_ma entry.drop_id = args->nightmaredrop.drop_id; entry.drop_type = args->nightmaredrop.drop_type; entry.drop_per = args->nightmaredrop.drop_per; - map[m].drop_list.push_back(entry); + mapdata->drop_list.push_back(entry); } - map[m].flag[mapflag] = status; + mapdata->flag[mapflag] = status; break; case MF_RESTRICTED: nullpo_retr(false, args); - map[m].flag[mapflag] = status; + mapdata->flag[mapflag] = status; if (!status) - map[m].zone ^= 1 << (args->flag_val + 1); + mapdata->zone ^= 1 << (args->flag_val + 1); else - map[m].zone |= 1 << (args->flag_val + 1); + mapdata->zone |= 1 << (args->flag_val + 1); break; case MF_NOCOMMAND: if (status) { nullpo_retr(false, args); - map[m].flag[mapflag] = ((args->flag_val <= 0) ? 100 : args->flag_val); + mapdata->flag[mapflag] = ((args->flag_val <= 0) ? 100 : args->flag_val); } else - map[m].flag[mapflag] = false; + mapdata->flag[mapflag] = false; break; case MF_JEXP: case MF_BEXP: @@ -4586,15 +4654,15 @@ bool map_setmapflag_sub(int16 m, enum e_mapflag mapflag, bool status, union u_ma if (mapflag == MF_JEXP && map_getmapflag(m, MF_NOJOBEXP)) { map_setmapflag(m, MF_NOJOBEXP, false); - ShowWarning("map_setmapflag: Unable to set No Job EXP and JEXP flags for the same map! Removing No Job EXP flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set No Job EXP and JEXP flags for the same map! Removing No Job EXP flag from %s.\n", mapdata->name); } if (mapflag == MF_BEXP && map_getmapflag(m, MF_NOBASEEXP)) { map_setmapflag(m, MF_NOBASEEXP, false); - ShowWarning("map_setmapflag: Unable to set No Base EXP and BEXP flags for the same map! Removing No Base EXP flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set No Base EXP and BEXP flags for the same map! Removing No Base EXP flag from %s.\n", mapdata->name); } - map[m].flag[mapflag] = args->flag_val; + mapdata->flag[mapflag] = args->flag_val; } else - map[m].flag[mapflag] = false; + mapdata->flag[mapflag] = false; break; case MF_BATTLEGROUND: if (status) { @@ -4602,61 +4670,61 @@ bool map_setmapflag_sub(int16 m, enum e_mapflag mapflag, bool status, union u_ma if (map_getmapflag(m, MF_PVP)) { map_setmapflag(m, MF_PVP, false); - ShowWarning("map_setmapflag: Unable to set PvP and Battleground flags for the same map! Removing PvP flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set PvP and Battleground flags for the same map! Removing PvP flag from %s.\n", mapdata->name); } if (map_getmapflag(m, MF_GVG)) { map_setmapflag(m, MF_GVG, false); - ShowWarning("map_setmapflag: Unable to set GvG and Battleground flags for the same map! Removing GvG flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set GvG and Battleground flags for the same map! Removing GvG flag from %s.\n", mapdata->name); } if (map_getmapflag(m, MF_GVG_DUNGEON)) { map_setmapflag(m, MF_GVG_DUNGEON, false); - ShowWarning("map_setmapflag: Unable to set GvG Dungeon and Battleground flags for the same map! Removing GvG Dungeon flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set GvG Dungeon and Battleground flags for the same map! Removing GvG Dungeon flag from %s.\n", mapdata->name); } if (map_getmapflag(m, MF_GVG_CASTLE)) { map_setmapflag(m, MF_GVG_CASTLE, false); - ShowWarning("map_setmapflag: Unable to set GvG Castle and Battleground flags for the same map! Removing GvG Castle flag from %s.\n", map[m].name); + ShowWarning("map_setmapflag: Unable to set GvG Castle and Battleground flags for the same map! Removing GvG Castle flag from %s.\n", mapdata->name); } - map[m].flag[mapflag] = ((args->flag_val <= 0 || args->flag_val > 2) ? 1 : args->flag_val); + mapdata->flag[mapflag] = ((args->flag_val <= 0 || args->flag_val > 2) ? 1 : args->flag_val); } else - map[m].flag[mapflag] = false; + mapdata->flag[mapflag] = false; break; case MF_NOLOOT: - map[m].flag[MF_NOMOBLOOT] = status; - map[m].flag[MF_NOMVPLOOT] = status; + mapdata->flag[MF_NOMOBLOOT] = status; + mapdata->flag[MF_NOMVPLOOT] = status; break; case MF_NOPENALTY: - map[m].flag[MF_NOEXPPENALTY] = status; - map[m].flag[MF_NOZENYPENALTY] = status; + mapdata->flag[MF_NOEXPPENALTY] = status; + mapdata->flag[MF_NOZENYPENALTY] = status; break; case MF_NOEXP: - map[m].flag[MF_NOBASEEXP] = status; - map[m].flag[MF_NOJOBEXP] = status; + mapdata->flag[MF_NOBASEEXP] = status; + mapdata->flag[MF_NOJOBEXP] = status; break; case MF_SKILL_DAMAGE: if (!status) { - map[m].damage_adjust = {}; - map[m].skill_damage.clear(); + mapdata->damage_adjust = {}; + mapdata->skill_damage.clear(); } else { nullpo_retr(false, args); if (!args->flag_val) { // Signifies if it's a single skill or global damage adjustment if (!args->skill_damage.caster) { - ShowError("map_setmapflag: Skill damage adjustment without casting type for map %s.\n", map[m].name); + ShowError("map_setmapflag: Skill damage adjustment without casting type for map %s.\n", mapdata->name); return false; } for (int i = 0; i < SKILLDMG_MAX; i++) { - map[m].damage_adjust.rate[i] = cap_value(args->skill_damage.rate[i], -100, 100000); + mapdata->damage_adjust.rate[i] = cap_value(args->skill_damage.rate[i], -100, 100000); - if (map[m].flag.find(mapflag) != map[m].flag.end() && map[m].damage_adjust.rate[i]) - map[m].damage_adjust.caster = args->skill_damage.caster; + if (mapdata->flag.find(mapflag) != mapdata->flag.end() && mapdata->damage_adjust.rate[i]) + mapdata->damage_adjust.caster = args->skill_damage.caster; } } } - map[m].flag[mapflag] = status; + mapdata->flag[mapflag] = status; break; default: - map[m].flag[mapflag] = status; + mapdata->flag[mapflag] = status; break; } @@ -4674,18 +4742,13 @@ static int cleanup_db_sub(DBKey key, DBData *data, va_list va) /*========================================== * map destructor *------------------------------------------*/ -void do_final(void) -{ - int i, j; - struct map_session_data* sd; - struct s_mapiterator* iter; - +void do_final(void){ ShowStatus("Terminating...\n"); channel_config.closing = true; //Ladies and babies first. - iter = mapit_getallusers(); - for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + struct s_mapiterator* iter = mapit_getallusers(); + for( struct map_session_data* sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) map_quit(sd); mapit_free(iter); @@ -4693,12 +4756,11 @@ void do_final(void) do_clear_npc(); // remove all objects on maps - for (i = 0; i < map.size(); i++) { - ShowStatus("Cleaning up maps [%d/%d]: %s..." CL_CLL "\r", i+1, map.size(), map[i].name); - if (map[i].m >= 0) { - map_foreachinmap(cleanup_sub, i, BL_ALL); - channel_delete(map[i].channel,false); - } + int i = 0; + for( auto& pair : map ){ + ShowStatus("Cleaning up maps [%d/%d]: %s..." CL_CLL "\r", i++, map.size(), pair.second.name); + map_foreachinmap(cleanup_sub, pair.first, BL_ALL); + channel_delete(pair.second.channel,false); } ShowStatus("Cleaned up %d maps." CL_CLL "\n", map.size()); @@ -4740,18 +4802,20 @@ void do_final(void) map_db->destroy(map_db, map_db_final); - for (i=0; icell) aFree(mapdata->cell); + if(mapdata->block) aFree(mapdata->block); + if(mapdata->block_mob) aFree(mapdata->block_mob); if(battle_config.dynamic_mobs) { //Dynamic mobs flag by [random] - if(map[i].mob_delete_timer != INVALID_TIMER) - delete_timer(map[i].mob_delete_timer, map_removemobs_timer); - for (j=0; jmob_delete_timer != INVALID_TIMER) + delete_timer(mapdata->mob_delete_timer, map_removemobs_timer); + for (int j=0; jmoblist[j]) aFree(mapdata->moblist[j]); } - map_free_questinfo(i); - map[i].damage_adjust = {}; + map_free_questinfo(pair.first); + mapdata->damage_adjust = {}; } mapindex_final(); diff --git a/src/map/map.hpp b/src/map/map.hpp index 160ac16299..39da3a84cb 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -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; +extern std::map map; extern int autosave_interval; extern int minsave_interval; diff --git a/src/map/mob.cpp b/src/map/mob.cpp index 429edd8a3c..e1a23eea9b 100644 --- a/src/map/mob.cpp +++ b/src/map/mob.cpp @@ -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) diff --git a/src/map/npc.cpp b/src/map/npc.cpp index e2cefec648..6a6d457f39 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -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;inpc_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;inpc_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 );// , @@ -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] ); + } + } } /*========================================== diff --git a/src/map/party.cpp b/src/map/party.cpp index 8660ea8b6b..8d3f384fdd 100644 --- a/src/map/party.cpp +++ b/src/map/party.cpp @@ -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); } diff --git a/src/map/path.cpp b/src/map/path.cpp index e27f522d42..70bf66ddc2 100644 --- a/src/map/path.cpp +++ b/src/map/path.cpp @@ -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 diff --git a/src/map/pc.cpp b/src/map/pc.cpp index 7a3c799dad..9e406290f9 100755 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -4,7 +4,6 @@ #include "pc.hpp" #include -#include #include #include @@ -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;jbl.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; diff --git a/src/map/script.cpp b/src/map/script.cpp index b9e260da57..dd4339c5fa 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -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; diff --git a/src/map/skill.cpp b/src/map/skill.cpp index 735910b951..82adbed53b 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -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; } diff --git a/src/map/status.cpp b/src/map/status.cpp index 0f33b55b3b..6d8b5fb473 100644 --- a/src/map/status.cpp +++ b/src/map/status.cpp @@ -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]) diff --git a/src/map/vending.cpp b/src/map/vending.cpp index 6c696406be..73df92f89a 100755 --- a/src/map/vending.cpp +++ b/src/map/vending.cpp @@ -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); }