Browse Source

Cleaned up the mapflag system (#2943)

* Created setter and getter functions.
* Adjusted all calls to use these functions.
* Converted mapflags to C++ map container.
* Converted drop_list to vector.
* Converted skill_damage ERS into vector and increased limit from UINT8 to UINT16.
* Cleaned up several functions to be more dynamic to reduce redundancy that was all over the place.
* Renamed nosumstarmiracle to nosunmoonstarmiracle.
* Adjusted skill_damage mapflag to use proper defined constants.
* Refactored map index into a vector.
Thanks to @Lemongrass3110 for a lot of help and @secretdataz!
Aleos 6 years ago
parent
commit
a942853d55

+ 9 - 9
db/skill_damage_db.txt

@@ -4,12 +4,12 @@
 // SkillName,Caster,Map,Damage against Players{,Damage against Mobs{,Damage against Bosses{,Damage against Other}}}
 //
 // Caster: The groups for which the adjustment takes effect. (bitmask)
-//		 1 = Player
-//		 2 = Monster
-//		 4 = Pet
-//		 8 = Homunculus
-//		16 = Mercenary
-//		32 = Elemental
+//		BL_PC = Player
+//		BL_MOB = Monster
+//		BL_PET = Pet
+//		BL_HOM = Homunculus
+//		BL_MER = Mercenary
+//		BL_ELEM = Elemental
 //
 // Map:
 // 		1    - Normal (the maps that aren't classified as these maps below)
@@ -31,6 +31,6 @@
 //  	Negative values decrease damage and positive values increase it (0 = no change).
 //
 // Examples:
-// MC_MAMMONITE,1,1,50 // In normal maps, players deal +50% damage to other players with Mammonite.
-// MO_EXTREMITYFIST,1,6,-50 // In PVP and GVG, players deal -50% (half) damage to other players with Asura Strike.
-// AB_ADORAMUS,1,6,50,0,10,15 // In PVP and GVG, players deal +50% damage to other players, +0% to mobs, +10% to bosses, and +15% to other with Adoramus.
+// MC_MAMMONITE,BL_PC,1,50 // In normal maps, players deal +50% damage to other players with Mammonite.
+// MO_EXTREMITYFIST,BL_PC,6,-50 // In PVP and GVG, players deal -50% (half) damage to other players with Asura Strike.
+// AB_ADORAMUS,BL_PC,6,50,0,10,15 // In PVP and GVG, players deal +50% damage to other players, +0% to mobs, +10% to bosses, and +15% to other with Adoramus.

+ 15 - 14
doc/mapflags.txt

@@ -209,7 +209,7 @@ Disables skill WZ_ICEWALL on a map.
 
 ---------------------------------------
 
-*nosumstarmiracle
+*nosunmoonstarmiracle
 
 Disables Star Gladiator's "Solar, Lunar, and Stellar Miracle" from occurring on a map.
 
@@ -297,7 +297,7 @@ Notes:
 
 ---------------------------------------
 
-*skill_damage	{<skill_name>,<caster>,<damage1>,{<damage2>,{<damage3>,{<damage4>}}}}
+*skill_damage	{<skill_name>,<caster>,<SKILLDMG_PC>,{<SKILLDMG_MOB>,{<SKILLDMG_BOSS>,{<SKILLDMG_OTHER>}}}}
 
 Enables skill damage adjustment on a map. All adjustments in 'db/skill_damage_db.txt'
 for 'Map' type 16 will be applied.
@@ -307,21 +307,21 @@ This mapflag can also be used to adjust the damage of one skill by a percentage:
 	Name of the skill in 'db/(pre-)re/skill_db.txt' (ex. SM_BASH).
 	To adjust all skill damage, write "all" (without quotes).
  - caster: the groups for which the adjustment takes effect. (bitmask)
-	 1 = Player
-	 2 = Monster
-	 4 = Pet
-	 8 = Homunculus
-	16 = Mercenary
-	32 = Elemental
+	BL_PC = Player
+	BL_MOB = Monster
+	BL_PET = Pet
+	BL_HOM = Homunculus
+	BL_MER = Mercenary
+	BL_ELEM = Elemental
  - damage: percent adjustment rate (between -100 and 100000).
-	1 = against player
-	2 = against normal monster
-	3 = against boss monster
-	4 = against other (homunculus, mercenary, pet, elemental)
+	SKILLDMG_PC = against player
+	SKILLDMG_MOB = against normal monster
+	SKILLDMG_BOSS = against boss monster
+	SKILLDMG_OTHER = against other (homunculus, mercenary, pet, elemental)
 
 Notes:
  - You MUST enable ADJUST_SKILL_DAMAGE in 'src/config/core.hpp' for this mapflag to take effect.
- - Each map can contain up to 5 adjustments (MAX_MAP_SKILL_MODIFIER in 'src/map/map.h').
+ - Each map can contain up to UINT16_MAX adjustments.
 
 ---------------------------------------
 
@@ -368,7 +368,8 @@ Allows usage of item Neuralizer (ID 12213).
 *bexp	<rate>
 *jexp	<rate>
 
-Changes the base and job experience rates on a map.
+Changes the base and job experience rates on a map. Supports negative values to reduce EXP
+rates as well.
 <rate> is given as a percentage (i.e. 100 = 1x EXP). This takes into account the modifiers
 'base_exp_rate' and 'job_exp_rate' in '/conf/battle/exp.conf'.
 

+ 0 - 8
doc/script_commands.txt

@@ -7015,14 +7015,6 @@ mf_fireworks) and whether night will be in effect on this map (mf_nightenabled).
 
 The optional parameter 'zone' is used to set the zone for restricted mapflags.
 
-For the 'skill_damage' mapflag, 'zone' functions as 'value' (-100 to 100000) and
-'type' can be:
- 1: damage against players
- 2: damage against mobs
- 3: damage against bosses
- 4: damage against other
- 5: caster type
-
 ---------------------------------------
 
 *removemapflag "<map name>",<flag>{,<zone>};

+ 22 - 0
src/common/utilities.hpp

@@ -26,6 +26,12 @@ namespace rathena {
 			return map.find( key ) != map.end();
 		}
 
+		/**
+		 * Find a key-value pair and return the key value
+		 * @param map: Map to search through
+		 * @param key: Key wanted
+		 * @return Key value on success or nullptr on failure
+		 */
 		template <typename K, typename V> V* map_find( std::map<K,V>& map, K key ){
 			auto it = map.find( key );
 
@@ -35,6 +41,22 @@ namespace rathena {
 				return nullptr;
 			}
 		}
+
+		/**
+		 * Get a key-value pair and return the key value
+		 * @param map: 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 map_get(std::map<K, V>& map, K key, V defaultValue) {
+			auto it = map.find(key);
+
+			if (it != map.end())
+				return it->second;
+			else
+				return defaultValue;
+		}
 	}
 }
 

+ 1 - 1
src/config/core.hpp

@@ -44,7 +44,7 @@
 //#define SHOW_SERVER_STATS
 
 /// Uncomment to enable skills damage adjustments
-/// By enabling this, db/skill_damage.txt and the skill_damage mapflag will adjust the
+/// By enabling this, db/skill_damage_db.txt and the skill_damage mapflag will adjust the
 /// damage rate of specified skills.
 //#define ADJUST_SKILL_DAMAGE
 

+ 192 - 212
src/map/atcommand.cpp

@@ -488,11 +488,11 @@ ACMD_FUNC(mapmove)
 		if (!map_search_freecell(NULL, m, &x, &y, 10, 10, 1))
 			x = y = 0; //Invalid cell, use random spot.
 	}
-	if ((map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) || !pc_job_can_entermap((enum e_job)sd->status.class_, m, sd->group_level)) {
+	if ((map_getmapflag(m, MF_NOWARPTO) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) || !pc_job_can_entermap((enum e_job)sd->status.class_, m, sd->group_level)) {
 		clif_displaymessage(fd, msg_txt(sd,247)); // You are not authorized to warp to this map.
 		return -1;
 	}
-	if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+	if (sd->bl.m >= 0 && map_getmapflag(sd->bl.m, MF_NOWARP) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
 		clif_displaymessage(fd, msg_txt(sd,248)); // You are not authorized to warp from your current map.
 		return -1;
 	}
@@ -557,13 +557,13 @@ ACMD_FUNC(jumpto)
 		return -1;
 	}
 
-	if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
+	if (pl_sd->bl.m >= 0 && map_getmapflag(pl_sd->bl.m, MF_NOWARPTO) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
 	{
 		clif_displaymessage(fd, msg_txt(sd,247));	// You are not authorized to warp to this map.
 		return -1;
 	}
 
-	if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
+	if (sd->bl.m >= 0 && map_getmapflag(sd->bl.m, MF_NOWARP) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
 	{
 		clif_displaymessage(fd, msg_txt(sd,248));	// You are not authorized to warp from your current map.
 		return -1;
@@ -595,7 +595,7 @@ ACMD_FUNC(jump)
 
 	sscanf(message, "%6hd %6hd", &x, &y);
 
-	if (map[sd->bl.m].flag.noteleport && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+	if (map_getmapflag(sd->bl.m, MF_NOTELEPORT) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
 		clif_displaymessage(fd, msg_txt(sd,248));	// You are not authorized to warp from your current map.
 		return -1;
 	}
@@ -840,11 +840,11 @@ ACMD_FUNC(load)
 	nullpo_retr(-1, sd);
 
 	m = map_mapindex2mapid(sd->status.save_point.map);
-	if (m >= 0 && map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+	if (m >= 0 && map_getmapflag(m, MF_NOWARPTO) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
 		clif_displaymessage(fd, msg_txt(sd,249));	// You are not authorized to warp to your save map.
 		return -1;
 	}
-	if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+	if (sd->bl.m >= 0 && map_getmapflag(sd->bl.m, MF_NOWARP) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
 		clif_displaymessage(fd, msg_txt(sd,248));	// You are not authorized to warp from your current map.
 		return -1;
 	}
@@ -997,7 +997,7 @@ ACMD_FUNC(hide)
 		// increment the number of pvp players on the map
 		map[sd->bl.m].users_pvp++;
 
-		if( !battle_config.pk_mode && map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.pvp_nocalcrank )
+		if( !battle_config.pk_mode && map_getmapflag(sd->bl.m, MF_PVP) && !map_getmapflag(sd->bl.m, MF_PVP_NOCALCRANK) )
 		{// register the player for ranking calculations
 			sd->pvp_timer = add_timer( gettick() + 200, pc_calc_pvprank_timer, sd->bl.id, 0 );
 		}
@@ -1011,7 +1011,7 @@ ACMD_FUNC(hide)
 		// decrement the number of pvp players on the map
 		map[sd->bl.m].users_pvp--;
 
-		if( map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.pvp_nocalcrank && sd->pvp_timer != INVALID_TIMER )
+		if( map_getmapflag(sd->bl.m, MF_PVP) && !map_getmapflag(sd->bl.m, MF_PVP_NOCALCRANK) && sd->pvp_timer != INVALID_TIMER )
 		{// unregister the player for ranking
 			delete_timer( sd->pvp_timer, pc_calc_pvprank_timer );
 			sd->pvp_timer = INVALID_TIMER;
@@ -1632,12 +1632,12 @@ ACMD_FUNC(pvpoff)
 {
 	nullpo_retr(-1, sd);
 
-	if (!map[sd->bl.m].flag.pvp) {
+	if (!map_getmapflag(sd->bl.m, MF_PVP)) {
 		clif_displaymessage(fd, msg_txt(sd,160)); // PvP is already Off.
 		return -1;
 	}
 
-	map[sd->bl.m].flag.pvp = 0;
+	map_setmapflag(sd->bl.m, MF_PVP, false);
 
 	if (!battle_config.pk_mode){
 		clif_map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING);
@@ -1669,12 +1669,12 @@ ACMD_FUNC(pvpon)
 {
 	nullpo_retr(-1, sd);
 
-	if (map[sd->bl.m].flag.pvp) {
+	if (map_getmapflag(sd->bl.m, MF_PVP)) {
 		clif_displaymessage(fd, msg_txt(sd,161)); // PvP is already On.
 		return -1;
 	}
 
-	map[sd->bl.m].flag.pvp = 1;
+	map_setmapflag(sd->bl.m, MF_PVP, true);
 
 	if (!battle_config.pk_mode) {// display pvp circle and rank
 		clif_map_property_mapall(sd->bl.m, MAPPROPERTY_FREEPVPZONE);
@@ -1693,12 +1693,12 @@ ACMD_FUNC(gvgoff)
 {
 	nullpo_retr(-1, sd);
 
-	if (!map[sd->bl.m].flag.gvg) {
+	if (!map_getmapflag(sd->bl.m, MF_GVG)) {
 		clif_displaymessage(fd, msg_txt(sd,162)); // GvG is already Off.
 		return -1;
 	}
 
-	map[sd->bl.m].flag.gvg = 0;
+	map_setmapflag(sd->bl.m, MF_GVG, false);
 	clif_map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING);
 	map_foreachinmap(atcommand_stopattack,sd->bl.m, BL_CHAR, 0);
 	clif_displaymessage(fd, msg_txt(sd,33)); // GvG: Off.
@@ -1713,12 +1713,12 @@ ACMD_FUNC(gvgon)
 {
 	nullpo_retr(-1, sd);
 
-	if (map[sd->bl.m].flag.gvg) {
+	if (map_getmapflag(sd->bl.m, MF_GVG)) {
 		clif_displaymessage(fd, msg_txt(sd,163)); // GvG is already On.
 		return -1;
 	}
 
-	map[sd->bl.m].flag.gvg = 1;
+	map_setmapflag(sd->bl.m, MF_GVG, true);
 	clif_map_property_mapall(sd->bl.m, MAPPROPERTY_AGITZONE);
 	clif_displaymessage(fd, msg_txt(sd,34)); // GvG: On.
 
@@ -1932,7 +1932,7 @@ ACMD_FUNC(go)
 
 	nullpo_retr(-1, sd);
 
-	if( map[sd->bl.m].flag.nogo && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) {
+	if( map_getmapflag(sd->bl.m, MF_NOGO) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) {
 		clif_displaymessage(sd->fd,msg_txt(sd,995)); // You cannot use @go on this map.
 		return 0;
 	}
@@ -2054,11 +2054,11 @@ ACMD_FUNC(go)
 	if (town >= 0 && town < ARRAYLENGTH(data))
 	{
 		int16 m = map_mapname2mapid(data[town].map);
-		if (m >= 0 && map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+		if (m >= 0 && map_getmapflag(m, MF_NOWARPTO) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
 			clif_displaymessage(fd, msg_txt(sd,247)); // You are not authorized to warp to this map.
 			return -1;
 		}
-		if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+		if (sd->bl.m >= 0 && map_getmapflag(sd->bl.m, MF_NOWARP) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
 			clif_displaymessage(fd, msg_txt(sd,248)); // You are not authorized to warp from your current map.
 			return -1;
 		}
@@ -2921,11 +2921,11 @@ ACMD_FUNC(recall) {
 		return -1;
 	}
 
-	if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+	if (sd->bl.m >= 0 && map_getmapflag(sd->bl.m, MF_NOWARPTO) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
 		clif_displaymessage(fd, msg_txt(sd,1019)); // You are not authorized to warp someone to this map.
 		return -1;
 	}
-	if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+	if (pl_sd->bl.m >= 0 && map_getmapflag(pl_sd->bl.m, MF_NOWARP) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
 		clif_displaymessage(fd, msg_txt(sd,1020)); // You are not authorized to warp this player from their map.
 		return -1;
 	}
@@ -3651,7 +3651,7 @@ ACMD_FUNC(recallall)
 
 	memset(atcmd_output, '\0', sizeof(atcmd_output));
 
-	if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+	if (sd->bl.m >= 0 && map_getmapflag(sd->bl.m, MF_NOWARPTO) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
 		clif_displaymessage(fd, msg_txt(sd,1032)); // You are not authorized to warp someone to your current map.
 		return -1;
 	}
@@ -3664,7 +3664,7 @@ ACMD_FUNC(recallall)
 		{
 			if (pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y)
 				continue; // Don't waste time warping the character to the same place.
-			if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
+			if (pl_sd->bl.m >= 0 && map_getmapflag(pl_sd->bl.m, MF_NOWARP) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
 				count++;
 			else {
 				if( pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN) == SETPOS_AUTOTRADE ){
@@ -3704,7 +3704,7 @@ ACMD_FUNC(guildrecall)
 		return -1;
 	}
 
-	if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+	if (sd->bl.m >= 0 && map_getmapflag(sd->bl.m, MF_NOWARPTO) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
 		clif_displaymessage(fd, msg_txt(sd,1032)); // You are not authorized to warp someone to your current map.
 		return -1;
 	}
@@ -3725,7 +3725,7 @@ ACMD_FUNC(guildrecall)
 		{
 			if (pc_get_group_level(pl_sd) > pc_get_group_level(sd) || (pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y))
 				continue; // Skip GMs greater than you...             or chars already on the cell
-			if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
+			if (pl_sd->bl.m >= 0 && map_getmapflag(pl_sd->bl.m, MF_NOWARP) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
 				count++;
 			else{
 				if( pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN) == SETPOS_AUTOTRADE ){
@@ -3766,7 +3766,7 @@ ACMD_FUNC(partyrecall)
 		return -1;
 	}
 
-	if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+	if (sd->bl.m >= 0 && map_getmapflag(sd->bl.m, MF_NOWARPTO) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
 		clif_displaymessage(fd, msg_txt(sd,1032)); // You are not authorized to warp someone to your current map.
 		return -1;
 	}
@@ -3787,7 +3787,7 @@ ACMD_FUNC(partyrecall)
 		{
 			if (pc_get_group_level(pl_sd) > pc_get_group_level(sd) || (pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y))
 				continue; // Skip GMs greater than you...             or chars already on the cell
-			if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
+			if (pl_sd->bl.m >= 0 && map_getmapflag(pl_sd->bl.m, MF_NOWARP) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
 				count++;
 			else{
 				if( pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN) == SETPOS_AUTOTRADE ){
@@ -4036,46 +4036,45 @@ ACMD_FUNC(mapinfo) {
 	sprintf(atcmd_output, msg_txt(sd,1040), mapname, map[m_id].users, map[m_id].npc_num, chat_num, vend_num); // Map: %s | Players: %d | NPCs: %d | Chats: %d | Vendings: %d
 	clif_displaymessage(fd, atcmd_output);
 	clif_displaymessage(fd, msg_txt(sd,1041)); // ------ Map Flags ------
-	if (map[m_id].flag.town)
+	if (map_getmapflag(m_id, MF_TOWN))
 		clif_displaymessage(fd, msg_txt(sd,1042)); // Town Map
-	if (map[m_id].flag.restricted){
+	if (map_getmapflag(m_id, MF_RESTRICTED)){
 		sprintf(atcmd_output, " Restricted (zone %d)",map[m_id].zone);
 		clif_displaymessage(fd, atcmd_output);
 	}
 
-	if (battle_config.autotrade_mapflag == map[m_id].flag.autotrade)
+	if (battle_config.autotrade_mapflag == map_getmapflag(m_id, MF_AUTOTRADE))
 		clif_displaymessage(fd, msg_txt(sd,1043)); // Autotrade Enabled
 	else
 		clif_displaymessage(fd, msg_txt(sd,1044)); // Autotrade Disabled
 
-	if (map[m_id].flag.battleground){
-		sprintf(atcmd_output, msg_txt(sd,1045),map[m_id].flag.battleground); // Battlegrounds ON (type %d)
+	if (map_getmapflag(m_id, MF_BATTLEGROUND)){
+		sprintf(atcmd_output, msg_txt(sd,1045),map_getmapflag(m_id, MF_BATTLEGROUND)); // Battlegrounds ON (type %d)
 		clif_displaymessage(fd, atcmd_output);
 	}
 
 	/* Skill damage adjustment info [Cydh] */
 #ifdef ADJUST_SKILL_DAMAGE
