summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/pc.c49
-rw-r--r--src/map/pc.h12
-rw-r--r--src/map/skill.c17
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);
}
}