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