Browse Source

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!
Aleos 6 years ago
parent
commit
48ae1a1e05

+ 2 - 0
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.
 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.
 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:
 The optional parameter 'type' is used in the 'skill_damage' mapflag:
  SKILLDMG_MAX: if mapflag is set (default)
  SKILLDMG_MAX: if mapflag is set (default)
  SKILLDMG_PC: damage against players
  SKILLDMG_PC: damage against players

+ 2 - 4
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).
 // 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).
 // 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 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
 		if (map_server[i].fd > 0
 		&& (ip == (uint32)-1 || map_server[i].ip == ip)
 		&& (ip == (uint32)-1 || map_server[i].ip == ip)
 		&& (port == (uint16)-1 || map_server[i].port == port))
 		&& (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)
 				if (map_server[i].map[j] == map)
 					return i;
 					return i;
 		}
 		}

+ 1 - 0
src/common/mmo.hpp

@@ -32,6 +32,7 @@
 	#define MAX_HOTKEYS 38
 	#define MAX_HOTKEYS 38
 #endif
 #endif
 
 
+#define MAX_MAP_PER_SERVER 1500 /// Maximum amount of maps available on a server
 #define MAX_INVENTORY 100 ///Maximum items in player inventory
 #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 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 */
 * Max value tested was 265 */

+ 32 - 0
src/common/utilities.hpp

@@ -7,6 +7,7 @@
 #include <memory>
 #include <memory>
 #include <string>
 #include <string>
 #include <map>
 #include <map>
+#include <unordered_map>
 
 
 #include "cbasetypes.hpp"
 #include "cbasetypes.hpp"
 
 
@@ -57,6 +58,37 @@ namespace rathena {
 			else
 			else
 				return defaultValue;
 				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 <typename K, typename V> V* umap_find(std::unordered_map<K, V>& 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 <typename K, typename V> V umap_get(std::unordered_map<K, V>& map, K key, V defaultValue) {
+			auto it = map.find(key);
+
+			if (it != map.end())
+				return it->second;
+			else
+				return defaultValue;
+		}
 	}
 	}
 }
 }
 
 

+ 9 - 7
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 );
 	suggestions.reserve( MAX_SUGGESTIONS );
 
 
 	// check for maps that contain string
 	// 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
 		// Prevent suggestion of instance mapnames
 		if( mapdata->instance_id != 0 ){
 		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
 		// Levenshtein > 4 is bad
 		const int LEVENSHTEIN_MAX = 4;
 		const int LEVENSHTEIN_MAX = 4;
 
 
-		std::map<int, std::vector<const char*>> maps;
+		std::unordered_map<int, std::vector<const char*>> 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
 			// Prevent suggestion of instance mapnames
-			if( pair.second.instance_id != 0 ){
+			if(mapdata->instance_id != 0 ){
 				continue;
 				continue;
 			}
 			}
 
 
 			// Calculate the levenshtein distance of the two strings
 			// 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
 			// Check if it is above the maximum defined distance
 			if( distance > LEVENSHTEIN_MAX ){
 			if( distance > LEVENSHTEIN_MAX ){
@@ -442,7 +444,7 @@ static void warp_get_suggestions(struct map_session_data* sd, const char *name)
 				continue;
 				continue;
 			}
 			}
 
 
-			vector.push_back( pair.second.name );
+			vector.push_back(mapdata->name);
 		}
 		}
 
 
 		for( int distance = 0; distance <= LEVENSHTEIN_MAX; distance++ ){
 		for( int distance = 0; distance <= LEVENSHTEIN_MAX; distance++ ){

+ 41 - 33
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))
 	if (!(damage->caster&src->type))
 		return 0;
 		return 0;
 
 
-	union u_mapflag_args args = {};
-
-	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)))
+	struct map_data *mapdata = map_getmapdata(m);
+
+	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)];
 		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( 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;
 			wd.damage = wd.damage2 = 0;
 			return wd;
 			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);
 					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) {
 		if(!wd.damage2) {
 			wd.damage = battle_calc_damage(src,target,&wd,wd.damage,skill_id,skill_lv);
 			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);
 				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.damage=battle_calc_bg_damage(src,target,wd.damage,skill_id,wd.flag);
 		}
 		}
 		else if(!wd.damage) {
 		else if(!wd.damage) {
 			wd.damage2 = battle_calc_damage(src,target,&wd,wd.damage2,skill_id,skill_lv);
 			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);
 				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);
 				wd.damage2 = battle_calc_bg_damage(src,target,wd.damage2,skill_id,wd.flag);
 		}
 		}
 		else {
 		else {
 			int64 d1 = wd.damage + wd.damage2,d2 = wd.damage2;
 			int64 d1 = wd.damage + wd.damage2,d2 = wd.damage2;
 			wd.damage = battle_calc_damage(src,target,&wd,d1,skill_id,skill_lv);
 			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);
 				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.damage = battle_calc_bg_damage(src,target,wd.damage,skill_id,wd.flag);
 			wd.damage2 = (int64)d2*100/d1 * wd.damage/100;
 			wd.damage2 = (int64)d2*100/d1 * wd.damage/100;
 			if(wd.damage > 1 && wd.damage2 < 1) wd.damage2 = 1;
 			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
 #endif
 
 
+	struct map_data *mapdata = map_getmapdata(target->m);
+
 	ad.damage = battle_calc_damage(src,target,&ad,ad.damage,skill_id,skill_lv);
 	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);
 		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);
 		ad.damage = battle_calc_bg_damage(src,target,ad.damage,skill_id,ad.flag);
 
 
 	// Skill damage adjustment
 	// Skill damage adjustment
@@ -6777,10 +6781,12 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 			break;
 			break;
 	}
 	}
 
 
