Implemented SC Blocking Database

* This database contains status (SC) that will be disabled/blocked on certain map.
* The specified map for SC is determined by map type or zone.
* The disabled SC will be removed if player has the SC from previous map and will fail to be applied again.
Thanks to @cydh!
This commit is contained in:
aleos89 2016-02-01 12:20:18 -05:00
parent 918ef966f8
commit d457d2f5f9
5 changed files with 145 additions and 1 deletions

View File

@ -0,0 +1,25 @@
// Status Change Restriction Database
//
// Defines restrictions of status changes (SC).
// Disabled SC will always be removed or fail to be inflicted on this map.
//
// Structure of Database:
// SCType,Flag
//
// Legend for 'Flag' field (bitmask):
// 1 - restricted in normal maps
// 2 - restricted in PVP
// 4 - restricted in GVG
// 8 - restricted in Battlegrounds
// Restricted zones - configured by 'restricted <number>' mapflag
// 32 - restricted in zone 1
// 64 - restricted in zone 2
// 128 - restricted in zone 3
// 256 - restricted in zone 4
// 512 - restricted in zone 5
// 1024 - restricted in zone 6
// 2048 - restricted in zone 7
//
// Example:
// SC_ENDURE,4 // Endure status will be removed when the player enters GvG and WoE Castle maps; Also cannot be inflicted again.

25
db/status_disabled.txt Normal file
View File

@ -0,0 +1,25 @@
// Status Change Restriction Database
//
// Defines restrictions of status changes (SC).
// Disabled SC will always be removed or fail to be inflicted on this map.
//
// Structure of Database:
// SCType,Flag
//
// Legend for 'Flag' field (bitmask):
// 1 - restricted in normal maps
// 2 - restricted in PVP
// 4 - restricted in GVG
// 8 - restricted in Battlegrounds
// Restricted zones - configured by 'restricted <number>' mapflag
// 32 - restricted in zone 1
// 64 - restricted in zone 2
// 128 - restricted in zone 3
// 256 - restricted in zone 4
// 512 - restricted in zone 5
// 1024 - restricted in zone 6
// 2048 - restricted in zone 7
//
// Example:
// SC_ENDURE,4 // Endure status will be removed when the player enters GvG and WoE Castle maps; Also cannot be inflicted again.

View File

@ -10284,6 +10284,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
sd->state.hpmeter_visible = 1;
}
status_change_clear_onChangeMap(&sd->bl, &sd->sc);
map_iwall_get(sd); // Updates Walls Info on this Map to Client
status_calc_pc(sd, SCO_NONE); // Some conditions are map-dependent so we must recalculate
sd->state.changemap = false;

View File