-	if (map[m_id].flag.skill_damage) {
+	if (map_getmapflag(m_id, MF_SKILL_DAMAGE)) {
 		clif_displaymessage(fd,msg_txt(sd,1052));	// Skill Damage Adjustments:
 		sprintf(atcmd_output," > [Map] %d%%, %d%%, %d%%, %d%% | Caster:%d"
-			,map[m_id].adjust.damage.pc
-			,map[m_id].adjust.damage.mob
-			,map[m_id].adjust.damage.boss
-			,map[m_id].adjust.damage.other
-			,map[m_id].adjust.damage.caster);
+			,map[m_id].damage_adjust.rate[SKILLDMG_PC]
+			,map[m_id].damage_adjust.rate[SKILLDMG_MOB]
+			,map[m_id].damage_adjust.rate[SKILLDMG_BOSS]
+			,map[m_id].damage_adjust.rate[SKILLDMG_OTHER]
+			,map[m_id].damage_adjust.caster);
 		clif_displaymessage(fd, atcmd_output);
-		if (map[m_id].skill_damage.count) {
-			uint8 j;
+		if (map[m_id].skill_damage.size()) {
 			clif_displaymessage(fd," > [Map Skill] Name : Player, Monster, Boss Monster, Other | Caster");
-			for (j = 0; j < map[m_id].skill_damage.count; j++) {
+			for (int j = 0; j < map[m_id].skill_damage.size(); j++) {
 				sprintf(atcmd_output,"     %d. %s : %d%%, %d%%, %d%%, %d%% | %d"
 					,j+1
-					,skill_get_name(map[m_id].skill_damage.entries[j]->skill_id)
-					,map[m_id].skill_damage.entries[j]->pc
-					,map[m_id].skill_damage.entries[j]->mob
-					,map[m_id].skill_damage.entries[j]->boss
-					,map[m_id].skill_damage.entries[j]->other
-					,map[m_id].skill_damage.entries[j]->caster);
+					,skill_get_name(map[m_id].skill_damage[j].skill_id)
+					,map[m_id].skill_damage[j].rate[SKILLDMG_PC]
+					,map[m_id].skill_damage[j].rate[SKILLDMG_MOB]
+					,map[m_id].skill_damage[j].rate[SKILLDMG_BOSS]
+					,map[m_id].skill_damage[j].rate[SKILLDMG_OTHER]
+					,map[m_id].skill_damage[j].caster);
 				clif_displaymessage(fd,atcmd_output);
 			}
 		}
@@ -4083,55 +4082,55 @@ ACMD_FUNC(mapinfo) {
 #endif
 
 	strcpy(atcmd_output,msg_txt(sd,1046)); // PvP Flags:
-	if (map[m_id].flag.pvp)
+	if (map_getmapflag(m_id, MF_PVP))
 		strcat(atcmd_output, " Pvp ON |");
-	if (map[m_id].flag.pvp_noguild)
+	if (map_getmapflag(m_id, MF_PVP_NOGUILD))
 		strcat(atcmd_output, " NoGuild |");
-	if (map[m_id].flag.pvp_noparty)
+	if (map_getmapflag(m_id, MF_PVP_NOPARTY))
 		strcat(atcmd_output, " NoParty |");
-	if (map[m_id].flag.pvp_nightmaredrop)
+	if (map_getmapflag(m_id, MF_PVP_NIGHTMAREDROP))
 		strcat(atcmd_output, " NightmareDrop |");
-	if (map[m_id].flag.pvp_nocalcrank)
+	if (map_getmapflag(m_id, MF_PVP_NOCALCRANK))
 		strcat(atcmd_output, " NoCalcRank |");
 	clif_displaymessage(fd, atcmd_output);
 
 	strcpy(atcmd_output,msg_txt(sd,1047)); // GvG Flags:
-	if (map[m_id].flag.gvg)
+	if (map_getmapflag(m_id, MF_GVG))
 		strcat(atcmd_output, " GvG ON |");
-	if (map[m_id].flag.gvg_dungeon)
+	if (map_getmapflag(m_id, MF_GVG_DUNGEON))
 		strcat(atcmd_output, " GvG Dungeon |");
-	if (map[m_id].flag.gvg_castle)
+	if (map_getmapflag(m_id, MF_GVG_CASTLE))
 		strcat(atcmd_output, " GvG Castle |");
-	if (map[m_id].flag.gvg_te)
+	if (map_getmapflag(m_id, MF_GVG_TE))
 		strcat(atcmd_output, " GvG TE |");
-	if (map[m_id].flag.gvg_te_castle)
+	if (map_getmapflag(m_id, MF_GVG_TE_CASTLE))
 		strcat(atcmd_output, " GvG TE Castle |");
-	if (map[m_id].flag.gvg_noparty)
+	if (map_getmapflag(m_id, MF_GVG_NOPARTY))
 		strcat(atcmd_output, " NoParty |");
 	clif_displaymessage(fd, atcmd_output);
 
 	strcpy(atcmd_output,msg_txt(sd,1048)); // Teleport Flags:
-	if (map[m_id].flag.noteleport)
+	if (map_getmapflag(m_id, MF_NOTELEPORT))
 		strcat(atcmd_output, " NoTeleport |");
-	if (map[m_id].flag.monster_noteleport)
+	if (map_getmapflag(m_id, MF_MONSTER_NOTELEPORT))
 		strcat(atcmd_output, " Monster NoTeleport |");
-	if (map[m_id].flag.nowarp)
+	if (map_getmapflag(m_id, MF_NOWARP))
 		strcat(atcmd_output, " NoWarp |");
-	if (map[m_id].flag.nowarpto)
+	if (map_getmapflag(m_id, MF_NOWARPTO))
 		strcat(atcmd_output, " NoWarpTo |");
-	if (map[m_id].flag.noreturn)
+	if (map_getmapflag(m_id, MF_NORETURN))
 		strcat(atcmd_output, " NoReturn |");
-	if (map[m_id].flag.nogo)
+	if (map_getmapflag(m_id, MF_NOGO))
 		strcat(atcmd_output, " NoGo |"); //
-	if (map[m_id].flag.nomemo)
+	if (map_getmapflag(m_id, MF_NOMEMO))
 		strcat(atcmd_output, "  NoMemo |");
 	clif_displaymessage(fd, atcmd_output);
 
 	sprintf(atcmd_output, msg_txt(sd,1065),  // No Exp Penalty: %s | No Zeny Penalty: %s
-		(map[m_id].flag.noexppenalty) ? msg_txt(sd,1066) : msg_txt(sd,1067), (map[m_id].flag.nozenypenalty) ? msg_txt(sd,1066) : msg_txt(sd,1067)); // On / Off
+		(map_getmapflag(m_id, MF_NOEXPPENALTY)) ? msg_txt(sd,1066) : msg_txt(sd,1067), (map_getmapflag(m_id, MF_NOZENYPENALTY)) ? msg_txt(sd,1066) : msg_txt(sd,1067)); // On / Off
 	clif_displaymessage(fd, atcmd_output);
 
-	if (map[m_id].flag.nosave) {
+	if (map_getmapflag(m_id, MF_NOSAVE)) {
 		if (!map[m_id].save.map)
 			clif_displaymessage(fd, msg_txt(sd,1068)); // No Save (Return to last Save Point)
 		else if (map[m_id].save.x == -1 || map[m_id].save.y == -1 ) {
@@ -4146,77 +4145,77 @@ ACMD_FUNC(mapinfo) {
 	}
 
 	strcpy(atcmd_output,msg_txt(sd,1049)); // Weather Flags:
-	if (map[m_id].flag.snow)
+	if (map_getmapflag(m_id, MF_SNOW))
 		strcat(atcmd_output, " Snow |");
-	if (map[m_id].flag.fog)
+	if (map_getmapflag(m_id, MF_FOG))
 		strcat(atcmd_output, " Fog |");
-	if (map[m_id].flag.sakura)
+	if (map_getmapflag(m_id, MF_SAKURA))
 		strcat(atcmd_output, " Sakura |");
-	if (map[m_id].flag.clouds)
+	if (map_getmapflag(m_id, MF_CLOUDS))
 		strcat(atcmd_output, " Clouds |");
-	if (map[m_id].flag.clouds2)
+	if (map_getmapflag(m_id, MF_CLOUDS2))
 		strcat(atcmd_output, "  Clouds2 |");
-	if (map[m_id].flag.fireworks)
+	if (map_getmapflag(m_id, MF_FIREWORKS))
 		strcat(atcmd_output, " Fireworks |");
-	if (map[m_id].flag.leaves)
+	if (map_getmapflag(m_id, MF_LEAVES))
 		strcat(atcmd_output, "  Leaves |");
-	if (map[m_id].flag.nightenabled)
+	if (map_getmapflag(m_id, MF_NIGHTENABLED))
 		strcat(atcmd_output, "  Displays Night |");
 	clif_displaymessage(fd, atcmd_output);
 
 	strcpy(atcmd_output,msg_txt(sd,1050)); // Other Flags:
-	if (map[m_id].flag.nobranch)
+	if (map_getmapflag(m_id, MF_NOBRANCH))
 		strcat(atcmd_output, " NoBranch |");
-	if (map[m_id].flag.notrade)
+	if (map_getmapflag(m_id, MF_NOTRADE))
 		strcat(atcmd_output, " NoTrade |");
-	if (map[m_id].flag.novending)
+	if (map_getmapflag(m_id, MF_NOVENDING))
 		strcat(atcmd_output, " NoVending |");
-	if (map[m_id].flag.nodrop)
+	if (map_getmapflag(m_id, MF_NODROP))
 		strcat(atcmd_output, " NoDrop |");
-	if (map[m_id].flag.noskill)
+	if (map_getmapflag(m_id, MF_NOSKILL))
 		strcat(atcmd_output, " NoSkill |");
-	if (map[m_id].flag.noicewall)
+	if (map_getmapflag(m_id, MF_NOICEWALL))
 		strcat(atcmd_output, " NoIcewall |");
-	if (map[m_id].flag.allowks)
+	if (map_getmapflag(m_id, MF_ALLOWKS))
 		strcat(atcmd_output, " AllowKS |");
-	if (map[m_id].flag.reset)
+	if (map_getmapflag(m_id, MF_RESET))
 		strcat(atcmd_output, " Reset |");
-	if (map[m_id].flag.hidemobhpbar)
+	if (map_getmapflag(m_id, MF_HIDEMOBHPBAR))
 		strcat(atcmd_output, " HideMobHPBar |");
 	clif_displaymessage(fd, atcmd_output);
 
 	strcpy(atcmd_output,msg_txt(sd,1051)); // Other Flags2:
-	if (map[m_id].nocommand)
+	if (map_getmapflag(m_id, MF_NOCOMMAND))
 		strcat(atcmd_output, " NoCommand |");
-	if (map[m_id].flag.nobaseexp)
+	if (map_getmapflag(m_id, MF_NOBASEEXP))
 		strcat(atcmd_output, " NoBaseEXP |");
-	if (map[m_id].flag.nojobexp)
+	if (map_getmapflag(m_id, MF_NOJOBEXP))
 		strcat(atcmd_output, " NoJobEXP |");
-	if (map[m_id].flag.nomobloot)
+	if (map_getmapflag(m_id, MF_NOMOBLOOT))
 		strcat(atcmd_output, " NoMobLoot |");
-	if (map[m_id].flag.nomvploot)
+	if (map_getmapflag(m_id, MF_NOMVPLOOT))
 		strcat(atcmd_output, " NoMVPLoot |");
-	if (map[m_id].flag.partylock)
+	if (map_getmapflag(m_id, MF_PARTYLOCK))
 		strcat(atcmd_output, " PartyLock |");
-	if (map[m_id].flag.guildlock)
+	if (map_getmapflag(m_id, MF_GUILDLOCK))
 		strcat(atcmd_output, " GuildLock |");
-	if (map[m_id].flag.loadevent)
+	if (map_getmapflag(m_id, MF_LOADEVENT))
 		strcat(atcmd_output, " Loadevent |");
-	if (map[m_id].flag.chmautojoin)
-		strcat(atcmd_output, " Chmautojoin |");
-	if (map[m_id].flag.nousecart)
+	if (map_getmapflag(m_id, MF_NOMAPCHANNELAUTOJOIN))
+		strcat(atcmd_output, " NoMapChannelAutoJoin |");
+	if (map_getmapflag(m_id, MF_NOUSECART))
 		strcat(atcmd_output, " NoUsecart |");
-	if (map[m_id].flag.noitemconsumption)
+	if (map_getmapflag(m_id, MF_NOITEMCONSUMPTION))
 		strcat(atcmd_output, " NoItemConsumption |");
-	if (map[m_id].flag.nosumstarmiracle)
-		strcat(atcmd_output, " NoSumStarMiracle |");
-	if (map[m_id].flag.nomineeffect)
+	if (map_getmapflag(m_id, MF_NOSUNMOONSTARMIRACLE))
+		strcat(atcmd_output, " NoSunMoonStarMiracle |");
+	if (map_getmapflag(m_id, MF_NOMINEEFFECT))
 		strcat(atcmd_output, " NoMineEffect |");
-	if (map[m_id].flag.nolockon)
+	if (map_getmapflag(m_id, MF_NOLOCKON))
 		strcat(atcmd_output, " NoLockOn |");
-	if (map[m_id].flag.notomb)
+	if (map_getmapflag(m_id, MF_NOTOMB))
 		strcat(atcmd_output, " NoTomb |");
-	if (map[m_id].flag.nocostume)
+	if (map_getmapflag(m_id, MF_NOCOSTUME))
 		strcat(atcmd_output, " NoCostume |");
 	clif_displaymessage(fd, atcmd_output);
 
@@ -5367,7 +5366,7 @@ ACMD_FUNC(killable)
 ACMD_FUNC(skillon)
 {
 	nullpo_retr(-1, sd);
-	map[sd->bl.m].flag.noskill = 0;
+	map_setmapflag(sd->bl.m, MF_NOSKILL, false);
 	clif_displaymessage(fd, msg_txt(sd,244)); // Skills have been enabled on this map.
 	return 0;
 }
@@ -5379,7 +5378,7 @@ ACMD_FUNC(skillon)
 ACMD_FUNC(skilloff)
 {
 	nullpo_retr(-1, sd);
-	map[sd->bl.m].flag.noskill = 1;
+	map_setmapflag(sd->bl.m, MF_NOSKILL, true);
 	clif_displaymessage(fd, msg_txt(sd,243)); // Skills have been disabled on this map.
 	return 0;
 }
@@ -5952,7 +5951,7 @@ ACMD_FUNC(changelook)
 ACMD_FUNC(autotrade) {
 	nullpo_retr(-1, sd);
 
-	if( map[sd->bl.m].flag.autotrade != battle_config.autotrade_mapflag ) {
+	if( map_getmapflag(sd->bl.m, MF_AUTOTRADE) != battle_config.autotrade_mapflag ) {
 		clif_displaymessage(fd, msg_txt(sd,1179)); // Autotrade is not allowed on this map.
 		return -1;
 	}
@@ -6011,7 +6010,7 @@ ACMD_FUNC(changegm)
 		return -1;
 	}
 
-	if( map[sd->bl.m].flag.guildlock || map[sd->bl.m].flag.gvg_castle ) {
+	if( map_getmapflag(sd->bl.m, MF_GUILDLOCK) || map_getmapflag(sd->bl.m, MF_GVG_CASTLE) ) {
 		clif_displaymessage(fd, msg_txt(sd,1182)); // You cannot change guild leaders on this map.
 		return -1;
 	}
@@ -6331,21 +6330,19 @@ ACMD_FUNC(autoloottype)
 	return 0;
 }
 
-/**
- * No longer available, keeping here just in case it's back someday. [Ind]
- **/
 /*==========================================
  * It is made to rain.
+ * No longer available, keeping here just in case it's back someday. [Ind]
  *------------------------------------------*/
 //ACMD_FUNC(rain)
 //{
 //	nullpo_retr(-1, sd);
-//	if (map[sd->bl.m].flag.rain) {
-//		map[sd->bl.m].flag.rain=0;
+//	if (map_getmapflag(sd->bl.m, MF_RAIN)) {
+//		map_setmapflag(sd->bl.m, MF_RAIN, false);
 //		clif_weather(sd->bl.m);
 //		clif_displaymessage(fd, msg_txt(sd,1201)); // The rain has stopped.
 //	} else {
-//		map[sd->bl.m].flag.rain=1;
+//		map_setmapflag(sd->bl.m, MF_RAIN, true);
 //		clif_weather(sd->bl.m);
 //		clif_displaymessage(fd, msg_txt(sd,1202)); // It has started to rain.
 //	}
@@ -6358,12 +6355,12 @@ ACMD_FUNC(autoloottype)
 ACMD_FUNC(snow)
 {
 	nullpo_retr(-1, sd);
-	if (map[sd->bl.m].flag.snow) {
-		map[sd->bl.m].flag.snow=0;
+	if (map_getmapflag(sd->bl.m, MF_SNOW)) {
+		map_setmapflag(sd->bl.m, MF_SNOW, false);
 		clif_weather(sd->bl.m);
 		clif_displaymessage(fd, msg_txt(sd,1203)); // Snow has stopped falling.
 	} else {
-		map[sd->bl.m].flag.snow=1;
+		map_setmapflag(sd->bl.m, MF_SNOW, true);
 		clif_weather(sd->bl.m);
 		clif_displaymessage(fd, msg_txt(sd,1204)); // It has started to snow.
 	}
@@ -6377,12 +6374,12 @@ ACMD_FUNC(snow)
 ACMD_FUNC(sakura)
 {
 	nullpo_retr(-1, sd);
-	if (map[sd->bl.m].flag.sakura) {
-		map[sd->bl.m].flag.sakura=0;
+	if (map_getmapflag(sd->bl.m, MF_SAKURA)) {
+		map_setmapflag(sd->bl.m, MF_SAKURA, false);
 		clif_weather(sd->bl.m);
 		clif_displaymessage(fd, msg_txt(sd,1205)); // Cherry tree leaves no longer fall.
 	} else {
-		map[sd->bl.m].flag.sakura=1;
+		map_setmapflag(sd->bl.m, MF_SAKURA, true);
 		clif_weather(sd->bl.m);
 		clif_displaymessage(fd, msg_txt(sd,1206)); // Cherry tree leaves have begun to fall.
 	}
@@ -6395,12 +6392,12 @@ ACMD_FUNC(sakura)
 ACMD_FUNC(clouds)
 {
 	nullpo_retr(-1, sd);
-	if (map[sd->bl.m].flag.clouds) {
-		map[sd->bl.m].flag.clouds=0;
+	if (map_getmapflag(sd->bl.m, MF_CLOUDS)) {
+		map_setmapflag(sd->bl.m, MF_CLOUDS, false);
 		clif_weather(sd->bl.m);
 		clif_displaymessage(fd, msg_txt(sd,1207)); // The clouds has disappear.
 	} else {
-		map[sd->bl.m].flag.clouds=1;
+		map_setmapflag(sd->bl.m, MF_CLOUDS, true);
 		clif_weather(sd->bl.m);
 		clif_displaymessage(fd, msg_txt(sd,1208)); // Clouds appear.
 	}
@@ -6414,12 +6411,12 @@ ACMD_FUNC(clouds)
 ACMD_FUNC(clouds2)
 {
 	nullpo_retr(-1, sd);
-	if (map[sd->bl.m].flag.clouds2) {
-		map[sd->bl.m].flag.clouds2=0;
+	if (map_getmapflag(sd->bl.m, MF_CLOUDS2)) {
+		map_setmapflag(sd->bl.m, MF_CLOUDS2, false);
 		clif_weather(sd->bl.m);
 		clif_displaymessage(fd, msg_txt(sd,1209)); // The alternative clouds disappear.
 	} else {
-		map[sd->bl.m].flag.clouds2=1;
+		map_setmapflag(sd->bl.m, MF_CLOUDS2, true);
 		clif_weather(sd->bl.m);
 		clif_displaymessage(fd, msg_txt(sd,1210)); // Alternative clouds appear.
 	}
@@ -6433,12 +6430,12 @@ ACMD_FUNC(clouds2)
 ACMD_FUNC(fog)
 {
 	nullpo_retr(-1, sd);
-	if (map[sd->bl.m].flag.fog) {
-		map[sd->bl.m].flag.fog=0;
+	if (map_getmapflag(sd->bl.m, MF_FOG)) {
+		map_setmapflag(sd->bl.m, MF_FOG, false);
 		clif_weather(sd->bl.m);
 		clif_displaymessage(fd, msg_txt(sd,1211)); // The fog has gone.
 	} else {
-		map[sd->bl.m].flag.fog=1;
+		map_setmapflag(sd->bl.m, MF_FOG, true);
 		clif_weather(sd->bl.m);
 		clif_displaymessage(fd, msg_txt(sd,1212)); // Fog hangs over.
 	}
@@ -6451,12 +6448,12 @@ ACMD_FUNC(fog)
 ACMD_FUNC(leaves)
 {
 	nullpo_retr(-1, sd);
-	if (map[sd->bl.m].flag.leaves) {
-		map[sd->bl.m].flag.leaves=0;
+	if (map_getmapflag(sd->bl.m, MF_LEAVES)) {
+		map_setmapflag(sd->bl.m, MF_LEAVES, false);
 		clif_weather(sd->bl.m);
 		clif_displaymessage(fd, msg_txt(sd,1213)); // Leaves no longer fall.
 	} else {
-		map[sd->bl.m].flag.leaves=1;
+		map_setmapflag(sd->bl.m, MF_LEAVES, true);
 		clif_weather(sd->bl.m);
 		clif_displaymessage(fd, msg_txt(sd,1214)); // Fallen leaves fall.
 	}
@@ -6470,12 +6467,12 @@ ACMD_FUNC(leaves)
 ACMD_FUNC(fireworks)
 {
 	nullpo_retr(-1, sd);
-	if (map[sd->bl.m].flag.fireworks) {
-		map[sd->bl.m].flag.fireworks=0;
+	if (map_getmapflag(sd->bl.m, MF_FIREWORKS)) {
+		map_setmapflag(sd->bl.m, MF_FIREWORKS, false);
 		clif_weather(sd->bl.m);
 		clif_displaymessage(fd, msg_txt(sd,1215)); // Fireworks have ended.
 	} else {
-		map[sd->bl.m].flag.fireworks=1;
+		map_setmapflag(sd->bl.m, MF_FIREWORKS, true);
 		clif_weather(sd->bl.m);
 		clif_displaymessage(fd, msg_txt(sd,1216)); // Fireworks have launched.
 	}
@@ -6489,17 +6486,15 @@ ACMD_FUNC(fireworks)
 ACMD_FUNC(clearweather)
 {
 	nullpo_retr(-1, sd);
-	/**
-	 * No longer available, keeping here just in case it's back someday. [Ind]
-	 **/
-	//map[sd->bl.m].flag.rain=0;
-	map[sd->bl.m].flag.snow=0;
-	map[sd->bl.m].flag.sakura=0;
-	map[sd->bl.m].flag.clouds=0;
-	map[sd->bl.m].flag.clouds2=0;
-	map[sd->bl.m].flag.fog=0;
-	map[sd->bl.m].flag.fireworks=0;
-	map[sd->bl.m].flag.leaves=0;
+
+	//map_setmapflag(sd->bl.m, MF_RAIN, false); // No longer available, keeping here just in case it's back someday. [Ind]
+	map_setmapflag(sd->bl.m, MF_SNOW, false);
+	map_setmapflag(sd->bl.m, MF_SAKURA, false);
+	map_setmapflag(sd->bl.m, MF_CLOUDS, false);
+	map_setmapflag(sd->bl.m, MF_CLOUDS2, false);
+	map_setmapflag(sd->bl.m, MF_FOG, false);
+	map_setmapflag(sd->bl.m, MF_FIREWORKS, false);
+	map_setmapflag(sd->bl.m, MF_LEAVES, false);
 	clif_weather(sd->bl.m);
 	clif_displaymessage(fd, msg_txt(sd,291)); // Weather effects will dispell on warp/refresh
 
@@ -8150,84 +8145,69 @@ ACMD_FUNC(fakename)
  * Ragnarok Resources
  *------------------------------------------*/
 ACMD_FUNC(mapflag) {
-#define checkflag( cmd ) if ( map[ sd->bl.m ].flag.cmd ) clif_displaymessage(sd->fd,#cmd)
-#define setflag( cmd ) \
-	if ( strcmp( flag_name , #cmd ) == 0 ){\
-		map[ sd->bl.m ].flag.cmd = flag;\
-		sprintf(atcmd_output,"[ @mapflag ] %s flag has been set to %s value = %hd",#cmd,flag?"On":"Off",flag);\
-		clif_displaymessage(sd->fd,atcmd_output);\
-		return 0;\
-	}
-	char flag_name[100];
-	short flag=0,i;
+	char flag_name[CHAT_SIZE_MAX];
+	short flag = 0, i, j;
+	StringBuf buf;
+
 	nullpo_retr(-1, sd);
+
 	memset(flag_name, '\0', sizeof(flag_name));
 
 	if (!message || !*message || (sscanf(message, "%99s %6hd", flag_name, &flag) < 1)) {
 		clif_displaymessage(sd->fd,msg_txt(sd,1311)); // Enabled Mapflags in this map:
 		clif_displaymessage(sd->fd,"----------------------------------");
-		checkflag(town);				checkflag(autotrade);			checkflag(allowks);				checkflag(nomemo);
-		checkflag(noteleport);			checkflag(noreturn);			checkflag(monster_noteleport);	checkflag(nosave);
-		checkflag(nobranch);			checkflag(noexppenalty);		checkflag(pvp);					checkflag(pvp_noparty);
-		checkflag(pvp_noguild);			checkflag(pvp_nightmaredrop);	checkflag(pvp_nocalcrank);		checkflag(gvg_castle);
-		checkflag(gvg);					checkflag(gvg_dungeon);			checkflag(gvg_noparty);			checkflag(battleground);
-		checkflag(nozenypenalty);		checkflag(notrade);				checkflag(noskill);				checkflag(nowarp);
-		checkflag(nowarpto);			checkflag(noicewall);			checkflag(snow);				checkflag(clouds);
-		checkflag(clouds2);				checkflag(fog);					checkflag(fireworks);			checkflag(sakura);
-		checkflag(leaves);				checkflag(nogo);				checkflag(nobaseexp);			checkflag(nojobexp);
-		checkflag(nomobloot);			checkflag(nomvploot);			checkflag(nightenabled);		checkflag(restricted);
-		checkflag(nodrop);				checkflag(novending);			checkflag(loadevent);			checkflag(nochat);
-		checkflag(partylock);			checkflag(guildlock);			checkflag(reset);				checkflag(chmautojoin);
-		checkflag(nousecart);			checkflag(noitemconsumption);	checkflag(nosumstarmiracle);	checkflag(nomineeffect);
-		checkflag(nolockon);			checkflag(notomb);				checkflag(nocostume);			checkflag(gvg_te);
-		checkflag(gvg_te_castle);		checkflag(hidemobhpbar);
-#ifdef ADJUST_SKILL_DAMAGE
-		checkflag(skill_damage);
-#endif
+		for( i = MF_MIN; i < MF_MAX; i++ ){
+			if( map_getmapflag_name(static_cast<e_mapflag>(i), flag_name) && map_getmapflag( sd->bl.m, static_cast<e_mapflag>(i) ) ){
+				clif_displaymessage(sd->fd, flag_name);
+			}
+		}
+
 		clif_displaymessage(sd->fd," ");
 		clif_displaymessage(sd->fd,msg_txt(sd,1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On)
 		clif_displaymessage(sd->fd,msg_txt(sd,1313)); // Type "@mapflag available" to list the available mapflags.
 		return 1;
 	}
-	for (i = 0; flag_name[i]; i++) flag_name[i] = (char)tolower(flag_name[i]); //lowercase
-
-	setflag(town);				setflag(autotrade);			setflag(allowks);				setflag(nomemo);
-	setflag(noteleport);		setflag(noreturn);			setflag(monster_noteleport);	setflag(nosave);
-	setflag(nobranch);			setflag(noexppenalty);		setflag(pvp);					setflag(pvp_noparty);
-	setflag(pvp_noguild);		setflag(pvp_nightmaredrop);	setflag(pvp_nocalcrank);		setflag(gvg_castle);
-	setflag(gvg);				setflag(gvg_dungeon);		setflag(gvg_noparty);			setflag(battleground);
-	setflag(nozenypenalty);		setflag(notrade);			setflag(noskill);				setflag(nowarp);
-	setflag(nowarpto);			setflag(noicewall);			setflag(snow);					setflag(clouds);
-	setflag(clouds2);			setflag(fog);				setflag(fireworks);				setflag(sakura);
-	setflag(leaves);			setflag(nogo);				setflag(nobaseexp);				setflag(nojobexp);
-	setflag(nomobloot);			setflag(nomvploot);			setflag(nightenabled);			setflag(restricted);
-	setflag(nodrop);			setflag(novending);			setflag(loadevent);				setflag(nochat);
-	setflag(partylock);			setflag(guildlock);			setflag(reset);					setflag(chmautojoin);
-	setflag(nousecart);			setflag(noitemconsumption);	setflag(nosumstarmiracle);		setflag(nomineeffect);
-	setflag(nolockon);			setflag(notomb);			setflag(nocostume);				setflag(gvg_te);
-	setflag(gvg_te_castle);		setflag(hidemobhpbar);
-#ifdef ADJUST_SKILL_DAMAGE
-	setflag(skill_damage);
-#endif
 
-	clif_displaymessage(sd->fd,msg_txt(sd,1314)); // Invalid flag name or flag.
-	clif_displaymessage(sd->fd,msg_txt(sd,1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On)
+	// Check if the list of mapflags was requested
+	if( strcasecmp(flag_name,"available") ){
+		for (i = 0; flag_name[i]; i++) flag_name[i] = (char)tolower(flag_name[i]); //lowercase
+
+		enum e_mapflag mapflag = map_getmapflag_by_name(flag_name);
+
+		if( mapflag != MF_INVALID ){
+			map_setmapflag(sd->bl.m, static_cast<e_mapflag>(mapflag), flag != 0);
+			sprintf(atcmd_output,"[ @mapflag ] %s flag has been set to %s value = %hd",flag_name,flag?"On":"Off",flag);
+			clif_displaymessage(sd->fd,atcmd_output);
+			return 0;
+		}else{
+			clif_displaymessage(sd->fd, msg_txt(sd, 1314)); // Invalid flag name or flag.
+			clif_displaymessage(sd->fd, msg_txt(sd, 1313)); // Type "@mapflag available" to list the available mapflags.
+			return 1;
+		}
+	}
+
 	clif_displaymessage(sd->fd,msg_txt(sd,1315)); // Available Flags:
 	clif_displaymessage(sd->fd,"----------------------------------");
-	clif_displaymessage(sd->fd,"town, autotrade, allowks, nomemo, noteleport, noreturn, monster_noteleport, nosave,");
-	clif_displaymessage(sd->fd,"nobranch, noexppenalty, pvp, pvp_noparty, pvp_noguild, pvp_nightmaredrop,");
-	clif_displaymessage(sd->fd,"pvp_nocalcrank, gvg_castle, gvg, gvg_dungeon, gvg_noparty, battleground,");
-	clif_displaymessage(sd->fd,"nozenypenalty, notrade, noskill, nowarp, nowarpto, noicewall, snow, clouds, clouds2,");
-	clif_displaymessage(sd->fd,"fog, fireworks, sakura, leaves, nogo, nobaseexp, nojobexp, nomobloot, nomvploot,");
-	clif_displaymessage(sd->fd,"nightenabled, restricted, nodrop, novending, loadevent, nochat, partylock, guildlock,");
-	clif_displaymessage(sd->fd,"reset, chmautojoin, nousecart, noitemconsumption, nosumstarmiracle, nolockon, notomb,");
-	clif_displaymessage(sd->fd,"nocostume, gvg_te, gvg_te_castle, hidemobhpbar");
-#ifdef ADJUST_SKILL_DAMAGE
-	clif_displaymessage(sd->fd,"skill_damage");
-#endif
+	StringBuf_Init(&buf);
+	for( i = MF_MIN, j = 0; i < MF_MAX; i++ ){
+		if( map_getmapflag_name( static_cast<e_mapflag>(i), flag_name ) ){
+			StringBuf_AppendStr( &buf, flag_name );
 
-#undef checkflag
-#undef setflag
+			if( (i + 1) < MF_MAX ){
+				StringBuf_AppendStr( &buf, ", " );
+			}
+
+			j++;
+		}
+
+		if( i > MF_MIN && ( j == 6 || ( i + 1 ) == MF_MAX ) ){
+			clif_displaymessage(sd->fd, StringBuf_Value(&buf) );
+			StringBuf_Clear(&buf);
+			j = 0;
+		}
+	}
+	StringBuf_Destroy(&buf);
+	clif_displaymessage(sd->fd, msg_txt(sd, 1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On)
 
 	return 0;
 }
@@ -8671,11 +8651,11 @@ ACMD_FUNC(allowks)
 {
 	nullpo_retr(-1,sd);
 
-	if( map[sd->bl.m].flag.allowks ) {
-		map[sd->bl.m].flag.allowks = 0;
+	if( map_getmapflag(sd->bl.m, MF_ALLOWKS) ) {
+		map_setmapflag(sd->bl.m, MF_ALLOWKS, false);
 		clif_displaymessage(fd, msg_txt(sd,1330)); // [ Map K.S Protection Active ]
 	} else {
-		map[sd->bl.m].flag.allowks = 1;
+		map_setmapflag(sd->bl.m, MF_ALLOWKS, true);
 		clif_displaymessage(fd, msg_txt(sd,1331)); // [ Map K.S Protection Inactive ]
 	}
 	return 0;
@@ -10480,7 +10460,7 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
 	// type value 0|2 = script|console invoked: bypass restrictions
 	if ( type == 1 || type == 3) {
 		//Commands are disabled on maps flagged as 'nocommand'
-		if ( map[sd->bl.m].nocommand && pc_get_group_level(sd) < map[sd->bl.m].nocommand ) {
+		if ( pc_get_group_level(sd) < map_getmapflag(sd->bl.m, MF_NOCOMMAND) ) {
 			clif_displaymessage(fd, msg_txt(sd,143)); // Commands are disabled on this map.
 			return false;
 		}

+ 40 - 89
src/map/battle.cpp

@@ -1575,7 +1575,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 	} //End of caster SC_ check
 
 	//PK damage rates
-	if (battle_config.pk_mode && sd && bl->type == BL_PC && damage && map[bl->m].flag.pvp) {
+	if (battle_config.pk_mode && sd && bl->type == BL_PC && damage && map_getmapflag(bl->m, MF_PVP)) {
 		if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex]
 			if (flag&BF_WEAPON)
 				damage = damage * battle_config.pk_weapon_damage_rate / 100;
@@ -2157,24 +2157,19 @@ static int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id)
 }
 
 #ifdef ADJUST_SKILL_DAMAGE
-/**
- * Damage calculation for adjusting skill damage
- * @param caster Applied caster type for damage skill
- * @param type BL_Type of attacker
- */
-static bool battle_skill_damage_iscaster(uint8 caster, enum bl_type src_type) {
-	if (caster == 0)
-		return false;
-
-	switch (src_type) {
-		case BL_PC: if (caster&SDC_PC) return true; break;
-		case BL_MOB: if (caster&SDC_MOB) return true; break;
-		case BL_PET: if (caster&SDC_PET) return true; break;
-		case BL_HOM: if (caster&SDC_HOM) return true; break;
-		case BL_MER: if (caster&SDC_MER) return true; break;
-		case BL_ELEM: if (caster&SDC_ELEM) return true; break;
+static enum e_skill_damage_type battle_skill_damage_type( struct block_list* bl ){
+	switch( bl->type ){
+		case BL_PC:
+			return SKILLDMG_PC;
+		case BL_MOB:
+			if( status_get_class_(bl) == CLASS_BOSS ){
+				return SKILLDMG_BOSS;
+			}else{
+				return SKILLDMG_MOB;
+			}
+		default:
+			return SKILLDMG_OTHER;
 	}
-	return false;
 }
 
 /**
@@ -2187,7 +2182,6 @@ static bool battle_skill_damage_iscaster(uint8 caster, enum bl_type src_type) {
 static int battle_skill_damage_skill(struct block_list *src, struct block_list *target, uint16 skill_id) {
 	uint16 idx = skill_get_index(skill_id), m = src->m;
 	struct s_skill_damage *damage = NULL;
-	struct map_data *mapd = &map[m];
 
 	if (!idx || !skill_db[idx]->damage.map)
 		return 0;
@@ -2195,27 +2189,17 @@ static int battle_skill_damage_skill(struct block_list *src, struct block_list *
 	damage = &skill_db[idx]->damage;
 
 	//check the adjustment works for specified type
-	if (!battle_skill_damage_iscaster(damage->caster, src->type))
+	if (!(damage->caster&src->type))
 		return 0;
 
-	if ((damage->map&1 && (!mapd->flag.pvp && !map_flag_gvg2(m) && !mapd->flag.battleground && !mapd->flag.skill_damage && !mapd->flag.restricted)) ||
-		(damage->map&2 && mapd->flag.pvp) ||
+	if ((damage->map&1 && (!map_getmapflag(m, MF_PVP) && !map_flag_gvg2(m) && !map_getmapflag(m, MF_BATTLEGROUND) && !map_getmapflag(m, MF_SKILL_DAMAGE) && !map_getmapflag(m, MF_RESTRICTED))) ||
+		(damage->map&2 && map_getmapflag(m, MF_PVP)) ||
 		(damage->map&4 && map_flag_gvg2(m)) ||
-		(damage->map&8 && mapd->flag.battleground) ||
-		(damage->map&16 && mapd->flag.skill_damage) ||
-		(mapd->flag.restricted && damage->map&(8*mapd->zone)))
+		(damage->map&8 && map_getmapflag(m, MF_BATTLEGROUND)) ||
+		(damage->map&16 && map_getmapflag(m, MF_SKILL_DAMAGE)) ||
+		(map_getmapflag(m, MF_RESTRICTED) && damage->map&(8*map[m].zone)))
 	{
-		switch (target->type) {
-			case BL_PC:
-				return damage->pc;
-			case BL_MOB:
-				if (status_get_class_(target) == CLASS_BOSS)
-					return damage->boss;
-				else
-					return damage->mob;
-			default:
-				return damage->other;
-		}
+		return damage->rate[battle_skill_damage_type(target)];
 	}
 
 	return 0;
@@ -2230,55 +2214,22 @@ static int battle_skill_damage_skill(struct block_list *src, struct block_list *
  */
 static int battle_skill_damage_map(struct block_list *src, struct block_list *target, uint16 skill_id) {
 	int rate = 0;
-	uint8 i = 0;
-	struct map_data *mapd = NULL;
+	struct map_data *mapd = &map[src->m];
 
-	mapd = &map[src->m];
-
-	if (!mapd || !mapd->flag.skill_damage)
+	if (!mapd || !map_getmapflag(src->m, MF_SKILL_DAMAGE))
 		return 0;
 
 	// Damage rate for all skills at this map
-	if (battle_skill_damage_iscaster(mapd->adjust.damage.caster, src->type)) {
-		switch (target->type) {
-			case BL_PC:
-				rate = mapd->adjust.damage.pc;
-				break;
-			case BL_MOB:
-				if (status_get_class_(target) == CLASS_BOSS)
-					rate = mapd->adjust.damage.boss;
-				else
-					rate = mapd->adjust.damage.mob;
-				break;
-			default:
-				rate = mapd->adjust.damage.other;
-				break;
-		}
-	}
+	if (mapd->damage_adjust.caster&src->type)
+		rate = mapd->damage_adjust.rate[battle_skill_damage_type(target)];
 
-	if (!mapd->skill_damage.count)
+	if (mapd->skill_damage.empty())
 		return rate;
 
 	// Damage rate for specified skill at this map
-	for (i = 0; i < mapd->skill_damage.count; i++) {
-		if (mapd->skill_damage.entries[i]->skill_id == skill_id &&
-			battle_skill_damage_iscaster(mapd->skill_damage.entries[i]->caster, src->type))
-		{
-			switch (target->type) {
-				case BL_PC:
-					rate += mapd->skill_damage.entries[i]->pc;
-					break;
-				case BL_MOB:
-					if (status_get_class_(target) == CLASS_BOSS)
-						rate += mapd->skill_damage.entries[i]->boss;
-					else
-						rate += mapd->skill_damage.entries[i]->mob;
-					break;
-				default:
-					rate += mapd->skill_damage.entries[i]->other;
-					break;
-			}
-		}
+	for (int i = 0; i < mapd->skill_damage.size(); i++) {
+		if (mapd->skill_damage[i].skill_id == skill_id && mapd->skill_damage[i].caster&src->type)
+			rate += mapd->skill_damage[i].rate[battle_skill_damage_type(target)];
 	}
 	return rate;
 }
@@ -5111,14 +5062,14 @@ struct Damage battle_calc_attack_gvg_bg(struct Damage wd, struct block_list *src
 			wd.damage = battle_calc_damage(src,target,&wd,wd.damage,skill_id,skill_lv);
 			if( map_flag_gvg2(target->m) )
 				wd.damage=battle_calc_gvg_damage(src,target,wd.damage,skill_id,wd.flag);
-			else if( map[target->m].flag.battleground )
+			else if( map_getmapflag(target->m, MF_BATTLEGROUND) )
 				wd.damage=battle_calc_bg_damage(src,target,wd.damage,skill_id,wd.flag);
 		}
 		else if(!wd.damage) {
 			wd.damage2 = battle_calc_damage(src,target,&wd,wd.damage2,skill_id,skill_lv);
 			if( map_flag_gvg2(target->m) )
 				wd.damage2 = battle_calc_gvg_damage(src,target,wd.damage2,skill_id,wd.flag);
-			else if( map[target->m].flag.battleground )
+			else if( map_getmapflag(target->m, MF_BATTLEGROUND) )
 				wd.damage2 = battle_calc_bg_damage(src,target,wd.damage2,skill_id,wd.flag);
 		}
 		else {
@@ -5126,7 +5077,7 @@ struct Damage battle_calc_attack_gvg_bg(struct Damage wd, struct block_list *src
 			wd.damage = battle_calc_damage(src,target,&wd,d1,skill_id,skill_lv);
 			if( map_flag_gvg2(target->m) )
 				wd.damage = battle_calc_gvg_damage(src,target,wd.damage,skill_id,wd.flag);
-			else if( map[target->m].flag.battleground )
+			else if( map_getmapflag(target->m, MF_BATTLEGROUND) )
 				wd.damage = battle_calc_bg_damage(src,target,wd.damage,skill_id,wd.flag);
 			wd.damage2 = (int64)d2*100/d1 * wd.damage/100;
 			if(wd.damage > 1 && wd.damage2 < 1) wd.damage2 = 1;
@@ -6441,7 +6392,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 	ad.damage = battle_calc_damage(src,target,&ad,ad.damage,skill_id,skill_lv);
 	if (map_flag_gvg2(target->m))
 		ad.damage = battle_calc_gvg_damage(src,target,ad.damage,skill_id,ad.flag);
-	else if (map[target->m].flag.battleground)
+	else if (map_getmapflag(target->m, MF_BATTLEGROUND))
 		ad.damage = battle_calc_bg_damage(src,target,ad.damage,skill_id,ad.flag);
 
 	// Skill damage adjustment
@@ -6837,7 +6788,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 	md.damage = battle_calc_damage(src,target,&md,md.damage,skill_id,skill_lv);
 	if(map_flag_gvg2(target->m))
 		md.damage = battle_calc_gvg_damage(src,target,md.damage,skill_id,md.flag);
-	else if(map[target->m].flag.battleground)
+	else if(map_getmapflag(target->m, MF_BATTLEGROUND))
 		md.damage = battle_calc_bg_damage(src,target,md.damage,skill_id,md.flag);
 
 	// Skill damage adjustment
@@ -7756,7 +7707,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 						case NC_AXETORNADO:
 						case SR_SKYNETBLOW:
 							// Can only hit traps in PVP/GVG maps
-							if (!map[m].flag.pvp && !map[m].flag.gvg)
+							if (!map_getmapflag(m, MF_PVP) && !map_getmapflag(m, MF_GVG))
 								return 0;
 							break;
 					}
@@ -7773,7 +7724,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 					case NC_AXETORNADO:
 					case SR_SKYNETBLOW:
 						// Can only hit icewall in PVP/GVG maps
-						if (!map[m].flag.pvp && !map[m].flag.gvg)
+						if (!map_getmapflag(m, MF_PVP) && !map_getmapflag(m, MF_GVG))
 							return 0;
 						break;
 					case HT_CLAYMORETRAP:
@@ -7877,7 +7828,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 					state |= BCT_ENEMY; // Can kill anything
 					strip_enemy = 0;
 				}
-				else if( sd->duel_group && !((!battle_config.duel_allow_pvp && map[m].flag.pvp) || (!battle_config.duel_allow_gvg && map_flag_gvg(m))) )
+				else if( sd->duel_group && !((!battle_config.duel_allow_pvp && map_getmapflag(m, MF_PVP)) || (!battle_config.duel_allow_gvg && map_flag_gvg(m))) )
 				{
 					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.
@@ -7942,7 +7893,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 	if( map_flag_vs(m) )
 	{ //Check rivalry settings.
 		int sbg_id = 0, tbg_id = 0;
-		if( map[m].flag.battleground )
+		if( map_getmapflag(m, MF_BATTLEGROUND) )
 		{
 			sbg_id = bg_team_get_id(s_bl);
 			tbg_id = bg_team_get_id(t_bl);
@@ -7950,7 +7901,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 		if( flag&(BCT_PARTY|BCT_ENEMY) )
 		{
 			int s_party = status_get_party_id(s_bl);
-			if( s_party && s_party == status_get_party_id(t_bl) && !(map[m].flag.pvp && map[m].flag.pvp_noparty) && !(map_flag_gvg(m) && map[m].flag.gvg_noparty) && (!map[m].flag.battleground || sbg_id == tbg_id) )
+			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) )
 				state |= BCT_PARTY;
 			else
 				state |= BCT_ENEMY;
@@ -7959,12 +7910,12 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 		{
 			int s_guild = status_get_guild_id(s_bl);
 			int t_guild = status_get_guild_id(t_bl);
-			if( !(map[m].flag.pvp && map[m].flag.pvp_noguild) && s_guild && t_guild && (s_guild == t_guild || (!(flag&BCT_SAMEGUILD) && guild_isallied(s_guild, t_guild))) && (!map[m].flag.battleground || sbg_id == tbg_id) )
+			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) )
 				state |= BCT_GUILD;
 			else
 				state |= BCT_ENEMY;
 		}
-		if( state&BCT_ENEMY && map[m].flag.battleground && sbg_id && sbg_id == tbg_id )
+		if( state&BCT_ENEMY && map_getmapflag(m, MF_BATTLEGROUND) && sbg_id && sbg_id == tbg_id )
 			state &= ~BCT_ENEMY;
 
 		if( state&BCT_ENEMY && battle_config.pk_mode && !map_flag_gvg(m) && s_bl->type == BL_PC && t_bl->type == BL_PC )

+ 2 - 2
src/map/buyingstore.cpp

@@ -78,7 +78,7 @@ int8 buyingstore_setup(struct map_session_data* sd, unsigned char slots){
 		return 2;
 	}
 
-	if( map[sd->bl.m].flag.novending )
+	if( map_getmapflag(sd->bl.m, MF_NOVENDING) )
 	{// custom: no vending maps
 		clif_displaymessage(sd->fd, msg_txt(sd,276)); // "You can't open a shop on this map"
 		return 3;
@@ -146,7 +146,7 @@ int8 buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
 		return 2;
 	}
 
-	if( map[sd->bl.m].flag.novending )
+	if( map_getmapflag(sd->bl.m, MF_NOVENDING) )
 	{// custom: no vending maps
 		clif_displaymessage(sd->fd, msg_txt(sd,276)); // "You can't open a shop on this map"
 		return 3;

+ 1 - 1
src/map/chat.cpp

@@ -86,7 +86,7 @@ int chat_createpcchat(struct map_session_data* sd, const char* title, const char
 	if( sd->state.vending || sd->state.buyingstore ) // not chat, when you already have a store open
 		return 0;
 
-	if( map[sd->bl.m].flag.nochat ) {
+	if( map_getmapflag(sd->bl.m, MF_NOCHAT) ) {
 		clif_displaymessage(sd->fd, msg_txt(sd,281));
 		return 0; //Can't create chatrooms on this map.
 	}

+ 2 - 2
src/map/chrif.cpp

@@ -400,9 +400,9 @@ int chrif_sendmap(int fd) {
 	ShowStatus("Sending maps to char server...\n");
 
 	// Sending normal maps, not instances
-	WFIFOHEAD(fd, 4 + instance_start * 4);
+	WFIFOHEAD(fd, 4 + map.size() * 4);
 	WFIFOW(fd,0) = 0x2afa;
-	for(i = 0; i < instance_start; i++)
+	for(i = 0; i < map.size(); i++)
 		WFIFOW(fd,4+i*4) = map[i].index;
 	WFIFOW(fd,2) = 4 + i * 4;
 	WFIFOSET(fd,WFIFOW(fd,2));

+ 59 - 59
src/map/clif.cpp

@@ -1120,7 +1120,7 @@ static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool
 	WBUFW(buf,53) = (sd ? sd->status.font : 0);
 #endif
 #if PACKETVER >= 20120221
-	if ( battle_config.monster_hp_bars_info && !map[bl->m].flag.hidemobhpbar && bl->type == BL_MOB && (status_get_hp(bl) < status_get_max_hp(bl)) ) {
+	if ( battle_config.monster_hp_bars_info && !map_getmapflag(bl->m, MF_HIDEMOBHPBAR) && bl->type == BL_MOB && (status_get_hp(bl) < status_get_max_hp(bl)) ) {
 		WBUFL(buf,55) = status_get_max_hp(bl);		// maxHP
 		WBUFL(buf,59) = status_get_hp(bl);		// HP
 	} else {
@@ -1263,7 +1263,7 @@ static int clif_set_unit_walking(struct block_list* bl, struct unit_data* ud, un
 	WBUFW(buf,60) = (sd ? sd->status.font : 0);
 #endif
 #if PACKETVER >= 20120221
-	if ( battle_config.monster_hp_bars_info && !map[bl->m].flag.hidemobhpbar && bl->type == BL_MOB && (status_get_hp(bl) < status_get_max_hp(bl)) ) {
+	if ( battle_config.monster_hp_bars_info && !map_getmapflag(bl->m, MF_HIDEMOBHPBAR) && bl->type == BL_MOB && (status_get_hp(bl) < status_get_max_hp(bl)) ) {
 		WBUFL(buf,62) = status_get_max_hp(bl);		// maxHP
 		WBUFL(buf,66) = status_get_hp(bl);		// HP
 	} else {
@@ -1361,30 +1361,30 @@ static void clif_weather_check(struct map_session_data *sd)
 	int16 m = sd->bl.m;
 	int fd = sd->fd;
 
-	if (map[m].flag.snow
-		|| map[m].flag.clouds
-		|| map[m].flag.fog
-		|| map[m].flag.fireworks
-		|| map[m].flag.sakura
-		|| map[m].flag.leaves
-		|| map[m].flag.clouds2)
+	if (map_getmapflag(m, MF_SNOW)
+		|| map_getmapflag(m, MF_CLOUDS)
+		|| map_getmapflag(m, MF_FOG)
+		|| map_getmapflag(m, MF_FIREWORKS)
+		|| map_getmapflag(m, MF_SAKURA)
+		|| map_getmapflag(m, MF_LEAVES)
+		|| map_getmapflag(m, MF_CLOUDS2))
 	{
-		if (map[m].flag.snow)
+		if (map_getmapflag(m, MF_SNOW))
 			clif_specialeffect_single(&sd->bl, EF_SNOW, fd);
-		if (map[m].flag.clouds)
+		if (map_getmapflag(m, MF_CLOUDS))
 			clif_specialeffect_single(&sd->bl, EF_CLOUD3, fd);
-		if (map[m].flag.clouds2)
+		if (map_getmapflag(m, MF_CLOUDS2))
 			clif_specialeffect_single(&sd->bl, EF_CLOUD5, fd);
-		if (map[m].flag.fog)
+		if (map_getmapflag(m, MF_FOG))
 			clif_specialeffect_single(&sd->bl, EF_CLOUD4, fd);
-		if (map[m].flag.fireworks) {
+		if (map_getmapflag(m, MF_FIREWORKS)) {
 			clif_specialeffect_single(&sd->bl, EF_POKJUK, fd);
 			clif_specialeffect_single(&sd->bl, EF_THROWITEM2, fd);
 			clif_specialeffect_single(&sd->bl, EF_POKJUK_SOUND, fd);
 		}
-		if (map[m].flag.sakura)
+		if (map_getmapflag(m, MF_SAKURA))
 			clif_specialeffect_single(&sd->bl, EF_SAKURA, fd);
-		if (map[m].flag.leaves)
+		if (map_getmapflag(m, MF_LEAVES))
 			clif_specialeffect_single(&sd->bl, EF_MAPLE, fd);
 	}
 }
@@ -1445,7 +1445,7 @@ int clif_spawn(struct block_list *bl)
 				clif_specialeffect(bl,EF_GIANTBODY2,AREA);
 			else if(sd->state.size==SZ_MEDIUM)
 				clif_specialeffect(bl,EF_BABYBODY2,AREA);
-			if( sd->bg_id && map[sd->bl.m].flag.battleground )
+			if( sd->bg_id && map_getmapflag(sd->bl.m, MF_BATTLEGROUND) )
 				clif_sendbgemblem_area(sd);
 			if (sd->spiritcharm_type != CHARM_TYPE_NONE && sd->spiritcharm > 0)
 				clif_spiritcharm(sd);
@@ -4642,7 +4642,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl)
 				clif_specialeffect_single(bl,EF_GIANTBODY2,sd->fd);
 			else if(tsd->state.size==SZ_MEDIUM)
 				clif_specialeffect_single(bl,EF_BABYBODY2,sd->fd);
-			if( tsd->bg_id && map[tsd->bl.m].flag.battleground )
+			if( tsd->bg_id && map_getmapflag(tsd->bl.m, MF_BATTLEGROUND) )
 				clif_sendbgemblem_single(sd->fd,tsd);
 			if ( tsd->status.robe )
 				clif_refreshlook(&sd->bl,bl->id,LOOK_ROBE,tsd->status.robe,SELF);
@@ -4675,7 +4675,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl)
 			else if(md->special_state.size==SZ_MEDIUM)
 				clif_specialeffect_single(bl,EF_BABYBODY2,sd->fd);
 #if PACKETVER >= 20120404
-			if (battle_config.monster_hp_bars_info && !map[bl->m].flag.hidemobhpbar) {
+			if (battle_config.monster_hp_bars_info && !map_getmapflag(bl->m, MF_HIDEMOBHPBAR)) {
 				int i;
 				for(i = 0; i < DAMAGELOG_SIZE; i++)// must show hp bar to all char who already hit the mob.
 					if( md->dmglog[i].id == sd->status.char_id )
@@ -6343,17 +6343,17 @@ void clif_map_property(struct block_list *bl, enum map_property property, enum s
 	WBUFW(buf,2)=property;
 
 #if PACKETVER >= 20121010
-	WBUFL(buf,4) = ((map[bl->m].flag.pvp?1:0)<<0)| // PARTY - Show attack cursor on non-party members (PvP)
-		((map[bl->m].flag.battleground || map_flag_gvg2(bl->m)?1:0)<<1)|// GUILD - Show attack cursor on non-guild members (GvG)
-		((map[bl->m].flag.battleground || map_flag_gvg2(bl->m)?1:0)<<2)|// SIEGE - Show emblem over characters heads when in GvG (WoE castle)
-		((map[bl->m].flag.nomineeffect || !map_flag_gvg2(bl->m)?0:1)<<3)| // USE_SIMPLE_EFFECT - Automatically enable /mineffect
-		((map[bl->m].flag.nolockon || map_flag_vs(bl->m)?1:0)<<4)| // DISABLE_LOCKON - Only allow attacks on other players with shift key or /ns active
-		((map[bl->m].flag.pvp?1:0)<<5)| // COUNT_PK - Show the PvP counter
-		((map[bl->m].flag.partylock?1:0)<<6)| // NO_PARTY_FORMATION - Prevents party creation/modification (Might be used for instance dungeons)
-		((map[bl->m].flag.battleground?1:0)<<7)| // BATTLEFIELD - Unknown (Does something for battlegrounds areas)
-		((map[bl->m].flag.nocostume?1:0)<<8)| // DISABLE_COSTUMEITEM - Disable costume sprites
-		((map[bl->m].flag.nousecart?0:1)<<9)| // USECART - Allow opening cart inventory (Well force it to always allow it)
-		((map[bl->m].flag.nosumstarmiracle?0:1)<<10); // SUNMOONSTAR_MIRACLE - Unknown - (Guessing it blocks Star Gladiator's Miracle from activating)
+	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
 		//(1<<11); // Unused bits. 1 - 10 is 0x1 length and 11 is 0x15 length. May be used for future settings.
 #endif
 	
@@ -10088,7 +10088,7 @@ static bool clif_process_message(struct map_session_data* sd, bool whisperFormat
 inline void clif_pk_mode_message(struct map_session_data * sd)
 {
 	if (battle_config.pk_mode && battle_config.pk_mode_mes &&
-		sd && map[sd->bl.m].flag.pvp) {
+		sd && map_getmapflag(sd->bl.m, MF_PVP)) {
 		if( (int)sd->status.base_level < battle_config.pk_min_level ) {
 			char output[CHAT_SIZE_MAX];
 			// 1504: You've entered a PK Zone (safe until level %d).
@@ -10331,9 +10331,9 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 
 	if( sd->bg_id ) clif_bg_hp(sd); // BattleGround System
 
-	if(map[sd->bl.m].flag.pvp && !pc_isinvisible(sd)) {
+	if(map_getmapflag(sd->bl.m, MF_PVP) && !pc_isinvisible(sd)) {
 		if(!battle_config.pk_mode) { // remove pvp stuff for pk_mode [Valaris]
-			if (!map[sd->bl.m].flag.pvp_nocalcrank)
+			if (!map_getmapflag(sd->bl.m, MF_PVP_NOCALCRANK))
 				sd->pvp_timer = add_timer(gettick()+200, pc_calc_pvprank_timer, sd->bl.id, 0);
 			sd->pvp_rank = 0;
 			sd->pvp_lastusers = 0;
@@ -10344,7 +10344,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 		clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF);
 	} else if(sd->duel_group) // set flag, if it's a duel [LuzZza]
 		clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF);
-	else if (map[sd->bl.m].flag.gvg_dungeon)
+	else if (map_getmapflag(sd->bl.m, MF_GVG_DUNGEON))
 		clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF); //TODO: Figure out the real packet to send here.
 	else if( map_flag_gvg(sd->bl.m) )
 		clif_map_property(&sd->bl, MAPPROPERTY_AGITZONE, SELF);
@@ -10443,7 +10443,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 		if(hom_is_active(sd->hd))
 			hom_init_timers(sd->hd);
 
-		if (night_flag && map[sd->bl.m].flag.nightenabled) {
+		if (night_flag && map_getmapflag(sd->bl.m, MF_NIGHTENABLED)) {
 			sd->state.night = 1;
 			clif_status_load(&sd->bl, EFST_SKE, 1);
 		}
@@ -10500,10 +10500,10 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 		}
 
 		if( (battle_config.bg_flee_penalty != 100 || battle_config.gvg_flee_penalty != 100) &&
-			(map_flag_gvg(sd->state.pmap) || map_flag_gvg(sd->bl.m) || map[sd->state.pmap].flag.battleground || map[sd->bl.m].flag.battleground) )
+			(map_flag_gvg(sd->state.pmap) || map_flag_gvg(sd->bl.m) || map_getmapflag(sd->state.pmap, MF_BATTLEGROUND) || map_getmapflag(sd->bl.m, MF_BATTLEGROUND)) )
 			status_calc_bl(&sd->bl, SCB_FLEE); //Refresh flee penalty
 
-		if( night_flag && map[sd->bl.m].flag.nightenabled )
+		if( night_flag && map_getmapflag(sd->bl.m, MF_NIGHTENABLED) )
 		{	//Display night.
 			if( !sd->state.night )
 			{
@@ -10517,14 +10517,14 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 			clif_status_load(&sd->bl, EFST_SKE, 0);
 		}
 
-		if( map[sd->bl.m].flag.battleground )
+		if( map_getmapflag(sd->bl.m, MF_BATTLEGROUND) )
 		{
 			clif_map_type(sd, MAPTYPE_BATTLEFIELD); // Battleground Mode
-			if( map[sd->bl.m].flag.battleground == 2 )
+			if( map_getmapflag(sd->bl.m, MF_BATTLEGROUND) == 2 )
 				clif_bg_updatescore_single(sd);
 		}
 
-		if( map[sd->bl.m].flag.allowks && !map_flag_ks(sd->bl.m) )
+		if( map_getmapflag(sd->bl.m, MF_ALLOWKS) && !map_flag_ks(sd->bl.m) )
 		{
 			char output[128];
 			sprintf(output, "[ Kill Steal Protection Disable. KS is allowed in this map ]");
@@ -10544,7 +10544,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 		if (!sd->state.connect_new &&
 			!sd->vip.disableshowrate &&
 			sd->state.pmap != sd->bl.m &&
-			map[sd->state.pmap].adjust.bexp != map[sd->bl.m].adjust.bexp
+			map_getmapflag(sd->state.pmap, MF_BEXP) != map_getmapflag(sd->bl.m, MF_BEXP)
 			)
 		{
 			clif_display_pinfo(sd,ZC_PERSONAL_INFOMATION);
@@ -10553,7 +10553,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 #endif
 
 		// Instances do not need their own channels
-		if( channel_config.map_tmpl.name[0] && (channel_config.map_tmpl.opt&CHAN_OPT_AUTOJOIN) && !map[sd->bl.m].flag.chmautojoin && !map[sd->bl.m].instance_id )
+		if( channel_config.map_tmpl.name[0] && (channel_config.map_tmpl.opt&CHAN_OPT_AUTOJOIN) && !map_getmapflag(sd->bl.m,MF_NOMAPCHANNELAUTOJOIN) && !map[sd->bl.m].instance_id )
 			channel_mjoin(sd); //join new map
 
 		clif_pk_mode_message(sd);
@@ -10579,7 +10579,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 	}
 
 	// Don't trigger NPC event or opening vending/buyingstore will be failed
-	if(!sd->state.autotrade && map[sd->bl.m].flag.loadevent) // Lance
+	if(!sd->state.autotrade && map_getmapflag(sd->bl.m, MF_LOADEVENT)) // Lance
 		npc_script_event(sd, NPCE_LOADMAP);
 
 	if (pc_checkskill(sd, SG_DEVIL) && pc_is_maxjoblv(sd))
@@ -12908,7 +12908,7 @@ void clif_parse_CreateParty(int fd, struct map_session_data *sd){
 	char* name = RFIFOCP(fd,packet_db[RFIFOW(fd,0)].pos[0]);
 	name[NAME_LENGTH-1] = '\0';
 
-	if( map[sd->bl.m].flag.partylock ) {// Party locked.
+	if( map_getmapflag(sd->bl.m, MF_PARTYLOCK) ) {// Party locked.
 		clif_displaymessage(fd, msg_txt(sd,227));
 		return;
 	}
@@ -12928,7 +12928,7 @@ void clif_parse_CreateParty2(int fd, struct map_session_data *sd){
 	int item2 = RFIFOB(fd,info->pos[2]);
 	name[NAME_LENGTH-1] = '\0';
 
-	if( map[sd->bl.m].flag.partylock ) {// Party locked.
+	if( map_getmapflag(sd->bl.m, MF_PARTYLOCK) ) {// Party locked.
 		clif_displaymessage(fd, msg_txt(sd,227));
 		return;
 	}
@@ -12947,7 +12947,7 @@ void clif_parse_PartyInvite(int fd, struct map_session_data *sd)
 {
 	struct map_session_data *t_sd;
 
-	if(map[sd->bl.m].flag.partylock) {// Party locked.
+	if(map_getmapflag(sd->bl.m, MF_PARTYLOCK)) {// Party locked.
 		clif_displaymessage(fd, msg_txt(sd,227));
 		return;
 	}
@@ -12968,7 +12968,7 @@ void clif_parse_PartyInvite2(int fd, struct map_session_data *sd){
 	char *name = RFIFOCP(fd,packet_db[RFIFOW(fd,0)].pos[0]);
 	name[NAME_LENGTH-1] = '\0';
 
-	if(map[sd->bl.m].flag.partylock) {// Party locked.
+	if(map_getmapflag(sd->bl.m, MF_PARTYLOCK)) {// Party locked.
 		clif_displaymessage(fd, msg_txt(sd,227));
 		return;
 	}
@@ -13009,7 +13009,7 @@ void clif_parse_ReplyPartyInvite2(int fd,struct map_session_data *sd)
 /// 0100
 void clif_parse_LeaveParty(int fd, struct map_session_data *sd)
 {
-	if(map[sd->bl.m].flag.partylock) {// Party locked.
+	if(map_getmapflag(sd->bl.m, MF_PARTYLOCK)) {// Party locked.
 		clif_displaymessage(fd, msg_txt(sd,227));
 		return;
 	}
@@ -13022,7 +13022,7 @@ void clif_parse_LeaveParty(int fd, struct map_session_data *sd)
 void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd)
 {
 	struct s_packet_db* info = &packet_db[RFIFOW(fd,0)];
-	if(map[sd->bl.m].flag.partylock) {// Party locked.
+	if(map_getmapflag(sd->bl.m, MF_PARTYLOCK)) {// Party locked.
 		clif_displaymessage(fd, msg_txt(sd,227));
 		return;
 	}
@@ -13337,7 +13337,7 @@ void clif_parse_OpenVending(int fd, struct map_session_data* sd){
 
 	if( sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM )
 		return;
-	if( map[sd->bl.m].flag.novending ) {
+	if( map_getmapflag(sd->bl.m, MF_NOVENDING) ) {
 		clif_displaymessage (sd->fd, msg_txt(sd,276)); // "You can't open a shop on this map"
 		return;
 	}
@@ -13360,7 +13360,7 @@ void clif_parse_CreateGuild(int fd,struct map_session_data *sd){
 	char* name = RFIFOCP(fd,packet_db[RFIFOW(fd,0)].pos[1]);
 	name[NAME_LENGTH-1] = '\0';
 
-	if(map[sd->bl.m].flag.guildlock) { //Guild locked.
+	if(map_getmapflag(sd->bl.m, MF_GUILDLOCK)) { //Guild locked.
 		clif_displaymessage(fd, msg_txt(sd,228));
 		return;
 	}
@@ -13586,7 +13586,7 @@ int clif_sub_guild_invite(int fd, struct map_session_data *sd, struct map_sessio
 	if (t_sd == NULL) // not online or does not exist
 		return 1;
 
-	if (map[sd->bl.m].flag.guildlock) {//Guild locked.
+	if (map_getmapflag(sd->bl.m, MF_GUILDLOCK)) {//Guild locked.
 		clif_displaymessage(fd, msg_txt(sd,228));
 		return 1;
 	}
@@ -13644,7 +13644,7 @@ void clif_parse_GuildReplyInvite(int fd,struct map_session_data *sd){
 /// 0159 <guild id>.L <account id>.L <char id>.L <reason>.40B
 void clif_parse_GuildLeave(int fd,struct map_session_data *sd){
 	struct s_packet_db* info = &packet_db[RFIFOW(fd,0)];
-	if(map[sd->bl.m].flag.guildlock) { //Guild locked.
+	if(map_getmapflag(sd->bl.m, MF_GUILDLOCK)) { //Guild locked.
 		clif_displaymessage(fd, msg_txt(sd,228));
 		return;
 	}
@@ -13664,7 +13664,7 @@ void clif_parse_GuildLeave(int fd,struct map_session_data *sd){
 /// 015b <guild id>.L <account id>.L <char id>.L <reason>.40B
 void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd){
 	struct s_packet_db* info = &packet_db[RFIFOW(fd,0)];
-	if( map[sd->bl.m].flag.guildlock || sd->bg_id )
+	if( map_getmapflag(sd->bl.m, MF_GUILDLOCK) || sd->bg_id )
 	{ // Guild locked.
 		clif_displaymessage(fd, msg_txt(sd,228));
 		return;
@@ -13701,7 +13701,7 @@ void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd)
 	if(!sd->state.gmaster_flag)
 		return;
 
-	if(map[sd->bl.m].flag.guildlock) { //Guild locked.
+	if(map_getmapflag(sd->bl.m, MF_GUILDLOCK)) { //Guild locked.
 		clif_displaymessage(fd, msg_txt(sd,228));
 		return;
 	}
@@ -13743,7 +13743,7 @@ void clif_parse_GuildDelAlliance(int fd, struct map_session_data *sd){
 	if(!sd->state.gmaster_flag)
 		return;
 
-	if(map[sd->bl.m].flag.guildlock) { //Guild locked.
+	if(map_getmapflag(sd->bl.m, MF_GUILDLOCK)) { //Guild locked.
 		clif_displaymessage(fd, msg_txt(sd,228));
 		return;
 	}
@@ -13762,7 +13762,7 @@ void clif_parse_GuildOpposition(int fd, struct map_session_data *sd)
 	if(!sd->state.gmaster_flag)
 		return;
 
-	if(map[sd->bl.m].flag.guildlock) { //Guild locked.
+	if(map_getmapflag(sd->bl.m, MF_GUILDLOCK)) { //Guild locked.
 		clif_displaymessage(fd, msg_txt(sd,228));
 		return;
 	}
@@ -13786,7 +13786,7 @@ void clif_parse_GuildOpposition(int fd, struct map_session_data *sd)
 ///     field name and size is same as the one in CH_DELETE_CHAR.
 void clif_parse_GuildBreak(int fd, struct map_session_data *sd)
 {
-	if( map[sd->bl.m].flag.guildlock ) { //Guild locked.
+	if( map_getmapflag(sd->bl.m, MF_GUILDLOCK) ) { //Guild locked.
 		clif_displaymessage(fd, msg_txt(sd,228));
 		return;
 	}
@@ -18787,7 +18787,7 @@ void clif_display_pinfo(struct map_session_data *sd, int cmdtype) {
 		 * Set for EXP
 		 */
 		//0:PCRoom
-		details_bexp[0] = map[sd->bl.m].adjust.bexp;
+		details_bexp[0] = map_getmapflag(sd->bl.m, MF_BEXP);
 		if (details_bexp[0] == 100 || !details_bexp[0])
 			details_bexp[0] = 0;
 		else {

+ 0 - 2
src/map/instance.cpp

@@ -25,8 +25,6 @@
 
 #define INSTANCE_INTERVAL	60000	// Interval used to check when an instance is to be destroyed (ms)
 
-int instance_start = 0; // To keep the last index + 1 of normal map inserted in the map[ARRAY]
-
 struct instance_data instance_data[MAX_INSTANCE_DATA];
 struct eri *instance_maps_ers = NULL; ///< Array of maps per instance
 

+ 0 - 1
src/map/instance.hpp

@@ -72,7 +72,6 @@ struct instance_db {
 	uint8 maplist_count; ///< Number of used maps
 };
 
-extern int instance_start;
 extern struct instance_data instance_data[MAX_INSTANCE_DATA];
 
 struct instance_db *instance_searchtype_db(unsigned short instance_id);

+ 3 - 3
src/map/itemdb.cpp

@@ -1582,11 +1582,11 @@ bool itemdb_isNoEquip(struct item_data *id, uint16 m) {
 	if (!id->flag.no_equip)
 		return false;
 	if ((!map_flag_vs2(m) && id->flag.no_equip&1) || // Normal
-		(map[m].flag.pvp && id->flag.no_equip&2) || // PVP
+		(map_getmapflag(m, MF_PVP) && id->flag.no_equip&2) || // PVP
 		(map_flag_gvg2_no_te(m) && id->flag.no_equip&4) || // GVG
-		(map[m].flag.battleground && id->flag.no_equip&8) || // Battleground
+		(map_getmapflag(m, MF_BATTLEGROUND) && id->flag.no_equip&8) || // Battleground
 		(map_flag_gvg2_te(m) && id->flag.no_equip&16) || // WOE:TE
-		(map[m].flag.restricted && id->flag.no_equip&(8*map[m].zone)) // Zone restriction
+		(map_getmapflag(m, MF_RESTRICTED) && id->flag.no_equip&(8*map[m].zone)) // Zone restriction
 		)
 		return true;
 	return false;

+ 1 - 1
src/map/mail.cpp

@@ -326,7 +326,7 @@ void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg){
 bool mail_invalid_operation(struct map_session_data *sd)
 {
 #if PACKETVER < 20150513
-	if( !map[sd->bl.m].flag.town && !pc_can_use_command(sd, "mail", COMMAND_ATCOMMAND) )
+	if( !map_getmapflag(sd->bl.m, MF_TOWN) && !pc_can_use_command(sd, "mail", COMMAND_ATCOMMAND) )
 	{
 		ShowWarning("clif_parse_Mail: char '%s' trying to do invalid mail operations.\n", sd->status.name);
 		return true;

+ 418 - 111
src/map/map.cpp

@@ -18,6 +18,7 @@
 #include "../common/socket.hpp" // WFIFO*()
 #include "../common/strlib.hpp"
 #include "../common/timer.hpp"
+#include "../common/utilities.hpp"
 #include "../common/utils.hpp"
 
 #include "achievement.hpp"
@@ -49,6 +50,8 @@
 #include "storage.hpp"
 #include "trade.hpp"
 
+using namespace rathena;
+
 char default_codepage[32] = "";
 
 int map_server_port = 3306;
@@ -119,8 +122,7 @@ static int bl_list_count = 0;
 	#define MAP_MAX_MSG 1550
 #endif
 
-struct map_data map[MAX_MAP_PER_SERVER];
-int map_num = 0;
+std::vector<map_data> map;
 int map_port=0;
 
 int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
@@ -131,10 +133,6 @@ bool agit2_flag = false;
 bool agit3_flag = false;
 int night_flag = 0; // 0=day, 1=night [Yor]
 
-#ifdef ADJUST_SKILL_DAMAGE
-struct eri *map_skill_damage_ers = NULL;
-#endif
-
 struct charid_request {
 	struct charid_request* next;
 	int charid;// who want to be notified of the nick
@@ -311,9 +309,9 @@ int map_addblock(struct block_list* bl)
 	m = bl->m;
 	x = bl->x;
 	y = bl->y;
-	if( m < 0 || m >= map_num )
+	if( m < 0 || m >= map.size() )
 	{
-		ShowError("map_addblock: invalid map id (%d), only %d are loaded.\n", m, map_num);
+		ShowError("map_addblock: invalid map id (%d), only %d are loaded.\n", m, map.size());
 		return 1;
 	}
 	if( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys )
@@ -707,7 +705,7 @@ int map_foreachinareaV(int(*func)(struct block_list*, va_list), int16 m, int16 x
 	int blockcount = bl_list_count, i;
 	va_list ap_copy;
 
-	if (m < 0 || m >= map_num)
+	if (m < 0 || m >= map.size())
 		return 0;
 
 	if (x1 < x0)
@@ -2542,7 +2540,7 @@ bool map_addnpc(int16 m,struct npc_data *nd)
 {
 	nullpo_ret(nd);
 
-	if( m < 0 || m >= map_num )
+	if( m < 0 || m >= map.size() )
 		return false;
 
 	if( map[m].npc_num == MAX_NPC_PER_MAP )
@@ -2563,7 +2561,6 @@ bool map_addnpc(int16 m,struct npc_data *nd)
 int map_addinstancemap(const char *name, unsigned short instance_id)
 {
 	int src_m = map_mapname2mapid(name);
-	int dst_m = -1, i;
 	char iname[MAP_NAME_LENGTH];
 	size_t num_cell, size;
 
@@ -2576,24 +2573,15 @@ int map_addinstancemap(const char *name, unsigned short instance_id)
 		return -2;
 	}
 
-	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);
+	if(map.size() >= MAX_MAP_PER_SERVER) { // Out of bounds
+		ShowError("map_addinstancemap: Failed to add map. Map size (%d) > max maps (%d)\n", map.size(), MAX_MAP_PER_SERVER);
 		return -3;
 	}
 
 	// Copy the map
-	memcpy(&map[dst_m], &map[src_m], sizeof(struct map_data));
-
-	strcpy(iname,name);
+	int dst_m = map.size();
+	map.push_back(map[src_m]);
+	strcpy(iname, name);
 
 	// Alter the name
 	// Due to this being custom we only worry about preserving as many characters as necessary for accurate map distinguishing
@@ -3114,7 +3102,7 @@ void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag)
 {
 	int j;
 
-	if( m < 0 || m >= map_num || x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys )
+	if( m < 0 || m >= map.size() || x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys )
 		return;
 
 	j = x + y*map[m].xs;
@@ -3142,7 +3130,7 @@ void map_setgatcell(int16 m, int16 x, int16 y, int gat)
 	int j;
 	struct mapcell cell;
 
-	if( m < 0 || m >= map_num || x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys )
+	if( m < 0 || m >= map.size() || x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys )
 		return;
 
 	j = x + y*map[m].xs;
@@ -3423,27 +3411,27 @@ int map_addmap(char* mapname)
 {
 	if( strcmpi(mapname,"clear")==0 )
 	{
-		map_num = 0;
-		instance_start = 0;
+		map.clear();
 		return 0;
 	}
 
-	if( map_num >= MAX_MAP_PER_SERVER - 1 )
+	if( map.size() >= MAX_MAP_PER_SERVER )
 	{
 		ShowError("Could not add map '" CL_WHITE "%s" CL_RESET "', the limit of maps has been reached.\n",mapname);
 		return 1;
 	}
 
-	mapindex_getmapname(mapname, map[map_num].name);
-	map_num++;
+	struct map_data entry = {};
+
+	mapindex_getmapname(mapname, entry.name);
+	map.push_back(entry);
 	return 0;
 }
 
 static void map_delmapid(int id)
 {
 	ShowNotice("Removing map [ %s ] from maplist" CL_CLL "\n",map[id].name);
-	memmove(map+id, map+id+1, sizeof(map[0])*(map_num-id-1));
-	map_num--;
+	map.erase(map.begin() + id);
 }
 
 int map_delmap(char* mapname)
@@ -3452,12 +3440,12 @@ int map_delmap(char* mapname)
 	char map_name[MAP_NAME_LENGTH];
 
 	if (strcmpi(mapname, "all") == 0) {
-		map_num = 0;
+		map.clear();
 		return 0;
 	}
 
 	mapindex_getmapname(mapname, map_name);
-	for(i = 0; i < map_num; i++) {
+	for(i = 0; i < map.size(); i++) {
 		if (strcmp(map[i].name, map_name) == 0) {
 			map_delmapid(i);
 			return 1;
@@ -3469,30 +3457,26 @@ int map_delmap(char* mapname)
 /// Initializes map flags and adjusts them depending on configuration.
 void map_flags_init(void)
 {
-	int i;
-
-	for( i = 0; i < map_num; i++ )
+	for( int i = 0; i < map.size(); i++ )
 	{
-		// mapflags
-		memset(&map[i].flag, 0, sizeof(map[i].flag));
+		union u_mapflag_args args = {};
+
+		args.flag_val = 100;
 
 		// additional mapflag data
-		map[i].zone        = 0;  // restricted mapflag zone
-		map[i].nocommand   = 0;  // nocommand mapflag level
-		map[i].adjust.bexp = 100;  // per map base exp multiplicator
-		map[i].adjust.jexp = 100;  // per map job exp multiplicator
-		memset(map[i].drop_list, 0, sizeof(map[i].drop_list));  // pvp nightmare drop list
+		map[i].zone = 0; // restricted mapflag zone
+		map_setmapflag(i, MF_NOCOMMAND, false); // nocommand mapflag level
+		map_setmapflag_sub(i, MF_BEXP, true, &args); // per map base exp multiplicator
+		map_setmapflag_sub(i, MF_JEXP, true, &args); // per map job exp multiplicator
 
 		// skill damage
 #ifdef ADJUST_SKILL_DAMAGE
-		memset(&map[i].adjust.damage, 0, sizeof(map[i].adjust.damage));
-		if (map[i].skill_damage.count)
-			map_skill_damage_free(&map[i]);
+		memset(&map[i].damage_adjust, 0, sizeof(map[i].damage_adjust));
 #endif
 
 		// adjustments
 		if( battle_config.pk_mode )
-			map[i].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris]
+			map_setmapflag(i, MF_PVP, true); // make all maps pvp for pk_mode [Valaris]
 
 		map_free_questinfo(i);
 	}
@@ -3633,14 +3617,14 @@ int map_readallmaps (void)
 		}
 	}
 
-	for(i = 0; i < map_num; i++) {
+	for(i = 0; i < map.size(); i++) {
 		size_t size;
 		bool success = false;
 		unsigned short idx = 0;
 
 		if( enable_grf ){
 			// show progress
-			ShowStatus("Loading maps [%i/%i]: %s" CL_CLL "\r", i, map_num, map[i].name);
+			ShowStatus("Loading maps [%i/%i]: %s" CL_CLL "\r", i, map.size(), map[i].name);
 
 			// try to load the map
 			success = map_readgat(&map[i]) != 0;
@@ -3706,8 +3690,7 @@ int map_readallmaps (void)
 	}
 
 	// finished map loading
-	ShowInfo("Successfully loaded '" CL_WHITE "%d" CL_RESET "' maps." CL_CLL "\n",map_num);
-	instance_start = map_num; // Next Map Index will be instances
+	ShowInfo("Successfully loaded '" CL_WHITE "%d" CL_RESET "' maps." CL_CLL "\n",map.size());
 
 	if (maps_removed)
 		ShowNotice("Maps removed: '" CL_WHITE "%d" CL_RESET "'\n",maps_removed);
@@ -4298,62 +4281,393 @@ int cleanup_sub(struct block_list *bl, va_list ap)
 
 #ifdef ADJUST_SKILL_DAMAGE
 /**
- * Free all skill damage entries for a map
- * @param m Map data
- **/
-void map_skill_damage_free(struct map_data *m) {
-	uint8 i;
+ * Add new skill damage adjustment entry for a map
+ * @param m: Map data
+ * @param skill_id: Skill ID
+ * @param pc: Rate to PC
+ * @param mobs: Rate to Monster
+ * @param boss: Rate to Boss-monster
+ * @param other: Rate to Other target
+ * @param caster: Caster type
+ */
+void map_skill_damage_add(struct map_data *m, uint16 skill_id, int rate[SKILLDMG_MAX], uint16 caster) {
+	if (m->skill_damage.size() > UINT16_MAX)
+		return;
 
-	for (i = 0; i < m->skill_damage.count; i++) {
-		ers_free(map_skill_damage_ers, m->skill_damage.entries[i]);
-		m->skill_damage.entries[i] = NULL;
+	for (int i = 0; i < m->skill_damage.size(); i++) {
+		if (m->skill_damage[i].skill_id == skill_id) {
+			for (int j = 0; j < SKILLDMG_MAX; j++) {
+				m->skill_damage[i].rate[j] = rate[j];
+			}
+			m->skill_damage[i].caster = caster;
+			return;
+		}
 	}
 
-	aFree(m->skill_damage.entries);
-	m->skill_damage.entries = NULL;
-	m->skill_damage.count = 0;
+	struct s_skill_damage entry = {};
+
+	entry.skill_id = skill_id;
+	for (int i = 0; i < SKILLDMG_MAX; i++)
+		entry.rate[i] = rate[i];
+	entry.caster = caster;
+	m->skill_damage.push_back(entry);
 }
+#endif
 
 /**
- * Add new skill damage adjustment entry for a map
- * @param m Map data
- * @param skill_id Skill
- * @param pc Rate to PC
- * @param mobs Rate to Monster
- * @param boss Rate to Boss-monster
- * @param other Rate to Other target
- * @param caster Caster type
- **/
-void map_skill_damage_add(struct map_data *m, uint16 skill_id, int pc, int mob, int boss, int other, uint8 caster) {
-	struct s_skill_damage *entry;
-	int i = 0;
+ * PvP timer handling
+ * @param bl: Player block object
+ * @param ap: func* with va_list values
+ * @return 0
+ */
+static int map_mapflag_pvp_sub(struct block_list *bl, va_list ap)
+{
+	struct map_session_data *sd = map_id2sd(bl->id);
 
-	if (m->skill_damage.count >= UINT8_MAX)
-		return;
+	nullpo_retr(0, sd);
 
-	for (i = 0; i < m->skill_damage.count; i++) {
-		if (m->skill_damage.entries[i]->skill_id == skill_id) {
-			m->skill_damage.entries[i]->pc = pc;
-			m->skill_damage.entries[i]->mob = mob;
-			m->skill_damage.entries[i]->boss = boss;
-			m->skill_damage.entries[i]->other = other;
-			m->skill_damage.entries[i]->caster = caster;
-			return;
-		}
+	if (sd->pvp_timer == INVALID_TIMER) {
+		sd->pvp_timer = add_timer(gettick() + 200, pc_calc_pvprank_timer, sd->bl.id, 0);
+		sd->pvp_rank = 0;
+		sd->pvp_lastusers = 0;
+		sd->pvp_point = 5;
+		sd->pvp_won = 0;
+		sd->pvp_lost = 0;
 	}
 
-	entry = ers_alloc(map_skill_damage_ers, struct s_skill_damage);
-	entry->skill_id = skill_id;
-	entry->pc = pc;
-	entry->mob = mob;
-	entry->boss = boss;
-	entry->other = other;
-	entry->caster = caster;
+	clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF);
+	return 0;
+}
 
-	RECREATE(m->skill_damage.entries, struct s_skill_damage *, m->skill_damage.count+1);
-	m->skill_damage.entries[m->skill_damage.count++] = entry;
+/**
+ * Return the mapflag enum from the given name.
+ * @param name: Mapflag name
+ * @return Mapflag enum value
+ */
+enum e_mapflag map_getmapflag_by_name(char* name)
+{
+	char flag_constant[255];
+	int mapflag;
+
+	safesnprintf(flag_constant, sizeof(flag_constant), "mf_%s", name);
+
+	if (!script_get_constant(flag_constant, &mapflag))
+		return MF_INVALID;
+	else
+		return (enum e_mapflag)mapflag;
 }
+
+/**
+ * Return the mapflag name from the given enum.
+ * @param mapflag: Mapflag enum
+ * @param output: Stores the mapflag name
+ * @return True on success otherwise false
+ */
+bool map_getmapflag_name( enum e_mapflag mapflag, char* output ){
+	const char* constant;
+	const char* prefix = "mf_";
+	int i, len = strlen(prefix);
+
+	// Look it up
+	constant = script_get_constant_str( prefix, mapflag );
+
+	// Should never happen
+	if (constant == NULL)
+		return false;
+
+	// Begin copy after the prefix
+	for(i = len; constant[i]; i++)
+		output[i-len] = (char)tolower(constant[i]); // Force lowercase
+	output[i - len] = 0; // Terminate it
+
+	return true;
+}
+
+/**
+ * Get a mapflag value
+ * @param m: Map ID
+ * @param mapflag: Mapflag ID
+ * @param args: Arguments for special flags
+ * @return Mapflag value on success or -1 on failure
+ */
+int map_getmapflag_sub(int16 m, enum e_mapflag mapflag, union u_mapflag_args *args)
+{
+	if (m < 0 || m >= map.size()) {
+		ShowWarning("map_getmapflag: Invalid map ID %d.\n", m);
+		return -1;
+	}
+
+	if (mapflag < MF_MIN || mapflag >= MF_MAX) {
+		ShowWarning("map_getmapflag: Invalid mapflag %d on map %s.\n", mapflag, map[m].name);
+		return -1;
+	}
+
+	switch(mapflag) {
+		case MF_NOLOOT:
+			return util::map_get(map[m].flag, MF_NOMOBLOOT, 0) && util::map_get(map[m].flag, MF_NOMVPLOOT, 0);
+		case MF_NOPENALTY:
+			return util::map_get(map[m].flag, MF_NOEXPPENALTY, 0) && util::map_get(map[m].flag, MF_NOZENYPENALTY, 0);
+		case MF_NOEXP:
+			return util::map_get(map[m].flag, MF_NOBASEEXP, 0) && util::map_get(map[m].flag, MF_NOJOBEXP, 0);
+		case MF_SKILL_DAMAGE:
+#ifdef ADJUST_SKILL_DAMAGE
+			nullpo_retr(-1, args);
+
+			switch (args->flag_val) {
+				case SKILLDMG_PC:
+				case SKILLDMG_MOB:
+				case SKILLDMG_BOSS:
+				case SKILLDMG_OTHER:
+					return map[m].damage_adjust.rate[args->flag_val];
+				default:
+					return util::map_get(map[m].flag, mapflag, 0);
+			}
+#else
+			return 0;
 #endif
+		default:
+			return util::map_get(map[m].flag, mapflag, 0);
+	}
+}
+
+/**
+ * Set a mapflag
+ * @param m: Map ID
+ * @param mapflag: Mapflag ID
+ * @param status: true - Set mapflag, false - Remove mapflag
+ * @param args: Arguments for special flags
+ * @return True on success or false on failure
+ */
+bool map_setmapflag_sub(int16 m, enum e_mapflag mapflag, bool status, union u_mapflag_args *args)
+{
+	if (m < 0 || m >= map.size()) {
+		ShowWarning("map_setmapflag: Invalid map ID %d.\n", m);
+		return false;
+	}
+
+	if (mapflag < MF_MIN || mapflag >= MF_MAX) {
+		ShowWarning("map_setmapflag: Invalid mapflag %d on map %s.\n", mapflag, map[m].name);
+		return false;
+	}
+
+	switch(mapflag) {
+		case MF_NOSAVE:
+			if (status) {
+				nullpo_retr(false, args);
+
+				map[m].save.map = args->nosave.map;
+				map[m].save.x = args->nosave.x;
+				map[m].save.y = args->nosave.y;
+			}
+			map[m].flag[mapflag] = status;
+			break;
+		case MF_PVP:
+			if (!status)
+				clif_map_property_mapall(m, MAPPROPERTY_NOTHING);
+			else {
+				if (!battle_config.pk_mode)
+					map_foreachinmap(map_mapflag_pvp_sub, m, BL_PC);
+				if (map_getmapflag(m, MF_GVG)) {
+					map_setmapflag(m, MF_GVG, false);
+					ShowWarning("map_setmapflag: Unable to set GvG and PvP flags for the same map! Removing GvG flag from %s.\n", map[m].name);
+				}
+				if (map_getmapflag(m, MF_GVG_TE)) {
+					map_setmapflag(m, MF_GVG_TE, false);
+					ShowWarning("map_setmapflag: Unable to set GvG TE and PvP flags for the same map! Removing GvG TE flag from %s.\n", map[m].name);
+				}
+				if (map_getmapflag(m, MF_GVG_DUNGEON)) {
+					map_setmapflag(m, MF_GVG_DUNGEON, false);
+					ShowWarning("map_setmapflag: Unable to set GvG Dungeon and PvP flags for the same map! Removing GvG Dungeon flag from %s.\n", map[m].name);
+				}
+				if (map_getmapflag(m, MF_GVG_CASTLE)) {
+					map_setmapflag(m, MF_GVG_CASTLE, false);
+					ShowWarning("map_setmapflag: Unable to set GvG Castle and PvP flags for the same map! Removing GvG Castle flag from %s.\n", map[m].name);
+				}
+				if (map_getmapflag(m, MF_GVG_TE_CASTLE)) {
+					map_setmapflag(m, MF_GVG_TE_CASTLE, false);
+					ShowWarning("map_setmapflag: Unable to set GvG TE Castle and PvP flags for the same map! Removing GvG TE Castle flag from %s.\n", map[m].name);
+				}
+				if (map_getmapflag(m, MF_BATTLEGROUND)) {
+					map_setmapflag(m, MF_BATTLEGROUND, false);
+					ShowWarning("map_setmapflag: Unable to set Battleground and PvP flags for the same map! Removing Battleground flag from %s.\n", map[m].name);
+				}
+			}
+			map[m].flag[mapflag] = status;
+			break;
+		case MF_GVG:
+		case MF_GVG_TE:
+			if (!status)
+				clif_map_property_mapall(m, MAPPROPERTY_NOTHING);
+			else {
+				clif_map_property_mapall(m, MAPPROPERTY_AGITZONE);
+				if (map_getmapflag(m, MF_PVP)) {
+					map_setmapflag(m, MF_PVP, false);
+					ShowWarning("map_setmapflag: Unable to set PvP and GvG flags for the same map! Removing PvP flag from %s.\n", map[m].name);
+				}
+				if (map_getmapflag(m, MF_BATTLEGROUND)) {
+					map_setmapflag(m, MF_BATTLEGROUND, false);
+					ShowWarning("map_setmapflag: Unable to set Battleground and GvG flags for the same map! Removing Battleground flag from %s.\n", map[m].name);
+				}
+			}
+			map[m].flag[mapflag] = status;
+			break;
+		case MF_GVG_CASTLE:
+		case MF_GVG_TE_CASTLE:
+			if (status) {
+				if (mapflag == MF_GVG_CASTLE && map_getmapflag(m, MF_GVG_TE_CASTLE)) {
+					map_setmapflag(m, MF_GVG_TE_CASTLE, false);
+					ShowWarning("map_setmapflag: Unable to set GvG TE Castle and GvG Castle flags for the same map! Removing GvG TE Castle flag from %s.\n", map[m].name);
+				}
+				if (mapflag == MF_GVG_TE_CASTLE && map_getmapflag(m, MF_GVG_CASTLE)) {
+					map_setmapflag(m, MF_GVG_CASTLE, false);
+					ShowWarning("map_setmapflag: Unable to set GvG Castle and GvG TE Castle flags for the same map! Removing GvG Castle flag from %s.\n", map[m].name);
+				}
+				if (map_getmapflag(m, MF_PVP)) {
+					map_setmapflag(m, MF_PVP, false);
+					ShowWarning("npc_parse_mapflag: Unable to set PvP and GvG%s Castle flags for the same map! Removing PvP flag from %s.\n", (mapflag == MF_GVG_CASTLE ? NULL : " TE"), map[m].name);
+				}
+			}
+			map[m].flag[mapflag] = status;
+			break;
+		case MF_GVG_DUNGEON:
+			if (status && map_getmapflag(m, MF_PVP)) {
+				map_setmapflag(m, MF_PVP, false);
+				ShowWarning("map_setmapflag: Unable to set PvP and GvG Dungeon flags for the same map! Removing PvP flag from %s.\n", map[m].name);
+			}
+			map[m].flag[mapflag] = status;
+			break;
+		case MF_NOBASEEXP:
+		case MF_NOJOBEXP:
+			if (status) {
+				if (mapflag == MF_NOBASEEXP && map_getmapflag(m, MF_BEXP) != 100) {
+					map_setmapflag(m, MF_BEXP, false);
+					ShowWarning("map_setmapflag: Unable to set BEXP and No Base EXP flags for the same map! Removing BEXP flag from %s.\n", map[m].name);
+				}
+				if (mapflag == MF_NOJOBEXP && map_getmapflag(m, MF_JEXP) != 100) {
+					map_setmapflag(m, MF_JEXP, false);
+					ShowWarning("map_setmapflag: Unable to set JEXP and No Job EXP flags for the same map! Removing JEXP flag from %s.\n", map[m].name);
+				}
+			}
+			map[m].flag[mapflag] = status;
+			break;
+		case MF_PVP_NIGHTMAREDROP:
+			if (status) {
+				nullpo_retr(false, args);
+
+				if (map[m].drop_list.size() == MAX_DROP_PER_MAP) {
+					ShowWarning("map_setmapflag: Reached the maximum number of drop list items for mapflag pvp_nightmaredrop on %s. Skipping.\n", map[m].name);
+					break;
+				}
+
+				struct s_drop_list entry;
+
+				entry.drop_id = args->nightmaredrop.drop_id;
+				entry.drop_type = args->nightmaredrop.drop_type;
+				entry.drop_per = args->nightmaredrop.drop_per;
+				map[m].drop_list.push_back(entry);
+			}
+			map[m].flag[mapflag] = status;
+			break;
+		case MF_RESTRICTED:
+			nullpo_retr(false, args);
+
+			map[m].flag[mapflag] = status;
+			if (!status)
+				map[m].zone ^= 1 << (args->flag_val + 1);
+			else
+				map[m].zone |= 1 << (args->flag_val + 1);
+			break;
+		case MF_NOCOMMAND:
+			if (status) {
+				nullpo_retr(false, args);
+
+				map[m].flag[mapflag] = ((args->flag_val <= 0) ? 100 : args->flag_val);
+			} else
+				map[m].flag[mapflag] = false;
+			break;
+		case MF_JEXP:
+		case MF_BEXP:
+			if (status) {
+				nullpo_retr(false, args);
+
+				if (mapflag == MF_JEXP && map_getmapflag(m, MF_NOJOBEXP)) {
+					map_setmapflag(m, MF_NOJOBEXP, false);
+					ShowWarning("map_setmapflag: Unable to set No Job EXP and JEXP flags for the same map! Removing No Job EXP flag from %s.\n", map[m].name);
+				}
+				if (mapflag == MF_BEXP && map_getmapflag(m, MF_NOBASEEXP)) {
+					map_setmapflag(m, MF_NOBASEEXP, false);
+					ShowWarning("map_setmapflag: Unable to set No Base EXP and BEXP flags for the same map! Removing No Base EXP flag from %s.\n", map[m].name);
+				}
+				map[m].flag[mapflag] = args->flag_val;
+			} else
+				map[m].flag[mapflag] = false;
+			break;
+		case MF_BATTLEGROUND:
+			if (status) {
+				nullpo_retr(false, args);
+
+				if (map_getmapflag(m, MF_PVP)) {
+					map_setmapflag(m, MF_PVP, false);
+					ShowWarning("map_setmapflag: Unable to set PvP and Battleground flags for the same map! Removing PvP flag from %s.\n", map[m].name);
+				}
+				if (map_getmapflag(m, MF_GVG)) {
+					map_setmapflag(m, MF_GVG, false);
+					ShowWarning("map_setmapflag: Unable to set GvG and Battleground flags for the same map! Removing GvG flag from %s.\n", map[m].name);
+				}
+				if (map_getmapflag(m, MF_GVG_DUNGEON)) {
+					map_setmapflag(m, MF_GVG_DUNGEON, false);
+					ShowWarning("map_setmapflag: Unable to set GvG Dungeon and Battleground flags for the same map! Removing GvG Dungeon flag from %s.\n", map[m].name);
+				}
+				if (map_getmapflag(m, MF_GVG_CASTLE)) {
+					map_setmapflag(m, MF_GVG_CASTLE, false);
+					ShowWarning("map_setmapflag: Unable to set GvG Castle and Battleground flags for the same map! Removing GvG Castle flag from %s.\n", map[m].name);
+				}
+				map[m].flag[mapflag] = ((args->flag_val <= 0 || args->flag_val > 2) ? 1 : args->flag_val);
+			} else
+				map[m].flag[mapflag] = false;
+			break;
+		case MF_NOLOOT:
+			map[m].flag[MF_NOMOBLOOT] = status;
+			map[m].flag[MF_NOMVPLOOT] = status;
+			break;
+		case MF_NOPENALTY:
+			map[m].flag[MF_NOEXPPENALTY] = status;
+			map[m].flag[MF_NOZENYPENALTY] = status;
+			break;
+		case MF_NOEXP:
+			map[m].flag[MF_NOBASEEXP] = status;
+			map[m].flag[MF_NOJOBEXP] = status;
+			break;
+#ifdef ADJUST_SKILL_DAMAGE
+		case MF_SKILL_DAMAGE:
+			if (!status) {
+				memset(&map[m].damage_adjust, 0, sizeof(map[m].damage_adjust));
+				map[m].skill_damage.clear();
+			} else {
+				nullpo_retr(false, args);
+
+				if (!args->skill_damage.caster) {
+					ShowError("map_setmapflag: Skill damage adjustment without casting type for map %s.\n", map[m].name);
+					return false;
+				}
+
+				for (int i = 0; i < SKILLDMG_MAX; i++) {
+					map[m].damage_adjust.rate[i] = cap_value(args->skill_damage.rate[i], -100, 100000);
+
+					if (map[m].flag.find(mapflag) != map[m].flag.end() && map[m].damage_adjust.rate[i])
+						map[m].damage_adjust.caster = args->skill_damage.caster;
+				}
+			}
+			map[m].flag[mapflag] = status;
+			break;
+#endif
+		default:
+			map[m].flag[mapflag] = status;
+			break;
+	}
+
+	return true;
+}
 
 /**
  * @see DBApply
@@ -4385,14 +4699,14 @@ void do_final(void)
 	do_clear_npc();
 
 	// remove all objects on maps
-	for (i = 0; i < map_num; i++) {
-		ShowStatus("Cleaning up maps [%d/%d]: %s..." CL_CLL "\r", i+1, map_num, map[i].name);
+	for (i = 0; i < map.size(); i++) {
+		ShowStatus("Cleaning up maps [%d/%d]: %s..." CL_CLL "\r", i+1, map.size(), map[i].name);
 		if (map[i].m >= 0) {
 			map_foreachinmap(cleanup_sub, i, BL_ALL);
 			channel_delete(map[i].channel,false);
 		}
 	}
-	ShowStatus("Cleaned up %d maps." CL_CLL "\n", map_num);
+	ShowStatus("Cleaned up %d maps." CL_CLL "\n", map.size());
 
 	id_db->foreach(id_db,cleanup_db_sub);
 	chrif_char_reset_offline();
@@ -4432,7 +4746,7 @@ void do_final(void)
 
 	map_db->destroy(map_db, map_db_final);
 
-	for (i=0; i<map_num; i++) {
+	for (i=0; i<map.size(); i++) {
 		if(map[i].cell) aFree(map[i].cell);
 		if(map[i].block) aFree(map[i].block);
 		if(map[i].block_mob) aFree(map[i].block_mob);
@@ -4443,9 +4757,10 @@ void do_final(void)
 				if (map[i].moblist[j]) aFree(map[i].moblist[j]);
 		}
 		map_free_questinfo(i);
+		map[i].flag.clear();
+		map[i].drop_list.clear();
 #ifdef ADJUST_SKILL_DAMAGE
-		if (map[i].skill_damage.count)
-			map_skill_damage_free(&map[i]);
+		map[i].skill_damage.clear();
 #endif
 	}
 
@@ -4462,10 +4777,6 @@ void do_final(void)
 	iwall_db->destroy(iwall_db, NULL);
 	regen_db->destroy(regen_db, NULL);
 
-#ifdef ADJUST_SKILL_DAMAGE
-	ers_destroy(map_skill_damage_ers);
-#endif
-
 	map_sql_close();
 
 	ShowStatus("Finished.\n");
@@ -4717,10 +5028,6 @@ int do_init(int argc, char *argv[])
 	regen_db = idb_alloc(DB_OPT_BASE); // efficient status_natural_heal processing
 	iwall_db = strdb_alloc(DB_OPT_RELEASE_DATA,2*NAME_LENGTH+2+1); // [Zephyrus] Invisible Walls
 
-#ifdef ADJUST_SKILL_DAMAGE
-	map_skill_damage_ers = ers_new(sizeof(struct s_skill_damage), "map.cpp:map_skill_damage_ers", ERS_OPT_NONE);
-#endif
-
 	map_sql_init();
 	if (log_config.sql_logs)
 		log_sql_init();

+ 144 - 109
src/map/map.hpp

@@ -4,7 +4,10 @@
 #ifndef _MAP_HPP_
 #define _MAP_HPP_
 
+#include <algorithm>
+#include <map>
 #include <stdarg.h>
+#include <vector>
 
 #include "../common/cbasetypes.hpp"
 #include "../common/core.hpp" // CORE_ST_LAST
@@ -228,20 +231,20 @@ enum e_mapid {
 #define DEFAULT_AUTOSAVE_INTERVAL 5*60*1000
 
 /// Specifies maps where players may hit each other
-#define map_flag_vs(m) (map[m].flag.pvp || map[m].flag.gvg_dungeon || map[m].flag.gvg || ((agit_flag || agit2_flag) && map[m].flag.gvg_castle) || map[m].flag.gvg_te || (agit3_flag && map[m].flag.gvg_te_castle) || map[m].flag.battleground)
+#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[m].flag.pvp || map[m].flag.gvg_dungeon || map[m].flag.gvg || map[m].flag.gvg_castle || map[m].flag.gvg_te || map[m].flag.gvg_te_castle || map[m].flag.battleground)
+#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[m].flag.gvg || ((agit_flag || agit2_flag) && map[m].flag.gvg_castle) || map[m].flag.gvg_te || (agit3_flag && map[m].flag.gvg_te_castle))
+#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[m].flag.gvg || map[m].flag.gvg_te || map[m].flag.gvg_castle || map[m].flag.gvg_te_castle)
+#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[m].flag.town || map[m].flag.pvp || map[m].flag.gvg || map[m].flag.gvg_te || map[m].flag.battleground)
+#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[m].flag.gvg_te || map[m].flag.gvg_te_castle)
+#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[m].flag.gvg || map[m].flag.gvg_castle)
+#define map_flag_gvg2_no_te(m) (map_getmapflag(m, MF_GVG) || map_getmapflag(m, MF_GVG_CASTLE))
 
 //This stackable implementation does not means a BL can be more than one type at a time, but it's
 //meant to make it easier to check for multiple types at a time on invocations such as map_foreach* calls [Skotlex]
@@ -513,6 +516,122 @@ enum _look {
 	LOOK_BODY2
 };
 
+enum e_mapflag : int16 {
+	MF_INVALID = -1,
+	MF_MIN = 0,
+	MF_NOMEMO = 0,
+	MF_NOTELEPORT,
+	MF_NOSAVE,
+	MF_NOBRANCH,
+	MF_NOPENALTY,
+	MF_NOZENYPENALTY,
+	MF_PVP,
+	MF_PVP_NOPARTY,
+	MF_PVP_NOGUILD,
+	MF_GVG,
+	MF_GVG_NOPARTY,	//10
+	MF_NOTRADE,
+	MF_NOSKILL,
+	MF_NOWARP,
+	MF_PARTYLOCK,
+	MF_NOICEWALL,
+	MF_SNOW,
+	MF_FOG,
+	MF_SAKURA,
+	MF_LEAVES,
+	//MF_RAIN,	//20 - No longer available, keeping here just in case it's back someday. [Ind]
+	// 21 free
+	MF_NOGO = 22,
+	MF_CLOUDS,
+	MF_CLOUDS2,
+	MF_FIREWORKS,
+	MF_GVG_CASTLE,
+	MF_GVG_DUNGEON,
+	MF_NIGHTENABLED,
+	MF_NOBASEEXP,
+	MF_NOJOBEXP,	//30
+	MF_NOMOBLOOT,
+	MF_NOMVPLOOT,
+	MF_NORETURN,
+	MF_NOWARPTO,
+	MF_PVP_NIGHTMAREDROP,
+	MF_RESTRICTED,
+	MF_NOCOMMAND,
+	MF_NODROP,
+	MF_JEXP,
+	MF_BEXP,	//40
+	MF_NOVENDING,
+	MF_LOADEVENT,
+	MF_NOCHAT,
+	MF_NOEXPPENALTY,
+	MF_GUILDLOCK,
+	MF_TOWN,
+	MF_AUTOTRADE,
+	MF_ALLOWKS,
+	MF_MONSTER_NOTELEPORT,
+	MF_PVP_NOCALCRANK,	//50
+	MF_BATTLEGROUND,
+	MF_RESET,
+	MF_NOMAPCHANNELAUTOJOIN,
+	MF_NOUSECART,
+	MF_NOITEMCONSUMPTION,
+	MF_NOSUNMOONSTARMIRACLE,
+	MF_NOMINEEFFECT,
+	MF_NOLOCKON,
+	MF_NOTOMB,
+	MF_SKILL_DAMAGE,	//60
+	MF_NOCOSTUME,
+	MF_GVG_TE_CASTLE,
+	MF_GVG_TE,
+	MF_HIDEMOBHPBAR,
+	MF_NOLOOT,
+	MF_NOEXP,
+	MF_MAX
+};
+
+/// Enum of damage types
+enum e_skill_damage_type : uint8 {
+	SKILLDMG_PC,
+	SKILLDMG_MOB,
+	SKILLDMG_BOSS,
+	SKILLDMG_OTHER,
+	SKILLDMG_MAX
+};
+
+#ifdef ADJUST_SKILL_DAMAGE
+/// Struct for MF_SKILLDAMAGE
+struct s_skill_damage {
+	unsigned int map; ///< Maps (used for skill_damage_db.txt)
+	uint16 skill_id; ///< Skill ID (used for mapflag)
+	uint16 caster; ///< Caster type
+	int rate[SKILLDMG_MAX]; ///< Used for when all skills are adjusted
+};
+#endif
+
+/// Enum for item drop type for MF_PVP_NIGHTMAREDROP
+enum e_nightmare_drop_type : uint8 {
+	NMDT_INVENTORY = 0x1,
+	NMDT_EQUIP = 0x2,
+	NMDT_ALL = (NMDT_INVENTORY|NMDT_EQUIP)
+};
+
+/// Struct for MF_PVP_NIGHTMAREDROP
+struct s_drop_list {
+	int drop_id;
+	int drop_per;
+	enum e_nightmare_drop_type drop_type;
+};
+
+/// Union for mapflag values
+union u_mapflag_args {
+	struct point nosave;
+	struct s_drop_list nightmaredrop;
+#ifdef ADJUST_SKILL_DAMAGE
+	struct s_skill_damage skill_damage;
+#endif
+	int flag_val;
+};
+
 // used by map_setcell()
 enum cell_t{
 	CELL_WALKABLE,
@@ -583,21 +702,6 @@ struct iwall_data {
 	bool shootable;
 };
 
-#ifdef ADJUST_SKILL_DAMAGE
-/// Struct of skill damage adjustment
-struct s_skill_damage {
-	unsigned int map; ///< Maps (used for skill_damage_db.txt)
-	uint16 skill_id; ///< Skill ID (used for mapflag)
-	// Additional rates
-	int pc, ///< Rate to Player
-		mob, ///< Rate to Monster
-		boss, ///< Rate to Boss-Monster
-		other; ///< Rate to Other target
-	uint8 caster; ///< Caster type
-};
-extern struct eri *map_skill_damage_ers;
-#endif
-
 struct questinfo_req {
 	unsigned int quest_id;
 	unsigned state : 2; // 0: Doesn't have, 1: Inactive, 2: Active, 3: Complete //! TODO: CONFIRM ME!!
@@ -630,94 +734,20 @@ struct map_data {
 	int users;
 	int users_pvp;
 	int iwall_num; // Total of invisible walls in this map
-	struct map_flag {
-		unsigned town : 1; // [Suggestion to protect Mail System]
-		unsigned autotrade : 1;
-		unsigned allowks : 1; // [Kill Steal Protection]
-		unsigned nomemo : 1;
-		unsigned noteleport : 1;
-		unsigned noreturn : 1;
-		unsigned monster_noteleport : 1;
-		unsigned nosave : 1;
-		unsigned nobranch : 1;
-		unsigned noexppenalty : 1;
-		unsigned pvp : 1;
-		unsigned pvp_noparty : 1;
-		unsigned pvp_noguild : 1;
-		unsigned pvp_nightmaredrop :1;
-		unsigned pvp_nocalcrank : 1;
-		unsigned gvg_castle : 1;
-		unsigned gvg : 1; // Now it identifies gvg versus maps that are active 24/7
-		unsigned gvg_dungeon : 1; // Celest
-		unsigned gvg_noparty : 1;
-		unsigned battleground : 2; // [BattleGround System]
-		unsigned nozenypenalty : 1;
-		unsigned notrade : 1;
-		unsigned noskill : 1;
-		unsigned nowarp : 1;
-		unsigned nowarpto : 1;
-		unsigned noicewall : 1; // [Valaris]
-		unsigned snow : 1; // [Valaris]
-		unsigned clouds : 1;
-		unsigned clouds2 : 1; // [Valaris]
-		unsigned fog : 1; // [Valaris]
-		unsigned fireworks : 1;
-		unsigned sakura : 1; // [Valaris]
-		unsigned leaves : 1; // [Valaris]
-		unsigned nogo : 1; // [Valaris]
-		unsigned nobaseexp : 1; // [Lorky] added by Lupus
-		unsigned nojobexp : 1; // [Lorky]
-		unsigned nomobloot : 1; // [Lorky]
-		unsigned nomvploot : 1; // [Lorky]
-		unsigned nightenabled :1; //For night display. [Skotlex]
-		unsigned restricted : 1; // [Komurka]
-		unsigned nodrop : 1;
-		unsigned novending : 1;
-		unsigned loadevent : 1;
-		unsigned nochat :1;
-		unsigned partylock :1;
-		unsigned guildlock :1;
-		unsigned reset :1; // [Daegaladh]
-		unsigned chmautojoin : 1; //prevent to auto join map channel
-		unsigned nousecart : 1;	//prevent open up cart @FIXME client side only atm
-		unsigned noitemconsumption : 1; //prevent item usage
-		unsigned nosumstarmiracle : 1; //allow SG miracle to happen ?
-		unsigned nomineeffect : 1; //allow /mineeffect
-		unsigned nolockon : 1;
-		unsigned notomb : 1;
-		unsigned nocostume : 1; // Disable costume sprites [Cydh]
-		unsigned gvg_te : 1; // GVG WOE:TE. This was added as purpose to change 'gvg' for GVG TE, so item_noequp, skill_nocast exlude GVG TE maps from 'gvg' (flag &4)
-		unsigned gvg_te_castle : 1; // GVG WOE:TE Castle
-		unsigned hidemobhpbar : 1;
+
+	std::map<e_mapflag, int> flag;
+	struct point save;
+	std::vector<s_drop_list> drop_list;
+	uint32 zone; // zone number (for item/skill restrictions)
 #ifdef ADJUST_SKILL_DAMAGE
-		unsigned skill_damage : 1;
+	struct s_skill_damage damage_adjust; // Used for overall skill damage adjustment
+	std::vector<s_skill_damage> skill_damage; // Used for single skill damage adjustment
 #endif
-	} flag;
-	struct point save;
-	struct npc_data *npc[MAX_NPC_PER_MAP];
-	struct {
-		int drop_id;
-		int drop_type;
-		int drop_per;
-	} drop_list[MAX_DROP_PER_MAP];
 
+	struct npc_data *npc[MAX_NPC_PER_MAP];
 	struct spawn_data *moblist[MAX_MOB_LIST_PER_MAP]; // [Wizputer]
 	int mob_delete_timer;	// Timer ID for map_removemobs_timer [Skotlex]
-	uint32 zone;	// zone number (for item/skill restrictions)
-	int nocommand; //Blocks @/# commands for non-gms. [Skotlex]
-	struct {
-		int jexp;	// map experience multiplicator
-		int bexp;	// map experience multiplicator
-#ifdef ADJUST_SKILL_DAMAGE
-		struct s_skill_damage damage;
-#endif
-	} adjust;
-#ifdef ADJUST_SKILL_DAMAGE
-	struct {
-		struct s_skill_damage **entries;
-		uint8 count;
-	} skill_damage;
-#endif
+
 	// Instance Variables
 	unsigned short instance_id;
 	int instance_src_map;
@@ -748,8 +778,7 @@ int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk);
 void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag);
 void map_setgatcell(int16 m, int16 x, int16 y, int gat);
 
-extern struct map_data map[];
-extern int map_num;
+extern std::vector<map_data> map;
 
 extern int autosave_interval;
 extern int minsave_interval;
@@ -926,10 +955,16 @@ void map_addmap2db(struct map_data *m);
 void map_removemapdb(struct map_data *m);
 
 #ifdef ADJUST_SKILL_DAMAGE
-void map_skill_damage_free(struct map_data *m);
-void map_skill_damage_add(struct map_data *m, uint16 skill_id, int pc, int mob, int boss, int other, uint8 caster);
+void map_skill_damage_add(struct map_data *m, uint16 skill_id, int rate[SKILLDMG_MAX], uint16 caster);
 #endif
 
+enum e_mapflag map_getmapflag_by_name(char* name);
+bool map_getmapflag_name(enum e_mapflag mapflag, char* output);
+int map_getmapflag_sub(int16 m, enum e_mapflag mapflag, union u_mapflag_args *args);
+bool map_setmapflag_sub(int16 m, enum e_mapflag mapflag, bool status, union u_mapflag_args *args);
+#define map_getmapflag(m, mapflag) map_getmapflag_sub(m, mapflag, NULL)
+#define map_setmapflag(m, mapflag, status) map_setmapflag_sub(m, mapflag, status, NULL)
+
 #define CHK_ELEMENT(ele) ((ele) > ELE_NONE && (ele) < ELE_MAX) /// Check valid Element
 #define CHK_ELEMENT_LEVEL(lv) ((lv) >= 1 && (lv) <= MAX_ELE_LEVEL) /// Check valid element level
 #define CHK_RACE(race) ((race) > RC_NONE_ && (race) < RC_MAX) /// Check valid Race

+ 13 - 13
src/map/mob.cpp

@@ -568,7 +568,7 @@ bool mob_ksprotected (struct block_list *src, struct block_list *target)
 		struct map_session_data *pl_sd; // Owner
 		char output[128];
 		
-		if( map[md->bl.m].flag.allowks || map_flag_ks(md->bl.m) )
+		if( map_getmapflag(md->bl.m, MF_ALLOWKS) || map_flag_ks(md->bl.m) )
 			return false; // Ignores GVG, PVP and AllowKS map flags
 
 		if( md->db->mexp || md->master_id )
@@ -2402,7 +2402,7 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage)
 		clif_name_area(&md->bl);
 
 #if PACKETVER >= 20120404
-	if (battle_config.monster_hp_bars_info && !map[md->bl.m].flag.hidemobhpbar) {
+	if (battle_config.monster_hp_bars_info && !map_getmapflag(md->bl.m, MF_HIDEMOBHPBAR)) {
 		int i;
 		for(i = 0; i < DAMAGELOG_SIZE; i++){ // must show hp bar to all char who already hit the mob.
 			struct map_session_data *sd = map_charid2sd(md->dmglog[i].id);
@@ -2518,9 +2518,9 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 	}
 
 	if(!(type&2) && //No exp
-		(!map[m].flag.pvp || battle_config.pvp_exp) && //Pvp no exp rule [MouseJstr]
+		(!map_getmapflag(m, MF_PVP) || battle_config.pvp_exp) && //Pvp no exp rule [MouseJstr]
 		(!md->master_id || !md->special_state.ai) && //Only player-summoned mobs do not give exp. [Skotlex]
-		(!map[m].flag.nobaseexp || !map[m].flag.nojobexp) //Gives Exp
+		(!map_getmapflag(m, MF_NOBASEEXP) || !map_getmapflag(m, MF_NOJOBEXP)) //Gives Exp
 	) { //Experience calculation.
 		int bonus = 100; //Bonus on top of your share (common to all attackers).
 		int pnum = 0;
@@ -2583,21 +2583,21 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 					zeny*=rnd()%250;
 			}
 
-			if (map[m].flag.nobaseexp || !md->db->base_exp)
+			if (map_getmapflag(m, MF_NOBASEEXP) || !md->db->base_exp)
 				base_exp = 0;
 			else {
 				double exp = apply_rate2(md->db->base_exp, per, 1);
 				exp = apply_rate(exp, bonus);
-				exp = apply_rate(exp, map[m].adjust.bexp);
+				exp = apply_rate(exp, map_getmapflag(m, MF_BEXP));
 				base_exp = (unsigned int)cap_value(exp, 1, UINT_MAX);
 			}
 
-			if (map[m].flag.nojobexp || !md->db->job_exp || md->dmglog[i].flag == MDLF_HOMUN) //Homun earned job-exp is always lost.
+			if (map_getmapflag(m, MF_NOJOBEXP) || !md->db->job_exp || md->dmglog[i].flag == MDLF_HOMUN) //Homun earned job-exp is always lost.
 				job_exp = 0;
 			else {
 				double exp = apply_rate2(md->db->job_exp, per, 1);
 				exp = apply_rate(exp, bonus);
-				exp = apply_rate(exp, map[m].adjust.jexp);
+				exp = apply_rate(exp, map_getmapflag(m, MF_JEXP));
 				job_exp = (unsigned int)cap_value(exp, 1, UINT_MAX);
 			}
 
@@ -2660,7 +2660,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 
 	} //End EXP giving.
 
-	if( !(type&1) && !map[m].flag.nomobloot && !md->state.rebirth && (
+	if( !(type&1) && !map_getmapflag(m, MF_NOMOBLOOT) && !md->state.rebirth && (
 		!md->special_state.ai || //Non special mob
 		battle_config.alchemist_summon_reward == 2 || //All summoned give drops
 		(md->special_state.ai==AI_SPHERE && battle_config.alchemist_summon_reward == 1) //Marine Sphere Drops items.
@@ -2849,7 +2849,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 		double exp;
 
 		//mapflag: noexp check [Lorky]
-		if (map[m].flag.nobaseexp || type&2)
+		if (map_getmapflag(m, MF_NOBASEEXP) || type&2)
 			exp =1;
 		else {
 			exp = md->db->mexp;
@@ -2864,7 +2864,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 		pc_gainexp(mvp_sd, &md->bl, mexp,0, 0);
 		log_mvp[1] = mexp;
 
-		if( !(map[m].flag.nomvploot || type&1) ) {
+		if( !(map_getmapflag(m, MF_NOMVPLOOT) || type&1) ) {
 			//Order might be random depending on item_drop_mvp_mode config setting
 			struct s_mob_drop mdrop[MAX_MVP_DROP_TOTAL];
 
@@ -3039,7 +3039,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 	}
 
 	// MvP tomb [GreenBox]
-	if (battle_config.mvp_tomb_enabled && md->spawn->state.boss && map[md->bl.m].flag.notomb != 1)
+	if (battle_config.mvp_tomb_enabled && md->spawn->state.boss && map_getmapflag(md->bl.m, MF_NOTOMB) != 1)
 		mvptomb_create(md, mvp_sd ? mvp_sd->status.name : NULL, time(NULL));
 
 	if( !rebirth )
@@ -3271,7 +3271,7 @@ void mob_heal(struct mob_data *md,unsigned int heal)
 	if (battle_config.show_mob_info&3)
 		clif_name_area(&md->bl);
 #if PACKETVER >= 20120404
-	if (battle_config.monster_hp_bars_info && !map[md->bl.m].flag.hidemobhpbar) {
+	if (battle_config.monster_hp_bars_info && !map_getmapflag(md->bl.m, MF_HIDEMOBHPBAR)) {
 		int i;
 		for(i = 0; i < DAMAGELOG_SIZE; i++)// must show hp bar to all char who already hit the mob.
 			if( md->dmglog[i].id ) {

+ 147 - 298
src/map/npc.cpp

@@ -3934,327 +3934,176 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con
 {
 	int16 m;
 	char mapname[MAP_NAME_LENGTH_EXT];
-	int state = 1;
+	bool state = true;
+	enum e_mapflag mapflag;
 
 	// w1=<mapname>
-	if( sscanf(w1, "%15[^,]", mapname) != 1 )
-	{
+	if (sscanf(w1, "%15[^,]", mapname) != 1) {
 		ShowError("npc_parse_mapflag: Invalid mapflag definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
 		return strchr(start,'\n');// skip and continue
 	}
 	m = map_mapname2mapid(mapname);
-	if( m < 0 )
-	{
+	if (m < 0) {
 		ShowWarning("npc_parse_mapflag: Unknown map in file '%s', line '%d' : %s\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", mapname, filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
 		return strchr(start,'\n');// skip and continue
 	}
 
 	if (w4 && !strcmpi(w4, "off"))
-		state = 0;	//Disable mapflag rather than enable it. [Skotlex]
-
-	if (!strcmpi(w3, "nosave")) {
-		char savemap[MAP_NAME_LENGTH_EXT];
-		short savex, savey;
-		if (state == 0)
-			; //Map flag disabled.
-		else if (!strcmpi(w4, "SavePoint")) {
-			map[m].save.map = 0;
-			map[m].save.x = -1;
-			map[m].save.y = -1;
-		} else if (sscanf(w4, "%15[^,],%6hd,%6hd", savemap, &savex, &savey) == 3) {
-			map[m].save.map = mapindex_name2id(savemap);
-			map[m].save.x = savex;
-			map[m].save.y = savey;
-			if (!map[m].save.map) {
-				ShowWarning("npc_parse_mapflag: Specified save point map '%s' for mapflag 'nosave' not found (file '%s', line '%d'), using 'SavePoint'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", savemap, filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
-				map[m].save.x = -1;
-				map[m].save.y = -1;
-			}
-		}
-		map[m].flag.nosave = state;
-	}
-	else if (!strcmpi(w3,"autotrade"))
-		map[m].flag.autotrade=state;
-	else if (!strcmpi(w3,"allowks"))
-		map[m].flag.allowks=state; // [Kill Steal Protection]
-	else if (!strcmpi(w3,"town"))
-		map[m].flag.town=state;
-	else if (!strcmpi(w3,"nomemo"))
-		map[m].flag.nomemo=state;
-	else if (!strcmpi(w3,"noteleport"))
-		map[m].flag.noteleport=state;
-	else if (!strcmpi(w3,"nowarp"))
-		map[m].flag.nowarp=state;
-	else if (!strcmpi(w3,"nowarpto"))
-		map[m].flag.nowarpto=state;
-	else if (!strcmpi(w3,"noreturn"))
-		map[m].flag.noreturn=state;
-	else if (!strcmpi(w3,"monster_noteleport"))
-		map[m].flag.monster_noteleport=state;
-	else if (!strcmpi(w3,"nobranch"))
-		map[m].flag.nobranch=state;
-	else if (!strcmpi(w3,"nopenalty")) {
-		map[m].flag.noexppenalty=state;
-		map[m].flag.nozenypenalty=state;
-	}
-	else if (!strcmpi(w3,"pvp")) {
-		map[m].flag.pvp = state;
-		if( state && (map[m].flag.gvg || map[m].flag.gvg_dungeon || map[m].flag.gvg_castle) ) {
-			map[m].flag.gvg = 0;
-			map[m].flag.gvg_dungeon = 0;
-			map[m].flag.gvg_castle = 0;
-			ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing GvG flags from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
-		}
-		if( state && map[m].flag.battleground ) {
-			map[m].flag.battleground = 0;
-			ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing BattleGround flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
-		}
-	}
-	else if (!strcmpi(w3,"pvp_noparty"))
-		map[m].flag.pvp_noparty=state;
-	else if (!strcmpi(w3,"pvp_noguild"))
-		map[m].flag.pvp_noguild=state;
-	else if (!strcmpi(w3, "pvp_nightmaredrop")) {
-		char drop_arg1[16], drop_arg2[16];
-		int drop_per = 0;
-		if (sscanf(w4, "%15[^,],%15[^,],%11d", drop_arg1, drop_arg2, &drop_per) == 3) {
-			int drop_id = 0, drop_type = 0;
-			if (!strcmpi(drop_arg1, "random"))
-				drop_id = -1;
-			else if (itemdb_exists((drop_id = atoi(drop_arg1))) == NULL)
-				drop_id = 0;
-			if (!strcmpi(drop_arg2, "inventory"))
-				drop_type = 1;
-			else if (!strcmpi(drop_arg2,"equip"))
-				drop_type = 2;
-			else if (!strcmpi(drop_arg2,"all"))
-				drop_type = 3;
-
-			if (drop_id != 0){
-				int i;
-				for (i = 0; i < MAX_DROP_PER_MAP; i++) {
-					if (map[m].drop_list[i].drop_id == 0){
-						map[m].drop_list[i].drop_id = drop_id;
-						map[m].drop_list[i].drop_type = drop_type;
-						map[m].drop_list[i].drop_per = drop_per;
-						break;
-					}
+		state = false;	//Disable mapflag rather than enable it. [Skotlex]
+
+	mapflag = map_getmapflag_by_name(w3);
+
+	switch( mapflag ){
+		case MF_INVALID:
+			ShowError("npc_parse_mapflag: unrecognized mapflag '%s' (file '%s', line '%d').\n", w3, filepath, strline(buffer,start-buffer));
+			break;
+		case MF_NOSAVE: {
+			char savemap[MAP_NAME_LENGTH_EXT];
+			union u_mapflag_args args = {};
+
+			if (state && !strcmpi(w4, "SavePoint")) {
+				args.nosave.map = 0;
+				args.nosave.x = -1;
+				args.nosave.y = -1;
+			} else if (state && sscanf(w4, "%15[^,],%6hd,%6hd", savemap, &args.nosave.x, &args.nosave.y) == 3) {
+				args.nosave.map = mapindex_name2id(savemap);
+				if (!args.nosave.map) {
+					ShowWarning("npc_parse_mapflag: Specified save point map '%s' for mapflag 'nosave' not found (file '%s', line '%d'), using 'SavePoint'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", savemap, filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+					args.nosave.x = -1;
+					args.nosave.y = -1;
 				}
-				map[m].flag.pvp_nightmaredrop = 1;
 			}
-		} else if (!state) //Disable
-			map[m].flag.pvp_nightmaredrop = 0;
-	}
-	else if (!strcmpi(w3,"pvp_nocalcrank"))
-		map[m].flag.pvp_nocalcrank=state;
-	else if (!strcmpi(w3,"gvg")) {
-		map[m].flag.gvg = state;
-		if( state && map[m].flag.pvp ) {
-			map[m].flag.pvp = 0;
-			ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing PvP flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
-		}
-		if( state && map[m].flag.battleground ) {
-			map[m].flag.battleground = 0;
-			ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing BattleGround flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
-		}
-	}
-	else if (!strcmpi(w3,"gvg_noparty"))
-		map[m].flag.gvg_noparty=state;
-	else if (!strcmpi(w3,"gvg_dungeon")) {
-		map[m].flag.gvg_dungeon=state;
-		if (state) map[m].flag.pvp=0;
-	}
-	else if (!strcmpi(w3,"gvg_castle")) {
-		map[m].flag.gvg_castle=state;
-		if (state) map[m].flag.pvp=0;
-	}
-	else if (!strcmpi(w3,"gvg_te")) {
-		map[m].flag.gvg_te = state;
-		if( state && map[m].flag.pvp ) {
-			map[m].flag.pvp = 0;
-			ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing PvP flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
-		}
-		if( state && map[m].flag.battleground ) {
-			map[m].flag.battleground = 0;
-			ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing BattleGround flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
-		}
-	}
-	else if (!strcmpi(w3,"gvg_te_castle")) {
-		map[m].flag.gvg_te_castle = state;
-		if (state) {
-			map[m].flag.gvg_castle = 0;
-			map[m].flag.pvp = 0;
+			map_setmapflag_sub(m, MF_NOSAVE, state, &args);
+			break;
 		}
-	}
-	else if (!strcmpi(w3,"battleground")) {
-		if( state ) {
-			if( sscanf(w4, "%11d", &state) == 1 )
-				map[m].flag.battleground = state;
-			else
-				map[m].flag.battleground = 1; // Default value
-		} else
-			map[m].flag.battleground = 0;
 
-		if( map[m].flag.battleground && map[m].flag.pvp ) {
-			map[m].flag.pvp = 0;
-			ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing PvP flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
-		}
-		if( map[m].flag.battleground && (map[m].flag.gvg || map[m].flag.gvg_dungeon || map[m].flag.gvg_castle) ) {
-			map[m].flag.gvg = 0;
-			map[m].flag.gvg_dungeon = 0;
-			map[m].flag.gvg_castle = 0;
-			ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing GvG flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
+		case MF_PVP_NIGHTMAREDROP: {
+			char drop_arg1[16], drop_arg2[16];
+			union u_mapflag_args args = {};
+
+			if (sscanf(w4, "%15[^,],%15[^,],%11d", drop_arg1, drop_arg2, &args.nightmaredrop.drop_per) == 3) {
+
+				if (!strcmpi(drop_arg1, "random"))
+					args.nightmaredrop.drop_id = -1;
+				else if (itemdb_exists((args.nightmaredrop.drop_id = atoi(drop_arg1))) == NULL) {
+					args.nightmaredrop.drop_id = 0;
+					ShowWarning("npc_parse_mapflag: Invalid item ID '%d' supplied for mapflag 'pvp_nightmaredrop' (file '%s', line '%d'), removing.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", args.nightmaredrop.drop_id, filepath, strline(buffer, start - buffer), w1, w2, w3, w4);
+					break;
+				}
+				if (!strcmpi(drop_arg2, "inventory"))
+					args.nightmaredrop.drop_type = NMDT_INVENTORY;
+				else if (!strcmpi(drop_arg2, "equip"))
+					args.nightmaredrop.drop_type = NMDT_EQUIP;
+				else if (!strcmpi(drop_arg2, "all"))
+					args.nightmaredrop.drop_type = NMDT_ALL;
+
+				if (args.nightmaredrop.drop_id != 0)
+					map_setmapflag_sub(m, MF_PVP_NIGHTMAREDROP, true, &args);
+			} else if (!state)
+				map_setmapflag(m, MF_PVP_NIGHTMAREDROP, false);
+			break;
 		}
-	}
-	else if (!strcmpi(w3,"noexppenalty"))
-		map[m].flag.noexppenalty=state;
-	else if (!strcmpi(w3,"nozenypenalty"))
-		map[m].flag.nozenypenalty=state;
-	else if (!strcmpi(w3,"notrade"))
-		map[m].flag.notrade=state;
-	else if (!strcmpi(w3,"novending"))
-		map[m].flag.novending=state;
-	else if (!strcmpi(w3,"nodrop"))
-		map[m].flag.nodrop=state;
-	else if (!strcmpi(w3,"noskill"))
-		map[m].flag.noskill=state;
-	else if (!strcmpi(w3,"noicewall"))
-		map[m].flag.noicewall=state;
-	else if (!strcmpi(w3,"snow"))
-		map[m].flag.snow=state;
-	else if (!strcmpi(w3,"clouds"))
-		map[m].flag.clouds=state;
-	else if (!strcmpi(w3,"clouds2"))
-		map[m].flag.clouds2=state;
-	else if (!strcmpi(w3,"fog"))
-		map[m].flag.fog=state;
-	else if (!strcmpi(w3,"fireworks"))
-		map[m].flag.fireworks=state;
-	else if (!strcmpi(w3,"sakura"))
-		map[m].flag.sakura=state;
-	else if (!strcmpi(w3,"leaves"))
-		map[m].flag.leaves=state;
-	else if (!strcmpi(w3,"nightenabled"))
-		map[m].flag.nightenabled=state;
-	else if (!strcmpi(w3,"nogo"))
-		map[m].flag.nogo=state;
-	else if (!strcmpi(w3,"noexp")) {
-		map[m].flag.nobaseexp=state;
-		map[m].flag.nojobexp=state;
-	}
-	else if (!strcmpi(w3,"nobaseexp"))
-		map[m].flag.nobaseexp=state;
-	else if (!strcmpi(w3,"nojobexp"))
-		map[m].flag.nojobexp=state;
-	else if (!strcmpi(w3,"noloot")) {
-		map[m].flag.nomobloot=state;
-		map[m].flag.nomvploot=state;
-	}
-	else if (!strcmpi(w3,"nomobloot"))
-		map[m].flag.nomobloot=state;
-	else if (!strcmpi(w3,"nomvploot"))
-		map[m].flag.nomvploot=state;
-	else if (!strcmpi(w3,"nocommand")) {
-		if (state) {
-			if (sscanf(w4, "%11d", &state) == 1)
-				map[m].nocommand =state;
-			else //No level specified, block everyone.
-				map[m].nocommand =100;
-		} else
-			map[m].nocommand=0;
-	}
-	else if (!strcmpi(w3,"restricted")) {
-		if (state) {
-			if (sscanf(w4, "%11d", &state) == 1) {
-				map[m].flag.restricted = 1;
-				map[m].zone |= 1<<(state+1);
-			} else { // Could not be read, no value defined
-                                //we don't remove has other restricted may be set on the map
-				ShowWarning("npc_parse_mapflag: You did not set a zone value for the restricted mapflag! Skipped flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
+
+		case MF_BATTLEGROUND:
+			if (state) {
+				union u_mapflag_args args = {};
+
+				if (sscanf(w4, "%11d", &args.flag_val) < 1)
+					args.flag_val = 1; // Default value
+
+				map_setmapflag_sub(m, MF_BATTLEGROUND, true, &args);
+			} else
+				map_setmapflag(m, MF_BATTLEGROUND, false);
+			break;
+
+		case MF_NOCOMMAND:
+			if (state) {
+				union u_mapflag_args args = {};
+
+				if (sscanf(w4, "%11d", &args.flag_val) < 1)
+					args.flag_val = 100; // No level specified, block everyone.
+
+				map_setmapflag_sub(m, MF_NOCOMMAND, true, &args);
+			} else
+				map_setmapflag(m, MF_NOCOMMAND, false);
+			break;
+
+		case MF_RESTRICTED:
+			if (state) {
+				union u_mapflag_args args = {};
+
+				if (sscanf(w4, "%11d", &args.flag_val) == 1)
+					map_setmapflag_sub(m, MF_RESTRICTED, true, &args);
+				else // Could not be read, no value defined; don't remove as other restrictions may be set on the map
+					ShowWarning("npc_parse_mapflag: Zone value not set for the restricted mapflag! Skipped flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
+			} else
+				map_setmapflag(m, MF_RESTRICTED, false);
+			break;
+
+		case MF_JEXP:
+		case MF_BEXP: {
+				union u_mapflag_args args = {};
+
+				if (sscanf(w4, "%11d", &args.flag_val) < 1)
+					args.flag_val = 0;
+
+				map_setmapflag_sub(m, mapflag, state, &args);
 			}
-		} else {
-			map[m].flag.restricted=0;
-			map[m].zone = 0;
-		}
-	}
-	else if (!strcmpi(w3,"jexp")) {
-		map[m].adjust.jexp = (state) ? atoi(w4) : 100;
-		if( map[m].adjust.jexp < 0 ) map[m].adjust.jexp = 100;
-		map[m].flag.nojobexp = (map[m].adjust.jexp==0)?1:0;
-	}
-	else if (!strcmpi(w3,"bexp")) {
-		map[m].adjust.bexp = (state) ? atoi(w4) : 100;
-		if( map[m].adjust.bexp < 0 ) map[m].adjust.bexp = 100;
-		 map[m].flag.nobaseexp = (map[m].adjust.bexp==0)?1:0;
-	}
-	else if (!strcmpi(w3,"loadevent"))
-		map[m].flag.loadevent=state;
-	else if (!strcmpi(w3,"nochat"))
-		map[m].flag.nochat=state;
-	else if (!strcmpi(w3,"partylock"))
-		map[m].flag.partylock=state;
-	else if (!strcmpi(w3,"guildlock"))
-		map[m].flag.guildlock=state;
-	else if (!strcmpi(w3,"reset"))
-		map[m].flag.reset=state;
-	else if (!strcmpi(w3,"nomapchannelautojoin"))
-		map[m].flag.chmautojoin = state;
-	else if (!strcmpi(w3,"nousecart"))
-		map[m].flag.nousecart = state;
-	else if (!strcmpi(w3,"noitemconsumption"))
-		map[m].flag.noitemconsumption = state;
-	else if (!strcmpi(w3,"summonstarmiracle"))
-		map[m].flag.nosumstarmiracle = state;
-	else if (!strcmpi(w3,"nomineeffect"))
-		map[m].flag.nomineeffect = state;
-	else if (!strcmpi(w3,"nolockon"))
-		map[m].flag.nolockon = state;
-	else if (!strcmpi(w3,"notomb"))
-		map[m].flag.notomb = state;
-	else if (!strcmpi(w3,"nocostume"))
-		map[m].flag.nocostume = state;
-	else if (!strcmpi(w3,"hidemobhpbar"))
-		map[m].flag.hidemobhpbar = state;
-	else if (!strcmpi(w3,"skill_damage")) {
+			break;
+
+		case MF_SKILL_DAMAGE: {
 #ifdef ADJUST_SKILL_DAMAGE
-		char skill[SKILL_NAME_LENGTH];
-		int pc = 0, mob = 0, boss = 0, other = 0, caster = 0;
+			char skill_name[SKILL_NAME_LENGTH];
+			char caster_constant[NAME_LENGTH];
 
-		memset(skill, 0, sizeof(skill));
-		map[m].flag.skill_damage = state;	// Set the mapflag
+			memset(skill_name, 0, sizeof(skill_name));
 
-		if (!state) {
-			memset(&map[m].adjust.damage, 0, sizeof(map[m].adjust.damage));
-			if (map[m].skill_damage.count)
-				map_skill_damage_free(&map[m]);
-		}
-		else {
-			if (sscanf(w4, "%30[^,],%11d,%11d,%11d,%11d,%11d[^\n]", skill, &caster, &pc, &mob, &boss, &other) >= 3) {
-				caster = (!caster) ? SDC_ALL : caster;
-				pc = cap_value(pc, -100, INT_MAX);
-				mob = cap_value(mob, -100, INT_MAX);
-				boss = cap_value(boss, -100, INT_MAX);
-				other = cap_value(other, -100, INT_MAX);
-
-				if (strcmp(skill,"all") == 0) { // Adjust damages for all skills
-					map[m].adjust.damage.caster = caster;
-					map[m].adjust.damage.pc = pc;
-					map[m].adjust.damage.mob = mob;
-					map[m].adjust.damage.boss = boss;
-					map[m].adjust.damage.other = other;
+			if (!state)
+				map_setmapflag(m, MF_SKILL_DAMAGE, false);
+			else {
+				union u_mapflag_args args = {};
+
+				if (sscanf(w4, "%30[^,],%23[^,],%11d,%11d,%11d,%11d[^\n]", skill_name, caster_constant, &args.skill_damage.rate[SKILLDMG_PC], &args.skill_damage.rate[SKILLDMG_MOB], &args.skill_damage.rate[SKILLDMG_BOSS], &args.skill_damage.rate[SKILLDMG_OTHER]) >= 3) {
+					if (ISDIGIT(caster_constant[0]))
+						args.skill_damage.caster = atoi(caster_constant);
+					else {
+						int val;
+
+						if (!script_get_constant(caster_constant, &val)) {
+							ShowError( "npc_parse_mapflag: Unknown constant '%s'. Skipping (file '%s', line '%d').\n", caster_constant, filepath, strline(buffer, start - buffer) );
+							break;
+						}
+
+						args.skill_damage.caster = val;
+					}
+					
+					if (!args.skill_damage.caster)
+						args.skill_damage.caster = BL_ALL;
+
+					for (int i = 0; i < SKILLDMG_MAX; i++)
+						args.skill_damage.rate[i] = cap_value(args.skill_damage.rate[i], -100, INT_MAX);
+
+					if (strcmp(skill_name, "all") == 0) // Adjust damage for all skills
+						map_setmapflag_sub(m, MF_SKILL_DAMAGE, true, &args);
+					else if (skill_name2id(skill_name) <= 0)
+						ShowWarning("npc_parse_mapflag: Invalid skill name '%s' for Skill Damage mapflag. Skipping (file '%s', line '%d').\n", skill_name, filepath, strline(buffer, start - buffer));
+					else { // Adjusted damage for specified skill
+						map_setmapflag(m, MF_SKILL_DAMAGE, true);
+						map_skill_damage_add(&map[m], skill_name2id(skill_name), args.skill_damage.rate, args.skill_damage.caster);
+					}
 				}
-				else if (skill_name2id(skill) <= 0)
-					ShowWarning("npc_parse_mapflag: skill_damage: Invalid skill name '%s'. Skipping (file '%s', line '%d')\n", skill, filepath, strline(buffer,start-buffer));
-				else //Damages for specified skill
-					map_skill_damage_add(&map[m], skill_name2id(skill), pc, mob, boss, other, caster);
 			}
-		}
 #else
-		ShowInfo("npc_parse_mapflag: skill_damage: ADJUST_SKILL_DAMAGE is inactive (core.hpp). Skipping this mapflag..\n");
+			ShowWarning("npc_parse_mapflag: skill_damage: ADJUST_SKILL_DAMAGE is inactive (src/config/core.hpp). Skipping this mapflag..\n");
 #endif
+			break;
+		}
+
+		// All others do not need special treatment
+		default:
+			map_setmapflag(m, mapflag, state);
+			break;
 	}
-	else
-		ShowError("npc_parse_mapflag: unrecognized mapflag '%s' (file '%s', line '%d').\n", w3, filepath, strline(buffer,start-buffer));
 
 	return strchr(start,'\n');// continue
 }
@@ -4586,7 +4435,7 @@ int npc_reload(void) {
 	if(battle_config.dynamic_mobs)
 	{// dynamic check by [random]
 		int16 m;
-		for (m = 0; m < map_num; m++) {
+		for (m = 0; m < map.size(); m++) {
 			int16 i;
 			for (i = 0; i < MAX_MOB_LIST_PER_MAP; i++) {
 				if (map[m].moblist[i] != NULL) {
@@ -4727,7 +4576,7 @@ static void npc_debug_warps_sub(struct npc_data* nd)
 static void npc_debug_warps(void)
 {
 	int16 m, i;
-	for (m = 0; m < map_num; m++)
+	for (m = 0; m < map.size(); m++)
 		for (i = 0; i < map[m].npc_num; i++)
 			npc_debug_warps_sub(map[m].npc[i]);
 }

+ 1 - 1
src/map/party.cpp

@@ -791,7 +791,7 @@ int party_changeleader(struct map_session_data *sd, struct map_session_data *tsd
 			return -3;
 		}
 
-		if ( map[sd->bl.m].flag.partylock ) {
+		if ( map_getmapflag(sd->bl.m, MF_PARTYLOCK) ) {
 			clif_displaymessage(sd->fd, msg_txt(sd,287));
 			return 0;
 		}

+ 34 - 34
src/map/pc.cpp

@@ -712,7 +712,7 @@ void pc_makesavestatus(struct map_session_data *sd) {
 		sd->status.last_point.y = sd->bl.y;
 	}
 
-	if(map[sd->bl.m].flag.nosave) {
+	if(map_getmapflag(sd->bl.m, MF_NOSAVE)) {
 		struct map_data *m=&map[sd->bl.m];
 		if(m->save.map)
 			memcpy(&sd->status.last_point,&m->save,sizeof(sd->status.last_point));
@@ -1570,7 +1570,7 @@ void pc_reg_received(struct map_session_data *sd)
 		// decrement the number of pvp players on the map
 		map[sd->bl.m].users_pvp--;
 
-		if( map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.pvp_nocalcrank && sd->pvp_timer != INVALID_TIMER ){
+		if( map_getmapflag(sd->bl.m, MF_PVP) && !map_getmapflag(sd->bl.m, MF_PVP_NOCALCRANK) && sd->pvp_timer != INVALID_TIMER ){
 			// unregister the player for ranking
 			delete_timer( sd->pvp_timer, pc_calc_pvprank_timer );
 			sd->pvp_timer = INVALID_TIMER;
@@ -4764,7 +4764,7 @@ bool pc_dropitem(struct map_session_data *sd,int n,int amount)
 		)
 		return false;
 
-	if( map[sd->bl.m].flag.nodrop )
+	if( map_getmapflag(sd->bl.m, MF_NODROP) )
 	{
 		clif_displaymessage (sd->fd, msg_txt(sd,271));
 		return false; //Can't drop items in nodrop mapflag maps.
@@ -4882,7 +4882,7 @@ bool pc_isUseitem(struct map_session_data *sd,int n)
 		return false;
 	if (pc_has_permission(sd,PC_PERM_ITEM_UNCONDITIONAL))
 		return true;
-	if(map[sd->bl.m].flag.noitemconsumption) //consumable but mapflag prevent it
+	if(map_getmapflag(sd->bl.m, MF_NOITEMCONSUMPTION)) //consumable but mapflag prevent it
 		return false;
 	//Prevent mass item usage. [Skotlex]
 	if( DIFF_TICK(sd->canuseitem_tick,gettick()) > 0 ||
@@ -4900,14 +4900,14 @@ bool pc_isUseitem(struct map_session_data *sd,int n)
 		return false; // You cannot use this item while storage is open.
 	}
 
-	if (item->flag.dead_branch && (map[sd->bl.m].flag.nobranch || map_flag_gvg2(sd->bl.m)))
+	if (item->flag.dead_branch && (map_getmapflag(sd->bl.m, MF_NOBRANCH) || map_flag_gvg2(sd->bl.m)))
 		return false;
 
 	switch( nameid ) {
 		case ITEMID_WING_OF_FLY:
 		case ITEMID_GIANT_FLY_WING:
 		case ITEMID_N_FLY_WING:
-			if( map[sd->bl.m].flag.noteleport || map_flag_gvg2(sd->bl.m) ) {
+			if( map_getmapflag(sd->bl.m, MF_NOTELEPORT) || map_flag_gvg2(sd->bl.m) ) {
 				clif_skill_teleportmessage(sd,0);
 				return false;
 			}
@@ -4948,7 +4948,7 @@ bool pc_isUseitem(struct map_session_data *sd,int n)
 				clif_displaymessage(sd->fd, msg_txt(sd,663));
 				return false;
 			}
-			if( map[sd->bl.m].flag.noreturn && nameid != ITEMID_WING_OF_FLY && nameid != ITEMID_GIANT_FLY_WING && nameid != ITEMID_N_FLY_WING )
+			if( map_getmapflag(sd->bl.m, MF_NORETURN) && nameid != ITEMID_WING_OF_FLY && nameid != ITEMID_GIANT_FLY_WING && nameid != ITEMID_N_FLY_WING )
 				return false;
 			break;
 		case ITEMID_MERCENARY_RED_POTION:
@@ -4967,7 +4967,7 @@ bool pc_isUseitem(struct map_session_data *sd,int n)
 			break;
 
 		case ITEMID_NEURALIZER:
-			if( !map[sd->bl.m].flag.reset )
+			if( !map_getmapflag(sd->bl.m, MF_RESET) )
 				return false;
 			break;
 	}
@@ -5375,7 +5375,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil
 	md_status= status_get_status_data(bl);
 
 	if (md->master_id || status_has_mode(md_status, MD_STATUS_IMMUNE) || status_get_race2(&md->bl) == RC2_TREASURE ||
-		map[bl->m].flag.nomobloot || // check noloot map flag [Lorky]
+		map_getmapflag(bl->m, MF_NOMOBLOOT) || // check noloot map flag [Lorky]
 		(battle_config.skill_steal_max_tries && //Reached limit of steal attempts. [Lupus]
 			md->state.steal_flag++ >= battle_config.skill_steal_max_tries)
   	) { //Can't steal from
@@ -5555,7 +5555,7 @@ enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, in
 		if (sd->regen.state.gc)
 			sd->regen.state.gc = 0;
 		// make sure vending is allowed here
-		if (sd->state.vending && map[m].flag.novending) {
+		if (sd->state.vending && map_getmapflag(m, MF_NOVENDING)) {
 			clif_displaymessage (sd->fd, msg_txt(sd,276)); // "You can't open a shop on this map"
 			vending_closevending(sd);
 		}
@@ -5638,7 +5638,7 @@ enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, in
 	sd->bl.x = sd->ud.to_x = x;
 	sd->bl.y = sd->ud.to_y = y;
 
-	if( sd->status.guild_id > 0 && map[m].flag.gvg_castle )
+	if( sd->status.guild_id > 0 && map_getmapflag(m, MF_GVG_CASTLE) )
 	{	// Increased guild castle regen [Valaris]
 		struct guild_castle *gc = guild_mapindex2gc(sd->mapindex);
 		if(gc && gc->guild_id == sd->status.guild_id)
@@ -5704,7 +5704,7 @@ char pc_randomwarp(struct map_session_data *sd, clr_type type)
 
 	m=sd->bl.m;
 
-	if (map[sd->bl.m].flag.noteleport) //Teleport forbidden
+	if (map_getmapflag(sd->bl.m, MF_NOTELEPORT)) //Teleport forbidden
 		return 3;
 
 	do {
@@ -5729,7 +5729,7 @@ bool pc_memo(struct map_session_data* sd, int pos)
 	nullpo_ret(sd);
 
 	// check mapflags
-	if( sd->bl.m >= 0 && (map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) {
+	if( sd->bl.m >= 0 && (map_getmapflag(sd->bl.m, MF_NOMEMO) || map_getmapflag(sd->bl.m, MF_NOWARPTO)) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) {
 		clif_skill_teleportmessage(sd, 1); // "Saved point cannot be memorized."
 		return false;
 	}
@@ -6769,7 +6769,7 @@ void pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in
 
 	if (!(exp_flag&2)) {
 
-		if (!battle_config.pvp_exp && map[sd->bl.m].flag.pvp)  // [MouseJstr]
+		if (!battle_config.pvp_exp && map_getmapflag(sd->bl.m, MF_PVP))  // [MouseJstr]
 			return; // no exp on pvp maps
 	
 		if (sd->status.guild_id>0)
@@ -7776,7 +7776,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 
 	if(sd->status.pet_id > 0 && sd->pd) {
 		struct pet_data *pd = sd->pd;
-		if( !map[sd->bl.m].flag.noexppenalty ) {
+		if( !map_getmapflag(sd->bl.m, MF_NOEXPPENALTY) ) {
 			pet_set_intimate(pd, pd->pet.intimate - pd->get_pet_db()->die);
 			if( pd->pet.intimate < 0 )
 				pd->pet.intimate = 0;
@@ -7896,7 +7896,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 	}
 
 	if(battle_config.bone_drop==2
-		|| (battle_config.bone_drop==1 && map[sd->bl.m].flag.pvp))
+		|| (battle_config.bone_drop==1 && map_getmapflag(sd->bl.m, MF_PVP)))
 	{
 		struct item item_tmp;
 		memset(&item_tmp,0,sizeof(item_tmp));
@@ -7915,7 +7915,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 	// changed penalty options, added death by player if pk_mode [Valaris]
 	if(battle_config.death_penalty_type
 		&& (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE	// only novices will receive no penalty
-		&& !map[sd->bl.m].flag.noexppenalty && !map_flag_gvg2(sd->bl.m)
+		&& !map_getmapflag(sd->bl.m, MF_NOEXPPENALTY) && !map_flag_gvg2(sd->bl.m)
 		&& !sd->sc.data[SC_BABY] && !sd->sc.data[SC_LIFEINSURANCE])
 	{
 		uint32 base_penalty = 0;
@@ -7963,28 +7963,28 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 		if (base_penalty || job_penalty)
 			pc_lostexp(sd, base_penalty, job_penalty);
 
-		if( zeny_penalty > 0 && !map[sd->bl.m].flag.nozenypenalty) {
+		if( zeny_penalty > 0 && !map_getmapflag(sd->bl.m, MF_NOZENYPENALTY)) {
 			zeny_penalty = (uint32)( sd->status.zeny * ( zeny_penalty / 10000. ) );
 			if(zeny_penalty)
 				pc_payzeny(sd, zeny_penalty, LOG_TYPE_PICKDROP_PLAYER, NULL);
 		}
 	}
 
-	if(map[sd->bl.m].flag.pvp_nightmaredrop) { // Moved this outside so it works when PVP isn't enabled and during pk mode [Ancyker]
-		int j;
-		for(j=0;j<MAX_DROP_PER_MAP;j++){
+	if( map_getmapflag( sd->bl.m, MF_PVP_NIGHTMAREDROP ) ) { // Moved this outside so it works when PVP isn't enabled and during pk mode [Ancyker]
+		for(int j=0;j<MAX_DROP_PER_MAP;j++){
 			int id = map[sd->bl.m].drop_list[j].drop_id;
-			int type = map[sd->bl.m].drop_list[j].drop_type;
 			int per = map[sd->bl.m].drop_list[j].drop_per;
+			enum e_nightmare_drop_type type = map[sd->bl.m].drop_list[j].drop_type;
+
 			if(id == 0)
 				continue;
 			if(id == -1){
 				int eq_num=0,eq_n[MAX_INVENTORY];
 				memset(eq_n,0,sizeof(eq_n));
 				for(i=0;i<MAX_INVENTORY;i++) {
-					if( (type == 1 && !sd->inventory.u.items_inventory[i].equip)
-						|| (type == 2 && sd->inventory.u.items_inventory[i].equip)
-						||  type == 3)
+					if( (type&NMDT_INVENTORY && !sd->inventory.u.items_inventory[i].equip)
+						|| (type&NMDT_EQUIP && sd->inventory.u.items_inventory[i].equip)
+						||  type&NMDT_ALL)
 					{
 						int l;
 						ARR_FIND( 0, MAX_INVENTORY, l, eq_n[l] <= 0 );
@@ -8007,9 +8007,9 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 				for(i=0;i<MAX_INVENTORY;i++){
 					if(sd->inventory.u.items_inventory[i].nameid == id
 						&& rnd()%10000 < per
-						&& ((type == 1 && !sd->inventory.u.items_inventory[i].equip)
-							|| (type == 2 && sd->inventory.u.items_inventory[i].equip)
-							|| type == 3) ){
+						&& ((type&NMDT_INVENTORY && !sd->inventory.u.items_inventory[i].equip)
+							|| (type&NMDT_EQUIP && sd->inventory.u.items_inventory[i].equip)
+							|| type&NMDT_ALL) ){
 						if(sd->inventory.u.items_inventory[i].equip)
 							pc_unequipitem(sd,i,3);
 						pc_dropitem(sd,i,1);
@@ -8021,7 +8021,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 	}
 	// pvp
 	// disable certain pvp functions on pk_mode [Valaris]
-	if( map[sd->bl.m].flag.pvp && !battle_config.pk_mode && !map[sd->bl.m].flag.pvp_nocalcrank ) {
+	if( map_getmapflag(sd->bl.m, MF_PVP) && !battle_config.pk_mode && !map_getmapflag(sd->bl.m, MF_PVP_NOCALCRANK) ) {
 		sd->pvp_point -= 5;
 		sd->pvp_lost++;
 		if( src && src->type == BL_PC ) {
@@ -10584,7 +10584,7 @@ static TIMER_FUNC(pc_autosave){
 
 static int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap)
 {
-	if (sd->state.night != night_flag && map[sd->bl.m].flag.nightenabled)
+	if (sd->state.night != night_flag && map_getmapflag(sd->bl.m, MF_NIGHTENABLED))
 	{	//Night/day state does not match.
 		clif_status_load(&sd->bl, EFST_SKE, night_flag); //New night effect by dynamix [Skotlex]
 		sd->state.night = night_flag;
@@ -12476,11 +12476,11 @@ bool pc_job_can_entermap(enum e_job jobid, int m, int group_lv) {
 		return true;
 
 	if ((!map_flag_vs2(m) && job_info[idx].noenter_map.zone&1) || // Normal
-		(map[m].flag.pvp && job_info[idx].noenter_map.zone&2) || // PVP
+		(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[m].flag.battleground && job_info[idx].noenter_map.zone&8) || // Battleground
+		(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[m].flag.restricted && job_info[idx].noenter_map.zone&(8*map[m].zone)) // Zone restriction
+		(map_getmapflag(m, MF_RESTRICTED) && job_info[idx].noenter_map.zone&(8*map[m].zone)) // Zone restriction
 		)
 		return false;
 
@@ -12525,7 +12525,7 @@ void pc_set_costume_view(struct map_session_data *sd) {
 		sd->status.robe = id->look;
 
 	// Costumes check
-	if (!map[sd->bl.m].flag.nocostume) {
+	if (!map_getmapflag(sd->bl.m, MF_NOCOSTUME)) {
 		if ((i = sd->equip_index[EQI_COSTUME_HEAD_LOW]) != -1 && (id = sd->inventory_data[i])) {
 			if (!(id->equip&(EQP_COSTUME_HEAD_MID|EQP_COSTUME_HEAD_TOP)))
 				sd->status.head_bottom = id->look;

+ 128 - 386
src/map/script.cpp

@@ -380,77 +380,6 @@ const char* parse_subexpr(const char* p,int limit);
 int run_func(struct script_state *st);
 unsigned short script_instancegetid(struct script_state *st);
 
-enum {
-	MF_NOMEMO,	//0
-	MF_NOTELEPORT,
-	MF_NOSAVE,
-	MF_NOBRANCH,
-	MF_NOPENALTY,
-	MF_NOZENYPENALTY,
-	MF_PVP,
-	MF_PVP_NOPARTY,
-	MF_PVP_NOGUILD,
-	MF_GVG,
-	MF_GVG_NOPARTY,	//10
-	MF_NOTRADE,
-	MF_NOSKILL,
-	MF_NOWARP,
-	MF_PARTYLOCK,
-	MF_NOICEWALL,
-	MF_SNOW,
-	MF_FOG,
-	MF_SAKURA,
-	MF_LEAVES,
-	/**
-	 * No longer available, keeping here just in case it's back someday. [Ind]
-	 **/
-	//MF_RAIN,	//20
-	// 21 free
-	MF_NOGO = 22,
-	MF_CLOUDS,
-	MF_CLOUDS2,
-	MF_FIREWORKS,
-	MF_GVG_CASTLE,
-	MF_GVG_DUNGEON,
-	MF_NIGHTENABLED,
-	MF_NOBASEEXP,
-	MF_NOJOBEXP,	//30
-	MF_NOMOBLOOT,
-	MF_NOMVPLOOT,
-	MF_NORETURN,
-	MF_NOWARPTO,
-	MF_NIGHTMAREDROP,
-	MF_RESTRICTED,
-	MF_NOCOMMAND,
-	MF_NODROP,
-	MF_JEXP,
-	MF_BEXP,	//40
-	MF_NOVENDING,
-	MF_LOADEVENT,
-	MF_NOCHAT,
-	MF_NOEXPPENALTY,
-	MF_GUILDLOCK,
-	MF_TOWN,
-	MF_AUTOTRADE,
-	MF_ALLOWKS,
-	MF_MONSTER_NOTELEPORT,
-	MF_PVP_NOCALCRANK,	//50
-	MF_BATTLEGROUND,
-	MF_RESET,
-	MF_CHANNELAUTOJOIN,
-	MF_NOUSECART,
-	MF_NOITEMCONSUMPTION,
-	MF_SUMSTARTMIRACLE,
-	MF_NOMINEEFFECT,
-	MF_NOLOCKON,
-	MF_NOTOMB,
-	MF_SKILL_DAMAGE,	//60
-	MF_NOCOSTUME,
-	MF_GVG_TE_CASTLE,
-	MF_GVG_TE,
-	MF_HIDEMOBHPBAR,
-};
-
 const char* script_op2name(int op)
 {
 #define RETURN_OP_NAME(type) case type: return #type
@@ -2291,6 +2220,39 @@ static void add_buildin_func(void)
 	}
 }
 
+/**
+ * String comparison with a char array to a script constant
+ * @param prefix: Char array to compare
+ * @param value: Script constant
+ * @return Constant name as char array or NULL otherwise
+ */
+const char* script_get_constant_str( const char* prefix, int64 value ){
+	const char* name;
+
+	for(int i = 0; i < str_data_size; i++ ){
+		// Check if it is a constant
+		if( str_data[i].type != C_INT ){
+			continue;
+		}
+
+		// Check if the value matches
+		if( str_data[i].val != value ){
+			continue;
+		}
+
+		// Look up the actual string
+		name = get_str(i);
+
+		// Compare the prefix
+		if( !strncasecmp( name, prefix, strlen(prefix) ) ){
+			// We found a match
+			return name;
+		}
+	}
+
+	return NULL;
+}
+
 /// Retrieves the value of a constant parameter.
 bool script_get_parameter(const char* name, int* value)
 {
@@ -5652,15 +5614,15 @@ BUILDIN_FUNC(warpparty)
 		switch( type )
 		{
 		case 0: // Random
-			if(!map[pl_sd->bl.m].flag.nowarp)
+			if(!map_getmapflag(pl_sd->bl.m, MF_NOWARP))
 				pc_randomwarp(pl_sd,CLR_TELEPORT);
 		break;
 		case 1: // SavePointAll
-			if(!map[pl_sd->bl.m].flag.noreturn)
+			if(!map_getmapflag(pl_sd->bl.m, MF_NORETURN))
 				pc_setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT);
 		break;
 		case 2: // SavePoint
-			if(!map[pl_sd->bl.m].flag.noreturn)
+			if(!map_getmapflag(pl_sd->bl.m, MF_NORETURN))
 				pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
 		break;
 		case 3: // Leader
@@ -5678,7 +5640,7 @@ BUILDIN_FUNC(warpparty)
 				} while ((--attempts) > 0 && !map_getcell(m, x, y, CELL_CHKPASS));
 			}
 
-			if(!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp && pc_job_can_entermap((enum e_job)pl_sd->status.class_, m, pl_sd->group_level))
+			if(!map_getmapflag(pl_sd->bl.m, MF_NORETURN) && !map_getmapflag(pl_sd->bl.m, MF_NOWARP) && pc_job_can_entermap((enum e_job)pl_sd->status.class_, m, pl_sd->group_level))
 				pc_setpos(pl_sd,mapindex,x,y,CLR_TELEPORT);
 		break;
 		}
@@ -5736,19 +5698,19 @@ BUILDIN_FUNC(warpguild)
 		switch( type )
 		{
 		case 0: // Random
-			if(!map[pl_sd->bl.m].flag.nowarp)
+			if(!map_getmapflag(pl_sd->bl.m, MF_NOWARP))
 				pc_randomwarp(pl_sd,CLR_TELEPORT);
 		break;
 		case 1: // SavePointAll
-			if(!map[pl_sd->bl.m].flag.noreturn)
+			if(!map_getmapflag(pl_sd->bl.m, MF_NORETURN))
 				pc_setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT);
 		break;
 		case 2: // SavePoint
-			if(!map[pl_sd->bl.m].flag.noreturn)
+			if(!map_getmapflag(pl_sd->bl.m, MF_NORETURN))
 				pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
 		break;
 		case 3: // m,x,y
-			if(!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp && pc_job_can_entermap((enum e_job)pl_sd->status.class_, m, pl_sd->group_level))
+			if(!map_getmapflag(pl_sd->bl.m, MF_NORETURN) && !map_getmapflag(pl_sd->bl.m, MF_NOWARP) && pc_job_can_entermap((enum e_job)pl_sd->status.class_, m, pl_sd->group_level))
 				pc_setpos(pl_sd,mapindex,x,y,CLR_TELEPORT);
 		break;
 		}
@@ -12044,7 +12006,7 @@ BUILDIN_FUNC(warpwaitingpc)
 	{
 		TBL_PC* sd = cd->usersd[0];
 
-		if( strcmp(map_name,"SavePoint") == 0 && map[sd->bl.m].flag.noteleport )
+		if( strcmp(map_name,"SavePoint") == 0 && map_getmapflag(sd->bl.m, MF_NOTELEPORT) )
 		{// can't teleport on this map
 			break;
 		}
@@ -12261,6 +12223,7 @@ BUILDIN_FUNC(setmapflagnosave)
 	int16 m,x,y;
 	unsigned short mapindex;
 	const char *str,*str2;
+	union u_mapflag_args args = {};
 
 	str=script_getstr(st,2);
 	str2=script_getstr(st,3);
@@ -12269,331 +12232,110 @@ BUILDIN_FUNC(setmapflagnosave)
 	m = map_mapname2mapid(str);
 	mapindex = mapindex_name2id(str2);
 
-	if(m >= 0 && mapindex) {
-		map[m].flag.nosave=1;
-		map[m].save.map=mapindex;
-		map[m].save.x=x;
-		map[m].save.y=y;
+	if(m < 0) {
+		ShowWarning("buildin_setmapflagnosave: Invalid map name %s.\n", str);
+		return SCRIPT_CMD_FAILURE;
 	}
+
+	args.nosave.map = mapindex;
+	args.nosave.x = x;
+	args.nosave.y = y;
+
+	map_setmapflag_sub(m, MF_NOSAVE, true, &args);
 	return SCRIPT_CMD_SUCCESS;
 }
 
 BUILDIN_FUNC(getmapflag)
 {
-	int16 m,i;
+	int16 m;
+	int mf;
 	const char *str;
+	union u_mapflag_args args = {};
 
 	str=script_getstr(st,2);
-	i=script_getnum(st,3);
 
 	m = map_mapname2mapid(str);
-	if(m >= 0) {
-		switch(i) {
-			case MF_NOMEMO:				script_pushint(st,map[m].flag.nomemo); break;
-			case MF_NOTELEPORT:			script_pushint(st,map[m].flag.noteleport); break;
-			case MF_NOSAVE:				script_pushint(st,map[m].flag.nosave); break;
-			case MF_NOBRANCH:			script_pushint(st,map[m].flag.nobranch); break;
-			case MF_NOPENALTY:			script_pushint(st,map[m].flag.noexppenalty); break;
-			case MF_NOZENYPENALTY:		script_pushint(st,map[m].flag.nozenypenalty); break;
-			case MF_PVP:				script_pushint(st,map[m].flag.pvp); break;
-			case MF_PVP_NOPARTY:		script_pushint(st,map[m].flag.pvp_noparty); break;
-			case MF_PVP_NOGUILD:		script_pushint(st,map[m].flag.pvp_noguild); break;
-			case MF_GVG:				script_pushint(st,map[m].flag.gvg); break;
-			case MF_GVG_NOPARTY:		script_pushint(st,map[m].flag.gvg_noparty); break;
-			case MF_NOTRADE:			script_pushint(st,map[m].flag.notrade); break;
-			case MF_NOSKILL:			script_pushint(st,map[m].flag.noskill); break;
-			case MF_NOWARP:				script_pushint(st,map[m].flag.nowarp); break;
-			case MF_PARTYLOCK:			script_pushint(st,map[m].flag.partylock); break;
-			case MF_NOICEWALL:			script_pushint(st,map[m].flag.noicewall); break;
-			case MF_SNOW:				script_pushint(st,map[m].flag.snow); break;
-			case MF_FOG:				script_pushint(st,map[m].flag.fog); break;
-			case MF_SAKURA:				script_pushint(st,map[m].flag.sakura); break;
-			case MF_LEAVES:				script_pushint(st,map[m].flag.leaves); break;
-			case MF_NOGO:				script_pushint(st,map[m].flag.nogo); break;
-			case MF_CLOUDS:				script_pushint(st,map[m].flag.clouds); break;
-			case MF_CLOUDS2:			script_pushint(st,map[m].flag.clouds2); break;
-			case MF_FIREWORKS:			script_pushint(st,map[m].flag.fireworks); break;
-			case MF_GVG_CASTLE:			script_pushint(st,map[m].flag.gvg_castle); break;
-			case MF_GVG_DUNGEON:		script_pushint(st,map[m].flag.gvg_dungeon); break;
-			case MF_NIGHTENABLED:		script_pushint(st,map[m].flag.nightenabled); break;
-			case MF_NOBASEEXP:			script_pushint(st,map[m].flag.nobaseexp); break;
-			case MF_NOJOBEXP:			script_pushint(st,map[m].flag.nojobexp); break;
-			case MF_NOMOBLOOT:			script_pushint(st,map[m].flag.nomobloot); break;
-			case MF_NOMVPLOOT:			script_pushint(st,map[m].flag.nomvploot); break;
-			case MF_NORETURN:			script_pushint(st,map[m].flag.noreturn); break;
-			case MF_NOWARPTO:			script_pushint(st,map[m].flag.nowarpto); break;
-			case MF_NIGHTMAREDROP:		script_pushint(st,map[m].flag.pvp_nightmaredrop); break;
-			case MF_RESTRICTED:			script_pushint(st,map[m].flag.restricted); break;
-			case MF_NOCOMMAND:			script_pushint(st,map[m].nocommand); break;
-			case MF_NODROP:				script_pushint(st,map[m].flag.nodrop); break;
-			case MF_JEXP:				script_pushint(st,map[m].adjust.jexp); break;
-			case MF_BEXP:				script_pushint(st,map[m].adjust.bexp); break;
-			case MF_NOVENDING:			script_pushint(st,map[m].flag.novending); break;
-			case MF_LOADEVENT:			script_pushint(st,map[m].flag.loadevent); break;
-			case MF_NOCHAT:				script_pushint(st,map[m].flag.nochat); break;
-			case MF_NOEXPPENALTY:		script_pushint(st,map[m].flag.noexppenalty ); break;
-			case MF_GUILDLOCK:			script_pushint(st,map[m].flag.guildlock); break;
-			case MF_TOWN:				script_pushint(st,map[m].flag.town); break;
-			case MF_AUTOTRADE:			script_pushint(st,map[m].flag.autotrade); break;
-			case MF_ALLOWKS:			script_pushint(st,map[m].flag.allowks); break;
-			case MF_MONSTER_NOTELEPORT:	script_pushint(st,map[m].flag.monster_noteleport); break;
-			case MF_PVP_NOCALCRANK:		script_pushint(st,map[m].flag.pvp_nocalcrank); break;
-			case MF_BATTLEGROUND:		script_pushint(st,map[m].flag.battleground); break;
-			case MF_RESET:				script_pushint(st,map[m].flag.reset); break;
-			case MF_CHANNELAUTOJOIN:	script_pushint(st,map[m].flag.chmautojoin); break;
-			case MF_NOUSECART:			script_pushint(st,map[m].flag.nousecart); break;
-			case MF_NOITEMCONSUMPTION:	script_pushint(st,map[m].flag.noitemconsumption); break;
-			case MF_SUMSTARTMIRACLE:	script_pushint(st,map[m].flag.nosumstarmiracle); break;
-			case MF_NOMINEEFFECT:		script_pushint(st,map[m].flag.nomineeffect); break;
-			case MF_NOLOCKON:			script_pushint(st,map[m].flag.nolockon); break;
-			case MF_NOTOMB:				script_pushint(st,map[m].flag.notomb); break;
-			case MF_NOCOSTUME:			script_pushint(st,map[m].flag.nocostume); break;
-			case MF_GVG_TE_CASTLE:		script_pushint(st,map[m].flag.gvg_te_castle); break;
-			case MF_GVG_TE:				script_pushint(st,map[m].flag.gvg_te); break;
-			case MF_HIDEMOBHPBAR:		script_pushint(st,map[m].flag.hidemobhpbar); break;
-#ifdef ADJUST_SKILL_DAMAGE
-			case MF_SKILL_DAMAGE:
-				{
-					int ret_val=0, type=0;
-					FETCH(4,type);
-					switch (type) {
-						case 1: ret_val = map[m].adjust.damage.pc; break;
-						case 2: ret_val = map[m].adjust.damage.mob; break;
-						case 3: ret_val = map[m].adjust.damage.boss; break;
-						case 4: ret_val = map[m].adjust.damage.other; break;
-						case 5: ret_val = map[m].adjust.damage.caster; break;
-						default: ret_val = map[m].flag.skill_damage; break;
-					}
-					script_pushint(st,ret_val); break;
-				} break;
-#endif
-		}
+	if (m < 0) {
+		ShowWarning("buildin_getmapflag: Invalid map name %s.\n", str);
+		return SCRIPT_CMD_FAILURE;
 	}
-	return SCRIPT_CMD_SUCCESS;
-}
 
-/* pvp timer handling */
-static int script_mapflag_pvp_sub(struct block_list *bl,va_list ap) {
-	TBL_PC* sd = (TBL_PC*)bl;
-	if (sd->pvp_timer == INVALID_TIMER) {
-		sd->pvp_timer = add_timer(gettick() + 200, pc_calc_pvprank_timer, sd->bl.id, 0);
-		sd->pvp_rank = 0;
-		sd->pvp_lastusers = 0;
-		sd->pvp_point = 5;
-		sd->pvp_won = 0;
-		sd->pvp_lost = 0;
+	mf = script_getnum(st, 3);
+
+	if( mf < MF_MIN || mf > MF_MAX ){
+		ShowError( "buildin_getmapflag: Unsupported mapflag '%d'.\n", mf );
+		return SCRIPT_CMD_FAILURE;
 	}
-	clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE,SELF);
-	return 0;
+
+#ifdef ADJUST_SKILL_DAMAGE
+	FETCH(4, args.flag_val);
+#endif
+
+	script_pushint(st, map_getmapflag_sub(m, static_cast<e_mapflag>(mf), &args));
+
+	return SCRIPT_CMD_SUCCESS;
 }
 
 BUILDIN_FUNC(setmapflag)
 {
-	int16 m,i;
+	int16 m;
+	int mf;
 	const char *str;
-	int val=0;
+	union u_mapflag_args args = {};
+
+	str = script_getstr(st,2);
 
-	str=script_getstr(st,2);
-	i=script_getnum(st,3);
-	FETCH(4,val);
 	m = map_mapname2mapid(str);
-	if(m >= 0) {
-		switch(i) {
-			case MF_NOMEMO:				map[m].flag.nomemo = 1; break;
-			case MF_NOTELEPORT:			map[m].flag.noteleport = 1; break;
-			case MF_NOSAVE:				map[m].flag.nosave = 1; break;
-			case MF_NOBRANCH:			map[m].flag.nobranch = 1; break;
-			case MF_NOPENALTY:			map[m].flag.noexppenalty = 1; map[m].flag.nozenypenalty = 1; break;
-			case MF_NOZENYPENALTY:		map[m].flag.nozenypenalty = 1; break;
-			case MF_PVP:
-				map[m].flag.pvp = 1;
-				if( !battle_config.pk_mode ) {
-					map_foreachinmap(script_mapflag_pvp_sub,m,BL_PC);
-				}
-				break;
-			case MF_PVP_NOPARTY:		map[m].flag.pvp_noparty = 1; break;
-			case MF_PVP_NOGUILD:		map[m].flag.pvp_noguild = 1; break;
-			case MF_GVG:
-				map[m].flag.gvg = 1;
-				clif_map_property_mapall(m, MAPPROPERTY_AGITZONE);
-				break;
-			case MF_GVG_NOPARTY:		map[m].flag.gvg_noparty = 1; break;
-			case MF_NOTRADE:			map[m].flag.notrade = 1; break;
-			case MF_NOSKILL:			map[m].flag.noskill = 1; break;
-			case MF_NOWARP:				map[m].flag.nowarp = 1; break;
-			case MF_PARTYLOCK:			map[m].flag.partylock = 1; break;
-			case MF_NOICEWALL:			map[m].flag.noicewall = 1; break;
-			case MF_SNOW:				map[m].flag.snow = 1; break;
-			case MF_FOG:				map[m].flag.fog = 1; break;
-			case MF_SAKURA:				map[m].flag.sakura = 1; break;
-			case MF_LEAVES:				map[m].flag.leaves = 1; break;
-			case MF_NOGO:				map[m].flag.nogo = 1; break;
-			case MF_CLOUDS:				map[m].flag.clouds = 1; break;
-			case MF_CLOUDS2:			map[m].flag.clouds2 = 1; break;
-			case MF_FIREWORKS:			map[m].flag.fireworks = 1; break;
-			case MF_GVG_CASTLE:			map[m].flag.gvg_castle = 1; break;
-			case MF_GVG_DUNGEON:		map[m].flag.gvg_dungeon = 1; break;
-			case MF_NIGHTENABLED:		map[m].flag.nightenabled = 1; break;
-			case MF_NOBASEEXP:			map[m].flag.nobaseexp = 1; break;
-			case MF_NOJOBEXP:			map[m].flag.nojobexp = 1; break;
-			case MF_NOMOBLOOT:			map[m].flag.nomobloot = 1; break;
-			case MF_NOMVPLOOT:			map[m].flag.nomvploot = 1; break;
-			case MF_NORETURN:			map[m].flag.noreturn = 1; break;
-			case MF_NOWARPTO:			map[m].flag.nowarpto = 1; break;
-			case MF_NIGHTMAREDROP:		map[m].flag.pvp_nightmaredrop = 1; break;
-			case MF_RESTRICTED:
-				map[m].zone |= 1<<(val+1);
-				map[m].flag.restricted=1;
-				break;
-			case MF_NOCOMMAND:			map[m].nocommand = (val <= 0) ? 100 : val; break;
-			case MF_NODROP:				map[m].flag.nodrop = 1; break;
-			case MF_JEXP:				map[m].adjust.jexp = (val <= 0) ? 100 : val; break;
-			case MF_BEXP:				map[m].adjust.bexp = (val <= 0) ? 100 : val; break;
-			case MF_NOVENDING:			map[m].flag.novending = 1; break;
-			case MF_LOADEVENT:			map[m].flag.loadevent = 1; break;
-			case MF_NOCHAT:				map[m].flag.nochat = 1; break;
-			case MF_NOEXPPENALTY:		map[m].flag.noexppenalty  = 1; break;
-			case MF_GUILDLOCK:			map[m].flag.guildlock = 1; break;
-			case MF_TOWN:				map[m].flag.town = 1; break;
-			case MF_AUTOTRADE:			map[m].flag.autotrade = 1; break;
-			case MF_ALLOWKS:			map[m].flag.allowks = 1; break;
-			case MF_MONSTER_NOTELEPORT:	map[m].flag.monster_noteleport = 1; break;
-			case MF_PVP_NOCALCRANK:		map[m].flag.pvp_nocalcrank = 1; break;
-			case MF_BATTLEGROUND:		map[m].flag.battleground = (val <= 0 || val > 2) ? 1 : val; break;
-			case MF_RESET:				map[m].flag.reset = 1; break;
-			case MF_CHANNELAUTOJOIN:	map[m].flag.chmautojoin = 1 ; break;
-			case MF_NOUSECART:			map[m].flag.nousecart = 1 ; break;
-			case MF_NOITEMCONSUMPTION:	map[m].flag.noitemconsumption = 1 ; break;
-			case MF_SUMSTARTMIRACLE:	map[m].flag.nosumstarmiracle = 1 ; break;
-			case MF_NOMINEEFFECT:		map[m].flag.nomineeffect = 1 ; break;
-			case MF_NOLOCKON:			map[m].flag.nolockon = 1 ; break;
-			case MF_NOTOMB:				map[m].flag.notomb = 1; break;
-			case MF_NOCOSTUME:			map[m].flag.nocostume = 1; break;
-			case MF_GVG_TE_CASTLE:		map[m].flag.gvg_te_castle = 1; break;
-			case MF_GVG_TE:
-				map[m].flag.gvg_te = 1;
-				clif_map_property_mapall(m, MAPPROPERTY_AGITZONE);
-				break;
-			case MF_HIDEMOBHPBAR:		map[m].flag.hidemobhpbar = 1; break;
-#ifdef ADJUST_SKILL_DAMAGE
-			case MF_SKILL_DAMAGE:
-				{
-					int type=0;
-					FETCH(5,type);
-					switch (type) {
-						case 1: map[m].adjust.damage.pc = val; break;
-						case 2: map[m].adjust.damage.mob = val; break;
-						case 3: map[m].adjust.damage.boss = val; break;
-						case 4: map[m].adjust.damage.other = val; break;
-						case 5: map[m].adjust.damage.caster = val; break;
-					}
-					map[m].flag.skill_damage = 1;
-				} break;
-#endif
-		}
+	if (m < 0) {
+		ShowWarning("buildin_setmapflag: Invalid map name %s.\n", str);
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	mf = script_getnum(st, 3);
+
+	if( mf < MF_MIN || mf > MF_MAX ){
+		ShowError( "buildin_setmapflag: Unsupported mapflag '%d'.\n", mf );
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	if( mf == MF_SKILL_DAMAGE ){
+		ShowError( "buildin_setmapflag: Skill damage adjust is not supported. Please use setmapflagskilldmg.\n" );
+		return SCRIPT_CMD_FAILURE;
 	}
+
+	FETCH(4, args.flag_val);
+
+	map_setmapflag_sub(m, static_cast<e_mapflag>(mf), true, &args);
+
 	return SCRIPT_CMD_SUCCESS;
 }
 
 BUILDIN_FUNC(removemapflag)
 {
-	int16 m,i;
+	int16 m;
+	int mf;
 	const char *str;
-	int val=0;
+	union u_mapflag_args args = {};
+
+	str = script_getstr(st, 2);
 
-	str=script_getstr(st,2);
-	i=script_getnum(st,3);
-	FETCH(4,val);
 	m = map_mapname2mapid(str);
-	if(m >= 0) {
-		switch(i) {
-			case MF_NOMEMO:				map[m].flag.nomemo = 0; break;
-			case MF_NOTELEPORT:			map[m].flag.noteleport = 0; break;
-			case MF_NOSAVE:				map[m].flag.nosave = 0; break;
-			case MF_NOBRANCH:			map[m].flag.nobranch = 0; break;
-			case MF_NOPENALTY:			map[m].flag.noexppenalty = 0; map[m].flag.nozenypenalty = 0; break;
-			case MF_NOZENYPENALTY:		map[m].flag.nozenypenalty = 0; break;
-			case MF_PVP:
-				map[m].flag.pvp = 0;
-				clif_map_property_mapall(m, MAPPROPERTY_NOTHING);
-				break;
-			case MF_PVP_NOPARTY:		map[m].flag.pvp_noparty = 0; break;
-			case MF_PVP_NOGUILD:		map[m].flag.pvp_noguild = 0; break;
-			case MF_GVG:
-				map[m].flag.gvg = 0;
-				clif_map_property_mapall(m, MAPPROPERTY_NOTHING);
-				break;
-			case MF_GVG_NOPARTY:		map[m].flag.gvg_noparty = 0; break;
-			case MF_NOTRADE:			map[m].flag.notrade = 0; break;
-			case MF_NOSKILL:			map[m].flag.noskill = 0; break;
-			case MF_NOWARP:				map[m].flag.nowarp = 0; break;
-			case MF_PARTYLOCK:			map[m].flag.partylock = 0; break;
-			case MF_NOICEWALL:			map[m].flag.noicewall = 0; break;
-			case MF_SNOW:				map[m].flag.snow = 0; break;
-			case MF_FOG:				map[m].flag.fog = 0; break;
-			case MF_SAKURA:				map[m].flag.sakura = 0; break;
-			case MF_LEAVES:				map[m].flag.leaves = 0; break;
-			case MF_NOGO:				map[m].flag.nogo = 0; break;
-			case MF_CLOUDS:				map[m].flag.clouds = 0; break;
-			case MF_CLOUDS2:			map[m].flag.clouds2 = 0; break;
-			case MF_FIREWORKS:			map[m].flag.fireworks = 0; break;
-			case MF_GVG_CASTLE:			map[m].flag.gvg_castle = 0; break;
-			case MF_GVG_DUNGEON:		map[m].flag.gvg_dungeon = 0; break;
-			case MF_NIGHTENABLED:		map[m].flag.nightenabled = 0; break;
-			case MF_NOBASEEXP:			map[m].flag.nobaseexp = 0; break;
-			case MF_NOJOBEXP:			map[m].flag.nojobexp = 0; break;
-			case MF_NOMOBLOOT:			map[m].flag.nomobloot = 0; break;
-			case MF_NOMVPLOOT:			map[m].flag.nomvploot = 0; break;
-			case MF_NORETURN:			map[m].flag.noreturn = 0; break;
-			case MF_NOWARPTO:			map[m].flag.nowarpto = 0; break;
-			case MF_NIGHTMAREDROP:		map[m].flag.pvp_nightmaredrop = 0; break;
-			case MF_RESTRICTED:
-				map[m].zone ^= 1<<(val+1);
-				if (map[m].zone == 0){
-					map[m].flag.restricted=0;
-				}
-				break;
-			case MF_NOCOMMAND:			map[m].nocommand = 0; break;
-			case MF_NODROP:				map[m].flag.nodrop = 0; break;
-			case MF_JEXP:				map[m].adjust.jexp = 0; break;
-			case MF_BEXP:				map[m].adjust.bexp = 0; break;
-			case MF_NOVENDING:			map[m].flag.novending = 0; break;
-			case MF_LOADEVENT:			map[m].flag.loadevent = 0; break;
-			case MF_NOCHAT:				map[m].flag.nochat = 0; break;
-			case MF_NOEXPPENALTY:		map[m].flag.noexppenalty  = 0; break;
-			case MF_GUILDLOCK:			map[m].flag.guildlock = 0; break;
-			case MF_TOWN:				map[m].flag.town = 0; break;
-			case MF_AUTOTRADE:			map[m].flag.autotrade = 0; break;
-			case MF_ALLOWKS:			map[m].flag.allowks = 0; break;
-			case MF_MONSTER_NOTELEPORT:	map[m].flag.monster_noteleport = 0; break;
-			case MF_PVP_NOCALCRANK:		map[m].flag.pvp_nocalcrank = 0; break;
-			case MF_BATTLEGROUND:		map[m].flag.battleground = 0; break;
-			case MF_RESET:				map[m].flag.reset = 0; break;
-			case MF_CHANNELAUTOJOIN:	map[m].flag.chmautojoin = 0 ; break;
-			case MF_NOUSECART:			map[m].flag.nousecart = 0 ; break;
-			case MF_NOITEMCONSUMPTION:	map[m].flag.noitemconsumption = 0 ; break;
-			case MF_SUMSTARTMIRACLE:	map[m].flag.nosumstarmiracle = 0 ; break;
-			case MF_NOMINEEFFECT:		map[m].flag.nomineeffect = 0 ; break;
-			case MF_NOLOCKON:			map[m].flag.nolockon = 0 ; break;
-			case MF_NOTOMB:				map[m].flag.notomb = 0; break;
-			case MF_NOCOSTUME:			map[m].flag.nocostume = 0; break;
-			case MF_GVG_TE_CASTLE:		map[m].flag.gvg_te_castle = 0; break;
-			case MF_GVG_TE:
-				map[m].flag.gvg_te = 0;
-				clif_map_property_mapall(m, MAPPROPERTY_NOTHING);
-				break;
-			case MF_HIDEMOBHPBAR:		map[m].flag.hidemobhpbar = 0; break;
-#ifdef ADJUST_SKILL_DAMAGE
-			case MF_SKILL_DAMAGE:
-				{
-					map[m].flag.skill_damage = 0;
-					memset(&map[m].adjust.damage, 0, sizeof(map[m].adjust.damage));
-					if (map[m].skill_damage.count)
-						map_skill_damage_free(&map[m]);
-				} break;
-#endif
-		}
+	if (m < 0) {
+		ShowWarning("buildin_removemapflag: Invalid map name %s.\n", str);
+		return SCRIPT_CMD_FAILURE;
 	}
+
+	mf = script_getnum(st, 3);
+
+	if( mf < MF_MIN || mf > MF_MAX ){
+		ShowError( "buildin_removemapflag: Unsupported mapflag '%d'.\n", mf );
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	FETCH(4, args.flag_val);
+
+	map_setmapflag_sub(m, static_cast<e_mapflag>(mf), false, &args);
+
 	return SCRIPT_CMD_SUCCESS;
 }
 
@@ -12606,10 +12348,10 @@ BUILDIN_FUNC(pvpon)
 
 	str = script_getstr(st,2);
 	m = map_mapname2mapid(str);
-	if( m < 0 || map[m].flag.pvp )
+	if( m < 0 || map_getmapflag(m, MF_PVP) )
 		return SCRIPT_CMD_SUCCESS; // nothing to do
 
-	map[m].flag.pvp = 1;
+	map_setmapflag(m, MF_PVP, true);
 	clif_map_property_mapall(m, MAPPROPERTY_FREEPVPZONE);
 
 	if(battle_config.pk_mode) // disable ranking functions if pk_mode is on [Valaris]
@@ -12650,10 +12392,10 @@ BUILDIN_FUNC(pvpoff)
 
 	str=script_getstr(st,2);
 	m = map_mapname2mapid(str);
-	if(m < 0 || !map[m].flag.pvp)
+	if(m < 0 || !map_getmapflag(m, MF_PVP))
 		return SCRIPT_CMD_SUCCESS; //fixed Lupus
 
-	map[m].flag.pvp = 0;
+	map_setmapflag(m, MF_PVP, false);
 	clif_map_property_mapall(m, MAPPROPERTY_NOTHING);
 
 	if(battle_config.pk_mode) // disable ranking options if pk_mode is on [Valaris]
@@ -12670,8 +12412,8 @@ BUILDIN_FUNC(gvgon)
 
 	str=script_getstr(st,2);
 	m = map_mapname2mapid(str);
-	if(m >= 0 && !map[m].flag.gvg) {
-		map[m].flag.gvg = 1;
+	if(m >= 0 && !map_getmapflag(m, MF_GVG)) {
+		map_setmapflag(m, MF_GVG, true);
 		clif_map_property_mapall(m, MAPPROPERTY_AGITZONE);
 	}
 	return SCRIPT_CMD_SUCCESS;
@@ -12684,8 +12426,8 @@ BUILDIN_FUNC(gvgoff)
 
 	str=script_getstr(st,2);
 	m = map_mapname2mapid(str);
-	if(m >= 0 && map[m].flag.gvg) {
-		map[m].flag.gvg = 0;
+	if(m >= 0 && map_getmapflag(m, MF_GVG)) {
+		map_setmapflag(m, MF_GVG, false);
 		clif_map_property_mapall(m, MAPPROPERTY_NOTHING);
 	}
 	return SCRIPT_CMD_SUCCESS;
@@ -12698,8 +12440,8 @@ BUILDIN_FUNC(gvgon3)
 
 	str = script_getstr(st,2);
 	m = map_mapname2mapid(str);
-	if (m >= 0 && !map[m].flag.gvg_te) {
-		map[m].flag.gvg_te = 1;
+	if (m >= 0 && !map_getmapflag(m, MF_GVG_TE)) {
+		map_setmapflag(m, MF_GVG_TE, true);
 		clif_map_property_mapall(m, MAPPROPERTY_AGITZONE);
 	}
 	return SCRIPT_CMD_SUCCESS;
@@ -12712,8 +12454,8 @@ BUILDIN_FUNC(gvgoff3)
 
 	str = script_getstr(st,2);
 	m = map_mapname2mapid(str);
-	if (m >= 0 && map[m].flag.gvg_te) {
-		map[m].flag.gvg_te = 0;
+	if (m >= 0 && map_getmapflag(m, MF_GVG_TE)) {
+		map_setmapflag(m, MF_GVG_TE, false);
 		clif_map_property_mapall(m, MAPPROPERTY_NOTHING);
 	}
 	return SCRIPT_CMD_SUCCESS;

+ 1 - 0
src/map/script.hpp

@@ -1942,6 +1942,7 @@ struct DBMap* script_get_label_db(void);
 struct DBMap* script_get_userfunc_db(void);
 void script_run_autobonus(const char *autobonus, struct map_session_data *sd, unsigned int pos);
 
+const char* script_get_constant_str(const char* prefix, int64 value);
 bool script_get_parameter(const char* name, int* value);
 bool script_get_constant(const char* name, int* value);
 void script_set_constant(const char* name, int value, bool isparameter, bool deprecated);

+ 15 - 5
src/map/script_constants.hpp

@@ -419,7 +419,8 @@
 	export_constant(MF_NOMVPLOOT);
 	export_constant(MF_NORETURN);
 	export_constant(MF_NOWARPTO);
-	export_constant(MF_NIGHTMAREDROP);
+	export_constant(MF_PVP_NIGHTMAREDROP);
+	script_set_constant("mf_nightmaredrop",MF_PVP_NIGHTMAREDROP,false,true);
 	export_constant(MF_RESTRICTED);
 	export_constant(MF_NOCOMMAND);
 	export_constant(MF_NODROP);
@@ -437,12 +438,11 @@
 	export_constant(MF_PVP_NOCALCRANK);
 	export_constant(MF_BATTLEGROUND);
 	export_constant(MF_RESET);
-	// TODO: Check why it is called differently on source and const
-	//export_constant(MF_CHANNELAUTOJOIN);
-	export_constant2("mf_nomapchannelautojoin",MF_CHANNELAUTOJOIN);
+	export_constant(MF_NOMAPCHANNELAUTOJOIN);
 	export_constant(MF_NOUSECART);
 	export_constant(MF_NOITEMCONSUMPTION);
-	export_constant(MF_SUMSTARTMIRACLE);
+	export_constant(MF_NOSUNMOONSTARMIRACLE);
+	script_set_constant("mf_sumstarmiracle",MF_NOSUNMOONSTARMIRACLE,false,true);
 	export_constant(MF_NOMINEEFFECT);
 	export_constant(MF_NOLOCKON);
 	export_constant(MF_NOTOMB);
@@ -451,6 +451,8 @@
 	export_constant(MF_GVG_TE_CASTLE);
 	export_constant(MF_GVG_TE);
 	export_constant(MF_HIDEMOBHPBAR);
+	export_constant(MF_NOLOOT);
+	export_constant(MF_NOEXP);
 
 	/* setcell types */
 	export_constant(CELL_WALKABLE);
@@ -7259,6 +7261,14 @@
 	export_constant(GSTORAGE_NO_STORAGE);
 	export_constant(GSTORAGE_NO_PERMISSION);
 
+	/* block list types */
+	export_constant(BL_PC);
+	export_constant(BL_MOB);
+	export_constant(BL_PET);
+	export_constant(BL_HOM);
+	export_constant(BL_MER);
+	export_constant(BL_ELEM);
+
 	#undef export_constant
 	#undef export_constant2
 	#undef export_parameter

+ 35 - 37
src/map/skill.cpp

@@ -668,7 +668,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
 	if (skill_id == AL_TELEPORT && sd->skillitem == skill_id && sd->skillitemlv > 2)
 		return false; // Teleport lv 3 bypasses this check.[Inkfish]
 
-	if (map[m].flag.noskill)
+	if (map_getmapflag(m, MF_NOSKILL))
 		return true;
 
 	// Epoque:
@@ -696,11 +696,11 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
 	skill_nocast = skill_get_nocast(skill_id);
 	// Check skill restrictions [Celest]
 	if( (!map_flag_vs2(m) && skill_nocast&1) ||
-		(map[m].flag.pvp && skill_nocast&2) ||
+		(map_getmapflag(m, MF_PVP) && skill_nocast&2) ||
 		(map_flag_gvg2_no_te(m) && skill_nocast&4) ||
-		(map[m].flag.battleground && skill_nocast&8) ||
+		(map_getmapflag(m, MF_BATTLEGROUND) && skill_nocast&8) ||
 		(map_flag_gvg2_te(m) && skill_nocast&16) || // WOE:TE
-		(map[m].flag.restricted && map[m].zone && skill_nocast&(8*map[m].zone)) ){
+		(map_getmapflag(m, MF_RESTRICTED) && map[m].zone && skill_nocast&(8*map[m].zone)) ){
 			clif_msg(sd, SKILL_CANT_USE_AREA); // This skill cannot be used within this area
 			return true;
 	}
@@ -713,7 +713,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
 		case RETURN_TO_ELDICASTES:
 		case ALL_GUARDIAN_RECALL:
 		case ECLAGE_RECALL:
-			if(map[m].flag.nowarp) {
+			if(map_getmapflag(m, MF_NOWARP)) {
 				clif_skill_teleportmessage(sd,0);
 				return true;
 			}
@@ -723,7 +723,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
 		case SC_DIMENSIONDOOR:
 		case ALL_ODINS_RECALL:
 		case WE_CALLALLFAMILY:
-			if(map[m].flag.noteleport) {
+			if(map_getmapflag(m, MF_NOTELEPORT)) {
 				clif_skill_teleportmessage(sd,0);
 				return true;
 			}
@@ -731,14 +731,14 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
 		case WE_CALLPARTNER:
 		case WE_CALLPARENT:
 		case WE_CALLBABY:
-			if (map[m].flag.nomemo) {
+			if (map_getmapflag(m, MF_NOMEMO)) {
 				clif_skill_teleportmessage(sd,1);
 				return true;
 			}
 			break;
 		case MC_VENDING:
 		case ALL_BUYING_STORE:
-			if( map[sd->bl.m].flag.novending ) {
+			if( map_getmapflag(sd->bl.m, MF_NOVENDING) ) {
 				clif_displaymessage (sd->fd, msg_txt(sd,276)); // "You can't open a shop on this map"
 				clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
 				return true;
@@ -760,7 +760,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
 			return false; // always allowed
 		case WZ_ICEWALL:
 			// noicewall flag [Valaris]
-			if (map[m].flag.noicewall) {
+			if (map_getmapflag(m, MF_NOICEWALL)) {
 				clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
 				return true;
 			}
@@ -776,7 +776,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
 			if (
 				!(battle_config.emergency_call&((is_agit_start())?2:1)) ||
 				!(battle_config.emergency_call&(map_flag_gvg2(m)?8:4)) ||
-				(battle_config.emergency_call&16 && map[m].flag.nowarpto && !(map[m].flag.gvg_castle || map[m].flag.gvg_te_castle))
+				(battle_config.emergency_call&16 && map_getmapflag(m, MF_NOWARPTO) && !(map_getmapflag(m, MF_GVG_CASTLE) || map_getmapflag(m, MF_GVG_TE_CASTLE)))
 			)	{
 				clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
 				return true;
@@ -2371,7 +2371,7 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
 	}
 
 	if(sd && (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR &&
-		map[sd->bl.m].flag.nosumstarmiracle == 0)	//SG_MIRACLE [Komurka]
+		map_getmapflag(sd->bl.m, MF_NOSUNMOONSTARMIRACLE) == 0)	//SG_MIRACLE [Komurka]
 		status_change_start(src,src,SC_MIRACLE,battle_config.sg_miracle_skill_ratio,1,0,0,0,battle_config.sg_miracle_skill_duration,SCSTART_NONE);
 
 	if(sd && skill_id && attack_type&BF_MAGIC && status_isdead(bl) &&
@@ -4857,7 +4857,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
 			else
 				y = 0;
 			// Ashura Strike still has slide effect in GVG
-			if ((mbl == src || (!map_flag_gvg2(src->m) && !map[src->m].flag.battleground)) &&
+			if ((mbl == src || (!map_flag_gvg2(src->m) && !map_getmapflag(src->m, MF_BATTLEGROUND))) &&
 				unit_movepos(src, mbl->x + x, mbl->y + y, 1, 1)) {
 				clif_blown(src);
 				clif_spiritball(src);
@@ -5354,7 +5354,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
 			sc_start(src,src,SC_HIDING,100,skill_lv,skill_get_time(skill_id,skill_lv));
 		break;
 	case NJ_KIRIKAGE:
-		if( !map_flag_gvg2(src->m) && !map[src->m].flag.battleground )
+		if( !map_flag_gvg2(src->m) && !map_getmapflag(src->m, MF_BATTLEGROUND) )
 		{	//You don't move on GVG grounds.
 			short x, y;
 			map_search_freecell(bl, 0, &x, &y, 1, 1, 0);
@@ -6209,7 +6209,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 				break;
 			}
 			skill_area_temp[0] = battle_config.exp_cost_redemptio_limit - skill_area_temp[0]; // The actual penalty...
-			if (skill_area_temp[0] > 0 && !map[src->m].flag.noexppenalty && battle_config.exp_cost_redemptio) { //Apply penalty
+			if (skill_area_temp[0] > 0 && !map_getmapflag(src->m, MF_NOEXPPENALTY) && battle_config.exp_cost_redemptio) { //Apply penalty
 				//If total penalty is 1% => reduced 0.2% penalty per each revived player
 				pc_lostexp(sd, u32min(sd->status.base_exp, (pc_nextbaseexp(sd) * skill_area_temp[0] * battle_config.exp_cost_redemptio / battle_config.exp_cost_redemptio_limit) / 100), 0);
 			}
@@ -6223,7 +6223,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 			break;
 
 	case ALL_RESURRECTION:
-		if(sd && (map_flag_gvg2(bl->m) || map[bl->m].flag.battleground))
+		if(sd && (map_flag_gvg2(bl->m) || map_getmapflag(bl->m, MF_BATTLEGROUND)))
 		{	//No reviving in WoE grounds!
 			clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
 			break;
@@ -6237,7 +6237,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 				break;
 			}
 
-			if (map[bl->m].flag.pvp && dstsd && dstsd->pvp_point < 0)
+			if (map_getmapflag(bl->m, MF_PVP) && dstsd && dstsd->pvp_point < 0)
 				break;
 
 			switch(skill_lv){
@@ -7505,7 +7505,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 	case ALL_ODINS_RECALL:
 		if(sd)
 		{
-			if (map[bl->m].flag.noteleport && skill_lv <= 2) {
+			if (map_getmapflag(bl->m, MF_NOTELEPORT) && skill_lv <= 2) {
 				clif_skill_teleportmessage(sd,0);
 				break;
 			}
@@ -7974,8 +7974,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 			int x,y, dir = unit_getdir(src);
 
 			//Fails on noteleport maps, except for GvG and BG maps [Skotlex]
-			if( map[src->m].flag.noteleport &&
-				!(map[src->m].flag.battleground || map_flag_gvg2(src->m) )
+			if( map_getmapflag(src->m, MF_NOTELEPORT) &&
+				!(map_getmapflag(src->m, MF_BATTLEGROUND) || map_flag_gvg2(src->m) )
 			) {
 				x = src->x;
 				y = src->y;
@@ -8359,7 +8359,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 				map_freeblock_unlock();
 				return 1;
 			}
-			if ((map_flag_gvg2(bl->m) || map[bl->m].flag.battleground)) { // No reviving in WoE grounds!
+			if (map_flag_gvg2(bl->m) || map_getmapflag(bl->m, MF_BATTLEGROUND)) { // No reviving in WoE grounds!
 				clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
 				break;
 			}
@@ -8370,7 +8370,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 					break;
 				if (tsc && tsc->data[SC_HELLPOWER])
 					break;
-				if (map[bl->m].flag.pvp && dstsd->pvp_point < 0)
+				if (map_getmapflag(bl->m, MF_PVP) && dstsd->pvp_point < 0)
 					break;
 				if (dstsd->special_state.restart_full_recover)
 					per = sper = 100;
@@ -8812,7 +8812,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 				if (j > 8)
 					j = 0;
 				if ((dstsd = g->member[i].sd) != NULL && sd != dstsd && !dstsd->state.autotrade && !pc_isdead(dstsd)) {
-					if (map[dstsd->bl.m].flag.nowarp && !map_flag_gvg2(dstsd->bl.m))
+					if (map_getmapflag(dstsd->bl.m, MF_NOWARP) && !map_flag_gvg2(dstsd->bl.m))
 						continue;
 					if (!pc_job_can_entermap((enum e_job)dstsd->status.class_, src->m, dstsd->group_level))
 						continue;
@@ -9916,7 +9916,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		break;
 
 	case LG_INSPIRATION:
-		if( sd && !map[sd->bl.m].flag.noexppenalty && battle_config.exp_cost_inspiration )
+		if( sd && !map_getmapflag(sd->bl.m, MF_NOEXPPENALTY) && battle_config.exp_cost_inspiration )
 			pc_lostexp(sd, u32min(sd->status.base_exp, pc_nextbaseexp(sd) * battle_config.exp_cost_inspiration / 100), 0); // 1% penalty.
 		clif_skill_nodamage(bl,src,skill_id,skill_lv, sc_start(src,bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv)));
 		break;
@@ -12368,7 +12368,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
 			uint8 dir = map_calc_dir(src, x, y);
 
 			// Fails on noteleport maps, except for GvG and BG maps
-			if (map[src->m].flag.noteleport && !(map[src->m].flag.battleground || map_flag_gvg2(src->m))) {
+			if (map_getmapflag(src->m, MF_NOTELEPORT) && !(map_getmapflag(src->m, MF_BATTLEGROUND) || map_flag_gvg2(src->m))) {
 				x = src->x;
 				y = src->y;
 			} else if (dir%2) { // Diagonal
@@ -14078,7 +14078,7 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns
 			break;
 
 		case UNT_DIMENSIONDOOR:
-			if( tsd && !map[bl->m].flag.noteleport )
+			if( tsd && !map_getmapflag(bl->m, MF_NOTELEPORT) )
 				pc_randomwarp(tsd,CLR_TELEPORT);
 			else if( bl->type == BL_MOB && battle_config.mob_warp&8 )
 				unit_warp(bl,-1,-1,-1,CLR_TELEPORT);
@@ -16681,7 +16681,7 @@ int skill_delayfix(struct block_list *bl, uint16 skill_id, uint16 skill_lv)
 					time /= 2;
 				break;
 			case AS_SONICBLOW:
-				if (!map_flag_gvg2(bl->m) && !map[bl->m].flag.battleground && sc->data[SC_SPIRIT]->val2 == SL_ASSASIN)
+				if (!map_flag_gvg2(bl->m) && !map_getmapflag(bl->m, MF_BATTLEGROUND) && sc->data[SC_SPIRIT]->val2 == SL_ASSASIN)
 					time /= 2;
 				break;
 		}
@@ -18407,13 +18407,13 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
 				if(group->val1) {
 					sd = map_charid2sd(group->val1);
 					group->val1 = 0;
-					if (sd && !map[sd->bl.m].flag.nowarp && pc_job_can_entermap((enum e_job)sd->status.class_, unit->bl.m, sd->group_level))
+					if (sd && !map_getmapflag(sd->bl.m, MF_NOWARP) && pc_job_can_entermap((enum e_job)sd->status.class_, unit->bl.m, sd->group_level))
 						pc_setpos(sd,map_id2index(unit->bl.m),unit->bl.x,unit->bl.y,CLR_TELEPORT);
 				}
 				if(group->val2) {
 					sd = map_charid2sd(group->val2);
 					group->val2 = 0;
-					if (sd && !map[sd->bl.m].flag.nowarp && pc_job_can_entermap((enum e_job)sd->status.class_, unit->bl.m, sd->group_level))
+					if (sd && !map_getmapflag(sd->bl.m, MF_NOWARP) && pc_job_can_entermap((enum e_job)sd->status.class_, unit->bl.m, sd->group_level))
 						pc_setpos(sd,map_id2index(unit->bl.m),unit->bl.x,unit->bl.y,CLR_TELEPORT);
 				}
 				skill_delunit(unit);
@@ -20791,7 +20791,7 @@ static bool skill_check_unit_movepos(uint8 check_flag, struct block_list *bl, sh
 
 	nullpo_retr(false, bl);
 
-	if (check_flag&1 && map[bl->m].flag.battleground)
+	if (check_flag&1 && map_getmapflag(bl->m, MF_BATTLEGROUND))
 		return false;
 	if (check_flag&2 && map_flag_gvg(bl->m))
 		return false;
@@ -21475,13 +21475,11 @@ static bool skill_parse_row_skilldamage(char* split[], int columns, int current)
 	memset(&skill_db[id]->damage,0,sizeof(struct s_skill_damage));
 	skill_db[id]->damage.caster |= atoi(split[1]);
 	skill_db[id]->damage.map |= atoi(split[2]);
-	skill_db[id]->damage.pc = cap_value(atoi(split[3]),-100,INT_MAX);
-	if (split[3])
-		skill_db[id]->damage.mob = cap_value(atoi(split[4]),-100,INT_MAX);
-	if (split[4])
-		skill_db[id]->damage.boss = cap_value(atoi(split[5]),-100,INT_MAX);
-	if (split[5])
-		skill_db[id]->damage.other = cap_value(atoi(split[6]),-100,INT_MAX);
+
+	for(int offset = 3, int i = 0; i < SKILLDMG_MAX && offset < columns; i++, offset++ ){
+		skill_db[id]->damage.rate[i] = cap_value(atoi(split[offset]), -100, INT_MAX);
+	}
+
 	return true;
 }
 #endif
@@ -21593,7 +21591,7 @@ static void skill_readdb(void)
 		sv_readdb(dbsubpath1, "skill_changematerial_db.txt" , ',',   5,  5+2*MAX_SKILL_CHANGEMATERIAL_SET, MAX_SKILL_CHANGEMATERIAL_DB, skill_parse_row_changematerialdb, i > 0);
 		sv_readdb(dbsubpath1, "skill_nonearnpc_db.txt"      , ',',   2,  3, -1, skill_parse_row_nonearnpcrangedb, i > 0);
 #ifdef ADJUST_SKILL_DAMAGE
-		sv_readdb(dbsubpath1, "skill_damage_db.txt"         , ',',   4,  7, -1, skill_parse_row_skilldamage, i > 0);
+		sv_readdb(dbsubpath1, "skill_damage_db.txt"         , ',',   4,  3+SKILLDMG_MAX, -1, skill_parse_row_skilldamage, i > 0);
 #endif
 		aFree(dbsubpath1);
 		aFree(dbsubpath2);

+ 0 - 13
src/map/skill.hpp

@@ -2213,19 +2213,6 @@ void skill_combo(struct block_list* src,struct block_list *dsrc, struct block_li
 
 void skill_reveal_trap_inarea(struct block_list *src, int range, int x, int y);
 
-#ifdef ADJUST_SKILL_DAMAGE
-/// Skill Damage target
-enum e_skill_damage_caster {
-	SDC_PC   = 0x01,
-	SDC_MOB  = 0x02,
-	SDC_PET  = 0x04,
-	SDC_HOM  = 0x08,
-	SDC_MER  = 0x10,
-	SDC_ELEM = 0x20,
-	SDC_ALL  = SDC_PC|SDC_MOB|SDC_PET|SDC_HOM|SDC_MER|SDC_ELEM,
-};
-#endif
-
 /// Variable name of copied skill by Plagiarism
 #define SKILL_VAR_PLAGIARISM "CLONE_SKILL"
 /// Variable name of copied skill level by Plagiarism

+ 9 - 9
src/map/status.cpp

@@ -113,7 +113,7 @@ static unsigned int status_calc_maxhpsp_pc(struct map_session_data* sd, unsigned
 static int status_get_sc_interval(enum sc_type type);
 
 static bool status_change_isDisabledOnMap_(sc_type type, bool mapIsVS, bool mapIsPVP, bool mapIsGVG, bool mapIsBG, unsigned int mapZone, bool mapIsTE);
-#define status_change_isDisabledOnMap(type, m) ( status_change_isDisabledOnMap_((type), map_flag_vs2((m)), map[(m)].flag.pvp != 0, map_flag_gvg2_no_te((m)), map[(m)].flag.battleground != 0, (map[(m)].zone << 3) != 0, map_flag_gvg2_te((m))) )
+#define status_change_isDisabledOnMap(type, m) ( status_change_isDisabledOnMap_((type), map_flag_vs2((m)), map_getmapflag((m), MF_PVP) != 0, map_flag_gvg2_no_te((m)), map_getmapflag((m), MF_BATTLEGROUND) != 0, (map[(m)].zone << 3) != 0, map_flag_gvg2_te((m))) )
 
 /**
  * Returns the status change associated with a skill.
@@ -1716,7 +1716,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
 				* Endure count is only reduced by non-players on non-gvg maps.
 				* val4 signals infinite endure.
 				**/
-				if (src && src->type != BL_PC && !map_flag_gvg2(target->m) && !map[target->m].flag.battleground && --(sce->val2) <= 0)
+				if (src && src->type != BL_PC && !map_flag_gvg2(target->m) && !map_getmapflag(target->m, MF_BATTLEGROUND) && --(sce->val2) <= 0)
 					status_change_end(target, SC_ENDURE, INVALID_TIMER);
 			}
 			if ((sce=sc->data[SC_GRAVITATION]) && sce->val3 == BCT_SELF) {
@@ -6265,7 +6265,7 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change
 	if( bl->type == BL_PC ) {
 		if( map_flag_gvg(bl->m) )
 			flee -= flee * battle_config.gvg_flee_penalty/100;
-		else if( map[bl->m].flag.battleground )
+		else if( map_getmapflag(bl->m, MF_BATTLEGROUND) )
 			flee -= flee * battle_config.bg_flee_penalty/100;
 	}
 
@@ -7153,7 +7153,7 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
  */
 static unsigned short status_calc_dmotion(struct block_list *bl, struct status_change *sc, int dmotion)
 {
-	if( !sc || !sc->count || map_flag_gvg2(bl->m) || map[bl->m].flag.battleground )
+	if( !sc || !sc->count || map_flag_gvg2(bl->m) || map_getmapflag(bl->m, MF_BATTLEGROUND) )
 		return cap_value(dmotion,0,USHRT_MAX);
 
 	/// It has been confirmed on official servers that MvP mobs have no dmotion even without endure
@@ -9445,7 +9445,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			break;
 		case SC_ENDURE:
 			val2 = 7; // Hit-count [Celest]
-			if( !(flag&SCSTART_NOAVOID) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg2(bl->m) && !map[bl->m].flag.battleground && !val4 ) {
+			if( !(flag&SCSTART_NOAVOID) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg2(bl->m) && !map_getmapflag(bl->m, MF_BATTLEGROUND) && !val4 ) {
 				struct map_session_data *tsd;
 				if( sd ) {
 					int i;
@@ -9757,7 +9757,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE)
 				val3 -= 40;
 			val4 = 10+val1*2; // SP cost.
-			if (map_flag_gvg2(bl->m) || map[bl->m].flag.battleground) val4 *= 5;
+			if (map_flag_gvg2(bl->m) || map_getmapflag(bl->m, MF_BATTLEGROUND)) val4 *= 5;
 			break;
 		case SC_CLOAKING:
 			if (!sd) // Monsters should be able to walk with no penalties. [Skotlex]
@@ -9952,7 +9952,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 
 			if( (d_bl = map_id2bl(val1)) && (d_sc = status_get_sc(d_bl)) && d_sc->count ) { // Inherits Status From Source
 				const enum sc_type types[] = { SC_AUTOGUARD, SC_DEFENDER, SC_REFLECTSHIELD, SC_ENDURE };
-				int i = (map_flag_gvg2(bl->m) || map[bl->m].flag.battleground)?2:3;
+				int i = (map_flag_gvg2(bl->m) || map_getmapflag(bl->m, MF_BATTLEGROUND))?2:3;
 				while( i >= 0 ) {
 					enum sc_type type2 = types[i];
 					if( d_sc->data[type2] )
@@ -14351,9 +14351,9 @@ void status_change_clear_onChangeMap(struct block_list *bl, struct status_change
 	if (sc && sc->count) {
 		unsigned short i;
 		bool mapIsVS = map_flag_vs2(bl->m);
-		bool mapIsPVP = map[bl->m].flag.pvp != 0;
+		bool mapIsPVP = map_getmapflag(bl->m, MF_PVP) != 0;
 		bool mapIsGVG = map_flag_gvg2_no_te(bl->m);
-		bool mapIsBG = map[bl->m].flag.battleground != 0;
+		bool mapIsBG = map_getmapflag(bl->m, MF_BATTLEGROUND) != 0;
 		bool mapIsTE = map_flag_gvg2_te(bl->m);
 		unsigned int mapZone = map[bl->m].zone << 3;
 

+ 1 - 1
src/map/trade.cpp

@@ -32,7 +32,7 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
 {
 	nullpo_retv(sd);
 
-	if (map[sd->bl.m].flag.notrade) {
+	if (map_getmapflag(sd->bl.m, MF_NOTRADE)) {
 		clif_displaymessage (sd->fd, msg_txt(sd,272));
 		return; //Can't trade in notrade mapflag maps.
 	}

+ 5 - 5
src/map/unit.cpp

@@ -1138,7 +1138,7 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, enum e_skill_bl
 enum e_unit_blown unit_blown_immune(struct block_list* bl, uint8 flag)
 {
 	if ((flag&0x1)
-		&& (map_flag_gvg2(bl->m) || map[bl->m].flag.battleground)
+		&& (map_flag_gvg2(bl->m) || map_getmapflag(bl->m, MF_BATTLEGROUND))
 		&& ((flag&0x2) || !(battle_config.skill_trap_type&0x1)))
 		return UB_NO_KNOCKBACK_MAP; // No knocking back in WoE / BG
 
@@ -1204,14 +1204,14 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
 
 	switch (bl->type) {
 		case BL_MOB:
-			if (map[bl->m].flag.monster_noteleport && ((TBL_MOB*)bl)->master_id == 0)
+			if (map_getmapflag(bl->m, MF_MONSTER_NOTELEPORT) && ((TBL_MOB*)bl)->master_id == 0)
 				return 1;
 
-			if (m != bl->m && map[m].flag.nobranch && battle_config.mob_warp&4 && !(((TBL_MOB *)bl)->master_id))
+			if (m != bl->m && map_getmapflag(m, MF_NOBRANCH) && battle_config.mob_warp&4 && !(((TBL_MOB *)bl)->master_id))
 				return 1;
 			break;
 		case BL_PC:
-			if (map[bl->m].flag.noteleport)
+			if (map_getmapflag(bl->m, MF_NOTELEPORT))
 				return 1;
 			break;
 	}
@@ -2706,7 +2706,7 @@ int unit_skillcastcancel(struct block_list *bl, char type)
 			return 0;
 
 		if (sd && (sd->special_state.no_castcancel2 ||
-			((sd->sc.data[SC_UNLIMITEDHUMMINGVOICE] || sd->special_state.no_castcancel) && !map_flag_gvg2(bl->m) && !map[bl->m].flag.battleground))) // fixed flags being read the wrong way around [blackhole89]
+			((sd->sc.data[SC_UNLIMITEDHUMMINGVOICE] || sd->special_state.no_castcancel) && !map_flag_gvg2(bl->m) && !map_getmapflag(bl->m, MF_BATTLEGROUND)))) // fixed flags being read the wrong way around [blackhole89]
 			return 0;
 	}