+	struct map_data *mapdata = map_getmapdata(target->m);
+
 	md.damage = battle_calc_damage(src,target,&md,md.damage,skill_id,skill_lv);
 	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);
 		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);
 		md.damage = battle_calc_bg_damage(src,target,md.damage,skill_id,md.flag);
 
 
 	// Skill damage adjustment
 	// 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
 	switch( target->type ) { // Checks on actual target
 		case BL_PC: {
 		case BL_PC: {
 				struct status_change* sc = status_get_sc(src);
 				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 NC_AXETORNADO:
 						case SR_SKYNETBLOW:
 						case SR_SKYNETBLOW:
 							// Can only hit traps in PVP/GVG maps
 							// 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;
 								return 0;
 							break;
 							break;
 					}
 					}
@@ -7714,7 +7722,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 					case NC_AXETORNADO:
 					case NC_AXETORNADO:
 					case SR_SKYNETBLOW:
 					case SR_SKYNETBLOW:
 						// Can only hit icewall in PVP/GVG maps
 						// 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;
 							return 0;
 						break;
 						break;
 					case HT_CLAYMORETRAP:
 					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);
 			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.
 				return 0; // Disable guardians/emperiums owned by Guilds on non-woe times.
 			break;
 			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
 					state |= BCT_ENEMY; // Can kill anything
 					strip_enemy = 0;
 					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) )
 					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.
 						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
 						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.
 				return 0; //If you don't belong to a guild, can't target emperium.
 			if( t_bl->type != BL_PC )
 			if( t_bl->type != BL_PC )
 				state |= BCT_ENEMY; //Natural enemy.
 				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:
 		case BL_MOB:
 		{
 		{
 			struct mob_data *md = BL_CAST(BL_MOB, s_bl);
 			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.
 				return 0; // Disable guardians/emperium owned by Guilds on non-woe times.
 
 
 			if( !md->special_state.ai )
 			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;
 		return (flag&state)?1:-1;
 	}
 	}
 
 
-	if( map_flag_vs(m) )
+	if( mapdata_flag_vs(mapdata) )
 	{ //Check rivalry settings.
 	{ //Check rivalry settings.
 		int sbg_id = 0, tbg_id = 0;
 		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);
 			sbg_id = bg_team_get_id(s_bl);
 			tbg_id = bg_team_get_id(t_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) )
 		if( flag&(BCT_PARTY|BCT_ENEMY) )
 		{
 		{
 			int s_party = status_get_party_id(s_bl);
 			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;
 				state |= BCT_PARTY;
 			else
 			else
 				state |= BCT_ENEMY;
 				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 s_guild = status_get_guild_id(s_bl);
 			int t_guild = status_get_guild_id(t_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;
 				state |= BCT_GUILD;
 			else
 			else
 				state |= BCT_ENEMY;
 				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;
 			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)
 		{ // Prevent novice engagement on pk_mode (feature by Valaris)
 			TBL_PC *sd = (TBL_PC*)s_bl, *sd2 = (TBL_PC*)t_bl;
 			TBL_PC *sd = (TBL_PC*)s_bl, *sd2 = (TBL_PC*)t_bl;
 			if (
 			if (
@@ -7920,7 +7928,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 			)
 			)
 				state &= ~BCT_ENEMY;
 				state &= ~BCT_ENEMY;
 		}
 		}
-    }//end map_flag_vs chk rivality
+	}//end map_flag_vs chk rivality
 	else
 	else
 	{ //Non pvp/gvg, check party/guild settings.
 	{ //Non pvp/gvg, check party/guild settings.
 		if( flag&BCT_PARTY || state&BCT_ENEMY )
 		if( flag&BCT_PARTY || state&BCT_ENEMY )

+ 5 - 8
src/map/chrif.cpp

@@ -395,18 +395,15 @@ int chrif_connect(int fd) {
 
 
 // sends maps to char-server
 // sends maps to char-server
 int chrif_sendmap(int fd) {
 int chrif_sendmap(int fd) {
-	int i = 0, size = 4 + map.size() * 4;
 	ShowStatus("Sending maps to char server...\n");
 	ShowStatus("Sending maps to char server...\n");
 
 
 	// Sending normal maps, not instances
 	// Sending normal maps, not instances
-	WFIFOHEAD(fd, size);
+	WFIFOHEAD(fd, 4 + instance_start * 4);
 	WFIFOW(fd,0) = 0x2afa;
 	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;
 	return 0;
 }
 }

+ 32 - 28
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;
 	WBUFW(buf,2)=property;
 
 
 #if PACKETVER >= 20121010
 #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.
 		//(1<<11); // Unused bits. 1 - 10 is 0x1 length and 11 is 0x15 length. May be used for future settings.
 #endif
 #endif
 	
 	
@@ -10317,15 +10319,15 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 	if(sd->status.guild_id)
 	if(sd->status.guild_id)
 		guild_send_memberinfoshort(sd,1);
 		guild_send_memberinfoshort(sd,1);
 
 
+	struct map_data *mapdata = map_getmapdata(sd->bl.m);
+
 	if(battle_config.pc_invincible_time > 0) {
 	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);
 			pc_setinvincibletimer(sd,battle_config.pc_invincible_time<<1);
 		else
 		else
 			pc_setinvincibletimer(sd,battle_config.pc_invincible_time);
 			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 )
 	if( mapdata->users++ == 0 && battle_config.dynamic_mobs )
 		map_spawnmobs(sd->bl.m);
 		map_spawnmobs(sd->bl.m);
 	if( !pc_isinvisible(sd) ) { // increment the number of pvp players on the map
 	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( 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(!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_timer = add_timer(gettick()+200, pc_calc_pvprank_timer, sd->bl.id, 0);
 			sd->pvp_rank = 0;
 			sd->pvp_rank = 0;
 			sd->pvp_lastusers = 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);
 		clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF);
 	} else if(sd->duel_group) // set flag, if it's a duel [LuzZza]
 	} else if(sd->duel_group) // set flag, if it's a duel [LuzZza]
 		clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF);
 		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.
 		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);
 		clif_map_property(&sd->bl, MAPPROPERTY_AGITZONE, SELF);
 	else
 	else
 		clif_map_property(&sd->bl, MAPPROPERTY_NOTHING, SELF);
 		clif_map_property(&sd->bl, MAPPROPERTY_NOTHING, SELF);
