Removed an extra status calculation for players (#4525)

* Follow up to 2732176.
* Fixes #4150.
* Removed an extra status calculation for players resulting in some status data being nullified.
* Adjusted status calculation for autobonus and unequipping items.
* Cleaned up delayed damage logic.
Thanks to @cydh, @Hatfun, and @NeutralDev!
This commit is contained in:
Aleos 2020-01-17 20:30:35 -05:00 committed by GitHub
parent 69b68bc2f5
commit bf9a3b47fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 56 deletions

View File

@ -304,36 +304,28 @@ TIMER_FUNC(battle_delay_damage_sub){
struct delay_damage *dat = (struct delay_damage *)data;
if ( dat ) {
struct block_list* src = NULL;
struct block_list* src = map_id2bl(dat->src_id);
struct block_list* target = map_id2bl(dat->target_id);
if( !target || status_isdead(target) ) { /* Nothing we can do */
if( dat->src_type == BL_PC && (src = map_id2bl(dat->src_id)) &&
--((TBL_PC*)src)->delayed_damage == 0 && ((TBL_PC*)src)->state.hold_recalc ) {
((TBL_PC*)src)->state.hold_recalc = 0;
status_calc_pc(((TBL_PC*)src), SCO_FORCE);
if (target && !status_isdead(target)) {
if( src && target->m == src->m &&
(target->type != BL_PC || ((TBL_PC*)target)->invincible_timer == INVALID_TIMER) &&
check_distance_bl(src, target, dat->distance) ) //Check to see if you haven't teleported. [Skotlex]
{
//Deal damage
battle_damage(src, target, dat->damage, dat->delay, dat->skill_lv, dat->skill_id, dat->dmg_lv, dat->attack_type, dat->additional_effects, tick, dat->isspdamage);
} else if( !src && dat->skill_id == CR_REFLECTSHIELD ) { // it was monster reflected damage, and the monster died, we pass the damage to the character as expected
map_freeblock_lock();
status_fix_damage(target, target, dat->damage, dat->delay);
map_freeblock_unlock();
}
ers_free(delay_damage_ers, dat);
return 0;
}
src = map_id2bl(dat->src_id);
struct map_session_data *sd = BL_CAST(BL_PC, src);
if( src && target->m == src->m &&
(target->type != BL_PC || ((TBL_PC*)target)->invincible_timer == INVALID_TIMER) &&
check_distance_bl(src, target, dat->distance) ) //Check to see if you haven't teleported. [Skotlex]
{
//Deal damage
battle_damage(src, target, dat->damage, dat->delay, dat->skill_lv, dat->skill_id, dat->dmg_lv, dat->attack_type, dat->additional_effects, tick, dat->isspdamage);
} else if( !src && dat->skill_id == CR_REFLECTSHIELD ) { // it was monster reflected damage, and the monster died, we pass the damage to the character as expected
map_freeblock_lock();
status_fix_damage(target, target, dat->damage, dat->delay);
map_freeblock_unlock();
}
if( src && src->type == BL_PC && --((TBL_PC*)src)->delayed_damage == 0 && ((TBL_PC*)src)->state.hold_recalc ) {
((TBL_PC*)src)->state.hold_recalc = 0;
status_calc_pc(((TBL_PC*)src), SCO_FORCE);
if (sd && --sd->delayed_damage == 0 && sd->state.hold_recalc) {
sd->state.hold_recalc = false;
status_calc_pc(sd, SCO_FORCE);
}
}
ers_free(delay_damage_ers, dat);

View File

@ -2643,7 +2643,7 @@ void pc_exeautobonus(struct map_session_data *sd, std::vector<s_autobonus> *bonu
autobonus->active = add_timer(gettick()+autobonus->duration, pc_endautobonus, sd->bl.id, (intptr_t)bonus);
sd->state.autobonus |= autobonus->pos;
status_calc_pc(sd,SCO_FORCE);
status_calc_pc(sd,SCO_NONE);
}
/**
@ -2664,7 +2664,7 @@ TIMER_FUNC(pc_endautobonus){
}
}
status_calc_pc(sd,SCO_FORCE);
status_calc_pc(sd,SCO_NONE);
return 0;
}
@ -10417,8 +10417,10 @@ static void pc_unequipitem_sub(struct map_session_data *sd, int n, int flag) {
}
}
if (status_calc)
if (flag & 1 || status_calc) {
pc_checkallowskill(sd);
status_calc_pc(sd, SCO_NONE);
}
if (sd->sc.data[SC_SIGNUMCRUCIS] && !battle_check_undead(sd->battle_status.race, sd->battle_status.def_ele))
status_change_end(&sd->bl, SC_SIGNUMCRUCIS, INVALID_TIMER);
@ -10444,8 +10446,6 @@ static void pc_unequipitem_sub(struct map_session_data *sd, int n, int flag) {
}
}
if (flag & 1)
status_calc_pc(sd, SCO_FORCE);
sd->npc_item_flag = iflag;
}

View File

@ -300,7 +300,7 @@ struct map_session_data {
unsigned int prevend : 1;//used to flag wheather you've spent 40sp to open the vending or not.
unsigned int warping : 1;//states whether you're in the middle of a warp processing
unsigned int permanent_speed : 1; // When 1, speed cannot be changed through status_calc_pc().
unsigned int hold_recalc : 1;
bool hold_recalc;
unsigned int banking : 1; //1 when we using the banking system 0 when closed
unsigned int hpmeter_visible : 1;
unsigned disable_atcommand_on_npc : 1; //Prevent to use atcommand while talking with NPC [Kichi]

View File

@ -5349,12 +5349,16 @@ void status_calc_bl_(struct block_list* bl, enum scb_flag flag, enum e_status_ca
struct status_data b_status; // Previous battle status
struct status_data* status; // Pointer to current battle status
if (bl->type == BL_PC && ((TBL_PC*)bl)->delayed_damage != 0) {
if (opt&SCO_FORCE)
((TBL_PC*)bl)->state.hold_recalc = 0; /* Clear and move on */
else {
((TBL_PC*)bl)->state.hold_recalc = 1; /* Flag and stop */
return;
if (bl->type == BL_PC) {
struct map_session_data *sd = BL_CAST(BL_PC, bl);
if (sd->delayed_damage != 0) {
if (opt&SCO_FORCE)
sd->state.hold_recalc = false; // Clear and move on
else {
sd->state.hold_recalc = true; // Flag and stop
return;
}
}
}
@ -11766,33 +11770,31 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
else
sce->timer = INVALID_TIMER; // Infinite duration
if (calc_flag)
status_calc_bl(bl,calc_flag);
if (calc_flag) {
if (sd) {
switch(type) {
// Statuses that adjust HP/SP and heal after starting
case SC_BERSERK:
case SC_MERC_HPUP:
case SC_MERC_SPUP:
status_calc_bl_(bl, static_cast<scb_flag>(calc_flag), SCO_FORCE);
break;
default:
status_calc_bl(bl, calc_flag);
break;
}
} else
status_calc_bl(bl, calc_flag);
}
if ( sc_isnew && StatusChangeStateTable[type] ) // Non-zero
status_calc_state(bl,sc,( enum scs_flag ) StatusChangeStateTable[type],true);
if(sd) {
if (sd->pd)
pet_sc_check(sd, type); // Skotlex: Pet Status Effect Healing
switch (type) {
case SC_BERSERK:
case SC_MERC_HPUP:
case SC_MERC_SPUP:
status_calc_pc(sd, SCO_FORCE);
break;
default:
status_calc_pc(sd, SCO_NONE);
break;
}
}
if (sd && sd->pd)
pet_sc_check(sd, type); // Skotlex: Pet Status Effect Healing
// 1st thing to execute when loading status
switch (type) {
case SC_FULL_THROTTLE:
status_percent_heal(bl,100,0);
break;
case SC_BERSERK:
if (!(sce->val2)) { // Don't heal if already set
status_heal(bl, status->max_hp, 0, 1); // Do not use percent_heal as this healing must override BERSERK's block.
@ -11812,6 +11814,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
if (sd)
clif_bossmapinfo(sd, map_id2boss(sce->val1), BOSS_INFO_ALIVE_WITHMSG); // First Message
break;
case SC_FULL_THROTTLE:
case SC_MERC_HPUP:
status_percent_heal(bl, 100, 0); // Recover Full HP
break;