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!
This commit is contained in:
535
src/map/map.cpp
535
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);
|
||||
@@ -4297,64 +4280,395 @@ 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
aFree(m->skill_damage.entries);
|
||||
m->skill_damage.entries = NULL;
|
||||
m->skill_damage.count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
if (m->skill_damage.count >= UINT8_MAX)
|
||||
* @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++) {
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
struct s_skill_damage entry = {};
|
||||
|
||||
RECREATE(m->skill_damage.entries, struct s_skill_damage *, m->skill_damage.count+1);
|
||||
m->skill_damage.entries[m->skill_damage.count++] = 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
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
nullpo_retr(0, sd);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
Reference in New Issue
Block a user