@@ -10375,7 +10377,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 
 
 	// pet
 	// pet
 	if( sd->pd ) {
 	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));
 			clif_displaymessage(sd->fd, msg_txt(sd,666));
 			pet_menu(sd, 3); //Option 3 is return to egg.
 			pet_menu(sd, 3); //Option 3 is return to egg.
 		} else {
 		} else {
@@ -10461,7 +10463,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 		if(hom_is_active(sd->hd))
 		if(hom_is_active(sd->hd))
 			hom_init_timers(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;
 			sd->state.night = 1;
 			clif_status_load(&sd->bl, EFST_SKE, 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 (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
 				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.
 		{	//Display night.
 			if( !sd->state.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);
 			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
 			clif_map_type(sd, MAPTYPE_BATTLEFIELD); // Battleground Mode
 			if( map_getmapflag(sd->bl.m, MF_BATTLEGROUND) == 2 )
 			if( map_getmapflag(sd->bl.m, MF_BATTLEGROUND) == 2 )
 				clif_bg_updatescore_single(sd);
 				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];
 			char output[128];
 			sprintf(output, "[ Kill Steal Protection Disable. KS is allowed in this map ]");
 			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 &&
 		if (!sd->state.connect_new &&
 			!sd->vip.disableshowrate &&
 			!sd->vip.disableshowrate &&
 			sd->state.pmap != sd->bl.m &&
 			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);
 			clif_display_pinfo(sd,ZC_PERSONAL_INFOMATION);
@@ -10572,7 +10576,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 #endif
 #endif
 
 
 		// Instances do not need their own channels
 		// 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
 			channel_mjoin(sd); //join new map
 
 
 		clif_pk_mode_message(sd);
 		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
 	// 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);
 		npc_script_event(sd, NPCE_LOADMAP);
 
 
 	if (pc_checkskill(sd, SG_DEVIL) && pc_is_maxjoblv(sd))
 	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.
 	if (sd->sc.opt2) //Client loses these on warp.
 		clif_changeoption(&sd->bl);
 		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_MONSTER_TRANSFORM, INVALID_TIMER);
 		status_change_end(&sd->bl, SC_ACTIVE_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.
 		clif_displaymessage(sd->fd, msg_txt(sd,731)); // Transforming into monster is not allowed in Guild Wars.

+ 3 - 0
src/map/instance.cpp

@@ -28,6 +28,8 @@
 struct instance_data instance_data[MAX_INSTANCE_DATA];
 struct instance_data instance_data[MAX_INSTANCE_DATA];
 struct eri *instance_maps_ers = NULL; ///< Array of maps per instance
 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 *InstanceDB; /// Instance DB: struct instance_db, key: id
 static DBMap *InstanceNameDB; /// instance id, key: name
 static DBMap *InstanceNameDB; /// instance id, key: name
 
 
@@ -1137,6 +1139,7 @@ void do_init_instance(void) {
 	InstanceDB = uidb_alloc(DB_OPT_BASE);
 	InstanceDB = uidb_alloc(DB_OPT_BASE);
 	InstanceNameDB = strdb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA),0);
 	InstanceNameDB = strdb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA),0);
 
 
+	instance_start = map_num;
 	instance_readdb();
 	instance_readdb();
 	memset(instance_data, 0, sizeof(instance_data));
 	memset(instance_data, 0, sizeof(instance_data));
 	memset(&instance_wait, 0, sizeof(instance_wait));
 	memset(&instance_wait, 0, sizeof(instance_wait));

+ 2 - 0
src/map/instance.hpp

@@ -13,6 +13,8 @@
 enum send_target : uint8;
 enum send_target : uint8;
 struct block_list;
 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_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
 #define MAX_MAP_PER_INSTANCE	255	// Max number of maps per instance (Enter map is counted as one) - Supports up to 255 maps
 
 

+ 8 - 3
src/map/intif.cpp

@@ -690,9 +690,14 @@ int intif_party_changemap(struct map_session_data *sd,int online)
 	if(!sd)
 	if(!sd)
 		return 0;
 		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;
 		mapindex = sd->mapindex;
 
 
 	WFIFOHEAD(inter_fd,19);
 	WFIFOHEAD(inter_fd,19);

+ 9 - 6
src/map/itemdb.cpp

@@ -1581,12 +1581,15 @@ static int itemdb_read_sqldb(void) {
 bool itemdb_isNoEquip(struct item_data *id, uint16 m) {
 bool itemdb_isNoEquip(struct item_data *id, uint16 m) {
 	if (!id->flag.no_equip)
 	if (!id->flag.no_equip)
 		return false;
 		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 true;
 	return false;
 	return false;

+ 151 - 125
src/map/map.cpp

@@ -122,7 +122,8 @@ static int bl_list_count = 0;
 	#define MAP_MAX_MSG 1550
 	#define MAP_MAX_MSG 1550
 #endif
 #endif
 
 
-std::map<int16, map_data> map;
+struct map_data map[MAX_MAP_PER_SERVER];
+int map_num = 0;
 
 
 int map_port=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)
 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;
 	int16 m, x, y;
 	int pos;
 	int pos;
-	struct map_data *mapdata;
 
 
 	nullpo_ret(bl);
 	nullpo_ret(bl);
 
 
@@ -328,11 +331,11 @@ int map_addblock(struct block_list* bl)
 
 
 	if( m < 0 )
 	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;
 		return 1;
 	}
 	}
 
 
-	mapdata = map_getmapdata(m);
+	struct map_data *mapdata = map_getmapdata(m);
 
 
 	if( x < 0 || x >= mapdata->xs || y < 0 || y >= mapdata->ys )
 	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;
 	int16 bx,by;
 	struct block_list *bl;
 	struct block_list *bl;
 	struct skill_unit *unit;
 	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))
 	if (x < 0 || y < 0 || (x >= mapdata->xs) || (y >= mapdata->ys))
 		return NULL;
 		return NULL;
