Updates stacking for common statuses (#6807)
* Fixes #6798. * Updates the Fail, End, and EndReturn lists for OPT1 and OPT2 statuses. * Removes the hardcoded OPT1 overwrite prevention check. * OPT1 that have RemoveOnDamaged flag should not get applied again in the same attack. * Fixes Stone status not properly being inflicted by the bAddEff, bAddEff2, bAddEffWhenHit, and bAddEffOnSkill item bonuses. * Fixes Stone status not properly being inflicted by The Hanged Man from Tarot Card of Fate. Thanks to @Playtester!
This commit is contained in:
parent
b17b0c7a0b
commit
53bc2376a6
@ -70,7 +70,6 @@ Body:
|
||||
Stun: true
|
||||
Sleep: true
|
||||
Burning: true
|
||||
#Undead: true
|
||||
End:
|
||||
Aeterna: true
|
||||
EndReturn:
|
||||
@ -89,7 +88,6 @@ Body:
|
||||
Stun: true
|
||||
Sleep: true
|
||||
Burning: true
|
||||
#Undead: true
|
||||
EndReturn:
|
||||
StoneWait: true
|
||||
Stone: true
|
||||
@ -115,8 +113,13 @@ Body:
|
||||
Inspiration: true
|
||||
Warmer: true
|
||||
Gvg_Freez: true
|
||||
Stone: true
|
||||
StoneWait: true
|
||||
Freeze: true
|
||||
Stun: true
|
||||
Sleep: true
|
||||
Burning: true
|
||||
End:
|
||||
Dancing: true
|
||||
Aeterna: true
|
||||
- Status: Stun
|
||||
DurationLookup: NPC_STUNATTACK
|
||||
@ -135,8 +138,7 @@ Body:
|
||||
Refresh: true
|
||||
Inspiration: true
|
||||
Gvg_Stun: true
|
||||
End:
|
||||
Dancing: true
|
||||
Stun: true
|
||||
- Status: Sleep
|
||||
DurationLookup: NPC_SLEEPATTACK
|
||||
States:
|
||||
@ -155,8 +157,7 @@ Body:
|
||||
Refresh: true
|
||||
Inspiration: true
|
||||
Gvg_Sleep: true
|
||||
End:
|
||||
Dancing: true
|
||||
Sleep: true
|
||||
- Status: Poison
|
||||
DurationLookup: NPC_POISON
|
||||
CalcFlags:
|
||||
@ -172,6 +173,8 @@ Body:
|
||||
Fail:
|
||||
Refresh: true
|
||||
Inspiration: true
|
||||
Poison: true
|
||||
Dpoison: true
|
||||
- Status: Curse
|
||||
DurationLookup: NPC_CURSEATTACK
|
||||
CalcFlags:
|
||||
@ -189,6 +192,7 @@ Body:
|
||||
Refresh: true
|
||||
Inspiration: true
|
||||
Gvg_Curse: true
|
||||
Curse: true
|
||||
- Status: Silence
|
||||
DurationLookup: NPC_SILENCEATTACK
|
||||
States:
|
||||
@ -204,16 +208,16 @@ Body:
|
||||
Refresh: true
|
||||
Inspiration: true
|
||||
Gvg_Silence: true
|
||||
Silence: true
|
||||
- Status: Confusion
|
||||
DurationLookup: NPC_WIDECONFUSE
|
||||
Flags:
|
||||
BossResist: true
|
||||
StopWalking: true
|
||||
RemoveOnDamaged: true
|
||||
OverlapFail: true
|
||||
Fail:
|
||||
Refresh: true
|
||||
Inspiration: true
|
||||
EndReturn:
|
||||
Confusion: true
|
||||
- Status: Blind
|
||||
DurationLookup: NPC_BLINDATTACK
|
||||
@ -231,6 +235,7 @@ Body:
|
||||
Inspiration: true
|
||||
Fear: true
|
||||
Gvg_Blind: true
|
||||
Blind: true
|
||||
- Status: Bleeding
|
||||
Icon: EFST_BLOODING
|
||||
DurationLookup: NPC_BLEEDING
|
||||
@ -243,7 +248,6 @@ Body:
|
||||
BossResist: true
|
||||
NoSave: true
|
||||
NoClearance: true
|
||||
OverlapFail: true
|
||||
Fail:
|
||||
Refresh: true
|
||||
Inspiration: true
|
||||
@ -257,7 +261,6 @@ Body:
|
||||
Flags:
|
||||
SendOption: true
|
||||
BossResist: true
|
||||
OverlapFail: true
|
||||
Fail:
|
||||
Refresh: true
|
||||
Inspiration: true
|
||||
@ -415,6 +418,8 @@ Body:
|
||||
Flags:
|
||||
BossResist: true
|
||||
TaekwonAngel: true
|
||||
EndReturn:
|
||||
Curse: true
|
||||
- Status: Signumcrucis
|
||||
Icon: EFST_CRUCIS
|
||||
DurationLookup: AL_CRUCIS
|
||||
@ -2840,7 +2845,6 @@ Body:
|
||||
Flags:
|
||||
BossResist: true
|
||||
StopWalking: true
|
||||
OverlapFail: true
|
||||
Debuff: true
|
||||
Fail:
|
||||
Inspiration: true
|
||||
@ -2849,6 +2853,8 @@ Body:
|
||||
- Status: Burning
|
||||
Icon: EFST_BURNT
|
||||
DurationLookup: RK_DRAGONBREATH
|
||||
CalcFlags:
|
||||
Mdef: true
|
||||
Opt1: Burning
|
||||
Flags:
|
||||
SendOption: true
|
||||
@ -2861,8 +2867,6 @@ Body:
|
||||
Fail:
|
||||
Refresh: true
|
||||
Inspiration: true
|
||||
CalcFlags:
|
||||
Mdef: true
|
||||
- Status: Freezing
|
||||
Icon: EFST_FROSTMISTY
|
||||
DurationLookup: WL_FROSTMISTY
|
||||
@ -3076,13 +3080,8 @@ Body:
|
||||
SetStand: true
|
||||
StopWalking: true
|
||||
StopAttacking: true
|
||||
OverlapFail: true
|
||||
End:
|
||||
Dancing: true
|
||||
Burning: true
|
||||
Freezing: true
|
||||
Freeze: true
|
||||
Stone: true
|
||||
- Status: Marshofabyss
|
||||
Icon: EFST_MARSHOFABYSS
|
||||
DurationLookup: WL_MARSHOFABYSS
|
||||
|
@ -71,7 +71,6 @@ Body:
|
||||
Stun: true
|
||||
Sleep: true
|
||||
Burning: true
|
||||
#Undead: true
|
||||
End:
|
||||
Aeterna: true
|
||||
EndReturn:
|
||||
@ -91,7 +90,6 @@ Body:
|
||||
Stun: true
|
||||
Sleep: true
|
||||
Burning: true
|
||||
#Undead: true
|
||||
EndReturn:
|
||||
StoneWait: true
|
||||
Stone: true
|
||||
@ -117,8 +115,14 @@ Body:
|
||||
Inspiration: true
|
||||
Warmer: true
|
||||
Gvg_Freez: true
|
||||
Whiteimprison: true
|
||||
Stone: true
|
||||
StoneWait: true
|
||||
Freeze: true
|
||||
Stun: true
|
||||
Sleep: true
|
||||
Burning: true
|
||||
End:
|
||||
Dancing: true
|
||||
Aeterna: true
|
||||
- Status: Stun
|
||||
DurationLookup: NPC_STUNATTACK
|
||||
@ -137,8 +141,7 @@ Body:
|
||||
Refresh: true
|
||||
Inspiration: true
|
||||
Gvg_Stun: true
|
||||
End:
|
||||
Dancing: true
|
||||
Stun: true
|
||||
- Status: Sleep
|
||||
DurationLookup: NPC_SLEEPATTACK
|
||||
States:
|
||||
@ -157,8 +160,7 @@ Body:
|
||||
Refresh: true
|
||||
Inspiration: true
|
||||
Gvg_Sleep: true
|
||||
End:
|
||||
Dancing: true
|
||||
Sleep: true
|
||||
- Status: Poison
|
||||
DurationLookup: NPC_POISON
|
||||
CalcFlags:
|
||||
@ -175,6 +177,8 @@ Body:
|
||||
Fail:
|
||||
Refresh: true
|
||||
Inspiration: true
|
||||
Poison: true
|
||||
Dpoison: true
|
||||
- Status: Curse
|
||||
DurationLookup: NPC_WIDECURSE
|
||||
CalcFlags:
|
||||
@ -193,6 +197,7 @@ Body:
|
||||
Refresh: true
|
||||
Inspiration: true
|
||||
Gvg_Curse: true
|
||||
Curse: true
|
||||
- Status: Silence
|
||||
DurationLookup: NPC_SILENCEATTACK
|
||||
States:
|
||||
@ -209,17 +214,17 @@ Body:
|
||||
Refresh: true
|
||||
Inspiration: true
|
||||
Gvg_Silence: true
|
||||
Silence: true
|
||||
- Status: Confusion
|
||||
DurationLookup: NPC_WIDECONFUSE
|
||||
Flags:
|
||||
BossResist: true
|
||||
StopWalking: true
|
||||
RemoveOnDamaged: true
|
||||
OverlapFail: true
|
||||
SpreadEffect: true
|
||||
Fail:
|
||||
Refresh: true
|
||||
Inspiration: true
|
||||
EndReturn:
|
||||
Confusion: true
|
||||
- Status: Blind
|
||||
DurationLookup: NPC_BLINDATTACK
|
||||
@ -238,6 +243,7 @@ Body:
|
||||
Inspiration: true
|
||||
Fear: true
|
||||
Gvg_Blind: true
|
||||
Blind: true
|
||||
- Status: Bleeding
|
||||
Icon: EFST_BLOODING
|
||||
DurationLookup: NPC_BLEEDING
|
||||
@ -250,7 +256,6 @@ Body:
|
||||
BossResist: true
|
||||
NoSave: true
|
||||
NoClearance: true
|
||||
OverlapFail: true
|
||||
SpreadEffect: true
|
||||
Fail:
|
||||
Refresh: true
|
||||
@ -265,7 +270,6 @@ Body:
|
||||
Flags:
|
||||
SendOption: true
|
||||
BossResist: true
|
||||
OverlapFail: true
|
||||
Fail:
|
||||
Refresh: true
|
||||
Inspiration: true
|
||||
@ -2951,7 +2955,6 @@ Body:
|
||||
Flags:
|
||||
BossResist: true
|
||||
StopWalking: true
|
||||
OverlapFail: true
|
||||
Debuff: true
|
||||
Fail:
|
||||
Inspiration: true
|
||||
@ -3188,12 +3191,8 @@ Body:
|
||||
StopWalking: true
|
||||
StopAttacking: true
|
||||
StopCasting: true
|
||||
OverlapFail: true
|
||||
End:
|
||||
Burning: true
|
||||
Freezing: true
|
||||
Freeze: true
|
||||
Stone: true
|
||||
- Status: Marshofabyss
|
||||
Icon: EFST_MARSHOFABYSS
|
||||
DurationLookup: WL_MARSHOFABYSS
|
||||
|
@ -3,7 +3,7 @@
|
||||
//===== By: ==================================================
|
||||
//= rAthena Dev Team
|
||||
//===== Last Updated: ========================================
|
||||
//= 20220406
|
||||
//= 20220414
|
||||
//===== Description: =========================================
|
||||
//= Explanation of the status.yml file and structure.
|
||||
//============================================================
|
||||
@ -113,6 +113,7 @@ Opt1: Special effect when status is active (Aegis: BODYSTATE_*). This option is
|
||||
|
||||
None - No effect (Default)
|
||||
Stone - Stone curse effect
|
||||
StoneWait - Stone curse incubation effect
|
||||
Freeze - Freeze effect
|
||||
Stun - Stun effect
|
||||
Sleep - Sleep effect
|
||||
|
@ -1302,11 +1302,24 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
|
||||
type = it.sc;
|
||||
time = it.duration;
|
||||
|
||||
int32 val1 = 7, val2, val3;
|
||||
|
||||
if (type == SC_STONEWAIT) {
|
||||
val2 = src->id;
|
||||
val3 = skill_get_time(status_db.getSkill(type), 7);
|
||||
} else {
|
||||
val2 = 0;
|
||||
if (type == SC_BURNING)
|
||||
val3 = src->id;
|
||||
else
|
||||
val3 = 0;
|
||||
}
|
||||
|
||||
if (it.flag&ATF_TARGET)
|
||||
status_change_start(src,bl,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,time,SCSTART_NONE);
|
||||
status_change_start(src,bl,type,rate,val1,val2,val3,0,time,SCSTART_NONE);
|
||||
|
||||
if (it.flag&ATF_SELF)
|
||||
status_change_start(src,src,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,time,SCSTART_NONE);
|
||||
status_change_start(src,src,type,rate,val1,val2,val3,0,time,SCSTART_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1321,10 +1334,23 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
|
||||
type = it.sc;
|
||||
time = it.duration;
|
||||
|
||||
int32 val1 = 7, val2, val3;
|
||||
|
||||
if (type == SC_STONEWAIT) {
|
||||
val2 = src->id;
|
||||
val3 = skill_get_time(status_db.getSkill(type), 7);
|
||||
} else {
|
||||
val2 = 0;
|
||||
if (type == SC_BURNING)
|
||||
val3 = src->id;
|
||||
else
|
||||
val3 = 0;
|
||||
}
|
||||
|
||||
if (it.target&ATF_TARGET)
|
||||
status_change_start(src,bl,type,it.rate,7,0,0,0,time,SCSTART_NONE);
|
||||
status_change_start(src,bl,type,it.rate,val1,val2,val3,0,time,SCSTART_NONE);
|
||||
if (it.target&ATF_SELF)
|
||||
status_change_start(src,src,type,it.rate,7,0,0,0,time,SCSTART_NONE);
|
||||
status_change_start(src,src,type,it.rate,val1,val2,val3,0,time,SCSTART_NONE);
|
||||
}
|
||||
//"While the damage can be blocked by Pneuma, the chance to break armor remains", irowiki. [Cydh]
|
||||
if (dmg_lv == ATK_BLOCK && skill_id == AM_ACIDTERROR) {
|
||||
@ -2519,11 +2545,24 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
|
||||
type = it.sc;
|
||||
time = it.duration;
|
||||
|
||||
int32 val1 = 7, val2, val3;
|
||||
|
||||
if (type == SC_STONEWAIT) {
|
||||
val2 = src->id;
|
||||
val3 = skill_get_time(status_db.getSkill(type), 7);
|
||||
} else {
|
||||
val2 = 0;
|
||||
if (type == SC_BURNING)
|
||||
val3 = src->id;
|
||||
else
|
||||
val3 = 0;
|
||||
}
|
||||
|
||||
if (it.flag&ATF_TARGET && src != bl)
|
||||
status_change_start(src,src,type,rate,7,0,0,0,time,SCSTART_NONE);
|
||||
status_change_start(src,src,type,rate,val1,val2,val3,0,time,SCSTART_NONE);
|
||||
|
||||
if (it.flag&ATF_SELF && !status_isdead(bl))
|
||||
status_change_start(src,bl,type,rate,7,0,0,0,time,SCSTART_NONE);
|
||||
status_change_start(src,bl,type,rate,val1,val2,val3,0,time,SCSTART_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4848,10 +4887,14 @@ static int skill_tarotcard(struct block_list* src, struct block_list *target, ui
|
||||
}
|
||||
case 8: // THE HANGED MAN - stop, freeze or stoned
|
||||
{
|
||||
enum sc_type sc[] = { SC_STOP, SC_FREEZE, SC_STONE };
|
||||
enum sc_type sc[] = { SC_STOP, SC_FREEZE, SC_STONEWAIT };
|
||||
uint8 rand_eff = rnd() % 3;
|
||||
int time = ((rand_eff == 0) ? skill_get_time2(skill_id, skill_lv) : skill_get_time2(status_db.getSkill(sc[rand_eff]), 1));
|
||||
sc_start(src, target, sc[rand_eff], 100, skill_lv, time);
|
||||
|
||||
if (sc[rand_eff] == SC_STONEWAIT)
|
||||
sc_start4(src, target, SC_STONEWAIT, 100, skill_lv, src->id, skill_get_time(status_db.getSkill(SC_STONEWAIT), 1), 0, time);
|
||||
else
|
||||
sc_start(src, target, sc[rand_eff], 100, skill_lv, time);
|
||||
break;
|
||||
}
|
||||
case 9: // DEATH - curse, coma and poison
|
||||
|
@ -1000,8 +1000,15 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
|
||||
for (const auto &it : status_db) {
|
||||
sc_type type = static_cast<sc_type>(it.first);
|
||||
|
||||
if (sc->data[type] && it.second->flag[SCF_REMOVEONDAMAGED])
|
||||
if (sc->data[type] && it.second->flag[SCF_REMOVEONDAMAGED]) {
|
||||
// A status change that gets broken by damage should still be considered when calculating if a status change can be applied or not (for the same attack).
|
||||
// !TODO: This is a temporary solution until we refactor the code so that the calculation of an SC is done at the start of an attack rather than after the damage was applied.
|
||||
if (sc->opt1 > OPT1_NONE && sc->lastEffectTimer == INVALID_TIMER) {
|
||||
sc->lastEffectTimer = add_timer(gettick() + 10, status_clear_lastEffect_timer, target->id, 0);
|
||||
sc->lastEffect = type;
|
||||
}
|
||||
status_change_end(target, type, INVALID_TIMER);
|
||||
}
|
||||
}
|
||||
if ((sce=sc->data[SC_ENDURE]) && !sce->val4) {
|
||||
/** [Skotlex]
|
||||
@ -8640,6 +8647,8 @@ void status_change_init(struct block_list *bl)
|
||||
struct status_change *sc = status_get_sc(bl);
|
||||
nullpo_retv(sc);
|
||||
memset(sc, 0, sizeof (struct status_change));
|
||||
sc->lastEffect = SC_NONE;
|
||||
sc->lastEffectTimer = INVALID_TIMER;
|
||||
}
|
||||
|
||||
/*========================================== [Playtester]
|
||||
@ -9262,7 +9271,8 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
||||
// Check failing SCs from list
|
||||
if (!scdb->fail.empty()) {
|
||||
for (const auto &it : scdb->fail) {
|
||||
if (it && sc->data[it])
|
||||
// Don't let OPT1 that have RemoveOnDamaged start a new effect in the same attack.
|
||||
if (sc->data[it] || sc->lastEffect == it)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -9624,6 +9634,16 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for OPT1 stacking
|
||||
if (sc->opt1 > OPT1_NONE && scdb->opt1 > OPT1_NONE) {
|
||||
for (const auto &status_it : status_db) {
|
||||
sc_type opt1_type = status_it.second->type;
|
||||
|
||||
if (sc->data[opt1_type] && status_it.second->opt1 > OPT1_NONE)
|
||||
status_change_end(bl, opt1_type, INVALID_TIMER);
|
||||
}
|
||||
}
|
||||
|
||||
// Before overlapping fail, one must check for status cured.
|
||||
std::vector<sc_type> endlist;
|
||||
|
||||
@ -9652,12 +9672,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
||||
|
||||
// List of hardcoded status cured.
|
||||
switch (type) {
|
||||
case SC_STONE:
|
||||
if (sc->data[SC_DANCING]) {
|
||||
unit_stop_walking(bl, 1);
|
||||
status_change_end(bl, SC_DANCING, INVALID_TIMER);
|
||||
}
|
||||
break;
|
||||
case SC_BLESSING:
|
||||
// !TODO: Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM
|
||||
// !but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm]
|
||||
@ -9698,9 +9712,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
||||
pc_bonus_script_clear(sd, BSF_REM_ON_MADOGEAR);
|
||||
break;
|
||||
default:
|
||||
// If new SC has OPT1 while unit has OPT1, fail it!
|
||||
if (sc->opt1 && scdb->opt1)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -12012,14 +12023,13 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
||||
unit_stop_attack(bl);
|
||||
}
|
||||
break;
|
||||
case SC_WHITEIMPRISON:
|
||||
case SC_DEEPSLEEP:
|
||||
case SC_CRYSTALIZE:
|
||||
case SC_FREEZE:
|
||||
case SC_STUN:
|
||||
case SC_GRAVITYCONTROL:
|
||||
if (sc->data[SC_DANCING])
|
||||
case SC_STONE:
|
||||
if (sc->data[SC_DANCING]) {
|
||||
unit_stop_walking(bl, 1);
|
||||
status_change_end(bl, SC_DANCING, INVALID_TIMER);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!unit_blown_immune(bl,0x1))
|
||||
@ -12383,26 +12393,6 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
|
||||
}
|
||||
if (sce->timer != INVALID_TIMER) // Could be a SC with infinite duration
|
||||
delete_timer(sce->timer,status_change_timer);
|
||||
if (sc->opt1)
|
||||
switch (type) {
|
||||
// "Ugly workaround" [Skotlex]
|
||||
// delays status change ending so that a skill that sets opt1 fails to
|
||||
// trigger when it also removed one
|
||||
case SC_STONE:
|
||||
case SC_STONEWAIT:
|
||||
sce->val4 = -1; // Petrify time
|
||||
case SC_FREEZE:
|
||||
case SC_STUN:
|
||||
case SC_SLEEP:
|
||||
if (sce->val1) {
|
||||
// Removing the 'level' shouldn't affect anything in the code
|
||||
// since these SC are not affected by it, and it lets us know
|
||||
// if we have already delayed this attack or not.
|
||||
sce->val1 = 0;
|
||||
sce->timer = add_timer(gettick()+10, status_change_timer, bl->id, type);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(sc->count)--;
|
||||
@ -14495,6 +14485,29 @@ static TIMER_FUNC(status_natural_heal_timer){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the lastEffect value from a target
|
||||
* @param tid: Timer ID
|
||||
* @param tick: Current tick (time)
|
||||
* @param id: Object ID
|
||||
* @param data: data pushed through timer function
|
||||
* @return 0
|
||||
*/
|
||||
TIMER_FUNC(status_clear_lastEffect_timer) {
|
||||
block_list *bl = map_id2bl(id);
|
||||
|
||||
if (bl != nullptr) {
|
||||
status_change *sc = status_get_sc(bl);
|
||||
|
||||
if (sc != nullptr) {
|
||||
sc->lastEffect = SC_NONE;
|
||||
sc->lastEffectTimer = INVALID_TIMER;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if status is disabled on a map
|
||||
* @param type: Status Change data
|
||||
@ -15184,6 +15197,7 @@ void do_init_status(void) {
|
||||
|
||||
add_timer_func_list(status_change_timer,"status_change_timer");
|
||||
add_timer_func_list(status_natural_heal_timer,"status_natural_heal_timer");
|
||||
add_timer_func_list(status_clear_lastEffect_timer, "status_clear_lastEffect_timer");
|
||||
initDummyData();
|
||||
status_readdb();
|
||||
natural_heal_prev_tick = gettick();
|
||||
|
@ -3055,6 +3055,8 @@ struct status_change {
|
||||
unsigned short opt1;// body state
|
||||
unsigned short opt2;// health state (bitfield)
|
||||
unsigned char count;
|
||||
sc_type lastEffect; // Used to check for stacking damageable SC on the same attack
|
||||
int32 lastEffectTimer; // Timer for lastEffect
|
||||
//! TODO: See if it is possible to implement the following SC's without requiring extra parameters while the SC is inactive.
|
||||
struct {
|
||||
uint8 move;
|
||||
@ -3229,6 +3231,7 @@ 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, uint8 type);
|
||||
void status_change_clear_onChangeMap(struct block_list *bl, struct status_change *sc);
|
||||
TIMER_FUNC(status_clear_lastEffect_timer);
|
||||
|
||||
#define status_calc_mob(md, opt) status_calc_bl_(&(md)->bl, status_db.getSCB_ALL(), opt)
|
||||
#define status_calc_pet(pd, opt) status_calc_bl_(&(pd)->bl, status_db.getSCB_ALL(), opt)
|
||||
|
Loading…
x
Reference in New Issue
Block a user