From 6dc437fd08c961cc8caa86e55b9853e541ba63fe Mon Sep 17 00:00:00 2001 From: aleos89 Date: Wed, 23 Mar 2016 14:25:58 -0400 Subject: [PATCH] Implemented the official effect of Vellum Vanish (fixes #900 and fixes #1021) * The Vellum Vanish bonus only refers to bHPVanishRaceRate and bSPVanishRaceRate. * Requires client 2013-03-20 and newer to display blue damage. * Properly displays blue damage being done for SP Vellum Vanish. * Vellum Vanish items no longer deal physical damage except on skill usage. * Skill usage with Vellum Vanish does not cause vanish. * HP and SP Vellum Vanish items do not stack (SP will override HP). --- src/map/atcommand.c | 4 +- src/map/battle.c | 140 +++++++++++++++++++++++++++++--------------- src/map/battle.h | 8 ++- src/map/clif.c | 6 +- src/map/clif.h | 2 +- src/map/skill.c | 26 ++++---- src/map/status.c | 16 ++--- src/map/status.h | 2 + 8 files changed, 128 insertions(+), 76 deletions(-) diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 1895f3165a..e0cb8a943a 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -1166,7 +1166,7 @@ ACMD_FUNC(heal) if ( hp < 0 && sp <= 0 ) { status_damage(NULL, &sd->bl, -hp, -sp, 0, 0); - clif_damage(&sd->bl,&sd->bl, gettick(), 0, 0, -hp, 0, DMG_ENDURE, 0); + clif_damage(&sd->bl,&sd->bl, gettick(), 0, 0, -hp, 0, DMG_ENDURE, 0, false); clif_displaymessage(fd, msg_txt(sd,156)); // HP or/and SP modified. return 0; } @@ -1177,7 +1177,7 @@ ACMD_FUNC(heal) status_heal(&sd->bl, hp, 0, 0); else { status_damage(NULL, &sd->bl, -hp, 0, 0, 0); - clif_damage(&sd->bl,&sd->bl, gettick(), 0, 0, -hp, 0, DMG_ENDURE, 0); + clif_damage(&sd->bl,&sd->bl, gettick(), 0, 0, -hp, 0, DMG_ENDURE, 0, false); } } diff --git a/src/map/battle.c b/src/map/battle.c index eccb261f65..f791df25e8 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -254,11 +254,15 @@ struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int * @param dmg_lv: State of the attack (miss, etc.) * @param attack_type: Type of the attack (BF_NORMAL|BF_SKILL|BF_SHORT|BF_LONG|BF_WEAPON|BF_MAGIC|BF_MISC) * @param additional_effects: Whether additional effect should be applied +* @param isspdamage: If the damage is done to SP * @param tick: Current tick *------------------------------------------*/ -void battle_damage(struct block_list *src, struct block_list *target, int64 damage, int delay, uint16 skill_lv, uint16 skill_id, enum damage_lv dmg_lv, unsigned short attack_type, bool additional_effects, unsigned int tick) { +void battle_damage(struct block_list *src, struct block_list *target, int64 damage, int delay, uint16 skill_lv, uint16 skill_id, enum damage_lv dmg_lv, unsigned short attack_type, bool additional_effects, unsigned int tick, bool isspdamage) { map_freeblock_lock(); - status_fix_damage(src, target, damage, delay); // We have to separate here between reflect damage and others [icescope] + if (isspdamage) + status_fix_spdamage(src, target, damage, delay); + else + status_fix_damage(src, target, damage, delay); // We have to separate here between reflect damage and others [icescope] if (attack_type && !status_isdead(target) && additional_effects) skill_additional_effect(src, target, skill_id, skill_lv, attack_type, dmg_lv, tick); if (dmg_lv > ATK_BLOCK && attack_type) @@ -285,6 +289,7 @@ struct delay_damage { unsigned short attack_type; bool additional_effects; enum bl_type src_type; + bool isspdamage; }; int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) @@ -312,7 +317,7 @@ int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) 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); + 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); @@ -328,7 +333,7 @@ int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) return 0; } -int battle_delay_damage(unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects) +int battle_delay_damage(unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects, bool isspdamage) { struct delay_damage *dat; struct status_change *sc; @@ -353,7 +358,7 @@ int battle_delay_damage(unsigned int tick, int amotion, struct block_list *src, if ( !battle_config.delay_battle_damage || amotion <= 1 ) { //Deal damage - battle_damage(src, target, damage, ddelay, skill_lv, skill_id, dmg_lv, attack_type, additional_effects, gettick()); + battle_damage(src, target, damage, ddelay, skill_lv, skill_id, dmg_lv, attack_type, additional_effects, gettick(), isspdamage); return 0; } dat = ers_alloc(delay_damage_ers, struct delay_damage); @@ -368,6 +373,7 @@ int battle_delay_damage(unsigned int tick, int amotion, struct block_list *src, dat->distance = distance_bl(src, target) + (battle_config.snap_dodge ? 10 : AREA_SIZE); dat->additional_effects = additional_effects; dat->src_type = src->type; + dat->isspdamage = isspdamage; if (src->type != BL_PC && amotion > 1000) amotion = 1000; //Aegis places a damage-delay cap of 1 sec to non player attacks. [Skotlex] @@ -4893,11 +4899,11 @@ struct Damage battle_calc_attack_gvg_bg(struct Damage wd, struct block_list *src if( rdamage > 0 ) { //Item reflect gets calculated before any mapflag reducing is applicated struct block_list *d_bl = battle_check_devotion(src); - rdelay = clif_damage(src, (!d_bl) ? src : d_bl, tick, wd.amotion, sstatus->dmotion, rdamage, 1, DMG_ENDURE, 0); + rdelay = clif_damage(src, (!d_bl) ? src : d_bl, tick, wd.amotion, sstatus->dmotion, rdamage, 1, DMG_ENDURE, 0, false); if( tsd ) - battle_drain(tsd, src, rdamage, rdamage, sstatus->race, sstatus->class_, is_infinite_defense(src,wd.flag)); + battle_drain(tsd, src, rdamage, rdamage, sstatus->race, sstatus->class_); //Use Reflect Shield to signal this kind of skill trigger [Skotlex] - battle_delay_damage(tick, wd.amotion, target, (!d_bl) ? src : d_bl, 0, CR_REFLECTSHIELD, 0, rdamage, ATK_DEF, rdelay, true); + battle_delay_damage(tick, wd.amotion, target, (!d_bl) ? src : d_bl, 0, CR_REFLECTSHIELD, 0, rdamage, ATK_DEF, rdelay, true, false); skill_additional_effect(target, (!d_bl) ? src : d_bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL, ATK_DEF, tick); } } @@ -4961,7 +4967,7 @@ struct Damage battle_calc_weapon_final_atk_modifiers(struct Damage wd, struct bl ) { ATK_RATER(wd.damage, 50) - status_fix_damage(target,src,wd.damage,clif_damage(target,src,gettick(),0,0,wd.damage,0,DMG_NORMAL,0)); + status_fix_damage(target,src,wd.damage,clif_damage(target,src,gettick(),0,0,wd.damage,0,DMG_NORMAL,0,false)); clif_skill_nodamage(target,target,ST_REJECTSWORD,tsc->data[SC_REJECTSWORD]->val1,1); if( --(tsc->data[SC_REJECTSWORD]->val3) <= 0 ) status_change_end(target, SC_REJECTSWORD, INVALID_TIMER); @@ -4977,7 +4983,7 @@ struct Damage battle_calc_weapon_final_atk_modifiers(struct Damage wd, struct bl skill_blown(target, src, skill_get_blewcount(SR_CRESCENTELBOW_AUTOSPELL, tsc->data[SC_CRESCENTELBOW]->val1), unit_getdir(src), 0); clif_skill_damage(target, src, gettick(), status_get_amotion(src), 0, rdamage, 1, SR_CRESCENTELBOW_AUTOSPELL, tsc->data[SC_CRESCENTELBOW]->val1, 6); // This is how official does - clif_damage(src, target, gettick(), status_get_amotion(src)+1000, 0, rdamage/10, 1, DMG_NORMAL, 0); + clif_damage(src, target, gettick(), status_get_amotion(src)+1000, 0, rdamage/10, 1, DMG_NORMAL, 0, false); status_damage(target, src, rdamage, 0, 0, 0); status_damage(src, target, rdamage/10, 0, 0, 1); status_change_end(target, SC_CRESCENTELBOW, INVALID_TIMER); @@ -5160,11 +5166,11 @@ void battle_do_reflect(int attack_type, struct Damage *wd, struct block_list* sr if( attack_type == BF_WEAPON && tsc->data[SC_REFLECTDAMAGE] ) // Don't reflect your own damage (Grand Cross) map_foreachinshootrange(battle_damage_area,target,skill_get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,target,wd->amotion,sstatus->dmotion,rdamage,wd->flag); else if( attack_type == BF_WEAPON || attack_type == BF_MISC) { - rdelay = clif_damage(src, (!d_bl) ? src : d_bl, tick, wd->amotion, sstatus->dmotion, rdamage, 1, DMG_ENDURE, 0); + rdelay = clif_damage(src, (!d_bl) ? src : d_bl, tick, wd->amotion, sstatus->dmotion, rdamage, 1, DMG_ENDURE, 0, false); if( tsd ) - battle_drain(tsd, src, rdamage, rdamage, sstatus->race, sstatus->class_, is_infinite_defense(src,wd->flag)); + battle_drain(tsd, src, rdamage, rdamage, sstatus->race, sstatus->class_); // It appears that official servers give skill reflect damage a longer delay - battle_delay_damage(tick, wd->amotion, target, (!d_bl) ? src : d_bl, 0, CR_REFLECTSHIELD, 0, rdamage, ATK_DEF, rdelay ,true); + battle_delay_damage(tick, wd->amotion, target, (!d_bl) ? src : d_bl, 0, CR_REFLECTSHIELD, 0, rdamage, ATK_DEF, rdelay ,true, false); skill_additional_effect(target, (!d_bl) ? src : d_bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL, ATK_DEF, tick); } } @@ -6786,12 +6792,69 @@ int64 battle_calc_return_damage(struct block_list* bl, struct block_list *src, i return cap_value(min(rdamage,max_damage),INT_MIN,INT_MAX); } +/** + * Calculate vanish from target + * @param sd: Player with vanish item + * @param target: Target to vanish HP/SP + * @param wd: Reference to Damage struct + */ +void battle_vanish(struct map_session_data *sd, struct block_list *target, struct Damage *wd) +{ + struct status_data *tstatus; + int hp = 0, sp = 0, race = status_get_race(target); + short vrate_hp = 0, vrate_sp = 0, v_hp = 0, v_sp = 0; + uint8 i = 0; + + nullpo_retv(sd); + nullpo_retv(target); + + tstatus = status_get_status_data(target); + wd->isspdamage = false; + + hp = (sd->bonus.hp_vanish_rate * 10) + sd->hp_vanish_race[race].rate + sd->hp_vanish_race[RC_ALL].rate; + vrate_hp = cap_value(hp, 0, SHRT_MAX); + hp = sd->bonus.hp_vanish_per + sd->hp_vanish_race[race].per + sd->hp_vanish_race[RC_ALL].per; + v_hp = cap_value(hp, SHRT_MIN, SHRT_MAX); + + sp = (sd->bonus.sp_vanish_rate * 10) + sd->sp_vanish_race[race].rate + sd->sp_vanish_race[RC_ALL].rate; + vrate_sp = cap_value(sp, 0, SHRT_MAX); + sp = sd->bonus.sp_vanish_per + sd->sp_vanish_race[race].per + sd->sp_vanish_race[RC_ALL].per; + v_sp = cap_value(sp, SHRT_MIN, SHRT_MAX); + + if (wd->flag) { + // The HP and SP vanish bonus from these items can't stack because of the special damage display. + if (v_hp && vrate_hp && (vrate_hp >= 10000 || rnd()%10000 < vrate_hp)) + i = 1; + if (v_sp && vrate_sp && (vrate_sp >= 10000 || rnd()%10000 < vrate_sp)) + i = 2; + + if (i == 1) { + wd->damage = apply_rate(tstatus->max_hp, v_hp); + wd->damage2 = 0; + } + if (i == 2) { + wd->damage = apply_rate(tstatus->max_sp, v_sp); + wd->damage2 = 0; + wd->isspdamage = true; + } + } else { + if (v_hp && vrate_hp && (vrate_hp >= 10000 || rnd()%10000 < vrate_hp)) + i |= 1; + if (v_sp && vrate_sp && (vrate_sp >= 10000 || rnd()%10000 < vrate_sp)) + i |= 2; + + if (i) + status_percent_damage(&sd->bl, target, (i&1) ? (int8)(-v_hp) : 0, (i&2) ? (int8)(-v_sp) : 0, false); + } +} + /*=========================================== * Perform battle drain effects (HP/SP loss) *-------------------------------------------*/ -void battle_drain(struct map_session_data *sd, struct block_list *tbl, int64 rdamage, int64 ldamage, int race, int class_, bool infdef) +void battle_drain(struct map_session_data *sd, struct block_list *tbl, int64 rdamage, int64 ldamage, int race, int class_) { struct weapon_data *wd; + struct Damage d; int64 *damage; int thp = 0, // HP gained tsp = 0, // SP gained @@ -6799,32 +6862,14 @@ void battle_drain(struct map_session_data *sd, struct block_list *tbl, int64 rda //rsp = 0, // SP reduced from target hp = 0, sp = 0; uint8 i = 0; - short vrate_hp = 0, vrate_sp = 0, v_hp = 0, v_sp = 0; if (!CHK_RACE(race) && !CHK_CLASS(class_)) return; + memset(&d, 0, sizeof(d)); + // Check for vanish HP/SP. !CHECKME: Which first, drain or vanish? - hp = (sd->bonus.hp_vanish_rate*10) + sd->hp_vanish_race[race].rate + sd->hp_vanish_race[RC_ALL].rate; - vrate_hp = cap_value(hp, 0, SHRT_MAX); - hp = sd->bonus.hp_vanish_per + sd->hp_vanish_race[race].per + sd->hp_vanish_race[RC_ALL].per; - v_hp = cap_value(hp, SHRT_MIN, SHRT_MAX); - - sp = (sd->bonus.sp_vanish_rate*10) + sd->sp_vanish_race[race].rate + sd->sp_vanish_race[RC_ALL].rate; - vrate_sp = cap_value(sp, 0, SHRT_MAX); - sp = sd->bonus.sp_vanish_per + sd->sp_vanish_race[race].per + sd->sp_vanish_race[RC_ALL].per; - v_sp = cap_value(sp, INT8_MIN, INT8_MAX); - - if (v_hp > 0 && vrate_hp > 0 && (vrate_hp >= 10000 || rnd()%10000 < vrate_hp)) - i |= 1; - if (v_sp > 0 && vrate_sp > 0 && (vrate_sp >= 10000 || rnd()%10000 < vrate_sp)) - i |= 2; - if (i) { - if (infdef) - status_zap(tbl, v_hp ? v_hp/100 : 0, v_sp ? v_sp/100 : 0); - else - status_percent_damage(&sd->bl, tbl, (i&1 ? (int8)(-v_hp): 0), (i&2 ? (int8)(-v_sp) : 0), false); - } + battle_vanish(sd, tbl, &d); // Check for drain HP/SP hp = sp = i = 0; @@ -6908,12 +6953,12 @@ int battle_damage_area(struct block_list *bl, va_list ap) { if( bl != src && battle_check_target(src,bl,BCT_ENEMY) > 0 ) { map_freeblock_lock(); if( src->type == BL_PC ) - battle_drain((TBL_PC*)src, bl, damage, damage, status_get_race(bl), status_get_class_(bl), is_infinite_defense(bl,flag)); + battle_drain((TBL_PC*)src, bl, damage, damage, status_get_race(bl), status_get_class_(bl)); if( amotion ) - battle_delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0,true); + battle_delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0,true,false); else status_fix_damage(src,bl,damage,0); - clif_damage(bl,bl,tick,amotion,dmotion,damage,1,DMG_ENDURE,0); + clif_damage(bl,bl,tick,amotion,dmotion,damage,1,DMG_ENDURE,0,false); skill_additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); map_freeblock_unlock(); } @@ -7007,7 +7052,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t uint16 skill_lv = tsc->data[SC_AUTOCOUNTER]->val1; clif_skillcastcancel(target); //Remove the casting bar. [Skotlex] - clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, DMG_NORMAL, 0); //Display MISS. + clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, DMG_NORMAL, 0, false); //Display MISS. status_change_end(target, SC_AUTOCOUNTER, INVALID_TIMER); skill_attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skill_lv,tick,0); return ATK_BLOCK; @@ -7021,7 +7066,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER); if(sc_start4(src,src, SC_BLADESTOP, 100, sd?pc_checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration)) { //Target locked. - clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, DMG_NORMAL, 0); //Display MISS. + clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, DMG_NORMAL, 0, false); //Display MISS. clif_bladestop(target, src->id, 1); sc_start4(src,target, SC_BLADESTOP, 100, skill_lv, 0, 0, src->id, duration); return ATK_BLOCK; @@ -7101,6 +7146,9 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t wd = battle_calc_attack(BF_WEAPON, src, target, 0, 0, flag); + if (sd && wd.damage + wd.damage2 > 0) + battle_vanish(sd, target, &wd); + if( sc && sc->count ) { if (sc->data[SC_EXEEDBREAK]) { wd.damage *= sc->data[SC_EXEEDBREAK]->val2 / 100; @@ -7143,7 +7191,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t } } - wd.dmotion = clif_damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , (enum e_damage_type)wd.type, wd.damage2); + wd.dmotion = clif_damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , (enum e_damage_type)wd.type, wd.damage2, wd.isspdamage); if (sd && sd->bonus.splash_range > 0 && damage > 0) skill_castend_damage_id(src, target, 0, 1, tick, 0); @@ -7168,7 +7216,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t if( wd.dmg_lv > ATK_BLOCK ) skill_counter_additional_effect(src, target, 0, 0, wd.flag, tick); } else - battle_delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion, true); + battle_delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion, true, wd.isspdamage); if( tsc ) { if( tsc->data[SC_DEVOTION] ) { struct status_change_entry *sce = tsc->data[SC_DEVOTION]; @@ -7179,7 +7227,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == target->id) ) && check_distance_bl(target, d_bl, sce->val3) ) { - clif_damage(d_bl, d_bl, gettick(), 0, 0, damage, 0, DMG_NORMAL, 0); + clif_damage(d_bl, d_bl, gettick(), 0, 0, damage, 0, DMG_NORMAL, 0, false); status_fix_damage(NULL, d_bl, damage, 0); } else @@ -7197,7 +7245,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t struct block_list *e_bl = map_id2bl(tsc->data[SC_WATER_SCREEN_OPTION]->val1); if (e_bl && !status_isdead(e_bl)) { - clif_damage(e_bl, e_bl, tick, 0, 0, damage, wd.div_, DMG_NORMAL, 0); + clif_damage(e_bl, e_bl, tick, 0, 0, damage, wd.div_, DMG_NORMAL, 0, false); status_fix_damage(NULL, e_bl, damage, 0); } } @@ -7305,9 +7353,9 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t if (wd.flag & BF_WEAPON && src != target && damage > 0) { if (battle_config.left_cardfix_to_right) - battle_drain(sd, target, wd.damage, wd.damage, tstatus->race, tstatus->class_, is_infinite_defense(target,wd.flag)); + battle_drain(sd, target, wd.damage, wd.damage, tstatus->race, tstatus->class_); else - battle_drain(sd, target, wd.damage, wd.damage2, tstatus->race, tstatus->class_, is_infinite_defense(target,wd.flag)); + battle_drain(sd, target, wd.damage, wd.damage2, tstatus->race, tstatus->class_); } } diff --git a/src/map/battle.h b/src/map/battle.h index aa07125e1b..58ab1a1f11 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -69,6 +69,7 @@ struct Damage { int flag; /// chk e_battle_flag int miscflag; enum damage_lv dmg_lv; /// ATK_LUCKY,ATK_FLEE,ATK_DEF + bool isspdamage; /// Display blue damage numbers in clif_damage }; //(Used in read pc.c,) attribute table (battle_attr_fix) @@ -85,7 +86,8 @@ struct Damage battle_calc_attack_plant(struct Damage wd, struct block_list *src, int64 battle_calc_return_damage(struct block_list *bl, struct block_list *src, int64 *, int flag, uint16 skill_id, bool status_reflect); -void battle_drain(struct map_session_data *sd, struct block_list *tbl, int64 rdamage, int64 ldamage, int race, int class_, bool infdef); +void battle_drain(struct map_session_data *sd, struct block_list *tbl, int64 rdamage, int64 ldamage, int race, int class_); +void battle_vanish(struct map_session_data *sd, struct block_list *target, struct Damage *wd); int battle_attr_ratio(int atk_elem,int def_type, int def_lv); int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 damage,int atk_elem,int def_type, int def_lv); @@ -96,8 +98,8 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64 damage,uint16 skill_id,int flag); int64 battle_calc_bg_damage(struct block_list *src,struct block_list *bl,int64 damage,uint16 skill_id,int flag); -void battle_damage(struct block_list *src, struct block_list *target, int64 damage, int delay, uint16 skill_lv, uint16 skill_id, enum damage_lv dmg_lv, unsigned short attack_type, bool additional_effects, unsigned int tick); -int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects); +void battle_damage(struct block_list *src, struct block_list *target, int64 damage, int delay, uint16 skill_lv, uint16 skill_id, enum damage_lv dmg_lv, unsigned short attack_type, bool additional_effects, unsigned int tick, bool spdamage); +int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects, bool spdamage); // Summary normal attack treatment (basic attack) enum damage_lv battle_weapon_attack( struct block_list *bl,struct block_list *target,unsigned int tick,int flag); diff --git a/src/map/clif.c b/src/map/clif.c index fd1b4bbc10..8e79ccd2be 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -4663,7 +4663,7 @@ static int clif_calc_walkdelay(struct block_list *bl,int delay, char type, int64 /// 10 = critical hit /// 11 = lucky dodge /// 12 = (touch skill?) -int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int64 sdamage, int div, enum e_damage_type type, int64 sdamage2) +int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int64 sdamage, int div, enum e_damage_type type, int64 sdamage2, bool spdamage) { unsigned char buf[34]; struct status_change *sc; @@ -4711,7 +4711,7 @@ int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tic #endif } #if PACKETVER >= 20131223 - WBUFB(buf,26) = 0; // IsSPDamage - Displays blue digits. Need a way to handle this. [Rytech] + WBUFB(buf,26) = (spdamage) ? 1 : 0; // IsSPDamage - Displays blue digits. #endif WBUFW(buf,24+offset) = div; WBUFB(buf,26+offset) = type; @@ -4749,7 +4749,7 @@ int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tic *------------------------------------------*/ void clif_takeitem(struct block_list* src, struct block_list* dst) { - //clif_damage(src,dst,0,0,0,0,0,DMG_PICKUP_ITEM,0); + //clif_damage(src,dst,0,0,0,0,0,DMG_PICKUP_ITEM,0,false); unsigned char buf[32]; nullpo_retv(src); diff --git a/src/map/clif.h b/src/map/clif.h index b7fd4fdbe6..ab5e34b13e 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -538,7 +538,7 @@ void clif_dropitem(struct map_session_data *sd,int n,int amount); //self void clif_delitem(struct map_session_data *sd,int n,int amount, short reason); //self void clif_updatestatus(struct map_session_data *sd,int type); //self void clif_changestatus(struct map_session_data* sd,int type,int val); //area -int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int64 sdamage, int div, enum e_damage_type type, int64 sdamage2); // area +int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int64 sdamage, int div, enum e_damage_type type, int64 sdamage2, bool spdamage); // area void clif_takeitem(struct block_list* src, struct block_list* dst); void clif_sitting(struct block_list* bl); void clif_standing(struct block_list* bl); diff --git a/src/map/skill.c b/src/map/skill.c index 58c6ea84a4..cd2ad08438 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -3243,7 +3243,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list * case NPC_CRITICALSLASH: case TF_DOUBLE: case GS_CHAINACTION: - dmg.dmotion = clif_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,(enum e_damage_type)dmg.type,dmg.damage2); + dmg.dmotion = clif_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,(enum e_damage_type)dmg.type,dmg.damage2,false); break; case AS_SPLASHER: @@ -3393,7 +3393,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list * if( dmg.flag > ATK_BLOCK ) skill_counter_additional_effect(src, bl, skill_id, skill_lv, dmg.flag, tick); } else - battle_delay_damage(tick, dmg.amotion,src,bl,dmg.flag,skill_id,skill_lv,damage,dmg.dmg_lv,dmg.dmotion, additional_effects); + battle_delay_damage(tick, dmg.amotion,src,bl,dmg.flag,skill_id,skill_lv,damage,dmg.dmg_lv,dmg.dmotion, additional_effects, false); } if (tsc && skill_id != PA_PRESSURE && skill_id != HW_GRAVITATION && skill_id != NPC_EVILLAND) { @@ -3407,7 +3407,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list * ) && check_distance_bl(bl, d_bl, sce->val3) ) { if (!rmdamage) { - clif_damage(d_bl, d_bl, gettick(), 0, 0, damage, 0, DMG_NORMAL, 0); + clif_damage(d_bl, d_bl, gettick(), 0, 0, damage, 0, DMG_NORMAL, 0, false); status_fix_damage(NULL, d_bl, damage, 0); } else { bool isDevotRdamage = false; @@ -3417,7 +3417,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list * // If !isDevotRdamage, reflected magics are done directly on the target not on paladin // This check is only for magical skill. // For BF_WEAPON skills types track var rdamage and function battle_calc_return_damage - clif_damage(bl, (!isDevotRdamage) ? bl : d_bl, gettick(), 0, 0, damage, 0, DMG_NORMAL, 0); + clif_damage(bl, (!isDevotRdamage) ? bl : d_bl, gettick(), 0, 0, damage, 0, DMG_NORMAL, 0, false); status_fix_damage(bl, (!isDevotRdamage) ? bl : d_bl, damage, 0); } } else { @@ -3459,9 +3459,9 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list * (dmg.flag&BF_MISC && (skill_id == RA_CLUSTERBOMB || skill_id == RA_FIRINGTRAP || skill_id == RA_ICEBOUNDTRAP)) ) ) { if (battle_config.left_cardfix_to_right) - battle_drain(sd, bl, dmg.damage, dmg.damage, tstatus->race, tstatus->class_, is_infinite_defense(bl,dmg.flag)); + battle_drain(sd, bl, dmg.damage, dmg.damage, tstatus->race, tstatus->class_); else - battle_drain(sd, bl, dmg.damage, dmg.damage2, tstatus->race, tstatus->class_, is_infinite_defense(bl,dmg.flag)); + battle_drain(sd, bl, dmg.damage, dmg.damage2, tstatus->race, tstatus->class_); } if( damage > 0 ) { // Post-damage effects @@ -4937,7 +4937,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint break; case CH_PALMSTRIKE: // Palm Strike takes effect 1sec after casting. [Skotlex] // clif_skill_nodamage(src,bl,skill_id,skill_lv,0); //Can't make this one display the correct attack animation delay :/ - clif_damage(src,bl,tick,status_get_amotion(src),0,-1,1,DMG_ENDURE,0); //Display an absorbed damage attack. + clif_damage(src,bl,tick,status_get_amotion(src),0,-1,1,DMG_ENDURE,0,false); //Display an absorbed damage attack. skill_addtimerskill(src, tick + (1000+status_get_amotion(src)), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag); break; @@ -8411,7 +8411,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case 3: // 1000 damage, random armor destroyed { status_fix_damage(src, bl, 1000, 0); - clif_damage(src,bl,tick,0,0,1000,0,DMG_NORMAL,0); + clif_damage(src,bl,tick,0,0,1000,0,DMG_NORMAL,0,false); if( !status_isdead(bl) ) { int where[] = { EQP_ARMOR, EQP_SHIELD, EQP_HELM, EQP_SHOES, EQP_GARMENT }; skill_break_equip(src,bl, where[rnd()%5], 10000, BCT_ENEMY); @@ -8450,14 +8450,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui break; case 10: // 6666 damage, atk matk halved, cursed status_fix_damage(src, bl, 6666, 0); - clif_damage(src,bl,tick,0,0,6666,0,DMG_NORMAL,0); + clif_damage(src,bl,tick,0,0,6666,0,DMG_NORMAL,0,false); sc_start(src,bl,SC_INCATKRATE,100,-50,skill_get_time2(skill_id,skill_lv)); sc_start(src,bl,SC_INCMATKRATE,100,-50,skill_get_time2(skill_id,skill_lv)); sc_start(src,bl,SC_CURSE,skill_lv,100,skill_get_time2(skill_id,skill_lv)); break; case 11: // 4444 damage status_fix_damage(src, bl, 4444, 0); - clif_damage(src,bl,tick,0,0,4444,0,DMG_NORMAL,0); + clif_damage(src,bl,tick,0,0,4444,0,DMG_NORMAL,0,false); break; case 12: // stun sc_start(src,bl,SC_STUN,100,skill_lv,5000); @@ -9938,7 +9938,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui sc_start(src,bl, type, 100, skill_lv,skill_get_time(skill_id, skill_lv)); } else if( flag&2 ) { if( src->id != bl->id && battle_check_target(src,bl,BCT_ENEMY) > 0 ) - status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,DMG_NORMAL,0)); + status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,DMG_NORMAL,0,false)); } else if( sd ) { short chance = sstatus->int_/6 + sd->status.job_level/5 + skill_lv*4; if( !sd->status.party_id || (rnd()%100 > chance)) { @@ -9954,7 +9954,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui clif_skill_nodamage(src, bl, skill_id, skill_lv, sc_start(src,src,SC_STOP,100,skill_lv,skill_get_time2(skill_id,skill_lv))); if( flag&2 ) // Dealed here to prevent conflicts - status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,DMG_NORMAL,0)); + status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,DMG_NORMAL,0,false)); } break; case WM_SONG_OF_MANA: @@ -17413,7 +17413,7 @@ bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit) return false; } - status_damage(bl, src, damage, 0, clif_damage(src, src, gettick(), 500, 500, damage, hit, (hit > 1 ? DMG_MULTI_HIT : DMG_NORMAL), 0), 0); + status_damage(bl, src, damage, 0, clif_damage(src, src, gettick(), 500, 500, damage, hit, (hit > 1 ? DMG_MULTI_HIT : DMG_NORMAL), 0, false), 0); if( sc && sc->data[SC__SHADOWFORM] && (--sc->data[SC__SHADOWFORM]->val3) <= 0 ) { status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); if( src->type == BL_PC ) diff --git a/src/map/status.c b/src/map/status.c index aa6cedb874..b43ad4e67a 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -11465,7 +11465,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const struct block_list* src = map_id2bl(sce->val2); if( tid == -1 || !src) break; // Terminated by Damage - status_fix_damage(src,bl,400*sce->val1,clif_damage(bl,bl,gettick(),0,0,400*sce->val1,0,DMG_NORMAL,0)); + status_fix_damage(src,bl,400*sce->val1,clif_damage(bl,bl,gettick(),0,0,400*sce->val1,0,DMG_NORMAL,0,false)); } break; case SC_WUGDASH: @@ -12023,7 +12023,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) int64 damage = 1000 + (3 * status->max_hp) / 100; // Deals fixed (1000 + 3%*MaxHP) map_freeblock_lock(); dounlock = true; - status_fix_damage(bl, bl, damage, clif_damage(bl, bl, tick, 0, 1, damage, 1, DMG_NORMAL, 0)); + status_fix_damage(bl, bl, damage, clif_damage(bl, bl, tick, 0, 1, damage, 1, DMG_NORMAL, 0, false)); } break; @@ -12031,7 +12031,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) if (sce->val4 >= 0) { // Damage is every 10 seconds including 3%sp drain. map_freeblock_lock(); dounlock = true; - status_damage(bl, bl, 1, status->max_sp * 3 / 100, clif_damage(bl, bl, tick, status->amotion, status->dmotion + 500, 1, 1, DMG_NORMAL, 0), 0); + status_damage(bl, bl, 1, status->max_sp * 3 / 100, clif_damage(bl, bl, tick, status->amotion, status->dmotion + 500, 1, 1, DMG_NORMAL, 0, false), 0); } break; @@ -12083,7 +12083,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) if (sce->val4 >= 0) { map_freeblock_lock(); dounlock = true; - status_fix_damage(bl, bl, 100, clif_damage(bl, bl, tick, status->amotion, status->dmotion + 500, 100, 1, DMG_NORMAL, 0)); + status_fix_damage(bl, bl, 100, clif_damage(bl, bl, tick, status->amotion, status->dmotion + 500, 100, 1, DMG_NORMAL, 0, false)); } break; @@ -12092,7 +12092,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) int64 damage = status->vit * (sce->val1 - 3) + status->max_hp / 100; // {Target VIT x (New Poison Research Skill Level - 3)} + (Target HP/100) map_freeblock_lock(); dounlock = true; - status_fix_damage(bl, bl, damage, clif_damage(bl, bl, tick, status->amotion, status->dmotion + 500, damage, 1, DMG_NORMAL, 0)); + status_fix_damage(bl, bl, damage, clif_damage(bl, bl, tick, status->amotion, status->dmotion + 500, damage, 1, DMG_NORMAL, 0, false)); unit_skillcastcancel(bl, 2); } break; @@ -12394,7 +12394,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) damage = 1; else damage = 200 + 100 * sce->val1 + status_get_int(src); - status_damage(src, bl, damage, 0, clif_damage(bl,bl,tick,status->amotion,status->dmotion+200,damage,1,DMG_NORMAL,0), 0); + status_damage(src, bl, damage, 0, clif_damage(bl,bl,tick,status->amotion,status->dmotion+200,damage,1,DMG_NORMAL,0,false), 0); unit_skillcastcancel(bl,1); if ( sc->data[type] ) { sc_timer_next(1000 + tick, status_change_timer, bl->id, data); @@ -12501,7 +12501,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) int damage = status->max_hp / 100; // Suggestion 1% each second if( damage >= status->hp ) damage = status->hp - 1; // Do not kill, just keep you with 1 hp minimum map_freeblock_lock(); - status_fix_damage(NULL,bl,damage,clif_damage(bl,bl,tick,0,0,damage,0,DMG_NORMAL,0)); + status_fix_damage(NULL,bl,damage,clif_damage(bl,bl,tick,0,0,damage,0,DMG_NORMAL,0,false)); if( sc->data[type] ) { sc_timer_next(1000 + tick, status_change_timer, bl->id, data); } @@ -12586,7 +12586,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) int damage = sce->val2; map_freeblock_lock(); - clif_damage(bl, bl, tick, 0, 0, damage, 1, DMG_MULTI_HIT_ENDURE, 0); + clif_damage(bl, bl, tick, 0, 0, damage, 1, DMG_MULTI_HIT_ENDURE, 0, false); status_damage(src, bl, damage,0, 0, 1); if( sc->data[type] ) { sc_timer_next(2000 + tick, status_change_timer, bl->id, data); diff --git a/src/map/status.h b/src/map/status.h index 68fb06dc84..0eab96e77a 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -2095,6 +2095,8 @@ int StatusIconChangeTable[SC_MAX]; /// status -> "icon" (icon is a bit int status_damage(struct block_list *src,struct block_list *target,int64 dhp,int64 dsp, int walkdelay, int flag); //Define for standard HP damage attacks. #define status_fix_damage(src, target, hp, walkdelay) status_damage(src, target, hp, 0, walkdelay, 0) +//Define for standard SP damage attacks. +#define status_fix_spdamage(src, target, sp, walkdelay) status_damage(src, target, 0, sp, walkdelay, 0) //Define for standard HP/SP damage triggers. #define status_zap(bl, hp, sp) status_damage(NULL, bl, hp, sp, 0, 1) //Define for standard HP/SP skill-related cost triggers (mobs require no HP/SP to use skills)