@@ -615,14 +616,14 @@ int map_foreachinrangeV(int (*func)(struct block_list*,va_list),struct block_lis
 	struct block_list *bl;
 	struct block_list *bl;
 	int blockcount = bl_list_count, i;
 	int blockcount = bl_list_count, i;
 	int x0, x1, y0, y1;
 	int x0, x1, y0, y1;
-	struct map_data *mapdata;
 	va_list ap_copy;
 	va_list ap_copy;
 
 
 	m = center->m;
 	m = center->m;
 	if( m < 0 )
 	if( m < 0 )
 		return 0;
 		return 0;
 
 
-	mapdata = map_getmapdata(m);
+	struct map_data *mapdata = map_getmapdata(m);
+
 	x0 = i16max(center->x - range, 0);
 	x0 = i16max(center->x - range, 0);
 	y0 = i16max(center->y - range, 0);
 	y0 = i16max(center->y - range, 0);
 	x1 = i16min(center->x + range, mapdata->xs - 1);
 	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()
 	int returnCount = 0;	//total sum of returned values of func()
 	struct block_list *bl;
 	struct block_list *bl;
 	int blockcount = bl_list_count, i;
 	int blockcount = bl_list_count, i;
-	struct map_data *mapdata;
 	va_list ap_copy;
 	va_list ap_copy;
 
 
 	if (m < 0)
 	if (m < 0)
@@ -741,7 +741,8 @@ int map_foreachinareaV(int(*func)(struct block_list*, va_list), int16 m, int16 x
 	if (y1 < y0)
 	if (y1 < y0)
 		SWAP(y0, y1);
 		SWAP(y0, y1);
 
 
-	mapdata = map_getmapdata(m);
+	struct map_data *mapdata = map_getmapdata(m);
+
 	x0 = i16max(x0, 0);
 	x0 = i16max(x0, 0);
 	y0 = i16max(y0, 0);
 	y0 = i16max(y0, 0);
 	x1 = i16min(x1, mapdata->xs - 1);
 	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]
 	int returnCount = 0;	//total sum of returned values of func() [Skotlex]
 	struct block_list *bl;
 	struct block_list *bl;
 	int blockcount = bl_list_count, i;
 	int blockcount = bl_list_count, i;
-	struct map_data *mapdata;
 	va_list ap;
 	va_list ap;
 
 
 	if ( m < 0 )
 	if ( m < 0 )
@@ -911,7 +911,8 @@ int map_forcountinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x
 	if ( y1 < y0 )
 	if ( y1 < y0 )
 		SWAP(y0, y1);
 		SWAP(y0, y1);
 
 
-	mapdata = map_getmapdata(m);
+	struct map_data *mapdata = map_getmapdata(m);
+
 	x0 = i16max(x0, 0);
 	x0 = i16max(x0, 0);
 	y0 = i16max(y0, 0);
 	y0 = i16max(y0, 0);
 	x1 = i16min(x1, mapdata->xs - 1);
 	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;
 	struct block_list *bl;
 	int blockcount = bl_list_count, i;
 	int blockcount = bl_list_count, i;
 	int16 x0, x1, y0, y1;
 	int16 x0, x1, y0, y1;
-	struct map_data *mapdata;
 	va_list ap;
 	va_list ap;
 
 
 	if ( !range ) return 0;
 	if ( !range ) return 0;
 	if ( !dx && !dy ) return 0; //No movement.
 	if ( !dx && !dy ) return 0; //No movement.
 
 
 	m = center->m;
 	m = center->m;
-	mapdata = map_getmapdata(m);
+
+	struct map_data *mapdata = map_getmapdata(m);
+
 	x0 = center->x - range;
 	x0 = center->x - range;
 	x1 = center->x + range;
 	x1 = center->x + range;
 	y0 = center->y - 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 magnitude2, len_limit; //The square of the magnitude
 	int k, xi, yi, xu, yu;
 	int k, xi, yi, xu, yu;
 	int mx0 = x0, mx1 = x1, my0 = y0, my1 = y1;
 	int mx0 = x0, mx1 = x1, my0 = y0, my1 = y1;
-	struct map_data *mapdata;
 	va_list ap;
 	va_list ap;
 
 
 	//Avoid needless calculations by not getting the sqrt right away.
 	//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 )
 	if ( my0 > my1 )
 		SWAP(my0, my1);
 		SWAP(my0, my1);
 
 
-	mapdata = map_getmapdata(m);
+	struct map_data *mapdata = map_getmapdata(m);
+
 	mx0 = max(mx0, 0);
 	mx0 = max(mx0, 0);
 	my0 = max(my0, 0);
 	my0 = max(my0, 0);
 	mx1 = min(mx1, mapdata->xs - 1);
 	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);
 	uint8 dir = map_calc_dir_xy(x0, y0, x1, y1, 6);
 	short dx = dirx[dir];
 	short dx = dirx[dir];
 	short dy = diry[dir];
 	short dy = diry[dir];
-	struct map_data *mapdata;
 	va_list ap;
 	va_list ap;
 
 
 	if (m < 0)
 	if (m < 0)
@@ -1350,7 +1351,8 @@ int map_foreachindir(int(*func)(struct block_list*, va_list), int16 m, int16 x0,
 		length++;
 		length++;
 	}
 	}
 
 
-	mapdata = map_getmapdata(m);
+	struct map_data *mapdata = map_getmapdata(m);
+
 	//Get area that needs to be checked
 	//Get area that needs to be checked
 	mx0 = x0 + dx*(offset / ((dir % 2) + 1));
 	mx0 = x0 + dx*(offset / ((dir % 2) + 1));
 	my0 = y0 + dy*(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;
 		return -2;
 	}
 	}
 
 
-	// Copy the map
-	int16 dst_m = static_cast<int16>(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);
 	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
 	// Retrieve new map data
 	struct map_data *dst_map = map_getmapdata(dst_m);
 	struct map_data *dst_map = map_getmapdata(dst_m);
