diff options
author | Haru <haru@dotalux.com> | 2015-05-14 20:33:05 +0200 |
---|---|---|
committer | Haru <haru@dotalux.com> | 2015-05-17 01:03:43 +0200 |
commit | 5be01dc1fe3f75e3a099f52dee2affb0c01f45a7 (patch) | |
tree | 790ad3595e895956b0ff50e41a25e9ed207356a8 /src/map | |
parent | 6f2b524a4f1349a588bd5db4526b485eda7a6d2d (diff) | |
download | hercules-5be01dc1fe3f75e3a099f52dee2affb0c01f45a7.tar.gz hercules-5be01dc1fe3f75e3a099f52dee2affb0c01f45a7.tar.bz2 hercules-5be01dc1fe3f75e3a099f52dee2affb0c01f45a7.tar.xz hercules-5be01dc1fe3f75e3a099f52dee2affb0c01f45a7.zip |
Added bonus4 variant of bAddEff to specify a duration
- When a duration value is specified, the effect will have a fixed,
non-reducible duration, as required by item scripts.
- Special thanks to Michieru
Signed-off-by: Haru <haru@dotalux.com>
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/pc.c | 49 | ||||
-rw-r--r-- | src/map/pc.h | 12 | ||||
-rw-r--r-- | src/map/skill.c | 17 |
3 files changed, 62 insertions, 16 deletions
diff --git a/src/map/pc.c b/src/map/pc.c index 0905df61b..00c09b108 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1877,7 +1877,20 @@ int pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short src_ski return 1; } -int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, short rate, short arrow_rate, unsigned char flag) +/** + * Adds an AddEff/AddEff2/AddEffWhenHit bonus to a character. + * + * @param effect Effects array to append to. + * @param max Size of the effect array. + * @param id Effect ID (@see enum sc_type). + * @param rate Trigger rate. + * @param arrow_rate Trigger rate modifier for ranged attacks (adds to the base rate). + * @param flag Trigger flags (@see enum auto_trigger_flag). + * @param duration Fixed (non-reducible) duration in ms. If 0, uses the default (reducible) duration of the given effect. + * @retval 1 on success. + * @retval 0 on failure. + */ +int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, int16 rate, int16 arrow_rate, uint8 flag, uint16 duration) { int i; if (!(flag&(ATF_SHORT|ATF_LONG))) @@ -1888,8 +1901,8 @@ int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, short flag|=ATF_WEAPON; //Default type: weapon. for (i = 0; i < max && effect[i].flag; i++) { - if (effect[i].id == id && effect[i].flag == flag) - { + // Update existing effect if any. + if (effect[i].id == id && effect[i].flag == flag && effect[i].duration == duration) { effect[i].rate += rate; effect[i].arrow_rate += arrow_rate; return 1; @@ -1903,6 +1916,7 @@ int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, short effect[i].rate = rate; effect[i].arrow_rate = arrow_rate; effect[i].flag = flag; + effect[i].duration = duration; return 1; } @@ -2814,7 +2828,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; } pc->bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, - sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, 0); + sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, 0, 0); break; case SP_ADDEFF2: if (type2 > SC_MAX) { @@ -2822,7 +2836,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; } pc->bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, - sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, ATF_SELF); + sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, ATF_SELF, 0); break; case SP_RESEFF: if (type2 < SC_COMMON_MIN || type2 > SC_COMMON_MAX) { @@ -3034,7 +3048,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; } if(sd->state.lr_flag != 2) - pc->bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, val, 0, 0); + pc->bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, val, 0, 0, 0); break; case SP_SKILL_ATK: if(sd->state.lr_flag == 2) @@ -3443,7 +3457,7 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) break; } pc->bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, - sd->state.lr_flag!=2?type3:0, sd->state.lr_flag==2?type3:0, val); + sd->state.lr_flag!=2?type3:0, sd->state.lr_flag==2?type3:0, val, 0); break; case SP_ADDEFF_WHENHIT: @@ -3452,7 +3466,7 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) break; } if(sd->state.lr_flag != 2) - pc->bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, type3, 0, val); + pc->bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, type3, 0, val, 0); break; case SP_ADDEFF_ONSKILL: @@ -3553,6 +3567,25 @@ int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4 sd->mdef_set_race[type2].value = val; break; + case SP_ADDEFF: + { + uint16 duration; + if (type2 > SC_MAX) { + ShowWarning("pc_bonus4 (Add Effect): %d is not supported.\n", type2); + break; + } + if (val < 0 || val > UINT16_MAX) { + ShowWarning("pc_bonus4 (Add Effect): invalid duration %d. Valid range: [0:%d].\n", val, UINT16_MAX); + duration = (val < 0 ? 0 : UINT16_MAX); + } else { + duration = (uint16)type4; + } + + pc->bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, + sd->state.lr_flag!=2?type3:0, sd->state.lr_flag==2?type3:0, val, duration); + } + break; + default: ShowWarning("pc_bonus4: unknown type %d %d %d %d %d!\n",type,type2,type3,type4,val); break; diff --git a/src/map/pc.h b/src/map/pc.h index 39b705b8f..867344d58 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -90,10 +90,14 @@ struct s_autospell { short id, lv, rate, card_id, flag; bool lock; // bAutoSpellOnSkill: blocks autospell from triggering again, while being executed }; +/// AddEff bonus data struct s_addeffect { - enum sc_type id; - short rate, arrow_rate; - unsigned char flag; + enum sc_type id; ///< Effect ID + int16 rate; ///< Base success rate + int16 arrow_rate; ///< Success rate modifier for ranged attacks (adds to the base rate) + uint8 flag; ///< Trigger flag (@see enum auto_trigger_flag) + uint16 duration; ///< Optional, non-reducible duration in ms. If 0, the default, reducible effect's duration is used. + // TODO[Haru]: Duration is only used in addeff (set through bonus4 bAddEff). The other addeffect types could also use it. }; struct s_addeffectonskill { enum sc_type id; @@ -990,7 +994,7 @@ struct pc_interface { void (*check_skilltree) (struct map_session_data *sd, int skill_id); int (*bonus_autospell) (struct s_autospell *spell, int max, short id, short lv, short rate, short flag, short card_id); int (*bonus_autospell_onskill) (struct s_autospell *spell, int max, short src_skill, short id, short lv, short rate, short card_id); - int (*bonus_addeff) (struct s_addeffect* effect, int max, enum sc_type id, short rate, short arrow_rate, unsigned char flag); + int (*bonus_addeff) (struct s_addeffect* effect, int max, enum sc_type id, int16 rate, int16 arrow_rate, uint8 flag, uint16 duration); int (*bonus_addeff_onskill) (struct s_addeffectonskill* effect, int max, enum sc_type id, short rate, short skill_id, unsigned char target); int (*bonus_item_drop) (struct s_add_drop *drop, const short max, short id, short group, int race, int rate); void (*calcexp) (struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src); diff --git a/src/map/skill.c b/src/map/skill.c index fa1dd44cb..64b0cebe8 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -671,7 +671,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 if( skill_id != WS_CARTTERMINATION && skill_id != AM_DEMONSTRATION && skill_id != CR_REFLECTSHIELD && skill_id != MS_REFLECTSHIELD && skill_id != ASC_BREAKER ) { // Trigger status effects enum sc_type type; - int i; + int i, flag; 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] @@ -695,13 +695,22 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 } type = sd->addeff[i].id; - temp = skill->get_time2(status->sc2skill(type),7); + + if (sd->addeff[i].duration > 0) { + // Fixed duration + temp = sd->addeff[i].duration; + flag = SCFLAG_NOAVOID; + } else { + // Default duration + temp = skill->get_time2(status->sc2skill(type),7); + flag = SCFLAG_NONE; + } if (sd->addeff[i].flag&ATF_TARGET) - status->change_start(src,bl,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,SCFLAG_NONE); + status->change_start(src,bl,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,flag); if (sd->addeff[i].flag&ATF_SELF) - status->change_start(src,src,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,SCFLAG_NONE); + status->change_start(src,src,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,flag); } } |