@ -50,6 +50,8 @@ unsigned int current_equip_combo_pos; /// For combo items we need to save the po
int current_equip_card_id; /// To prevent card-stacking (from jA) [Skotlex]
// We need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only to avoid cards exploits
unsigned int SCDisabled[SC_MAX]; ///< List of disabled SC on map zones. [Cydh]
static unsigned short status_calc_str(struct block_list *,struct status_change *,int);
static unsigned short status_calc_agi(struct block_list *,struct status_change *,int);
static unsigned short status_calc_vit(struct block_list *,struct status_change *,int);
@ -86,6 +88,9 @@ static int status_get_hpbonus(struct block_list *bl, enum e_status_bonus type);
static int status_get_spbonus(struct block_list *bl, enum e_status_bonus type);
static unsigned int status_calc_maxhpsp_pc(struct map_session_data* sd, unsigned int stat, bool isHP);
static bool status_change_isDisabledOnMap_(sc_type type, bool mapIsVS, bool mapIsPVP, bool mapIsGVG, bool mapIsBG, unsigned int mapZone);
#define status_change_isDisabledOnMap(type, m) ( status_change_isDisabledOnMap_((type), map_flag_vs((m)), map[(m)].flag.pvp, map_flag_gvg((m)), map[(m)].flag.battleground, map[(m)].zone << 3) )
/**
* Returns the status change associated with a skill.
* @param skill The skill to look up
@ -200,7 +205,7 @@ void initChangeTables(void)
memset(StatusChangeFlagTable, 0, sizeof(StatusChangeFlagTable));
memset(StatusChangeStateTable, 0, sizeof(StatusChangeStateTable));
memset(StatusDisplayType, 0, sizeof(StatusDisplayType));
memset(SCDisabled, 0, sizeof(SCDisabled));
/* First we define the skill for common ailments. These are used in skill_additional_effect through sc cards. [Skotlex] */
set_sc( NPC_PETRIFYATTACK , SC_STONE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF );
@ -7802,6 +7807,9 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
if( 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))
return 0;
if( bl->type == BL_MOB) {
struct mob_data *md = BL_CAST(BL_MOB,bl);
if(md && (md->mob_id == MOBID_EMPERIUM || mob_is_battleground(md)) && type != SC_SAFETYWALL && type != SC_PNEUMA)
@ -13309,6 +13317,87 @@ int status_get_refine_chance(enum refine_type wlv, int refine)
return refine_info[wlv].chance[refine];
}
/**
* Check if status is disabled on a map
* @param type: Status Change data
* @param mapIsVS: If the map is a map_flag_vs type
* @param mapisPVP: If the map is a PvP type
* @param mapIsGVG: If the map is a map_flag_gvg type
* @param mapIsBG: If the map is a Battleground type
* @param mapZone: Map Zone type
* @return True - SC disabled on map; False - SC not disabled on map/Invalid SC
*/
static bool status_change_isDisabledOnMap_(sc_type type, bool mapIsVS, bool mapIsPVP, bool mapIsGVG, bool mapIsBG, unsigned int mapZone)
{
if (type <= SC_NONE || type >= SC_MAX)
return false;
if ((!mapIsVS && SCDisabled[type]&1) ||
(mapIsPVP && SCDisabled[type]&2) ||
(mapIsGVG && SCDisabled[type]&4) ||
(mapIsBG && SCDisabled[type]&8) ||
(SCDisabled[type]&(mapZone)))
{
return true;
}
return false;
}
/**
* Clear a status if it is disabled on a map
* @param bl: Block list data
* @param sc: Status Change data
*/
void status_change_clear_onChangeMap(struct block_list *bl, struct status_change *sc)
{
nullpo_retv(bl);
if (sc && sc->count) {
unsigned short i;
bool mapIsVS = map_flag_vs(bl->m);
bool mapIsPVP = map[bl->m].flag.pvp;
bool mapIsGVG = map_flag_gvg(bl->m);
bool mapIsBG = map[bl->m].flag.battleground;
unsigned int mapZone = map[bl->m].zone << 3;
for (i = 0; i < SC_MAX; i++) {
if (!sc->data[i] || !SCDisabled[i])
continue;
if (status_change_isDisabledOnMap_((sc_type)i, mapIsVS, mapIsPVP, mapIsGVG, mapIsBG, mapZone))
status_change_end(bl, (sc_type)i, INVALID_TIMER);
}
}
}
/**
* Read status_disabled.txt file
* @param str: Fields passed from sv_readdb
* @param columns: Columns passed from sv_readdb function call
* @param current: Current row being read into SCDisabled array
* @return True - Successfully stored, False - Invalid SC
*/
static bool status_readdb_status_disabled(char **str, int columns, int current)
{
int type = SC_NONE;
if (ISDIGIT(str[0][0]))
type = atoi(str[0]);
else {
if (!script_get_constant(str[0],&type))
type = SC_NONE;
}
if (type <= SC_NONE || type >= SC_MAX) {
ShowError("status_readdb_status_disabled: Invalid SC with type %s.\n", str[0]);
return false;
}
SCDisabled[type] = (unsigned int)atol(str[1]);
return true;
}
/**
* Read sizefix database for attack calculations
* @param fields: Fields passed from sv_readdb
@ -13441,6 +13530,8 @@ int status_readdb(void)
//add other path here
};
// Initialize databases to default
memset(SCDisabled, 0, sizeof(SCDisabled));
// size_fix.txt
for(i=0;i<ARRAYLENGTH(atkmods);i++)
for(j=0;j<MAX_WEAPON_TYPE;j++)
@ -13479,6 +13570,7 @@ int status_readdb(void)
}
status_readdb_attrfix(dbsubpath2,i); // !TODO use sv_readdb ?
sv_readdb(dbsubpath1, "status_disabled.txt", ',', 2, 2, -1, &status_readdb_status_disabled, i);
sv_readdb(dbsubpath1, "size_fix.txt",',',MAX_WEAPON_TYPE,MAX_WEAPON_TYPE,ARRAYLENGTH(atkmods),&status_readdb_sizefix, i);
sv_readdb(dbsubpath2, "refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(refine_info), &status_readdb_refine, i);
aFree(dbsubpath1);

View File

@ -2164,6 +2164,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data);
int status_change_timer_sub(struct block_list* bl, va_list ap);
int status_change_clear(struct block_list* bl, int type);
void status_change_clear_buffs(struct block_list* bl, int type);
void status_change_clear_onChangeMap(struct block_list *bl, struct status_change *sc);
#define status_calc_bl(bl, flag) status_calc_bl_(bl, (enum scb_flag)(flag), SCO_NONE)
#define status_calc_mob(md, opt) status_calc_bl_(&(md)->bl, SCB_ALL, opt)