@@ -2747,7 +2764,6 @@ int map_delinstancemap(int m)
 
 
 	mapindex_removemap( mapdata->index );
 	mapindex_removemap( mapdata->index );
 	map_removemapdb(mapdata);
 	map_removemapdb(mapdata);
-	map.erase(m);
 	return 1;
 	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;
 	iwall->size = i;
 
 
-	struct map_data *mapdata = map_getmapdata(m);
-
 	strdb_put(iwall_db, iwall->wall_name, iwall);
 	strdb_put(iwall_db, iwall->wall_name, iwall);
-	mapdata->iwall_num++;
+	map_getmapdata(m)->iwall_num++;
 
 
 	return true;
 	return true;
 }
 }
@@ -3281,9 +3295,8 @@ void map_iwall_get(struct map_session_data *sd) {
 	DBIterator* iter;
 	DBIterator* iter;
 	int16 x1, y1;
 	int16 x1, y1;
 	int i;
 	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;
 		return;
 
 
 	iter = db_iterator(iwall_db);
 	iter = db_iterator(iwall_db);
@@ -3480,35 +3493,41 @@ int map_addmap(char* mapname)
 {
 {
 	if( strcmpi(mapname,"clear")==0 )
 	if( strcmpi(mapname,"clear")==0 )
 	{
 	{
-		map.clear();
+		map_num = 0;
+		instance_start = 0;
 		return 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<int16>(map.size()), entry });
+	mapindex_getmapname(mapname, map[map_num].name);
+	map_num++;
 	return 0;
 	return 0;
 }
 }
 
 
 static void map_delmapid(int id)
 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){
 int map_delmap(char* mapname){
 	char map_name[MAP_NAME_LENGTH];
 	char map_name[MAP_NAME_LENGTH];
 
 
 	if (strcmpi(mapname, "all") == 0) {
 	if (strcmpi(mapname, "all") == 0) {
-		map.clear();
+		map_num = 0;
 		return 0;
 		return 0;
 	}
 	}
 
 
 	mapindex_getmapname(mapname, map_name);
 	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;
 			return 1;
 		}
 		}
 	}
 	}
@@ -3518,26 +3537,26 @@ int map_delmap(char* mapname){
 
 
 /// Initializes map flags and adjusts them depending on configuration.
 /// Initializes map flags and adjusts them depending on configuration.
 void map_flags_init(void){
 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 = {};
 		union u_mapflag_args args = {};
 
 
 		args.flag_val = 100;
 		args.flag_val = 100;
 
 
 		// additional mapflag data
 		// additional mapflag data
 		mapdata->zone = 0; // restricted mapflag zone
 		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
 		// skill damage
 		mapdata->damage_adjust = {};
 		mapdata->damage_adjust = {};
 
 
 		// adjustments
 		// 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<int16> maps_removed;
+	int maps_removed = 0;
 
 
-	for( auto &pair : map ){
+	for (int i = 0; i < map_num; i++) {
 		size_t size;
 		size_t size;
 		bool success = false;
 		bool success = false;
 		unsigned short idx = 0;
 		unsigned short idx = 0;
-		struct map_data *mapdata = &pair.second;
+		struct map_data *mapdata = &map[i];
 
 
 		// show progress
 		// 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 ){
 		if( enable_grf ){
 			// try to load the map
 			// try to load the map
@@ -3703,23 +3721,30 @@ int map_readallmaps (void)
 		}
 		}
 
 
 		// The map was not found - remove it
 		// 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;
 			continue;
 		}
 		}
 
 
 		mapdata->index = idx;
 		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);
 			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;
 			continue;
 		}
 		}
 
 
 		map_addmap2db(mapdata);
 		map_addmap2db(mapdata);
 
 
-		mapdata->m = pair.first;
+		mapdata->m = i;
 		memset(mapdata->moblist, 0, sizeof(mapdata->moblist));	//Initialize moblist [Skotlex]
 		memset(mapdata->moblist, 0, sizeof(mapdata->moblist));	//Initialize moblist [Skotlex]
 		mapdata->mob_delete_timer = INVALID_TIMER;	//Initialize timer [Skotlex]
 		mapdata->mob_delete_timer = INVALID_TIMER;	//Initialize timer [Skotlex]
 
 
@@ -3742,16 +3767,11 @@ int map_readallmaps (void)
 		aFree(map_cache_buffer[0]);
 		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
 	// 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;
 	return 0;
 }
 }
@@ -4457,7 +4477,7 @@ int map_getmapflag_sub(int16 m, enum e_mapflag mapflag, union u_mapflag_args *ar
 		return -1;
 		return -1;
 	}
 	}
 
 
-	struct map_data *mapdata = map_getmapdata(m);
+	struct map_data *mapdata = &map[m];
 
 
 	if (mapflag < MF_MIN || mapflag >= MF_MAX) {
 	if (mapflag < MF_MIN || mapflag >= MF_MAX) {
 		ShowWarning("map_getmapflag: Invalid mapflag %d on map %s.\n", mapflag, mapdata->name);
 		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) {
 	switch(mapflag) {
+		case MF_RESTRICTED:
+			return mapdata->zone;
 		case MF_NOLOOT:
 		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<int16>(MF_NOMOBLOOT), 0) && util::umap_get(mapdata->flag, static_cast<int16>(MF_NOMVPLOOT), 0);
 		case MF_NOPENALTY:
 		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<int16>(MF_NOEXPPENALTY), 0) && util::umap_get(mapdata->flag, static_cast<int16>(MF_NOZENYPENALTY), 0);
 		case MF_NOEXP:
 		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<int16>(MF_NOBASEEXP), 0) && util::umap_get(mapdata->flag, static_cast<int16>(MF_NOJOBEXP), 0);
 		case MF_SKILL_DAMAGE:
 		case MF_SKILL_DAMAGE:
 			nullpo_retr(-1, args);
 			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:
 				case SKILLDMG_CASTER:
 					return mapdata->damage_adjust.caster;
 					return mapdata->damage_adjust.caster;
 				default:
 				default:
