From 48ae1a1e05db440263ac2a4fe0d887d1528151f3 Mon Sep 17 00:00:00 2001 From: Aleos Date: Fri, 10 Aug 2018 13:52:07 -0400 Subject: [PATCH] Cleaned up map storage type (#3384) * Fixes #3369, fixes #3370, and fixes #3382. * Converted maps storage container back to static array. * Converted mapflag storage containers to unordered_map. * Removed a lot of redundancy and recursive lookups. * Fixed a couple short-circuit checks to help with performance. * Fixed multiple instance creation/destruction issues. * Fixed PK Mode attempting to set PvP on flags that are already active. * Getting MF_RESTRICTED will return the map's zone value instead of the state. * Converted mapflag macros to inline functions. Thanks to @teededung, @lelouch22, @mazvi, @Lemongrass3110, and @cydh! --- doc/script_commands.txt | 2 + src/char/char.cpp | 6 +- src/common/mmo.hpp | 1 + src/common/utilities.hpp | 32 +++++ src/map/atcommand.cpp | 16 ++- src/map/battle.cpp | 72 +++++----- src/map/chrif.cpp | 13 +- src/map/clif.cpp | 60 +++++---- src/map/instance.cpp | 3 + src/map/instance.hpp | 2 + src/map/intif.cpp | 11 +- src/map/itemdb.cpp | 15 ++- src/map/map.cpp | 276 +++++++++++++++++++++------------------ src/map/map.hpp | 194 ++++++++++++++++++++++++--- src/map/mob.cpp | 19 ++- src/map/npc.cpp | 23 ++-- src/map/pc.cpp | 19 +-- src/map/script.cpp | 6 +- src/map/skill.cpp | 55 ++++---- src/map/status.cpp | 23 ++-- 20 files changed, 548 insertions(+), 300 deletions(-) diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 004397f63f..49b350dae9 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -7038,6 +7038,8 @@ The optional parameter 'zone' is used to remove the zone from restricted mapflag This command checks the status of a given mapflag and returns the mapflag's state. 0 means OFF, and 1 means ON. See 'setmapflag' for a list of mapflags. +For MF_RESTRICTED, the zone value of the map is returned. + The optional parameter 'type' is used in the 'skill_damage' mapflag: SKILLDMG_MAX: if mapflag is set (default) SKILLDMG_PC: damage against players diff --git a/src/char/char.cpp b/src/char/char.cpp index 9c47080964..dba1586e4c 100644 --- a/src/char/char.cpp +++ b/src/char/char.cpp @@ -2087,15 +2087,13 @@ int char_loadName(uint32 char_id, char* name){ // Searches for the mapserver that has a given map (and optionally ip/port, if not -1). // If found, returns the server's index in the 'server' array (otherwise returns -1). int char_search_mapserver(unsigned short map, uint32 ip, uint16 port){ - int i, j; - - for(i = 0; i < ARRAYLENGTH(map_server); i++) + for(int i = 0; i < ARRAYLENGTH(map_server); i++) { if (map_server[i].fd > 0 && (ip == (uint32)-1 || map_server[i].ip == ip) && (port == (uint16)-1 || map_server[i].port == port)) { - for (j = 0; map_server[i].map[j]; j++) + for (int j = 0; map_server[i].map[j]; j++) if (map_server[i].map[j] == map) return i; } diff --git a/src/common/mmo.hpp b/src/common/mmo.hpp index 5240a4ed92..6d07f195a9 100644 --- a/src/common/mmo.hpp +++ b/src/common/mmo.hpp @@ -32,6 +32,7 @@ #define MAX_HOTKEYS 38 #endif +#define MAX_MAP_PER_SERVER 1500 /// Maximum amount of maps available on a server #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/common/utilities.hpp b/src/common/utilities.hpp index 7b04cff38f..5765b55e80 100644 --- a/src/common/utilities.hpp +++ b/src/common/utilities.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "cbasetypes.hpp" @@ -57,6 +58,37 @@ namespace rathena { else return defaultValue; } + + /** + * Find a key-value pair and return the key value + * @param map: Unordered Map to search through + * @param key: Key wanted + * @return Key value on success or nullptr on failure + */ + template V* umap_find(std::unordered_map& map, K key) { + auto it = map.find(key); + + if (it != map.end()) + return &it->second; + else + return nullptr; + } + + /** + * Get a key-value pair and return the key value + * @param map: Unordered Map to search through + * @param key: Key wanted + * @param defaultValue: Value returned if key doesn't exist + * @return Key value on success or defaultValue on failure + */ + template V umap_get(std::unordered_map& map, K key, V defaultValue) { + auto it = map.find(key); + + if (it != map.end()) + return it->second; + else + return defaultValue; + } } } diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index 8d4e5a93f7..c21905d45d 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -397,8 +397,8 @@ static void warp_get_suggestions(struct map_session_data* sd, const char *name) suggestions.reserve( MAX_SUGGESTIONS ); // check for maps that contain string - for( auto& pair : map ){ - struct map_data *mapdata = &pair.second; + for (int i = 0; i < map_num; i++) { + struct map_data *mapdata = map_getmapdata(i); // Prevent suggestion of instance mapnames if( mapdata->instance_id != 0 ){ @@ -419,16 +419,18 @@ static void warp_get_suggestions(struct map_session_data* sd, const char *name) // Levenshtein > 4 is bad const int LEVENSHTEIN_MAX = 4; - std::map> maps; + std::unordered_map> maps; + + for (int i = 0; i < map_num; i++) { + struct map_data *mapdata = map_getmapdata(i); - for( auto& pair : map ){ // Prevent suggestion of instance mapnames - if( pair.second.instance_id != 0 ){ + if(mapdata->instance_id != 0 ){ continue; } // Calculate the levenshtein distance of the two strings - int distance = levenshtein( pair.second.name, name ); + int distance = levenshtein(mapdata->name, name); // Check if it is above the maximum defined distance if( distance > LEVENSHTEIN_MAX ){ @@ -442,7 +444,7 @@ static void warp_get_suggestions(struct map_session_data* sd, const char *name) continue; } - vector.push_back( pair.second.name ); + vector.push_back(mapdata->name); } for( int distance = 0; distance <= LEVENSHTEIN_MAX; distance++ ){ diff --git a/src/map/battle.cpp b/src/map/battle.cpp index e82f025fa8..a3e92acf15 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -2191,15 +2191,14 @@ static int battle_skill_damage_skill(struct block_list *src, struct block_list * if (!(damage->caster&src->type)) return 0; - union u_mapflag_args args = {}; + struct map_data *mapdata = map_getmapdata(m); - args.flag_val = SKILLDMG_MAX; // Check if it's enabled first - if ((damage->map&1 && (!map_getmapflag(m, MF_PVP) && !map_flag_gvg2(m) && !map_getmapflag(m, MF_BATTLEGROUND) && !map_getmapflag_sub(m, MF_SKILL_DAMAGE, &args) && !map_getmapflag(m, MF_RESTRICTED))) || - (damage->map&2 && map_getmapflag(m, MF_PVP)) || - (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_getmapdata(m)->zone))) + if ((damage->map&1 && (!mapdata->flag[MF_PVP] && !mapdata_flag_gvg2(mapdata) && !mapdata->flag[MF_BATTLEGROUND] && !mapdata->flag[MF_SKILL_DAMAGE] && !mapdata->flag[MF_RESTRICTED])) || + (damage->map&2 && mapdata->flag[MF_PVP]) || + (damage->map&4 && mapdata_flag_gvg2(mapdata)) || + (damage->map&8 && mapdata->flag[MF_BATTLEGROUND]) || + (damage->map&16 && mapdata->flag[MF_SKILL_DAMAGE]) || + (damage->map&(8*mapdata->zone) && mapdata->flag[MF_RESTRICTED])) { return damage->rate[battle_skill_damage_type(target)]; } @@ -4930,7 +4929,7 @@ struct Damage battle_calc_attack_plant(struct Damage wd, struct block_list *src, } if( attack_hits && class_ == MOBID_EMPERIUM ) { - if(target && map_flag_gvg2(target->m) && !battle_can_hit_gvg_target(src,target,skill_id,(skill_id)?BF_SKILL:0)) { + if(target && !battle_can_hit_gvg_target(src,target,skill_id,(skill_id)?BF_SKILL:0) && map_flag_gvg2(target->m)) { wd.damage = wd.damage2 = 0; return wd; } @@ -5061,26 +5060,29 @@ struct Damage battle_calc_attack_gvg_bg(struct Damage wd, struct block_list *src skill_additional_effect(target, (!d_bl) ? src : d_bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL, ATK_DEF, tick); } } + + struct map_data *mapdata = map_getmapdata(target->m); + if(!wd.damage2) { wd.damage = battle_calc_damage(src,target,&wd,wd.damage,skill_id,skill_lv); - if( map_flag_gvg2(target->m) ) + if( mapdata_flag_gvg2(mapdata) ) wd.damage=battle_calc_gvg_damage(src,target,wd.damage,skill_id,wd.flag); - else if( map_getmapflag(target->m, MF_BATTLEGROUND) ) + else if( mapdata->flag[MF_BATTLEGROUND] ) wd.damage=battle_calc_bg_damage(src,target,wd.damage,skill_id,wd.flag); } else if(!wd.damage) { wd.damage2 = battle_calc_damage(src,target,&wd,wd.damage2,skill_id,skill_lv); - if( map_flag_gvg2(target->m) ) + if( mapdata_flag_gvg2(mapdata) ) wd.damage2 = battle_calc_gvg_damage(src,target,wd.damage2,skill_id,wd.flag); - else if( map_getmapflag(target->m, MF_BATTLEGROUND) ) + else if( mapdata->flag[MF_BATTLEGROUND] ) wd.damage2 = battle_calc_bg_damage(src,target,wd.damage2,skill_id,wd.flag); } else { int64 d1 = wd.damage + wd.damage2,d2 = wd.damage2; wd.damage = battle_calc_damage(src,target,&wd,d1,skill_id,skill_lv); - if( map_flag_gvg2(target->m) ) + if( mapdata_flag_gvg2(mapdata) ) wd.damage = battle_calc_gvg_damage(src,target,wd.damage,skill_id,wd.flag); - else if( map_getmapflag(target->m, MF_BATTLEGROUND) ) + else if( mapdata->flag[MF_BATTLEGROUND] ) wd.damage = battle_calc_bg_damage(src,target,wd.damage,skill_id,wd.flag); wd.damage2 = (int64)d2*100/d1 * wd.damage/100; if(wd.damage > 1 && wd.damage2 < 1) wd.damage2 = 1; @@ -6385,10 +6387,12 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list } #endif + struct map_data *mapdata = map_getmapdata(target->m); + ad.damage = battle_calc_damage(src,target,&ad,ad.damage,skill_id,skill_lv); - if (map_flag_gvg2(target->m)) + if (mapdata_flag_gvg2(mapdata)) ad.damage = battle_calc_gvg_damage(src,target,ad.damage,skill_id,ad.flag); - else if (map_getmapflag(target->m, MF_BATTLEGROUND)) + else if (mapdata->flag[MF_BATTLEGROUND]) ad.damage = battle_calc_bg_damage(src,target,ad.damage,skill_id,ad.flag); // Skill damage adjustment @@ -6777,10 +6781,12 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * break; } + struct map_data *mapdata = map_getmapdata(target->m); + md.damage = battle_calc_damage(src,target,&md,md.damage,skill_id,skill_lv); - if(map_flag_gvg2(target->m)) + if(mapdata_flag_gvg2(mapdata)) md.damage = battle_calc_gvg_damage(src,target,md.damage,skill_id,md.flag); - else if(map_getmapflag(target->m, MF_BATTLEGROUND)) + else if(mapdata->flag[MF_BATTLEGROUND]) md.damage = battle_calc_bg_damage(src,target,md.damage,skill_id,md.flag); // Skill damage adjustment @@ -7651,6 +7657,8 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f } } + struct map_data *mapdata = map_getmapdata(m); + switch( target->type ) { // Checks on actual target case BL_PC: { struct status_change* sc = status_get_sc(src); @@ -7697,7 +7705,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f case NC_AXETORNADO: case SR_SKYNETBLOW: // Can only hit traps in PVP/GVG maps - if (!map_getmapflag(m, MF_PVP) && !map_getmapflag(m, MF_GVG)) + if (!mapdata->flag[MF_PVP] && !mapdata->flag[MF_GVG]) return 0; break; } @@ -7714,7 +7722,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f case NC_AXETORNADO: case SR_SKYNETBLOW: // Can only hit icewall in PVP/GVG maps - if (!map_getmapflag(m, MF_PVP) && !map_getmapflag(m, MF_GVG)) + if (!mapdata->flag[MF_PVP] && !mapdata->flag[MF_GVG]) return 0; break; case HT_CLAYMORETRAP: @@ -7767,7 +7775,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f { struct mob_data *md = BL_CAST(BL_MOB, t_bl); - if( !map_flag_gvg(m) && md->guardian_data && md->guardian_data->guild_id ) + if( md->guardian_data && md->guardian_data->guild_id && !mapdata_flag_gvg(mapdata) ) return 0; // Disable guardians/emperiums owned by Guilds on non-woe times. break; } @@ -7818,7 +7826,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f state |= BCT_ENEMY; // Can kill anything strip_enemy = 0; } - else if( sd->duel_group && !((!battle_config.duel_allow_pvp && map_getmapflag(m, MF_PVP)) || (!battle_config.duel_allow_gvg && map_flag_gvg(m))) ) + else if( sd->duel_group && !((!battle_config.duel_allow_pvp && mapdata->flag[MF_PVP]) || (!battle_config.duel_allow_gvg && mapdata_flag_gvg(mapdata))) ) { if( t_bl->type == BL_PC && (sd->duel_group == ((TBL_PC*)t_bl)->duel_group) ) return (BCT_ENEMY&flag)?1:-1; // Duel targets can ONLY be your enemy, nothing else. @@ -7826,7 +7834,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f return 0; // You can't target anything out of your duel } } - if( map_flag_gvg(m) && !sd->status.guild_id && t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->mob_id == MOBID_EMPERIUM ) + if( !sd->status.guild_id && t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->mob_id == MOBID_EMPERIUM && mapdata_flag_gvg(mapdata) ) return 0; //If you don't belong to a guild, can't target emperium. if( t_bl->type != BL_PC ) state |= BCT_ENEMY; //Natural enemy. @@ -7835,7 +7843,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f case BL_MOB: { struct mob_data *md = BL_CAST(BL_MOB, s_bl); - if( !map_flag_gvg(m) && md->guardian_data && md->guardian_data->guild_id ) + if( md->guardian_data && md->guardian_data->guild_id && !mapdata_flag_gvg(mapdata) ) return 0; // Disable guardians/emperium owned by Guilds on non-woe times. if( !md->special_state.ai ) @@ -7880,10 +7888,10 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f return (flag&state)?1:-1; } - if( map_flag_vs(m) ) + if( mapdata_flag_vs(mapdata) ) { //Check rivalry settings. int sbg_id = 0, tbg_id = 0; - if( map_getmapflag(m, MF_BATTLEGROUND) ) + if(mapdata->flag[MF_BATTLEGROUND] ) { sbg_id = bg_team_get_id(s_bl); tbg_id = bg_team_get_id(t_bl); @@ -7891,7 +7899,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f if( flag&(BCT_PARTY|BCT_ENEMY) ) { int s_party = status_get_party_id(s_bl); - if( s_party && s_party == status_get_party_id(t_bl) && !(map_getmapflag(m, MF_PVP) && map_getmapflag(m, MF_PVP_NOPARTY)) && !(map_flag_gvg(m) && map_getmapflag(m, MF_GVG_NOPARTY)) && (!map_getmapflag(m, MF_BATTLEGROUND) || sbg_id == tbg_id) ) + if( s_party && s_party == status_get_party_id(t_bl) && !(mapdata->flag[MF_PVP] && mapdata->flag[MF_PVP_NOPARTY]) && !(mapdata_flag_gvg(mapdata) && mapdata->flag[MF_GVG_NOPARTY]) && (!mapdata->flag[MF_BATTLEGROUND] || sbg_id == tbg_id) ) state |= BCT_PARTY; else state |= BCT_ENEMY; @@ -7900,15 +7908,15 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f { int s_guild = status_get_guild_id(s_bl); int t_guild = status_get_guild_id(t_bl); - if( !(map_getmapflag(m, MF_PVP) && map_getmapflag(m, MF_PVP_NOGUILD)) && s_guild && t_guild && (s_guild == t_guild || (!(flag&BCT_SAMEGUILD) && guild_isallied(s_guild, t_guild))) && (!map_getmapflag(m, MF_BATTLEGROUND) || sbg_id == tbg_id) ) + if( !(mapdata->flag[MF_PVP] && mapdata->flag[MF_PVP_NOGUILD]) && s_guild && t_guild && (s_guild == t_guild || (!(flag&BCT_SAMEGUILD) && guild_isallied(s_guild, t_guild))) && (!mapdata->flag[MF_BATTLEGROUND] || sbg_id == tbg_id) ) state |= BCT_GUILD; else state |= BCT_ENEMY; } - if( state&BCT_ENEMY && map_getmapflag(m, MF_BATTLEGROUND) && sbg_id && sbg_id == tbg_id ) + if( state&BCT_ENEMY && mapdata->flag[MF_BATTLEGROUND] && sbg_id && sbg_id == tbg_id ) state &= ~BCT_ENEMY; - if( state&BCT_ENEMY && battle_config.pk_mode && !map_flag_gvg(m) && s_bl->type == BL_PC && t_bl->type == BL_PC ) + if( state&BCT_ENEMY && battle_config.pk_mode && !mapdata_flag_gvg(mapdata) && s_bl->type == BL_PC && t_bl->type == BL_PC ) { // Prevent novice engagement on pk_mode (feature by Valaris) TBL_PC *sd = (TBL_PC*)s_bl, *sd2 = (TBL_PC*)t_bl; if ( @@ -7920,7 +7928,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f ) state &= ~BCT_ENEMY; } - }//end map_flag_vs chk rivality + }//end map_flag_vs chk rivality else { //Non pvp/gvg, check party/guild settings. if( flag&BCT_PARTY || state&BCT_ENEMY ) diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp index e570b4b3c2..3c0cb27ba3 100644 --- a/src/map/chrif.cpp +++ b/src/map/chrif.cpp @@ -395,18 +395,15 @@ int chrif_connect(int fd) { // sends maps to char-server int chrif_sendmap(int fd) { - int i = 0, size = 4 + map.size() * 4; ShowStatus("Sending maps to char server...\n"); // Sending normal maps, not instances - WFIFOHEAD(fd, size); + WFIFOHEAD(fd, 4 + instance_start * 4); WFIFOW(fd,0) = 0x2afa; - WFIFOW(fd,2) = size; - for( auto& pair : map ){ - WFIFOW(fd,4+i*4) = pair.second.index; - i++; - } - WFIFOSET(fd,size); + for (int i = 0; i < instance_start; i++) + WFIFOW(fd, 4 + i * 4) = map[i].index; + WFIFOW(fd, 2) = 4 + instance_start * 4; + WFIFOSET(fd, WFIFOW(fd, 2)); return 0; } diff --git a/src/map/clif.cpp b/src/map/clif.cpp index ad6b3155ca..35b6e48dee 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -6343,17 +6343,19 @@ void clif_map_property(struct block_list *bl, enum map_property property, enum s WBUFW(buf,2)=property; #if PACKETVER >= 20121010 - WBUFL(buf,4) = ((map_getmapflag(bl->m, MF_PVP)?1:0)<<0)| // PARTY - Show attack cursor on non-party members (PvP) - ((map_getmapflag(bl->m, MF_BATTLEGROUND) || map_flag_gvg2(bl->m)?1:0)<<1)|// GUILD - Show attack cursor on non-guild members (GvG) - ((map_getmapflag(bl->m, MF_BATTLEGROUND) || map_flag_gvg2(bl->m)?1:0)<<2)|// SIEGE - Show emblem over characters heads when in GvG (WoE castle) - ((map_getmapflag(bl->m, MF_NOMINEEFFECT) || !map_flag_gvg2(bl->m)?0:1)<<3)| // USE_SIMPLE_EFFECT - Automatically enable /mineffect - ((map_getmapflag(bl->m, MF_NOLOCKON) || map_flag_vs(bl->m)?1:0)<<4)| // DISABLE_LOCKON - Only allow attacks on other players with shift key or /ns active - ((map_getmapflag(bl->m, MF_PVP)?1:0)<<5)| // COUNT_PK - Show the PvP counter - ((map_getmapflag(bl->m, MF_PARTYLOCK)?1:0)<<6)| // NO_PARTY_FORMATION - Prevents party creation/modification (Might be used for instance dungeons) - ((map_getmapflag(bl->m, MF_BATTLEGROUND)?1:0)<<7)| // BATTLEFIELD - Unknown (Does something for battlegrounds areas) - ((map_getmapflag(bl->m, MF_NOCOSTUME)?1:0)<<8)| // DISABLE_COSTUMEITEM - Disable costume sprites - ((map_getmapflag(bl->m, MF_NOUSECART)?0:1)<<9)| // USECART - Allow opening cart inventory (Well force it to always allow it) - ((map_getmapflag(bl->m, MF_NOSUNMOONSTARMIRACLE)?0:1)<<10); // SUNMOONSTAR_MIRACLE - Blocks Star Gladiator's Miracle from activating + struct map_data *mapdata = map_getmapdata(bl->m); + + WBUFL(buf,4) = ((mapdata->flag[MF_PVP]?1:0)<<0)| // PARTY - Show attack cursor on non-party members (PvP) + ((mapdata->flag[MF_BATTLEGROUND] || mapdata_flag_gvg2(mapdata)?1:0)<<1)|// GUILD - Show attack cursor on non-guild members (GvG) + ((mapdata->flag[MF_BATTLEGROUND] || mapdata_flag_gvg2(mapdata)?1:0)<<2)|// SIEGE - Show emblem over characters heads when in GvG (WoE castle) + ((mapdata->flag[MF_NOMINEEFFECT] || !mapdata_flag_gvg2(mapdata)?0:1)<<3)| // USE_SIMPLE_EFFECT - Automatically enable /mineffect + ((mapdata->flag[MF_NOLOCKON] || mapdata_flag_vs(mapdata)?1:0)<<4)| // DISABLE_LOCKON - Only allow attacks on other players with shift key or /ns active + ((mapdata->flag[MF_PVP]?1:0)<<5)| // COUNT_PK - Show the PvP counter + ((mapdata->flag[MF_PARTYLOCK]?1:0)<<6)| // NO_PARTY_FORMATION - Prevents party creation/modification (Might be used for instance dungeons) + ((mapdata->flag[MF_BATTLEGROUND]?1:0)<<7)| // BATTLEFIELD - Unknown (Does something for battlegrounds areas) + ((mapdata->flag[MF_NOCOSTUME]?1:0)<<8)| // DISABLE_COSTUMEITEM - Disable costume sprites + ((mapdata->flag[MF_NOUSECART]?0:1)<<9)| // USECART - Allow opening cart inventory (Well force it to always allow it) + ((mapdata->flag[MF_NOSUNMOONSTARMIRACLE]?0:1)<<10); // SUNMOONSTAR_MIRACLE - Blocks Star Gladiator's Miracle from activating //(1<<11); // Unused bits. 1 - 10 is 0x1 length and 11 is 0x15 length. May be used for future settings. #endif @@ -10317,15 +10319,15 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) if(sd->status.guild_id) guild_send_memberinfoshort(sd,1); + struct map_data *mapdata = map_getmapdata(sd->bl.m); + if(battle_config.pc_invincible_time > 0) { - if(map_flag_gvg(sd->bl.m)) + if(mapdata_flag_gvg(mapdata)) pc_setinvincibletimer(sd,battle_config.pc_invincible_time<<1); else pc_setinvincibletimer(sd,battle_config.pc_invincible_time); } - 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 @@ -10349,9 +10351,9 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) if( sd->bg_id ) clif_bg_hp(sd); // BattleGround System - if(map_getmapflag(sd->bl.m, MF_PVP) && !pc_isinvisible(sd)) { + if(!pc_isinvisible(sd) && mapdata->flag[MF_PVP]) { if(!battle_config.pk_mode) { // remove pvp stuff for pk_mode [Valaris] - if (!map_getmapflag(sd->bl.m, MF_PVP_NOCALCRANK)) + if (!mapdata->flag[MF_PVP_NOCALCRANK]) sd->pvp_timer = add_timer(gettick()+200, pc_calc_pvprank_timer, sd->bl.id, 0); sd->pvp_rank = 0; sd->pvp_lastusers = 0; @@ -10362,9 +10364,9 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF); } else if(sd->duel_group) // set flag, if it's a duel [LuzZza] clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF); - else if (map_getmapflag(sd->bl.m, MF_GVG_DUNGEON)) + else if (mapdata->flag[MF_GVG_DUNGEON]) clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF); //TODO: Figure out the real packet to send here. - else if( map_flag_gvg(sd->bl.m) ) + else if( mapdata_flag_gvg(mapdata) ) clif_map_property(&sd->bl, MAPPROPERTY_AGITZONE, SELF); else clif_map_property(&sd->bl, MAPPROPERTY_NOTHING, SELF); @@ -10375,7 +10377,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) // pet if( sd->pd ) { - if( battle_config.pet_no_gvg && map_flag_gvg(sd->bl.m) ) { //Return the pet to egg. [Skotlex] + if( battle_config.pet_no_gvg && mapdata_flag_gvg(mapdata) ) { //Return the pet to egg. [Skotlex] clif_displaymessage(sd->fd, msg_txt(sd,666)); pet_menu(sd, 3); //Option 3 is return to egg. } else { @@ -10461,7 +10463,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) if(hom_is_active(sd->hd)) hom_init_timers(sd->hd); - if (night_flag && map_getmapflag(sd->bl.m, MF_NIGHTENABLED)) { + if (night_flag && mapdata->flag[MF_NIGHTENABLED]) { sd->state.night = 1; clif_status_load(&sd->bl, EFST_SKE, 1); } @@ -10518,11 +10520,13 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) } 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)))) + struct map_data *pmap = map_getmapdata(sd->state.pmap); + + if ((pmap != nullptr && (mapdata_flag_gvg(pmap) || pmap->flag[MF_BATTLEGROUND])) || (mapdata != nullptr && (mapdata_flag_gvg(mapdata) || mapdata->flag[MF_BATTLEGROUND]))) status_calc_bl(&sd->bl, SCB_FLEE); //Refresh flee penalty } - if( night_flag && map_getmapflag(sd->bl.m, MF_NIGHTENABLED) ) + if( night_flag && mapdata->flag[MF_NIGHTENABLED] ) { //Display night. if( !sd->state.night ) { @@ -10536,14 +10540,14 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) clif_status_load(&sd->bl, EFST_SKE, 0); } - if( map_getmapflag(sd->bl.m, MF_BATTLEGROUND) ) + if( mapdata->flag[MF_BATTLEGROUND] ) { clif_map_type(sd, MAPTYPE_BATTLEFIELD); // Battleground Mode if( map_getmapflag(sd->bl.m, MF_BATTLEGROUND) == 2 ) clif_bg_updatescore_single(sd); } - if( map_getmapflag(sd->bl.m, MF_ALLOWKS) && !map_flag_ks(sd->bl.m) ) + if( mapdata->flag[MF_ALLOWKS] && !mapdata_flag_ks(mapdata) ) { char output[128]; sprintf(output, "[ Kill Steal Protection Disable. KS is allowed in this map ]"); @@ -10563,7 +10567,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) if (!sd->state.connect_new && !sd->vip.disableshowrate && sd->state.pmap != sd->bl.m && - map_getmapflag(sd->state.pmap, MF_BEXP) != map_getmapflag(sd->bl.m, MF_BEXP) + map_getmapflag(sd->state.pmap, MF_BEXP) != mapdata->flag[MF_BEXP] ) { clif_display_pinfo(sd,ZC_PERSONAL_INFOMATION); @@ -10572,7 +10576,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) && !mapdata->instance_id ) + if( channel_config.map_tmpl.name[0] && (channel_config.map_tmpl.opt&CHAN_OPT_AUTOJOIN) && !mapdata->instance_id && !mapdata->flag[MF_NOMAPCHANNELAUTOJOIN] ) channel_mjoin(sd); //join new map clif_pk_mode_message(sd); @@ -10598,7 +10602,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) } // Don't trigger NPC event or opening vending/buyingstore will be failed - if(!sd->state.autotrade && map_getmapflag(sd->bl.m, MF_LOADEVENT)) // Lance + if(!sd->state.autotrade && mapdata->flag[MF_LOADEVENT]) // Lance npc_script_event(sd, NPCE_LOADMAP); if (pc_checkskill(sd, SG_DEVIL) && pc_is_maxjoblv(sd)) @@ -10607,7 +10611,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) if (sd->sc.opt2) //Client loses these on warp. clif_changeoption(&sd->bl); - if ((sd->sc.data[SC_MONSTER_TRANSFORM] || sd->sc.data[SC_ACTIVE_MONSTER_TRANSFORM]) && battle_config.mon_trans_disable_in_gvg && map_flag_gvg2(sd->bl.m)) { + if ((sd->sc.data[SC_MONSTER_TRANSFORM] || sd->sc.data[SC_ACTIVE_MONSTER_TRANSFORM]) && battle_config.mon_trans_disable_in_gvg && mapdata_flag_gvg2(mapdata)) { status_change_end(&sd->bl, SC_MONSTER_TRANSFORM, INVALID_TIMER); status_change_end(&sd->bl, SC_ACTIVE_MONSTER_TRANSFORM, INVALID_TIMER); clif_displaymessage(sd->fd, msg_txt(sd,731)); // Transforming into monster is not allowed in Guild Wars. diff --git a/src/map/instance.cpp b/src/map/instance.cpp index 86131bd1b4..9f83e74e59 100644 --- a/src/map/instance.cpp +++ b/src/map/instance.cpp @@ -28,6 +28,8 @@ struct instance_data instance_data[MAX_INSTANCE_DATA]; struct eri *instance_maps_ers = NULL; ///< Array of maps per instance +int16 instance_start = 0; + static DBMap *InstanceDB; /// Instance DB: struct instance_db, key: id static DBMap *InstanceNameDB; /// instance id, key: name @@ -1137,6 +1139,7 @@ void do_init_instance(void) { InstanceDB = uidb_alloc(DB_OPT_BASE); InstanceNameDB = strdb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA),0); + instance_start = map_num; instance_readdb(); memset(instance_data, 0, sizeof(instance_data)); memset(&instance_wait, 0, sizeof(instance_wait)); diff --git a/src/map/instance.hpp b/src/map/instance.hpp index c299091ac6..8988b5faaa 100644 --- a/src/map/instance.hpp +++ b/src/map/instance.hpp @@ -13,6 +13,8 @@ enum send_target : uint8; struct block_list; +extern int16 instance_start; + #define MAX_INSTANCE_DATA 300 // Essentially how many instances we can create, but instance creation is primarily decided by MAX_MAP_PER_SERVER #define MAX_MAP_PER_INSTANCE 255 // Max number of maps per instance (Enter map is counted as one) - Supports up to 255 maps diff --git a/src/map/intif.cpp b/src/map/intif.cpp index f1871a2559..75c7fc20ef 100644 --- a/src/map/intif.cpp +++ b/src/map/intif.cpp @@ -690,9 +690,14 @@ int intif_party_changemap(struct map_session_data *sd,int online) if(!sd) return 0; - if( (m=map_mapindex2mapid(sd->mapindex)) >= 0 && map_getmapdata(m)->instance_id ) - mapindex = map_getmapdata(map_getmapdata(m)->instance_src_map)->index; - else + if ((m = map_mapindex2mapid(sd->mapindex)) >= 0) { + struct map_data *mapdata = map_getmapdata(m); + + if (mapdata->instance_id) + mapindex = map_getmapdata(mapdata->instance_src_map)->index; + else + mapindex = sd->mapindex; + } else mapindex = sd->mapindex; WFIFOHEAD(inter_fd,19); diff --git a/src/map/itemdb.cpp b/src/map/itemdb.cpp index d791292b8f..1faa56422b 100644 --- a/src/map/itemdb.cpp +++ b/src/map/itemdb.cpp @@ -1581,12 +1581,15 @@ static int itemdb_read_sqldb(void) { bool itemdb_isNoEquip(struct item_data *id, uint16 m) { if (!id->flag.no_equip) return false; - if ((!map_flag_vs2(m) && id->flag.no_equip&1) || // Normal - (map_getmapflag(m, MF_PVP) && id->flag.no_equip&2) || // PVP - (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_getmapdata(m)->zone)) // Zone restriction + + struct map_data *mapdata = map_getmapdata(m); + + if ((id->flag.no_equip&1 && !mapdata_flag_vs2(mapdata)) || // Normal + (id->flag.no_equip&2 && mapdata->flag[MF_PVP]) || // PVP + (id->flag.no_equip&4 && mapdata_flag_gvg2_no_te(mapdata)) || // GVG + (id->flag.no_equip&8 && mapdata->flag[MF_BATTLEGROUND]) || // Battleground + (id->flag.no_equip&16 && mapdata_flag_gvg2_te(mapdata)) || // WOE:TE + (id->flag.no_equip&(8*mapdata->zone) && mapdata->flag[MF_RESTRICTED]) // Zone restriction ) return true; return false; diff --git a/src/map/map.cpp b/src/map/map.cpp index 8c554b1212..a2c13d19d8 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::map map; +struct map_data map[MAX_MAP_PER_SERVER]; +int map_num = 0; int map_port=0; @@ -188,7 +189,10 @@ int enable_grf = 0; //To enable/disable reading maps from GRF files, bypassing m */ struct map_data *map_getmapdata(int16 mapid) { - return util::map_find(map, mapid); + if (mapid < 0 || mapid >= MAX_MAP_PER_SERVER) + return nullptr; + + return &map[mapid]; } /*========================================== @@ -313,7 +317,6 @@ int map_addblock(struct block_list* bl) { int16 m, x, y; int pos; - struct map_data *mapdata; nullpo_ret(bl); @@ -328,11 +331,11 @@ int map_addblock(struct block_list* bl) if( m < 0 ) { - ShowError("map_addblock: invalid map id (%d), only %d are loaded.\n", m, map.size()); + ShowError("map_addblock: invalid map id (%d), only %d are loaded.\n", m, map_num); return 1; } - mapdata = map_getmapdata(m); + struct map_data *mapdata = map_getmapdata(m); if( x < 0 || x >= mapdata->xs || y < 0 || y >= mapdata->ys ) { @@ -581,9 +584,7 @@ struct skill_unit* map_find_skill_unit_oncell(struct block_list* target,int16 x, int16 bx,by; struct block_list *bl; struct skill_unit *unit; - struct map_data *mapdata; - - mapdata = map_getmapdata(target->m); + struct map_data *mapdata = map_getmapdata(target->m); if (x < 0 || y < 0 || (x >= mapdata->xs) || (y >= mapdata->ys)) return NULL; @@ -615,14 +616,14 @@ 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); + struct map_data *mapdata = map_getmapdata(m); + x0 = i16max(center->x - range, 0); y0 = i16max(center->y - range, 0); x1 = i16min(center->x + range, mapdata->xs - 1); @@ -730,7 +731,6 @@ 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) @@ -741,7 +741,8 @@ int map_foreachinareaV(int(*func)(struct block_list*, va_list), int16 m, int16 x if (y1 < y0) SWAP(y0, y1); - mapdata = map_getmapdata(m); + struct map_data *mapdata = map_getmapdata(m); + x0 = i16max(x0, 0); y0 = i16max(y0, 0); x1 = i16min(x1, mapdata->xs - 1); @@ -900,7 +901,6 @@ 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 ) @@ -911,7 +911,8 @@ int map_forcountinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x if ( y1 < y0 ) SWAP(y0, y1); - mapdata = map_getmapdata(m); + struct map_data *mapdata = map_getmapdata(m); + x0 = i16max(x0, 0); y0 = i16max(y0, 0); x1 = i16min(x1, mapdata->xs - 1); @@ -962,14 +963,15 @@ 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); + + struct map_data *mapdata = map_getmapdata(m); + x0 = center->x - range; x1 = center->x + range; y0 = center->y - range; @@ -1168,7 +1170,6 @@ 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. @@ -1210,7 +1211,8 @@ 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); + struct map_data *mapdata = map_getmapdata(m); + mx0 = max(mx0, 0); my0 = max(my0, 0); mx1 = min(mx1, mapdata->xs - 1); @@ -1329,7 +1331,6 @@ 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) @@ -1350,7 +1351,8 @@ int map_foreachindir(int(*func)(struct block_list*, va_list), int16 m, int16 x0, length++; } - mapdata = map_getmapdata(m); + struct map_data *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)); @@ -2620,11 +2622,26 @@ int map_addinstancemap(const char *name, unsigned short instance_id) return -2; } - // Copy the map - int16 dst_m = static_cast(map.size()); + int16 dst_m = -1, i; + + for (i = instance_start; i < MAX_MAP_PER_SERVER; i++) { + if (!map[i].name[0]) + break; + } + if (i < map_num) // Destination map value overwrites another + dst_m = i; + else if (i < MAX_MAP_PER_SERVER) // Destination map value increments to new map + dst_m = map_num++; + else { + // Out of bounds + ShowError("map_addinstancemap failed. map_num(%d) > map_max(%d)\n", map_num, MAX_MAP_PER_SERVER); + return -3; + } + struct map_data *src_map = map_getmapdata(src_m); - map.insert({ dst_m, *src_map }); + // Copy the map + memcpy(&map[dst_m], src_map, sizeof(struct map_data)); // Retrieve new map data struct map_data *dst_map = map_getmapdata(dst_m); @@ -2747,7 +2764,6 @@ int map_delinstancemap(int m) mapindex_removemap( mapdata->index ); map_removemapdb(mapdata); - map.erase(m); return 1; } @@ -3268,10 +3284,8 @@ 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); - mapdata->iwall_num++; + map_getmapdata(m)->iwall_num++; return true; } @@ -3281,9 +3295,8 @@ 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( mapdata->iwall_num < 1 ) + if( map_getmapdata(sd->bl.m)->iwall_num < 1 ) return; iter = db_iterator(iwall_db); @@ -3480,35 +3493,41 @@ int map_addmap(char* mapname) { if( strcmpi(mapname,"clear")==0 ) { - map.clear(); + map_num = 0; + instance_start = 0; return 0; } - struct map_data entry = {}; + if (map_num >= MAX_MAP_PER_SERVER - 1) { + ShowError("Could not add map '" CL_WHITE "%s" CL_RESET "', the limit of maps has been reached.\n", mapname); + return 1; + } - mapindex_getmapname(mapname, entry.name); - map.insert({ static_cast(map.size()), entry }); + mapindex_getmapname(mapname, map[map_num].name); + map_num++; return 0; } static void map_delmapid(int id) { - ShowNotice("Removing map [ %s ] from maplist" CL_CLL "\n",map_getmapdata(id)->name); - map.erase(id); + ShowNotice("Removing map [ %s ] from maplist" CL_CLL "\n",map[id].name); + for (int i = id; i < map_num - 1; i++) + map[i] = map[i + 1]; + map_num--; } int map_delmap(char* mapname){ char map_name[MAP_NAME_LENGTH]; if (strcmpi(mapname, "all") == 0) { - map.clear(); + map_num = 0; return 0; } mapindex_getmapname(mapname, map_name); - for( auto& pair : map ){ - if (strcmp(pair.second.name, map_name) == 0) { - map_delmapid(pair.first); + for (int i = 0; i < map_num; i++) { + if (strcmp(map[i].name, map_name) == 0) { + map_delmapid(i); return 1; } } @@ -3518,26 +3537,26 @@ int map_delmap(char* mapname){ /// Initializes map flags and adjusts them depending on configuration. void map_flags_init(void){ - for( auto& pair : map ){ - struct map_data *mapdata = &pair.second; + for (int i = 0; i < map_num; i++) { + struct map_data *mapdata = &map[i]; union u_mapflag_args args = {}; args.flag_val = 100; // additional mapflag data 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 + mapdata->flag[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 // skill damage mapdata->damage_adjust = {}; // adjustments - if( battle_config.pk_mode ) - map_setmapflag(pair.first, MF_PVP, true); // make all maps pvp for pk_mode [Valaris] + if( battle_config.pk_mode && !mapdata->flag[MF_PVP] ) + mapdata->flag[MF_PVP] = true; // make all maps pvp for pk_mode [Valaris] - map_free_questinfo(pair.first); + map_free_questinfo(i); } } @@ -3674,17 +3693,16 @@ int map_readallmaps (void) } } - int i = 0; - std::vector maps_removed; + int maps_removed = 0; - for( auto &pair : map ){ + for (int i = 0; i < map_num; i++) { size_t size; bool success = false; unsigned short idx = 0; - struct map_data *mapdata = &pair.second; + struct map_data *mapdata = &map[i]; // show progress - ShowStatus("Loading maps [%i/%i]: %s" CL_CLL "\r", i++, map.size(), mapdata->name); + ShowStatus("Loading maps [%i/%i]: %s" CL_CLL "\r", i, map_num, mapdata->name); if( enable_grf ){ // try to load the map @@ -3703,23 +3721,30 @@ int map_readallmaps (void) } // The map was not found - remove it - if( !(idx = mapindex_name2id(mapdata->name)) || !success ){ - maps_removed.push_back(pair.first); + if (!(idx = mapindex_name2id(mapdata->name)) || !success) { + map_delmapid(i); + maps_removed++; + i--; continue; } mapdata->index = idx; - if (uidb_get(map_db,(unsigned int)mapdata->index) != NULL) - { + if (uidb_get(map_db,(unsigned int)mapdata->index) != NULL) { ShowWarning("Map %s already loaded!" CL_CLL "\n", mapdata->name); - maps_removed.push_back(pair.first); + if (mapdata->cell) { + aFree(mapdata->cell); + mapdata->cell = NULL; + } + map_delmapid(i); + maps_removed++; + i--; continue; } map_addmap2db(mapdata); - mapdata->m = pair.first; + mapdata->m = i; memset(mapdata->moblist, 0, sizeof(mapdata->moblist)); //Initialize moblist [Skotlex] mapdata->mob_delete_timer = INVALID_TIMER; //Initialize timer [Skotlex] @@ -3742,16 +3767,11 @@ 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()); - } + if (maps_removed) + ShowNotice("Maps removed: '" CL_WHITE "%d" CL_RESET "'\n", maps_removed); // finished map loading - ShowInfo("Successfully loaded '" CL_WHITE "%d" CL_RESET "' maps." CL_CLL "\n",map.size()); + ShowInfo("Successfully loaded '" CL_WHITE "%d" CL_RESET "' maps." CL_CLL "\n",map_num); return 0; } @@ -4457,7 +4477,7 @@ int map_getmapflag_sub(int16 m, enum e_mapflag mapflag, union u_mapflag_args *ar return -1; } - struct map_data *mapdata = map_getmapdata(m); + struct map_data *mapdata = &map[m]; if (mapflag < MF_MIN || mapflag >= MF_MAX) { ShowWarning("map_getmapflag: Invalid mapflag %d on map %s.\n", mapflag, mapdata->name); @@ -4465,12 +4485,14 @@ int map_getmapflag_sub(int16 m, enum e_mapflag mapflag, union u_mapflag_args *ar } switch(mapflag) { + case MF_RESTRICTED: + return mapdata->zone; case MF_NOLOOT: - return util::map_get(mapdata->flag, MF_NOMOBLOOT, 0) && util::map_get(mapdata->flag, MF_NOMVPLOOT, 0); + return util::umap_get(mapdata->flag, static_cast(MF_NOMOBLOOT), 0) && util::umap_get(mapdata->flag, static_cast(MF_NOMVPLOOT), 0); case MF_NOPENALTY: - return util::map_get(mapdata->flag, MF_NOEXPPENALTY, 0) && util::map_get(mapdata->flag, MF_NOZENYPENALTY, 0); + return util::umap_get(mapdata->flag, static_cast(MF_NOEXPPENALTY), 0) && util::umap_get(mapdata->flag, static_cast(MF_NOZENYPENALTY), 0); case MF_NOEXP: - return util::map_get(mapdata->flag, MF_NOBASEEXP, 0) && util::map_get(mapdata->flag, MF_NOJOBEXP, 0); + return util::umap_get(mapdata->flag, static_cast(MF_NOBASEEXP), 0) && util::umap_get(mapdata->flag, static_cast(MF_NOJOBEXP), 0); case MF_SKILL_DAMAGE: nullpo_retr(-1, args); @@ -4483,10 +4505,10 @@ int map_getmapflag_sub(int16 m, enum e_mapflag mapflag, union u_mapflag_args *ar case SKILLDMG_CASTER: return mapdata->damage_adjust.caster; default: - return util::map_get(mapdata->flag, mapflag, 0); + return util::umap_get(mapdata->flag, static_cast(mapflag), 0); } default: - return util::map_get(mapdata->flag, mapflag, 0); + return util::umap_get(mapdata->flag, static_cast(mapflag), 0); } } @@ -4505,7 +4527,7 @@ bool map_setmapflag_sub(int16 m, enum e_mapflag mapflag, bool status, union u_ma return false; } - struct map_data *mapdata = map_getmapdata(m); + struct map_data *mapdata = &map[m]; if (mapflag < MF_MIN || mapflag >= MF_MAX) { ShowWarning("map_setmapflag: Invalid mapflag %d on map %s.\n", mapflag, mapdata->name); @@ -4529,28 +4551,28 @@ bool map_setmapflag_sub(int16 m, enum e_mapflag mapflag, bool status, union u_ma else { if (!battle_config.pk_mode) map_foreachinmap(map_mapflag_pvp_sub, m, BL_PC); - if (map_getmapflag(m, MF_GVG)) { - map_setmapflag(m, MF_GVG, false); + if (mapdata->flag[MF_GVG]) { + mapdata->flag[MF_GVG] = false; 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); + if (mapdata->flag[MF_GVG_TE]) { + mapdata->flag[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", mapdata->name); } - if (map_getmapflag(m, MF_GVG_DUNGEON)) { - map_setmapflag(m, MF_GVG_DUNGEON, false); + if (mapdata->flag[MF_GVG_DUNGEON]) { + mapdata->flag[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", mapdata->name); } - if (map_getmapflag(m, MF_GVG_CASTLE)) { - map_setmapflag(m, MF_GVG_CASTLE, false); + if (mapdata->flag[MF_GVG_CASTLE]) { + mapdata->flag[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", mapdata->name); } - if (map_getmapflag(m, MF_GVG_TE_CASTLE)) { - map_setmapflag(m, MF_GVG_TE_CASTLE, false); + if (mapdata->flag[MF_GVG_TE_CASTLE]) { + mapdata->flag[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", mapdata->name); } - if (map_getmapflag(m, MF_BATTLEGROUND)) { - map_setmapflag(m, MF_BATTLEGROUND, false); + if (mapdata->flag[MF_BATTLEGROUND]) { + mapdata->flag[MF_BATTLEGROUND] = false; ShowWarning("map_setmapflag: Unable to set Battleground and PvP flags for the same map! Removing Battleground flag from %s.\n", mapdata->name); } } @@ -4562,12 +4584,13 @@ bool map_setmapflag_sub(int16 m, enum e_mapflag mapflag, bool status, union u_ma clif_map_property_mapall(m, MAPPROPERTY_NOTHING); else { 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", mapdata->name); + if (mapdata->flag[MF_PVP]) { + mapdata->flag[MF_PVP] = false; + if (!battle_config.pk_mode) + 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); + if (mapdata->flag[MF_BATTLEGROUND]) { + mapdata->flag[MF_BATTLEGROUND] = false; ShowWarning("map_setmapflag: Unable to set Battleground and GvG flags for the same map! Removing Battleground flag from %s.\n", mapdata->name); } } @@ -4576,37 +4599,39 @@ bool map_setmapflag_sub(int16 m, enum e_mapflag mapflag, bool status, union u_ma 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); + if (mapflag == MF_GVG_CASTLE && mapdata->flag[MF_GVG_TE_CASTLE]) { + mapdata->flag[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", mapdata->name); } - if (mapflag == MF_GVG_TE_CASTLE && map_getmapflag(m, MF_GVG_CASTLE)) { - map_setmapflag(m, MF_GVG_CASTLE, false); + if (mapflag == MF_GVG_TE_CASTLE && mapdata->flag[MF_GVG_CASTLE]) { + mapdata->flag[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", 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"), mapdata->name); + if (mapdata->flag[MF_PVP]) { + mapdata->flag[MF_PVP] = false; + if (!battle_config.pk_mode) + 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); } } 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", mapdata->name); + if (status && mapdata->flag[MF_PVP]) { + mapdata->flag[MF_PVP] = false; + if (!battle_config.pk_mode) + ShowWarning("map_setmapflag: Unable to set PvP and GvG Dungeon flags for the same map! Removing PvP flag from %s.\n", mapdata->name); } 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); + if (mapflag == MF_NOBASEEXP && mapdata->flag[MF_BEXP] != 100) { + mapdata->flag[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", mapdata->name); } - if (mapflag == MF_NOJOBEXP && map_getmapflag(m, MF_JEXP) != 100) { - map_setmapflag(m, MF_JEXP, false); + if (mapflag == MF_NOJOBEXP && mapdata->flag[MF_JEXP] != 100) { + mapdata->flag[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", mapdata->name); } } @@ -4652,12 +4677,12 @@ bool map_setmapflag_sub(int16 m, enum e_mapflag mapflag, bool status, union u_ma if (status) { nullpo_retr(false, args); - if (mapflag == MF_JEXP && map_getmapflag(m, MF_NOJOBEXP)) { - map_setmapflag(m, MF_NOJOBEXP, false); + if (mapflag == MF_JEXP && mapdata->flag[MF_NOJOBEXP]) { + mapdata->flag[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", mapdata->name); } - if (mapflag == MF_BEXP && map_getmapflag(m, MF_NOBASEEXP)) { - map_setmapflag(m, MF_NOBASEEXP, false); + if (mapflag == MF_BEXP && mapdata->flag[MF_NOBASEEXP]) { + mapdata->flag[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", mapdata->name); } mapdata->flag[mapflag] = args->flag_val; @@ -4668,20 +4693,20 @@ bool map_setmapflag_sub(int16 m, enum e_mapflag mapflag, bool status, union u_ma if (status) { nullpo_retr(false, args); - if (map_getmapflag(m, MF_PVP)) { - map_setmapflag(m, MF_PVP, false); + if (mapdata->flag[MF_PVP]) { + mapdata->flag[MF_PVP] = false; 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); + if (mapdata->flag[MF_GVG]) { + mapdata->flag[MF_GVG] = false; 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); + if (mapdata->flag[MF_GVG_DUNGEON]) { + mapdata->flag[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", mapdata->name); } - if (map_getmapflag(m, MF_GVG_CASTLE)) { - map_setmapflag(m, MF_GVG_CASTLE, false); + if (mapdata->flag[MF_GVG_CASTLE]) { + mapdata->flag[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", mapdata->name); } mapdata->flag[mapflag] = ((args->flag_val <= 0 || args->flag_val > 2) ? 1 : args->flag_val); @@ -4756,13 +4781,14 @@ void do_final(void){ do_clear_npc(); // remove all objects on maps - 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); + for (int i = 0; i < map_num; i++) { + struct map_data *mapdata = map_getmapdata(i); + + ShowStatus("Cleaning up maps [%d/%d]: %s..." CL_CLL "\r", i++, map_num, mapdata->name); + map_foreachinmap(cleanup_sub, i, BL_ALL); + channel_delete(mapdata->channel,false); } - ShowStatus("Cleaned up %d maps." CL_CLL "\n", map.size()); + ShowStatus("Cleaned up %d maps." CL_CLL "\n", map_num); id_db->foreach(id_db,cleanup_db_sub); chrif_char_reset_offline(); @@ -4802,8 +4828,8 @@ void do_final(void){ map_db->destroy(map_db, map_db_final); - for( auto& pair : map ){ - struct map_data *mapdata = &pair.second; + for (int i = 0; i < map_num; i++) { + struct map_data *mapdata = map_getmapdata(i); if(mapdata->cell) aFree(mapdata->cell); if(mapdata->block) aFree(mapdata->block); @@ -4814,7 +4840,7 @@ void do_final(void){ for (int j=0; jmoblist[j]) aFree(mapdata->moblist[j]); } - map_free_questinfo(pair.first); + map_free_questinfo(i); mapdata->damage_adjust = {}; } diff --git a/src/map/map.hpp b/src/map/map.hpp index 3248b82a7b..e570dc21f0 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -5,8 +5,8 @@ #define _MAP_HPP_ #include -#include #include +#include #include #include "../common/cbasetypes.hpp" @@ -231,22 +231,6 @@ enum e_mapid { #define DEFAULT_AUTOSAVE_INTERVAL 5*60*1000 -/// Specifies maps where players may hit each other -#define map_flag_vs(m) (map_getmapflag(m, MF_PVP) || map_getmapflag(m, MF_GVG_DUNGEON) ||map_getmapflag(m, MF_GVG) || ((agit_flag || agit2_flag) && map_getmapflag(m, MF_GVG_CASTLE)) || map_getmapflag(m, MF_GVG_TE) || (agit3_flag && map_getmapflag(m, MF_GVG_TE_CASTLE)) || map_getmapflag(m, MF_BATTLEGROUND)) -/// Versus map: PVP, BG, GVG, GVG Dungeons, and GVG Castles (regardless of agit_flag status) -#define map_flag_vs2(m) (map_getmapflag(m, MF_PVP) || map_getmapflag(m, MF_GVG_DUNGEON) || map_getmapflag(m, MF_GVG) || map_getmapflag(m, MF_GVG_CASTLE) || map_getmapflag(m, MF_GVG_TE) || map_getmapflag(m, MF_GVG_TE_CASTLE) || map_getmapflag(m, MF_BATTLEGROUND)) -/// Specifies maps that have special GvG/WoE restrictions -#define map_flag_gvg(m) (map_getmapflag(m, MF_GVG) || ((agit_flag || agit2_flag) && map_getmapflag(m, MF_GVG_CASTLE)) || map_getmapflag(m, MF_GVG_TE) || (agit3_flag && map_getmapflag(m, MF_GVG_TE_CASTLE))) -/// Specifies if the map is tagged as GvG/WoE (regardless of agit_flag status) -#define map_flag_gvg2(m) (map_getmapflag(m, MF_GVG) || map_getmapflag(m, MF_GVG_TE) || map_getmapflag(m, MF_GVG_CASTLE) || map_getmapflag(m, MF_GVG_TE_CASTLE)) -/// No Kill Steal Protection -#define map_flag_ks(m) (map_getmapflag(m, MF_TOWN) || map_getmapflag(m, MF_PVP) || map_getmapflag(m, MF_GVG) || map_getmapflag(m, MF_GVG_TE) || map_getmapflag(m, MF_BATTLEGROUND)) - -/// WOE:TE Maps (regardless of agit_flag status) [Cydh] -#define map_flag_gvg2_te(m) (map_getmapflag(m, MF_GVG_TE) || map_getmapflag(m, MF_GVG_TE_CASTLE)) -/// Check if map is GVG maps exclusion for item, skill, and status restriction check (regardless of agit_flag status) [Cydh] -#define map_flag_gvg2_no_te(m) (map_getmapflag(m, MF_GVG) || map_getmapflag(m, MF_GVG_CASTLE)) - //This stackable implementation does not means a BL can be more than one type at a time, but it's //meant to make it easier to check for multiple types at a time on invocations such as map_foreach* calls [Skotlex] enum bl_type : uint16{ @@ -735,7 +719,7 @@ struct map_data { int users_pvp; int iwall_num; // Total of invisible walls in this map - std::map flag; + std::unordered_map flag; struct point save; std::vector drop_list; uint32 zone; // zone number (for item/skill restrictions) @@ -776,7 +760,8 @@ 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::map map; +extern struct map_data map[]; +extern int map_num; extern int autosave_interval; extern int minsave_interval; @@ -790,6 +775,177 @@ extern bool agit2_flag; extern bool agit3_flag; #define is_agit_start() (agit_flag || agit2_flag || agit3_flag) +/** + * Specifies maps where players may hit each other + * @param mapdata: Map Data + * @return True on success or false otherwise + */ +inline bool mapdata_flag_vs(struct map_data *mapdata) { + if (mapdata == nullptr) + return false; + + if (mapdata->flag[MF_PVP] || mapdata->flag[MF_GVG_DUNGEON] || mapdata->flag[MF_GVG] || ((agit_flag || agit2_flag) && mapdata->flag[MF_GVG_CASTLE]) || mapdata->flag[MF_GVG_TE] || (agit3_flag && mapdata->flag[MF_GVG_TE_CASTLE]) || mapdata->flag[MF_BATTLEGROUND]) + return true; + + return false; +} + +/** + * Versus map: PVP, BG, GVG, GVG Dungeons, and GVG Castles (regardless of agit_flag status) + * @param mapdata: Map Data + * @return True on success or false otherwise + */ +inline bool mapdata_flag_vs2(struct map_data *mapdata) { + if (mapdata == nullptr) + return false; + + if (mapdata->flag[MF_PVP] || mapdata->flag[MF_GVG_DUNGEON] || mapdata->flag[MF_GVG] || mapdata->flag[MF_GVG_CASTLE] || mapdata->flag[MF_GVG_TE] || mapdata->flag[MF_GVG_TE_CASTLE] || mapdata->flag[MF_BATTLEGROUND]) + return true; + + return false; +} + +/** + * Specifies maps that have special GvG/WoE restrictions + * @param mapdata: Map Data + * @return True on success or false otherwise + */ +inline bool mapdata_flag_gvg(struct map_data *mapdata) { + if (mapdata == nullptr) + return false; + + if (mapdata->flag[MF_GVG] || ((agit_flag || agit2_flag) && mapdata->flag[MF_GVG_CASTLE]) || mapdata->flag[MF_GVG_TE] || (agit3_flag && mapdata->flag[MF_GVG_TE_CASTLE])) + return true; + + return false; +} + +/** + * Specifies if the map is tagged as GvG/WoE (regardless of agit_flag status) + * @param mapdata: Map Data + * @return True on success or false otherwise + */ +inline bool mapdata_flag_gvg2(struct map_data *mapdata) { + if (mapdata == nullptr) + return false; + + if (mapdata->flag[MF_GVG] || mapdata->flag[MF_GVG_TE] || mapdata->flag[MF_GVG_CASTLE] || mapdata->flag[MF_GVG_TE_CASTLE]) + return true; + + return false; +} + +/** + * No Kill Steal Protection + * @param mapdata: Map Data + * @return True on success or false otherwise + */ +inline bool mapdata_flag_ks(struct map_data *mapdata) { + if (mapdata == nullptr) + return false; + + if (mapdata->flag[MF_TOWN] || mapdata->flag[MF_PVP] || mapdata->flag[MF_GVG] || mapdata->flag[MF_GVG_TE] || mapdata->flag[MF_BATTLEGROUND]) + return true; + + return false; +} + +/** + * WOE:TE Maps (regardless of agit_flag status) + * @param mapdata: Map Data + * @return True on success or false otherwise + * @author Cydh + */ +inline bool mapdata_flag_gvg2_te(struct map_data *mapdata) { + if (mapdata == nullptr) + return false; + + if (mapdata->flag[MF_GVG_TE] || mapdata->flag[MF_GVG_TE_CASTLE]) + return true; + + return false; +} + +/** + * Check if map is GVG maps exclusion for item, skill, and status restriction check (regardless of agit_flag status) + * @param mapdata: Map Data + * @return True on success or false otherwise + * @author Cydh + */ +inline bool mapdata_flag_gvg2_no_te(struct map_data *mapdata) { + if (mapdata == nullptr) + return false; + + if (mapdata->flag[MF_GVG] || mapdata->flag[MF_GVG_CASTLE]) + return true; + + return false; +} + +/// Backwards compatibility +inline bool map_flag_vs(int16 m) { + if (m < 0) + return false; + + struct map_data *mapdata = &map[m]; + + return mapdata_flag_vs(mapdata); +} + +inline bool map_flag_vs2(int16 m) { + if (m < 0) + return false; + + struct map_data *mapdata = &map[m]; + + return mapdata_flag_vs2(mapdata); +} + +inline bool map_flag_gvg(int16 m) { + if (m < 0) + return false; + + struct map_data *mapdata = &map[m]; + + return mapdata_flag_gvg(mapdata); +} + +inline bool map_flag_gvg2(int16 m) { + if (m < 0) + return false; + + struct map_data *mapdata = &map[m]; + + return mapdata_flag_gvg2(mapdata); +} + +inline bool map_flag_ks(int16 m) { + if (m < 0) + return false; + + struct map_data *mapdata = &map[m]; + + return mapdata_flag_ks(mapdata); +} + +inline bool map_flag_gvg2_te(int16 m) { + if (m < 0) + return false; + + struct map_data *mapdata = &map[m]; + + return mapdata_flag_gvg2_te(mapdata); +} + +inline bool map_flag_gvg2_no_te(int16 m) { + if (m < 0) + return false; + + struct map_data *mapdata = &map[m]; + + return mapdata_flag_gvg2_no_te(mapdata); +} + extern char motd_txt[]; extern char help_txt[]; extern char help2_txt[]; diff --git a/src/map/mob.cpp b/src/map/mob.cpp index c0fc4cfe5f..586300682e 100644 --- a/src/map/mob.cpp +++ b/src/map/mob.cpp @@ -568,9 +568,10 @@ bool mob_ksprotected (struct block_list *src, struct block_list *target) do { struct status_change_entry *sce; struct map_session_data *pl_sd; // Owner + struct map_data *mapdata = map_getmapdata(md->bl.m); char output[128]; - if( map_getmapflag(md->bl.m, MF_ALLOWKS) || map_flag_ks(md->bl.m) ) + if( mapdata->flag[MF_ALLOWKS] || mapdata_flag_ks(mapdata) ) return false; // Ignores GVG, PVP and AllowKS map flags if( md->db->mexp || md->master_id ) @@ -839,8 +840,6 @@ int mob_spawn_guardian(const char* mapname, int16 x, int16 y, const char* mobnam return 0; } - struct map_data *mapdata = map_getmapdata(m); - data.m = m; data.num = 1; if(mob_id<=0) { @@ -856,13 +855,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, mapdata->name); + ShowError("mob_spawn_guardian: Invalid guardian index %d for guardian %d (castle map %s)\n", guardian, mob_id, mapname); 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, mapdata->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, mapname); return 0; } data.x = x; @@ -872,14 +871,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(mapdata->name); + gc=guild_mapname2gc(mapname); if (gc == NULL) { - ShowError("mob_spawn_guardian: No castle set at map %s\n", mapdata->name); + ShowError("mob_spawn_guardian: No castle set at map %s\n", mapname); 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, mapdata->name); + ShowWarning("mob_spawn_guardian: Spawning guardian %d on a castle with no guild (castle map %s)\n", mob_id, mapname); else g = guild_search(gc->guild_id); @@ -889,7 +888,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, mapdata->name); + ShowError("mob_spawn_guardian: Attempted to spawn guardian in position %d which already has a guardian (castle map %s)\n", guardian, mapname); return 0; } } @@ -953,7 +952,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_getmapdata(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, mapname); return 0; } diff --git a/src/map/npc.cpp b/src/map/npc.cpp index 6a6d457f39..6b904c0765 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -1424,10 +1424,9 @@ 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, mapdata->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, map_mapid2mapname(nd->bl.m), nd->bl.x, nd->bl.y); return ERROR_TYPE_PURCHASE_FAIL; } if (cost[0] < (price - points)) { @@ -1440,7 +1439,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, mapdata->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, map_mapid2mapname(nd->bl.m), nd->bl.x, nd->bl.y); return ERROR_TYPE_PURCHASE_FAIL; } } @@ -1680,7 +1679,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_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); + nd->exname, map_mapid2mapname(nd->bl.m), 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; } @@ -3296,7 +3295,7 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) { 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_getmapdata(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_mapid2mapname(dm), snd->exname); return 1; } @@ -4058,7 +4057,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_getmapdata(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_mapid2mapname(m), filepath, strline(buffer,start-buffer)); } else map_setmapflag(m, MF_RESTRICTED, false); break; @@ -4456,9 +4455,9 @@ int npc_reload(void) { // dynamic check by [random] if( battle_config.dynamic_mobs ){ - for( auto& pair : map ){ + for (int i = 0; i < map_num; i++) { for( int16 i = 0; i < MAX_MOB_LIST_PER_MAP; i++ ){ - struct map_data *mapdata = &pair.second; + struct map_data *mapdata = map_getmapdata(i); if (mapdata->moblist[i] != NULL) { aFree(mapdata->moblist[i]); @@ -4601,9 +4600,11 @@ static void npc_debug_warps_sub(struct npc_data* nd) } 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] ); + for (int i = 0; i < map_num; i++) { + struct map_data *mapdata = map_getmapdata(i); + + for( int i = 0; i < mapdata->npc_num; i++ ){ + npc_debug_warps_sub(mapdata->npc[i]); } } } diff --git a/src/map/pc.cpp b/src/map/pc.cpp index 9e406290f9..14ad45065b 100755 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -7973,9 +7973,10 @@ 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_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; + struct map_data *mapdata = map_getmapdata(sd->bl.m); + int id = mapdata->drop_list[j].drop_id; + int per = mapdata->drop_list[j].drop_per; + enum e_nightmare_drop_type type = mapdata->drop_list[j].drop_type; if(id == 0) continue; @@ -12489,12 +12490,12 @@ bool pc_job_can_entermap(enum e_job jobid, int m, int group_lv) { if (!job_info[idx].noenter_map.zone || group_lv > job_info[idx].noenter_map.group_lv) return true; - if ((!map_flag_vs2(m) && job_info[idx].noenter_map.zone&1) || // Normal - (map_getmapflag(m, MF_PVP) && job_info[idx].noenter_map.zone&2) || // PVP - (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*mapdata->zone)) // Zone restriction + if ((job_info[idx].noenter_map.zone&1 && !mapdata_flag_vs2(mapdata)) || // Normal + (job_info[idx].noenter_map.zone&2 && mapdata->flag[MF_PVP]) || // PVP + (job_info[idx].noenter_map.zone&4 && mapdata_flag_gvg2_no_te(mapdata)) || // GVG + (job_info[idx].noenter_map.zone&8 && mapdata->flag[MF_BATTLEGROUND]) || // Battleground + (job_info[idx].noenter_map.zone&16 && mapdata_flag_gvg2_te(mapdata)) || // WOE:TE + (job_info[idx].noenter_map.zone&(8*mapdata->zone) && mapdata->flag[MF_RESTRICTED]) // Zone restriction ) return false; diff --git a/src/map/script.cpp b/src/map/script.cpp index dd4339c5fa..d17b43ad8b 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -490,18 +490,16 @@ 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, mapdata->name, bl->x, bl->y); + ShowDebug("Source (NPC): %s at %s (%d,%d)\n", ((struct npc_data *)bl)->name, map_mapid2mapname(bl->m), 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), mapdata->name, bl->x, bl->y); + ShowDebug("Source (Non-NPC type %d): name %s at %s (%d,%d)\n", bl->type, status_get_name(bl), map_mapid2mapname(bl->m), 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; diff --git a/src/map/skill.cpp b/src/map/skill.cpp index 82adbed53b..168dbb148e 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -693,14 +693,16 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd) if( sd->skillitem == skill_id && !sd->skillitem_keep_requirement ) return false; + struct map_data *mapdata = map_getmapdata(m); + skill_nocast = skill_get_nocast(skill_id); // Check skill restrictions [Celest] - if( (!map_flag_vs2(m) && skill_nocast&1) || - (map_getmapflag(m, MF_PVP) && skill_nocast&2) || - (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_getmapdata(m)->zone && skill_nocast&(8*map_getmapdata(m)->zone)) ){ + if( (skill_nocast&1 && !mapdata_flag_vs2(mapdata)) || + (skill_nocast&2 && mapdata->flag[MF_PVP]) || + (skill_nocast&4 && mapdata_flag_gvg2_no_te(mapdata)) || + (skill_nocast&8 && mapdata->flag[MF_BATTLEGROUND]) || + (skill_nocast&16 && mapdata_flag_gvg2_te(mapdata)) || // WOE:TE + (mapdata->zone && skill_nocast&(8*mapdata->zone) && mapdata->flag[MF_RESTRICTED]) ){ clif_msg(sd, SKILL_CANT_USE_AREA); // This skill cannot be used within this area return true; } @@ -713,7 +715,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd) case RETURN_TO_ELDICASTES: case ALL_GUARDIAN_RECALL: case ECLAGE_RECALL: - if(map_getmapflag(m, MF_NOWARP)) { + if(mapdata->flag[MF_NOWARP]) { clif_skill_teleportmessage(sd,0); return true; } @@ -723,7 +725,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd) case SC_DIMENSIONDOOR: case ALL_ODINS_RECALL: case WE_CALLALLFAMILY: - if(map_getmapflag(m, MF_NOTELEPORT)) { + if(mapdata->flag[MF_NOTELEPORT]) { clif_skill_teleportmessage(sd,0); return true; } @@ -731,7 +733,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd) case WE_CALLPARTNER: case WE_CALLPARENT: case WE_CALLBABY: - if (map_getmapflag(m, MF_NOMEMO)) { + if (mapdata->flag[MF_NOMEMO]) { clif_skill_teleportmessage(sd,1); return true; } @@ -760,13 +762,13 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd) return false; // always allowed case WZ_ICEWALL: // noicewall flag [Valaris] - if (map_getmapflag(m, MF_NOICEWALL)) { + if (mapdata->flag[MF_NOICEWALL]) { clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return true; } break; case GC_DARKILLUSION: - if( map_flag_gvg2(m) ) { + if( mapdata_flag_gvg2(mapdata) ) { clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return true; } @@ -775,8 +777,8 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd) case GD_ITEMEMERGENCYCALL: if ( !(battle_config.emergency_call&((is_agit_start())?2:1)) || - !(battle_config.emergency_call&(map_flag_gvg2(m)?8:4)) || - (battle_config.emergency_call&16 && map_getmapflag(m, MF_NOWARPTO) && !(map_getmapflag(m, MF_GVG_CASTLE) || map_getmapflag(m, MF_GVG_TE_CASTLE))) + !(battle_config.emergency_call&(mapdata_flag_gvg2(mapdata)?8:4)) || + (battle_config.emergency_call&16 && mapdata->flag[MF_NOWARPTO] && !(mapdata->flag[MF_GVG_CASTLE] || mapdata->flag[MF_GVG_TE_CASTLE])) ) { clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return true; @@ -786,7 +788,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd) case WM_SOUND_OF_DESTRUCTION: case WM_LULLABY_DEEPSLEEP: case WM_SATURDAY_NIGHT_FEVER: - if( !map_flag_vs(m) ) { + if( !mapdata_flag_vs(mapdata) ) { clif_skill_teleportmessage(sd,2); // This skill uses this msg instead of skill fails. return true; } @@ -9431,7 +9433,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui if (flag&1) sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)); else { - map_foreachinallrange(skill_area_sub,src,skill_get_splash(skill_id, skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,(map_flag_vs(src->m)?BCT_ALL:BCT_ENEMY|BCT_SELF)|flag|1,skill_castend_nodamage_id); + struct map_data *mapdata = map_getmapdata(src->m); + + map_foreachinallrange(skill_area_sub,src,skill_get_splash(skill_id, skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,(mapdata_flag_vs(mapdata)?BCT_ALL:BCT_ENEMY|BCT_SELF)|flag|1,skill_castend_nodamage_id); clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); } break; @@ -12734,8 +12738,7 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_ case GN_HELLS_PLANT: if( skill_id == GN_HELLS_PLANT && map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) ) return NULL; - if (map_flag_vs(src->m) && battle_config.vs_traps_bctall - && (src->type&battle_config.vs_traps_bctall)) + if (battle_config.vs_traps_bctall && (src->type&battle_config.vs_traps_bctall) && map_flag_vs(src->m)) target = BCT_ALL; break; case HT_SKIDTRAP: @@ -12770,7 +12773,7 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_ req_item = req.itemid[i]; if (skill_id == RL_B_TRAP) // Target type should not change on GvG maps. break; - if( battle_config.vs_traps_bctall && map_flag_vs(src->m) && (src->type&battle_config.vs_traps_bctall) ) + if( battle_config.vs_traps_bctall && (src->type&battle_config.vs_traps_bctall) && map_flag_vs(src->m) ) target = BCT_ALL; } break; @@ -13262,7 +13265,9 @@ static int skill_unit_onplace(struct skill_unit *unit, struct block_list *bl, un //Duration in PVP is: 1st - 4s, 2nd - 8s, 3rd - 12s int sec = skill_get_time2(sg->skill_id, sg->skill_lv); const struct TimerData* td; - if (map_flag_vs(bl->m)) + struct map_data *mapdata = map_getmapdata(bl->m); + + if (mapdata_flag_vs(mapdata)) sec /= 2; if (sc->data[type]) { if (sc->data[type]->val2 && sc->data[type]->val3 && sc->data[type]->val4) { @@ -13271,9 +13276,9 @@ static int skill_unit_onplace(struct skill_unit *unit, struct block_list *bl, un break; } //Don't increase val1 here, we need a higher val in status_change_start so it overwrites the old one - if (map_flag_vs(bl->m) && sc->data[type]->val1 < 3) + if (mapdata_flag_vs(mapdata) && sc->data[type]->val1 < 3) sec *= (sc->data[type]->val1 + 1); - else if(!map_flag_vs(bl->m) && sc->data[type]->val1 < 2) + else if(!mapdata_flag_vs(mapdata) && sc->data[type]->val1 < 2) sec *= (sc->data[type]->val1 + 1); //Add group id to status change if (sc->data[type]->val2 == 0) @@ -20792,11 +20797,13 @@ static bool skill_check_unit_movepos(uint8 check_flag, struct block_list *bl, sh nullpo_retr(false, bl); - if (check_flag&1 && map_getmapflag(bl->m, MF_BATTLEGROUND)) + struct map_data *mapdata = map_getmapdata(bl->m); + + if (check_flag&1 && mapdata->flag[MF_BATTLEGROUND]) return false; - if (check_flag&2 && map_flag_gvg(bl->m)) + if (check_flag&2 && mapdata_flag_gvg(mapdata)) return false; - if (check_flag&4 && map_flag_gvg2(bl->m)) + if (check_flag&4 && mapdata_flag_gvg2(mapdata)) return false; sc = status_get_sc(bl); diff --git a/src/map/status.cpp b/src/map/status.cpp index 148bf77400..68821018df 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_getmapdata(m)->zone << 3) != 0, map_flag_gvg2_te((m))) ) +#define status_change_isDisabledOnMap(type, m) ( status_change_isDisabledOnMap_((type), mapdata_flag_vs2((m)), m->flag[MF_PVP] != 0, mapdata_flag_gvg2_no_te((m)), m->flag[MF_BATTLEGROUND] != 0, (m->zone << 3) != 0, mapdata_flag_gvg2_te((m))) ) /** * Returns the status change associated with a skill. @@ -6279,9 +6279,11 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change static signed short status_calc_flee(struct block_list *bl, struct status_change *sc, int flee) { if( bl->type == BL_PC ) { - if( map_flag_gvg(bl->m) ) + struct map_data *mapdata = map_getmapdata(bl->m); + + if( mapdata_flag_gvg(mapdata) ) flee -= flee * battle_config.gvg_flee_penalty/100; - else if( map_getmapflag(bl->m, MF_BATTLEGROUND) ) + else if( mapdata->flag[MF_BATTLEGROUND] ) flee -= flee * battle_config.bg_flee_penalty/100; } @@ -8442,7 +8444,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty if( bl->type != BL_NPC && status_isdead(bl) && ( type != SC_NOCHAT && type != SC_JAILED ) ) // SC_NOCHAT and SC_JAILED should work even on dead characters return 0; - if (status_change_isDisabledOnMap(type, bl->m)) + if (status_change_isDisabledOnMap(type, map_getmapdata(bl->m))) return 0; // Uncomment to prevent status adding hp to gvg mob (like bloodylust=hp*3 etc... @@ -14365,13 +14367,14 @@ void status_change_clear_onChangeMap(struct block_list *bl, struct status_change nullpo_retv(bl); if (sc && sc->count) { + struct map_data *mapdata = map_getmapdata(bl->m); unsigned short i; - bool mapIsVS = map_flag_vs2(bl->m); - bool mapIsPVP = map_getmapflag(bl->m, MF_PVP) != 0; - 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_getmapdata(bl->m)->zone << 3; + bool mapIsVS = mapdata_flag_vs2(mapdata); + bool mapIsPVP = mapdata->flag[MF_PVP] != 0; + bool mapIsGVG = mapdata_flag_gvg2_no_te(mapdata); + bool mapIsBG = mapdata->flag[MF_BATTLEGROUND] != 0; + bool mapIsTE = mapdata_flag_gvg2_te(mapdata); + unsigned int mapZone = mapdata->zone << 3; for (i = 0; i < SC_MAX; i++) { if (!sc->data[i] || !SCDisabled[i])