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:
parent
69b68bc2f5
commit
bf9a3b47fe
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user