-					return util::map_get(mapdata->flag, mapflag, 0);
+					return util::umap_get(mapdata->flag, static_cast<int16>(mapflag), 0);
 			}
 			}
 		default:
 		default:
-			return util::map_get(mapdata->flag, mapflag, 0);
+			return util::umap_get(mapdata->flag, static_cast<int16>(mapflag), 0);
 	}
 	}
 }
 }
 
 
@@ -4505,7 +4527,7 @@ bool map_setmapflag_sub(int16 m, enum e_mapflag mapflag, bool status, union u_ma
 		return false;
 		return false;
 	}
 	}
 
 
-	struct map_data *mapdata = map_getmapdata(m);
+	struct map_data *mapdata = &map[m];
 
 
 	if (mapflag < MF_MIN || mapflag >= MF_MAX) {
 	if (mapflag < MF_MIN || mapflag >= MF_MAX) {
 		ShowWarning("map_setmapflag: Invalid mapflag %d on map %s.\n", mapflag, mapdata->name);
 		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 {
 			else {
 				if (!battle_config.pk_mode)
 				if (!battle_config.pk_mode)
 					map_foreachinmap(map_mapflag_pvp_sub, m, BL_PC);
 					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);
 					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);
 					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);
 					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);
 					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);
 					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);
 					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);
 				clif_map_property_mapall(m, MAPPROPERTY_NOTHING);
 			else {
 			else {
 				clif_map_property_mapall(m, MAPPROPERTY_AGITZONE);
 				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);
 					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_CASTLE:
 		case MF_GVG_TE_CASTLE:
 		case MF_GVG_TE_CASTLE:
 			if (status) {
 			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);
 					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);
 					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;
 			mapdata->flag[mapflag] = status;
 			break;
 			break;
 		case MF_GVG_DUNGEON:
 		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;
 			mapdata->flag[mapflag] = status;
 			break;
 			break;
 		case MF_NOBASEEXP:
 		case MF_NOBASEEXP:
 		case MF_NOJOBEXP:
 		case MF_NOJOBEXP:
 			if (status) {
 			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);
 					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);
 					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) {
 			if (status) {
 				nullpo_retr(false, args);
 				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);
 					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);
 					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;
 				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) {
 			if (status) {
 				nullpo_retr(false, args);
 				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);
 					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);
 					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);
 					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);
 					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);
 				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();
 	do_clear_npc();
 
 
 	// remove all objects on maps
 	// 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);
 	id_db->foreach(id_db,cleanup_db_sub);
 	chrif_char_reset_offline();
 	chrif_char_reset_offline();
@@ -4802,8 +4828,8 @@ void do_final(void){
 
 
 	map_db->destroy(map_db, map_db_final);
 	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->cell) aFree(mapdata->cell);
 		if(mapdata->block) aFree(mapdata->block);
 		if(mapdata->block) aFree(mapdata->block);
@@ -4814,7 +4840,7 @@ void do_final(void){
 			for (int j=0; j<MAX_MOB_LIST_PER_MAP; j++)
 			for (int j=0; j<MAX_MOB_LIST_PER_MAP; j++)
 				if (mapdata->moblist[j]) aFree(mapdata->moblist[j]);
 				if (mapdata->moblist[j]) aFree(mapdata->moblist[j]);
 		}
 		}
-		map_free_questinfo(pair.first);
+		map_free_questinfo(i);
 		mapdata->damage_adjust = {};
 		mapdata->damage_adjust = {};
 	}
 	}
 
 

+ 175 - 19
src/map/map.hpp

@@ -5,8 +5,8 @@
 #define _MAP_HPP_
 #define _MAP_HPP_
 
 
 #include <algorithm>
 #include <algorithm>
-#include <map>
 #include <stdarg.h>
 #include <stdarg.h>
+#include <unordered_map>
 #include <vector>
 #include <vector>
 
 
 #include "../common/cbasetypes.hpp"
 #include "../common/cbasetypes.hpp"
@@ -231,22 +231,6 @@ enum e_mapid {
 
 
 #define DEFAULT_AUTOSAVE_INTERVAL 5*60*1000
 #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
 //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]
 //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{
 enum bl_type : uint16{
@@ -735,7 +719,7 @@ struct map_data {
 	int users_pvp;
 	int users_pvp;
 	int iwall_num; // Total of invisible walls in this map
 	int iwall_num; // Total of invisible walls in this map
 
 
-	std::map<e_mapflag, int> flag;
+	std::unordered_map<int16, int> flag;
 	struct point save;
 	struct point save;
 	std::vector<s_drop_list> drop_list;
 	std::vector<s_drop_list> drop_list;
 	uint32 zone; // zone number (for item/skill restrictions)
 	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_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag);
 void map_setgatcell(int16 m, int16 x, int16 y, int gat);
 void map_setgatcell(int16 m, int16 x, int16 y, int gat);
 
 
-extern std::map<int16, map_data> map;
+extern struct map_data map[];
+extern int map_num;
 
 
 extern int autosave_interval;
 extern int autosave_interval;
 extern int minsave_interval;
 extern int minsave_interval;
@@ -790,6 +775,177 @@ extern bool agit2_flag;
 extern bool agit3_flag;
 extern bool agit3_flag;
 #define is_agit_start() (agit_flag || agit2_flag || 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 motd_txt[];
 extern char help_txt[];
 extern char help_txt[];
 extern char help2_txt[];
 extern char help2_txt[];

+ 9 - 10
src/map/mob.cpp

@@ -568,9 +568,10 @@ bool mob_ksprotected (struct block_list *src, struct block_list *target)
 	do {
 	do {
 		struct status_change_entry *sce;
 		struct status_change_entry *sce;
 		struct map_session_data *pl_sd; // Owner
 		struct map_session_data *pl_sd; // Owner
+		struct map_data *mapdata = map_getmapdata(md->bl.m);
 		char output[128];
 		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
 			return false; // Ignores GVG, PVP and AllowKS map flags
 
 
 		if( md->db->mexp || md->master_id )
 		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;
 		return 0;
 	}
 	}
 
 
-	struct map_data *mapdata = map_getmapdata(m);
-
 	data.m = m;
 	data.m = m;
 	data.num = 1;
 	data.num = 1;
 	if(mob_id<=0) {
 	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 )
 	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;
 		return 0;
 	}
 	}
 
 
 	if((x<=0 || y<=0) && !map_search_freecell(NULL, m, &x, &y, -1,-1, 1))
 	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;
 		return 0;
 	}
 	}
 	data.x = x;
 	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))
 	if (!mob_parse_dataset(&data))
 		return 0;
 		return 0;
 
 
