From 45e87f58af948434abe3603f0bd314ccef79fd49 Mon Sep 17 00:00:00 2001 From: Inkfish Date: Wed, 13 May 2009 11:07:09 +0000 Subject: PNEUMA, BASILICA and SAFETYWALL no longer protect you from such negative status changes as COMA, STUN, FREEZE and etc. (bugreport:1346) git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@13767 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/battle.c | 60 +++++++++++++++++------- src/map/battle.h | 1 + src/map/clif.c | 5 +- src/map/skill.c | 140 +++++++++++++++++++++++++++++-------------------------- 4 files changed, 118 insertions(+), 88 deletions(-) (limited to 'src/map') diff --git a/src/map/battle.c b/src/map/battle.c index 6c009ee64..28531f0c1 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -165,12 +165,10 @@ int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr data) { map_freeblock_lock(); status_fix_damage(dat->src, target, dat->damage, dat->delay); - if (dat->damage > 0 && dat->attack_type) - { - if (!status_isdead(target)) - skill_additional_effect(dat->src,target,dat->skill_id,dat->skill_lv,dat->attack_type,tick); + if( dat->attack_type && (dat->damage > 0 || dat->attack_type&0xf000) && !status_isdead(target) ) + skill_additional_effect(dat->src,target,dat->skill_id,dat->skill_lv,dat->attack_type,tick); + if( dat->damage > 0 && dat->attack_type ) skill_counter_additional_effect(dat->src,target,dat->skill_id,dat->skill_lv,dat->attack_type,tick); - } map_freeblock_unlock(); } ers_free(delay_damage_ers, dat); @@ -186,12 +184,10 @@ int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, if (!battle_config.delay_battle_damage) { map_freeblock_lock(); status_fix_damage(src, target, damage, ddelay); - if (damage > 0 && attack_type) - { - if (!status_isdead(target)) - skill_additional_effect(src, target, skill_id, skill_lv, attack_type, gettick()); + if( attack_type && (damage > 0 || attack_type&0xf000) && !status_isdead(target) ) + skill_additional_effect(src, target, skill_id, skill_lv, attack_type, gettick()); + if( damage > 0 && attack_type ) skill_counter_additional_effect(src, target, skill_id, skill_lv, attack_type, gettick()); - } map_freeblock_unlock(); return 0; } @@ -307,7 +303,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i { //First, sc_*'s that reduce damage to 0. if( sc->data[SC_BASILICA] && !(status_get_mode(src)&MD_BOSS) && skill_num != PA_PRESSURE ) - return 0; // Basilica reduces damage to 0 except Pressure + return -1; // Trigger status effects. if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT ) { @@ -315,13 +311,13 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i if (group) { if (--group->val2<=0) skill_delunitgroup(NULL,group); - return 0; + return -1; // Trigger status effects. } status_change_end(bl,SC_SAFETYWALL,-1); } if( sc->data[SC_PNEUMA] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG ) - return 0; + return -1; // Trigger status effects. if( (sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK) && rand()%100 < sce->val2 ) { @@ -2134,25 +2130,43 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo if(!flag.lh && wd.damage2) wd.damage2=0; - if(wd.damage + wd.damage2) + if( wd.damage + wd.damage2 ) { //There is a total damage value - if(!wd.damage2) { + if(!wd.damage2) + { wd.damage=battle_calc_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); + if( wd.damage == -1 ) + { + wd.flag |= 0xf000; + wd.damage = 0; + } if( map_flag_gvg2(target->m) ) wd.damage=battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); else if( map[target->m].flag.battleground ) wd.damage=battle_calc_bg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); - } else - if(!wd.damage) { + } + else if(!wd.damage) + { wd.damage2=battle_calc_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag); + if( wd.damage2 == -1 ) + { + wd.flag |= 0xf000; + wd.damage2 = 0; + } if( map_flag_gvg2(target->m) ) wd.damage2=battle_calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag); else if( map[target->m].flag.battleground ) wd.damage=battle_calc_bg_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag); - } else + } + else { int d1=wd.damage+wd.damage2,d2=wd.damage2; wd.damage=battle_calc_damage(src,target,d1,wd.div_,skill_num,skill_lv,wd.flag); + if( wd.damage == -1 ) + { + wd.flag |= 0xf000; + wd.damage = 0; + } if( map_flag_gvg2(target->m) ) wd.damage=battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); else if( map[target->m].flag.battleground ) @@ -2555,6 +2569,11 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list ad.damage = ad.damage>0?1:-1; ad.damage=battle_calc_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag); + if( ad.damage == -1 ) + { + ad.flag |= 0xf000; + ad.damage = 0; + } if( map_flag_gvg2(target->m) ) ad.damage=battle_calc_gvg_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag); else if( map[target->m].flag.battleground ) @@ -2784,6 +2803,11 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * md.damage=battle_attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); md.damage=battle_calc_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag); + if( md.damage == -1 ) + { + md.flag |= 0xf000; + md.damage = 0; + } if( map_flag_gvg2(target->m) ) md.damage=battle_calc_gvg_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag); else if( map[target->m].flag.battleground ) diff --git a/src/map/battle.h b/src/map/battle.h index 8cca3886c..951f32d8d 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -56,6 +56,7 @@ enum { // BF_WEAPONMASK=0x000f, BF_RANGEMASK= 0x00f0, BF_SKILLMASK= 0x0f00, + //0xf000 is used for marking if a zero damage is resulted from SafetyWall and the like. [Inkfish] }; int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, int skill_id, int skill_lv, int damage, enum damage_lv dmg_lv, int ddelay); diff --git a/src/map/clif.c b/src/map/clif.c index 95eddb1f4..a7b25d345 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -8129,10 +8129,9 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) if( sd->state.changemap ) {// restore information that gets lost on map-change - if( (map_flag_gvg(sd->state.pmap) && battle_config.gvg_flee_penalty != 100) || (map[sd->state.pmap].flag.battleground && battle_config.bg_flee_penalty != 100) ) + if( (battle_config.bg_flee_penalty != 100 || battle_config.gvg_flee_penalty != 100) && + (map_flag_gvg(sd->state.pmap) || map_flag_gvg(sd->bl.m) || map[sd->state.pmap].flag.battleground || map[sd->bl.m].flag.battleground) ) status_calc_bl(&sd->bl, SCB_FLEE); //Refresh flee penalty - else if( (map_flag_gvg(sd->bl.m) && battle_config.gvg_flee_penalty != 100) || (map[sd->bl.m].flag.battleground && battle_config.bg_flee_penalty != 100) ) - status_calc_bl(&sd->bl, SCB_FLEE); if( night_flag && map[sd->bl.m].flag.nightenabled ) { //Display night. diff --git a/src/map/skill.c b/src/map/skill.c index 9449c6447..2e7a8016a 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -484,6 +484,74 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int //So if the target can't be inflicted with statuses, this is pointless. return 0; + if( sd ) + { // These status will be applied anyway even if there is no actual damage. [Inkfish] + if( sd->special_state.bonus_coma && !skillid) + { + rate = sd->weapon_coma_ele[tstatus->def_ele]; + rate += sd->weapon_coma_race[tstatus->race]; + rate += sd->weapon_coma_race[tstatus->mode&MD_BOSS?RC_BOSS:RC_NONBOSS]; + if (rate) + status_change_start(bl, SC_COMA, rate, 0, 0, 0, 0, 0, 0); + } + + if( skillid != WS_CARTTERMINATION && skillid != AM_DEMONSTRATION && skillid != CR_REFLECTSHIELD && skillid != MS_REFLECTSHIELD && skillid != ASC_BREAKER ) + { // Trigger status effects + enum sc_type type; + int i; + for( i = 0; i < ARRAYLENGTH(sd->addeff) && sd->addeff[i].flag; i++ ) + { + rate = sd->addeff[i].rate; + if( attack_type&BF_LONG ) // Any ranged physical attack takes status arrows into account (Grimtooth...) [DracoRPG] + rate += sd->addeff[i].arrow_rate; + if( !rate ) continue; + + if( (sd->addeff[i].flag&(ATF_WEAPON|ATF_SKILL)) != (ATF_WEAPON|ATF_SKILL) ) + { // Trigger has attack type consideration. + if( (sd->addeff[i].flag&ATF_WEAPON && !(attack_type&BF_WEAPON)) || (sd->addeff[i].flag&ATF_SKILL && !(attack_type&(BF_MAGIC|BF_MISC))) ) + continue; + } + + if( (sd->addeff[i].flag&(ATF_LONG|ATF_SHORT)) != (ATF_LONG|ATF_SHORT) ) + { // Trigger has range consideration. + if((sd->addeff[i].flag&ATF_LONG && !(attack_type&BF_LONG)) || + (sd->addeff[i].flag&ATF_SHORT && !(attack_type&BF_SHORT))) + continue; //Range Failed. + } + + type = sd->addeff[i].id; + skill = skill_get_time2(status_sc2skill(type),7); + + if (sd->addeff[i].flag&ATF_TARGET) + status_change_start(bl,type,rate,7,0,0,0,skill,0); + + if (sd->addeff[i].flag&ATF_SELF) + status_change_start(src,type,rate,7,0,0,0,skill,0); + } + } + + if( skillid ) + { // Trigger status effects on skills + enum sc_type type; + int i; + for( i = 0; i < ARRAYLENGTH(sd->addeff3) && sd->addeff3[i].skill; i++ ) + { + if( skillid != sd->addeff3[i].skill || !sd->addeff3[i].rate ) + continue; + type = sd->addeff3[i].id; + skill = skill_get_time2(status_sc2skill(type),7); + + if( sd->addeff3[i].target&ATF_TARGET ) + status_change_start(bl,type,sd->addeff3[i].rate,7,0,0,0,skill,0); + if( sd->addeff3[i].target&ATF_SELF ) + status_change_start(src,type,sd->addeff3[i].rate,7,0,0,0,skill,0); + } + } + } + + if( attack_type&0xf000 ) // no damage, return; + return 0; + switch(skillid) { case 0: // Normal attacks (no skill used) @@ -529,14 +597,6 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int (2000 - 4*sstatus->agi - 2*sstatus->dex)); } } - - if (sd->special_state.bonus_coma) { - rate = sd->weapon_coma_ele[tstatus->def_ele]; - rate += sd->weapon_coma_race[tstatus->race]; - rate += sd->weapon_coma_race[tstatus->mode&MD_BOSS?RC_BOSS:RC_NONBOSS]; - if (rate) - status_change_start(bl, SC_COMA, rate, 0, 0, 0, 0, 0, 0); - } } if (sc) { @@ -845,59 +905,6 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int break; } - if( sd && skillid != WS_CARTTERMINATION && skillid != AM_DEMONSTRATION && skillid != CR_REFLECTSHIELD && skillid != MS_REFLECTSHIELD && skillid != ASC_BREAKER ) - { // Trigger status effects - enum sc_type type; - int i; - for( i = 0; i < ARRAYLENGTH(sd->addeff) && sd->addeff[i].flag; i++ ) - { - rate = sd->addeff[i].rate; - if( attack_type&BF_LONG ) // Any ranged physical attack takes status arrows into account (Grimtooth...) [DracoRPG] - rate += sd->addeff[i].arrow_rate; - if( !rate ) continue; - - if( (sd->addeff[i].flag&(ATF_WEAPON|ATF_SKILL)) != (ATF_WEAPON|ATF_SKILL) ) - { // Trigger has attack type consideration. - if( (sd->addeff[i].flag&ATF_WEAPON && !(attack_type&BF_WEAPON)) || (sd->addeff[i].flag&ATF_SKILL && !(attack_type&(BF_MAGIC|BF_MISC))) ) - continue; - } - - if( (sd->addeff[i].flag&(ATF_LONG|ATF_SHORT)) != (ATF_LONG|ATF_SHORT) ) - { // Trigger has range consideration. - if((sd->addeff[i].flag&ATF_LONG && !(attack_type&BF_LONG)) || - (sd->addeff[i].flag&ATF_SHORT && !(attack_type&BF_SHORT))) - continue; //Range Failed. - } - - type = sd->addeff[i].id; - skill = skill_get_time2(status_sc2skill(type),7); - - if (sd->addeff[i].flag&ATF_TARGET) - status_change_start(bl,type,rate,7,0,0,0,skill,0); - - if (sd->addeff[i].flag&ATF_SELF) - status_change_start(src,type,rate,7,0,0,0,skill,0); - } - } - - if( sd && skillid ) - { // Trigger status effects on skills - enum sc_type type; - int i; - for( i = 0; i < ARRAYLENGTH(sd->addeff3) && sd->addeff3[i].skill; i++ ) - { - if( skillid != sd->addeff3[i].skill || !sd->addeff3[i].rate ) - continue; - type = sd->addeff3[i].id; - skill = skill_get_time2(status_sc2skill(type),7); - - if( sd->addeff3[i].target&ATF_TARGET ) - status_change_start(bl,type,sd->addeff3[i].rate,7,0,0,0,skill,0); - if( sd->addeff3[i].target&ATF_SELF ) - status_change_start(src,type,sd->addeff3[i].rate,7,0,0,0,skill,0); - } - } - if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai) { //Pass heritage to Master for status causing effects. [Skotlex] sd = map_id2sd(md->master_id); @@ -1778,14 +1785,13 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds ud->attackabletime = tick + type; } - if (!dmg.amotion) { + if( !dmg.amotion ) + { //Instant damage status_fix_damage(src,bl,damage,dmg.dmotion); //Deal damage before knockback to allow stuff like firewall+storm gust combo. - if (damage > 0) { - if (!status_isdead(bl)) - skill_additional_effect(src,bl,skillid,skilllv,attack_type,tick); - //Counter status effects [Skotlex] + if( (damage > 0 || attack_type&0xf000) && !status_isdead(bl) ) + skill_additional_effect(src,bl,skillid,skilllv,attack_type,tick); + if( damage > 0 ) //Counter status effects [Skotlex] skill_counter_additional_effect(dsrc,bl,skillid,skilllv,attack_type,tick); - } } //Only knockback if it's still alive, otherwise a "ghost" is left behind. [Skotlex] -- cgit v1.2.3-70-g09d2