-	gc=guild_mapname2gc(mapdata->name);
+	gc=guild_mapname2gc(mapname);
 	if (gc == NULL)
 	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;
 		return 0;
 	}
 	}
 	if (!gc->guild_id)
 	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
 	else
 		g = guild_search(gc->guild_id);
 		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 &&
 		if (md2 && md2->bl.type == BL_MOB &&
 			md2->guardian_data && md2->guardian_data->number == guardian)
 			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;
 			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;
 	data.id = mob_id;
 	if( (x <= 0 || y <= 0) && !map_search_freecell(NULL, m, &x, &y, -1,-1, 1) )
 	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;
 		return 0;
 	}
 	}
 
 

+ 12 - 11
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:
 		case NPCTYPE_ITEMSHOP:
 			{
 			{
 				struct item_data *id = itemdb_exists(nd->u.shop.itemshop_nameid);
 				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.
 				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;
 					return ERROR_TYPE_PURCHASE_FAIL;
 				}
 				}
 				if (cost[0] < (price - points)) {
 				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;
 					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)) {
 				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;
 					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);
 		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",
 		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;
 		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);
 			imap = map_mapname2mapid(map_getmapdata(dm)->name);
 
 
 		if( imap == -1 ) {
 		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;
 			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)
 				if (sscanf(w4, "%11d", &args.flag_val) == 1)
 					map_setmapflag_sub(m, MF_RESTRICTED, true, &args);
 					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
 				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
 			} else
 				map_setmapflag(m, MF_RESTRICTED, false);
 				map_setmapflag(m, MF_RESTRICTED, false);
 			break;
 			break;
@@ -4456,9 +4455,9 @@ int npc_reload(void) {
 
 
 	// dynamic check by [random]
 	// dynamic check by [random]
 	if( battle_config.dynamic_mobs ){
 	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++ ){
 			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) {
 				if (mapdata->moblist[i] != NULL) {
 					aFree(mapdata->moblist[i]);
 					aFree(mapdata->moblist[i]);
@@ -4601,9 +4600,11 @@ static void npc_debug_warps_sub(struct npc_data* nd)
 }
 }
 
 
 static void npc_debug_warps(void){
 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]);
 		}
 		}
 	}
 	}
 }
 }

+ 10 - 9
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]
 	if( map_getmapflag( sd->bl.m, MF_PVP_NIGHTMAREDROP ) ) { // Moved this outside so it works when PVP isn't enabled and during pk mode [Ancyker]
 		for(int j=0;j<MAX_DROP_PER_MAP;j++){
 		for(int j=0;j<MAX_DROP_PER_MAP;j++){
-			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;
+			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)
 			if(id == 0)
 				continue;
 				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)
 	if (!job_info[idx].noenter_map.zone || group_lv > job_info[idx].noenter_map.group_lv)
 		return true;
 		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;
 		return false;
 
 

+ 2 - 4
src/map/script.cpp

@@ -490,18 +490,16 @@ static void script_reportsrc(struct script_state *st)
 	if( bl == NULL )
 	if( bl == NULL )
 		return;
 		return;
 
 
-	struct map_data *mapdata = map_getmapdata(bl->m);
-
 	switch( bl->type ) {
 	switch( bl->type ) {
 		case BL_NPC:
 		case BL_NPC:
 			if( bl->m >= 0 )
 			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
 			else
 				ShowDebug("Source (NPC): %s (invisible/not on a map)\n", ((struct npc_data *)bl)->name);
 				ShowDebug("Source (NPC): %s (invisible/not on a map)\n", ((struct npc_data *)bl)->name);
 			break;
 			break;
 		default:
 		default:
 			if( bl->m >= 0 )
 			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
 			else
 				ShowDebug("Source (Non-NPC type %d): name %s (invisible/not on a map)\n", bl->type, status_get_name(bl));
 				ShowDebug("Source (Non-NPC type %d): name %s (invisible/not on a map)\n", bl->type, status_get_name(bl));
 			break;
 			break;

+ 31 - 24
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 )
 	if( sd->skillitem == skill_id && !sd->skillitem_keep_requirement )
 		return false;
 		return false;
 
 
+	struct map_data *mapdata = map_getmapdata(m);
+
 	skill_nocast = skill_get_nocast(skill_id);
 	skill_nocast = skill_get_nocast(skill_id);
 	// Check skill restrictions [Celest]
 	// 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
 			clif_msg(sd, SKILL_CANT_USE_AREA); // This skill cannot be used within this area
 			return true;
 			return true;
 	}
 	}
@@ -713,7 +715,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
 		case RETURN_TO_ELDICASTES:
 		case RETURN_TO_ELDICASTES:
 		case ALL_GUARDIAN_RECALL:
 		case ALL_GUARDIAN_RECALL:
 		case ECLAGE_RECALL:
 		case ECLAGE_RECALL:
-			if(map_getmapflag(m, MF_NOWARP)) {
+			if(mapdata->flag[MF_NOWARP]) {
 				clif_skill_teleportmessage(sd,0);
 				clif_skill_teleportmessage(sd,0);
 				return true;
 				return true;
 			}
 			}
@@ -723,7 +725,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
 		case SC_DIMENSIONDOOR:
 		case SC_DIMENSIONDOOR:
 		case ALL_ODINS_RECALL:
 		case ALL_ODINS_RECALL:
 		case WE_CALLALLFAMILY:
 		case WE_CALLALLFAMILY:
-			if(map_getmapflag(m, MF_NOTELEPORT)) {
+			if(mapdata->flag[MF_NOTELEPORT]) {
 				clif_skill_teleportmessage(sd,0);
 				clif_skill_teleportmessage(sd,0);
 				return true;
 				return true;
 			}
 			}
@@ -731,7 +733,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
 		case WE_CALLPARTNER:
 		case WE_CALLPARTNER:
 		case WE_CALLPARENT:
 		case WE_CALLPARENT:
 		case WE_CALLBABY:
 		case WE_CALLBABY:
-			if (map_getmapflag(m, MF_NOMEMO)) {
+			if (mapdata->flag[MF_NOMEMO]) {
 				clif_skill_teleportmessage(sd,1);
 				clif_skill_teleportmessage(sd,1);
 				return true;
 				return true;
 			}
 			}
@@ -760,13 +762,13 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
 			return false; // always allowed
 			return false; // always allowed
 		case WZ_ICEWALL:
 		case WZ_ICEWALL:
 			// noicewall flag [Valaris]
 			// noicewall flag [Valaris]
-			if (map_getmapflag(m, MF_NOICEWALL)) {
+			if (mapdata->flag[MF_NOICEWALL]) {
 				clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
 				clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
 				return true;
 				return true;
 			}
 			}
 			break;
 			break;
 		case GC_DARKILLUSION:
 		case GC_DARKILLUSION:
-			if( map_flag_gvg2(m) ) {
+			if( mapdata_flag_gvg2(mapdata) ) {
 				clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
 				clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
 				return true;
 				return true;
 			}
 			}
@@ -775,8 +777,8 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
 		case GD_ITEMEMERGENCYCALL:
 		case GD_ITEMEMERGENCYCALL:
 			if (
 			if (
 				!(battle_config.emergency_call&((is_agit_start())?2:1)) ||
 				!(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);
 				clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
 				return true;
 				return true;
@@ -786,7 +788,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
 		case WM_SOUND_OF_DESTRUCTION:
 		case WM_SOUND_OF_DESTRUCTION:
 		case WM_LULLABY_DEEPSLEEP:
 		case WM_LULLABY_DEEPSLEEP:
 		case WM_SATURDAY_NIGHT_FEVER:
 		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.
 				clif_skill_teleportmessage(sd,2); // This skill uses this msg instead of skill fails.
 				return true;
 				return true;
 			}
 			}
@@ -9431,7 +9433,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		if (flag&1)
 		if (flag&1)
 			sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv));
 			sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv));
 		else {
 		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);
 			clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
 		}
 		}
 		break;
 		break;
@@ -12734,8 +12738,7 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
 	case GN_HELLS_PLANT:
 	case GN_HELLS_PLANT:
 		if( skill_id == GN_HELLS_PLANT && map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) )
 		if( skill_id == GN_HELLS_PLANT && map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) )
 			return NULL;
 			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;
 			target = BCT_ALL;
 		break;
 		break;
 	case HT_SKIDTRAP:
 	case HT_SKIDTRAP:
@@ -12770,7 +12773,7 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
 				req_item = req.itemid[i];
 				req_item = req.itemid[i];
 			if (skill_id == RL_B_TRAP) // Target type should not change on GvG maps.
 			if (skill_id == RL_B_TRAP) // Target type should not change on GvG maps.
 				break;
 				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;
 				target = BCT_ALL;
 		}
 		}
 		break;
 		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
 				//Duration in PVP is: 1st - 4s, 2nd - 8s, 3rd - 12s
 				int sec = skill_get_time2(sg->skill_id, sg->skill_lv);
 				int sec = skill_get_time2(sg->skill_id, sg->skill_lv);
 				const struct TimerData* td;
 				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;
 					sec /= 2;
 				if (sc->data[type]) {
 				if (sc->data[type]) {
 					if (sc->data[type]->val2 && sc->data[type]->val3 && sc->data[type]->val4) {
 					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;
 						break;
 					}
 					}
 					//Don't increase val1 here, we need a higher val in status_change_start so it overwrites the old one
 					//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);
 						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);
 						sec *= (sc->data[type]->val1 + 1);
 					//Add group id to status change
 					//Add group id to status change
 					if (sc->data[type]->val2 == 0)
 					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);
 	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;
 		return false;
-	if (check_flag&2 && map_flag_gvg(bl->m))
+	if (check_flag&2 && mapdata_flag_gvg(mapdata))
 		return false;
 		return false;
-	if (check_flag&4 && map_flag_gvg2(bl->m))
+	if (check_flag&4 && mapdata_flag_gvg2(mapdata))
 		return false;
 		return false;
 
 
 	sc = status_get_sc(bl);
 	sc = status_get_sc(bl);

+ 13 - 10
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 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);
 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.
  * 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)
 static signed short status_calc_flee(struct block_list *bl, struct status_change *sc, int flee)
 {
 {
 	if( bl->type == BL_PC ) {
 	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;
 			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;
 			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
 	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;
 		return 0;
 
 
-	if (status_change_isDisabledOnMap(type, bl->m))
+	if (status_change_isDisabledOnMap(type, map_getmapdata(bl->m)))
 		return 0;
 		return 0;
 
 
 	// Uncomment to prevent status adding hp to gvg mob (like bloodylust=hp*3 etc...
 	// 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);
 	nullpo_retv(bl);
 
 
 	if (sc && sc->count) {
 	if (sc && sc->count) {
+		struct map_data *mapdata = map_getmapdata(bl->m);
 		unsigned short i;
 		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++) {
 		for (i = 0; i < SC_MAX; i++) {
 			if (!sc->data[i] || !SCDisabled[i])
 			if (!sc->data[i] || !SCDisabled[i])