summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/map/map.h8
-rw-r--r--src/map/pc.c114
-rw-r--r--src/map/pc.h15
-rw-r--r--src/map/script.c50
-rw-r--r--src/map/skill.c114
-rw-r--r--src/map/status.c13
-rw-r--r--src/map/status.h5
-rw-r--r--src/map/unit.c1
8 files changed, 282 insertions, 38 deletions
diff --git a/src/map/map.h b/src/map/map.h
index f96ae8db9..519138d1c 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -307,15 +307,14 @@ enum _sp {
SP_HP_DRAIN_VALUE,SP_SP_DRAIN_VALUE, // 1079-1080
SP_WEAPON_ATK,SP_WEAPON_ATK_RATE, // 1081-1082
SP_DELAYRATE,SP_HP_DRAIN_RATE_RACE,SP_SP_DRAIN_RATE_RACE, // 1083-1085
- SP_IGNORE_MDEF_RATE,SP_IGNORE_DEF_RATE,SP_SKILL_HEAL2, //1086-1088
-
-
+ SP_IGNORE_MDEF_RATE,SP_IGNORE_DEF_RATE,SP_SKILL_HEAL2,SP_ADDEFF_ONSKILL, //1086-1089
+
SP_RESTART_FULL_RECOVER=2000,SP_NO_CASTCANCEL,SP_NO_SIZEFIX,SP_NO_MAGIC_DAMAGE,SP_NO_WEAPON_DAMAGE,SP_NO_GEMSTONE, // 2000-2005
SP_NO_CASTCANCEL2,SP_NO_MISC_DAMAGE,SP_UNBREAKABLE_WEAPON,SP_UNBREAKABLE_ARMOR, SP_UNBREAKABLE_HELM, // 2006-2010
SP_UNBREAKABLE_SHIELD, SP_LONG_ATK_RATE, // 2011-2012
SP_CRIT_ATK_RATE, SP_CRITICAL_ADDRACE, SP_NO_REGEN, SP_ADDEFF_WHENHIT, SP_AUTOSPELL_WHENHIT, // 2013-2017
- SP_SKILL_ATK, SP_UNSTRIPABLE, SP_FREE, // 2018-2020
+ SP_SKILL_ATK, SP_UNSTRIPABLE, SP_AUTOSPELL_ONSKILL, // 2018-2020
SP_SP_GAIN_VALUE, SP_HP_REGEN_RATE, SP_HP_LOSS_RATE, SP_ADDRACE2, SP_HP_GAIN_VALUE, // 2021-2025
SP_SUBSIZE, SP_HP_DRAIN_VALUE_RACE, SP_ADD_ITEM_HEAL_RATE, SP_SP_DRAIN_VALUE_RACE, SP_EXP_ADDRACE, // 2026-2030
SP_SP_GAIN_RACE, SP_SUBRACE2, SP_FREE2, // 2031-2033
@@ -323,7 +322,6 @@ enum _sp {
SP_INTRAVISION, SP_ADD_MONSTER_DROP_ITEMGROUP, SP_SP_LOSS_RATE, // 2038-2040
SP_ADD_SKILL_BLOW, SP_SP_VANISH_RATE //2041
//Before adding new bonuses, reuse the currently free slots:
- //2020 (SP_FREE) (previously SP_ADD_DAMAGE_BY_CLASS)
//2033 (SP_FREE2) (previously SP_ADDEFF_WHENHIT_SHORT)
//1050 (SP_FREE3) (previously SP_ADD_SPEED)
};
diff --git a/src/map/pc.c b/src/map/pc.c
index 7de528cac..9e0157041 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -1398,7 +1398,7 @@ int pc_disguise(struct map_session_data *sd, int class_)
return 1;
}
-int pc_autoscript_add(struct s_autoscript *scripts, int max, short rate, short flag, short target, struct script_code *script)
+int pc_autoscript_add(struct s_autoscript *scripts, int max, short rate, short flag, short target, struct script_code *script, bool onskill)
{
int i;
ARR_FIND(0, max, i, scripts[i].script == NULL);
@@ -1411,17 +1411,20 @@ int pc_autoscript_add(struct s_autoscript *scripts, int max, short rate, short f
scripts[i].script = script;
scripts[i].rate = rate;
scripts[i].target = target; // 0 = Script on Self 1 = Script on Target
- //Auto-update flag value.
- if( !(flag&BF_RANGEMASK) )
- flag|=BF_SHORT|BF_LONG; //No range defined? Use both.
- if( !(flag&BF_WEAPONMASK) )
- flag|=BF_WEAPON; //No attack type defined? Use weapon.
- if( !(flag&BF_SKILLMASK) )
- {
- if( flag&(BF_MAGIC|BF_MISC) )
- flag|=BF_SKILL; //These two would never trigger without BF_SKILL
- if( flag&BF_WEAPON )
- flag|=BF_NORMAL|BF_SKILL;
+
+ if( !onskill )
+ { // Auto-update flag value.
+ if( !(flag&BF_RANGEMASK) )
+ flag|=BF_SHORT|BF_LONG; //No range defined? Use both.
+ if( !(flag&BF_WEAPONMASK) )
+ flag|=BF_WEAPON; //No attack type defined? Use weapon.
+ if( !(flag&BF_SKILLMASK) )
+ {
+ if( flag&(BF_MAGIC|BF_MISC) )
+ flag|=BF_SKILL; //These two would never trigger without BF_SKILL
+ if( flag&BF_WEAPON )
+ flag|=BF_NORMAL|BF_SKILL;
+ }
}
scripts[i].flag = flag;
return 1;
@@ -1501,6 +1504,36 @@ static int pc_bonus_autospell(struct s_autospell *spell, int max, short id, shor
return 1;
}
+static int pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short src_skill, short id, short lv, short rate, short card_id)
+{
+ int i;
+ if( rate < 0 )
+ return pc_bonus_autospell_del(spell, max, id, lv, -rate, card_id);
+
+ for( i = 0; i < max && spell[i].id; i++ )
+ {
+ if( spell[i].flag == src_skill && spell[i].id == id && spell[i].lv == lv && spell[i].card_id == card_id )
+ {
+ if( !battle_config.autospell_stacking )
+ rate += spell[i].rate;
+ break;
+ }
+ }
+
+ if( i == max )
+ {
+ ShowWarning("pc_bonus: Reached max (%d) number of autospells per character!\n", max);
+ return 0;
+ }
+
+ spell[i].flag = src_skill;
+ spell[i].id = id;
+ spell[i].lv = lv;
+ spell[i].rate = rate;
+ spell[i].card_id = card_id;
+ return 1;
+}
+
static int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, short rate, short arrow_rate, unsigned char flag)
{
int i;
@@ -1530,6 +1563,28 @@ static int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id,
return 1;
}
+static int pc_bonus_addeff_onskill(struct s_addeffectonskill* effect, int max, enum sc_type id, short rate, short skill, unsigned char target)
+{
+ int i;
+ for( i = 0; i < max && effect[i].skill; i++ )
+ {
+ if( effect[i].id == id && effect[i].skill == skill && effect[i].target == target )
+ {
+ effect[i].rate += rate;
+ return 1;
+ }
+ }
+ if( i == max ) {
+ ShowWarning("pc_bonus: Reached max (%d) number of add effects on skill per character!\n", max);
+ return 0;
+ }
+ effect[i].id = id;
+ effect[i].rate = rate;
+ effect[i].skill = skill;
+ effect[i].target = target;
+ return 1;
+}
+
static int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id, short group, int race, int rate)
{
int i;
@@ -2673,6 +2728,15 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
pc_bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, type3, 0, val);
break;
+ case SP_ADDEFF_ONSKILL:
+ if( type3 > SC_MAX ) {
+ ShowWarning("pc_bonus3 (Add Effect on skill): %d is not supported.\n", type3);
+ break;
+ }
+ if( sd->state.lr_flag != 2 )
+ pc_bonus_addeff_onskill(sd->addeff3, ARRAYLENGTH(sd->addeff3), (sc_type)type3, val, type2, 2);
+ break;
+
default:
ShowWarning("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val);
break;
@@ -2695,6 +2759,26 @@ int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4
if(sd->state.lr_flag != 2)
pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), (val&1?type2:-type2), (val&2?-type3:type3), type4, 0, current_equip_card_id);
break;
+
+ case SP_AUTOSPELL_ONSKILL:
+ if(sd->state.lr_flag != 2)
+ {
+ int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self.
+ target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF));
+
+ pc_bonus_autospell_onskill(sd->autospell3, ARRAYLENGTH(sd->autospell3), type2, target?-type3:type3, type4, val, current_equip_card_id);
+ }
+ break;
+
+ case SP_ADDEFF_ONSKILL:
+ if( type2 > SC_MAX ) {
+ ShowWarning("pc_bonus3 (Add Effect on skill): %d is not supported.\n", type2);
+ break;
+ }
+ if( sd->state.lr_flag != 2 )
+ pc_bonus_addeff_onskill(sd->addeff3, ARRAYLENGTH(sd->addeff3), (sc_type)type3, type4, type2, val);
+ break;
+
default:
ShowWarning("pc_bonus4: unknown type %d %d %d %d %d!\n",type,type2,type3,type4,val);
break;
@@ -2717,6 +2801,12 @@ int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4
if(sd->state.lr_flag != 2)
pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, current_equip_card_id);
break;
+
+ case SP_AUTOSPELL_ONSKILL:
+ if(sd->state.lr_flag != 2)
+ pc_bonus_autospell_onskill(sd->autospell3, ARRAYLENGTH(sd->autospell3), type2, (val&1?-type3:type3), (val&2?-type4:type4), type5, current_equip_card_id);
+ break;
+
default:
ShowWarning("pc_bonus5: unknown type %d %d %d %d %d %d!\n",type,type2,type3,type4,type5,val);
break;
diff --git a/src/map/pc.h b/src/map/pc.h
index 8a100f092..deedc4d70 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -56,6 +56,12 @@ struct s_addeffect {
unsigned char flag;
};
+struct s_addeffectonskill {
+ enum sc_type id;
+ short rate, skill;
+ unsigned char target;
+};
+
struct s_add_drop {
short id, group;
int race, rate;
@@ -116,6 +122,7 @@ struct map_session_data {
bool changemap;
struct guild *gmaster_flag;
unsigned int bg_id;
+ unsigned skillonskill : 1;
} state;
struct {
unsigned char no_weapon_damage, no_magic_damage, no_misc_damage;
@@ -208,8 +215,10 @@ struct map_session_data {
short sp_gain_race[RC_MAX];
// zeroed arrays end here.
// zeroed structures start here
- struct s_autospell autospell[15], autospell2[15];
+ struct s_autospell autospell[15], autospell2[15], autospell3[15];
struct s_addeffect addeff[MAX_PC_BONUS], addeff2[MAX_PC_BONUS];
+ struct s_addeffectonskill addeff3[MAX_PC_BONUS];
+
struct { //skillatk raises bonus dmg% of skills, skillheal increases heal%, skillblown increases bonus blewcount for some skills.
unsigned short id;
short val;
@@ -229,7 +238,7 @@ struct map_session_data {
} itemhealrate[MAX_PC_BONUS];
// zeroed structures end here
// manually zeroed structures start here.
- struct s_autoscript autoscript[10], autoscript2[10]; //Auto script on attack, when attacked
+ struct s_autoscript autoscript[10], autoscript2[10], autoscript3[10]; //Auto script on attack, when attacked, on skill usage
// manually zeroed structures end here.
// zeroed vars start here.
int arrow_atk,arrow_ele,arrow_cri,arrow_hit;
@@ -556,7 +565,7 @@ bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd,
int pc_updateweightstatus(struct map_session_data *sd);
-int pc_autoscript_add(struct s_autoscript *scripts, int max, short rate, short flag, short target, struct script_code *script);
+int pc_autoscript_add(struct s_autoscript *scripts, int max, short rate, short flag, short target, struct script_code *script, bool onskill);
void pc_autoscript_clear(struct s_autoscript *scripts, int max);
int pc_bonus(struct map_session_data*,int,int);
diff --git a/src/map/script.c b/src/map/script.c
index 5c1836c97..82c8079d1 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -6519,11 +6519,13 @@ BUILDIN_FUNC(bonus)
{
case SP_AUTOSPELL:
case SP_AUTOSPELL_WHENHIT:
+ case SP_AUTOSPELL_ONSKILL:
case SP_SKILL_ATK:
case SP_SKILL_HEAL:
case SP_SKILL_HEAL2:
case SP_ADD_SKILL_BLOW:
case SP_CASTRATE:
+ case SP_ADDEFF_ONSKILL:
// these bonuses support skill names
val1 = ( script_isstring(st,3) ? skill_name2id(script_getstr(st,3)) : script_getnum(st,3) );
break;
@@ -6547,13 +6549,21 @@ BUILDIN_FUNC(bonus)
pc_bonus3(sd, type, val1, val2, val3);
break;
case 4:
- val2 = script_getnum(st,4);
+ if( type == SP_AUTOSPELL_ONSKILL && script_isstring(st,4) )
+ val2 = skill_name2id(script_getstr(st,4)); // 2nd value can be skill name
+ else
+ val2 = script_getnum(st,4);
+
val3 = script_getnum(st,5);
val4 = script_getnum(st,6);
pc_bonus4(sd, type, val1, val2, val3, val4);
break;
case 5:
- val2 = script_getnum(st,4);
+ if( type == SP_AUTOSPELL_ONSKILL && script_isstring(st,4) )
+ val2 = skill_name2id(script_getstr(st,4)); // 2nd value can be skill name
+ else
+ val2 = script_getnum(st,4);
+
val3 = script_getnum(st,5);
val4 = script_getnum(st,6);
val5 = script_getnum(st,7);
@@ -6588,7 +6598,7 @@ BUILDIN_FUNC(bonusautoscript)
script = parse_script(str, "autoscript bonus", 0, 0);
if( !script )
return 1;
- if( !pc_autoscript_add(sd->autoscript, ARRAYLENGTH(sd->autoscript), rate, flag, target, script) )
+ if( !pc_autoscript_add(sd->autoscript, ARRAYLENGTH(sd->autoscript), rate, flag, target, script, false) )
{
script_free_code(script);
return 1;
@@ -6616,13 +6626,40 @@ BUILDIN_FUNC(bonusautoscript2)
script = parse_script(str, "autoscript2 bonus", 0, 0);
if (!script)
return 1;
- if (!pc_autoscript_add(sd->autoscript2, ARRAYLENGTH(sd->autoscript2), rate, flag, target, script))
+ if (!pc_autoscript_add(sd->autoscript2, ARRAYLENGTH(sd->autoscript2), rate, flag, target, script, false))
{
script_free_code(script);
return 1;
}
return 0;
}
+/// Bonus script that has a chance of being executed when used a skill
+BUILDIN_FUNC(bonusautoscript3)
+{
+ int rate, skill, target = 0;
+ const char *str;
+ struct script_code *script;
+ TBL_PC* sd;
+
+ sd = script_rid2sd(st);
+ if( sd == NULL )
+ return 0;// no player attached, report source
+
+ str = script_getstr(st,2);
+ rate = script_getnum(st,3);
+ skill = ( script_isstring(st,4) ? skill_name2id(script_getstr(st,4)) : script_getnum(st,4) );
+ if( script_hasdata(st,5) )
+ target = script_getnum(st,5);
+ script = parse_script(str, "autoscript3 bonus", 0, 0);
+ if( !script )
+ return 1;
+ if( !pc_autoscript_add(sd->autoscript3, ARRAYLENGTH(sd->autoscript3), rate, skill, target, script, true) )
+ {
+ script_free_code(script);
+ return 1;
+ }
+ return 0;
+}
/// Changes the level of a player skill.
/// <flag> defaults to 1
@@ -13649,10 +13686,11 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(bonus,"iv"),
BUILDIN_DEF2(bonus,"bonus2","ivi"),
BUILDIN_DEF2(bonus,"bonus3","ivii"),
- BUILDIN_DEF2(bonus,"bonus4","iviii"),
- BUILDIN_DEF2(bonus,"bonus5","iviiii"),
+ BUILDIN_DEF2(bonus,"bonus4","ivvii"),
+ BUILDIN_DEF2(bonus,"bonus5","ivviii"),
BUILDIN_DEF(bonusautoscript,"si??"),
BUILDIN_DEF(bonusautoscript2,"si??"),
+ BUILDIN_DEF(bonusautoscript3,"siv?"),
BUILDIN_DEF(skill,"vi?"),
BUILDIN_DEF(addtoskill,"vi?"), // [Valaris]
BUILDIN_DEF(guildskill,"vi"),
diff --git a/src/map/skill.c b/src/map/skill.c
index 78d29cb40..61749e058 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -880,6 +880,24 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
}
}
+ 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);
@@ -887,7 +905,8 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
}
// Autospell when attacking
- if(sd && !status_isdead(bl) && src != bl && sd->autospell[0].id) {
+ if( sd && !status_isdead(bl) && src != bl && sd->autospell[0].id )
+ {
struct block_list *tbl;
struct unit_data *ud;
int i, skilllv;
@@ -980,6 +999,64 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
return 0;
}
+int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, int skillid, unsigned int tick)
+{
+ int skill, skilllv, i;
+ struct block_list *tbl;
+
+ if( sd == NULL || skillid <= 0 )
+ return 0;
+
+ sd->state.skillonskill = 1;
+ for( i = 0; i < ARRAYLENGTH(sd->autospell3) && sd->autospell3[i].flag; i++ )
+ {
+ if( sd->autospell3[i].flag != skillid )
+ continue;
+ skill = (sd->autospell3[i].id > 0) ? sd->autospell3[i].id : -sd->autospell3[i].id;
+ if( skillnotok(skill, sd) )
+ continue;
+
+ skilllv = sd->autospell3[i].lv ? sd->autospell3[i].lv : 1;
+ if( skilllv < 0 ) skilllv = 1 + rand()%(-skilllv);
+
+ if( sd->autospell3[i].id >= 0 && bl == NULL )
+ continue; // No target
+ if( rand()%1000 > sd->autospell3[i].rate )
+ continue;
+
+ if( sd->autospell3[i].id < 0 )
+ tbl = &sd->bl;
+ else
+ tbl = bl;
+
+ switch( skill_get_casttype(skill) )
+ {
+ case CAST_GROUND: skill_castend_pos2(&sd->bl, tbl->x, tbl->y, skill, skilllv, tick, 0); break;
+ case CAST_NODAMAGE: skill_castend_nodamage_id(&sd->bl, tbl, skill, skilllv, tick, 0); break;
+ case CAST_DAMAGE: skill_castend_damage_id(&sd->bl, tbl, skill, skilllv, tick, 0); break;
+ }
+ break;
+ }
+
+ if( sd->autoscript3[0].script )
+ {
+ for( i = 0; i < ARRAYLENGTH(sd->autoscript3) && sd->autoscript3[i].script; i++ )
+ {
+ if( sd->autoscript3[i].flag != skillid )
+ continue;
+ if( sd->autoscript3[i].target && bl == NULL )
+ continue;
+ if( rand()%1000 > sd->autoscript3[i].rate )
+ continue;
+ run_script(sd->autoscript3[i].script,0,sd->bl.id,0);
+ break;
+ }
+ }
+
+ sd->state.skillonskill = 0;
+ return 1;
+}
+
/* Splitted off from skill_additional_effect, which is never called when the
* attack skill kills the enemy. Place in this function counter status effects
* when using skills (eg: Asura's sp regen penalty, or counter-status effects
@@ -2888,8 +2965,14 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
map_freeblock_unlock();
- if (sd && !(flag&1) && sd->state.arrow_atk) //Consume arrow on last invocation to this skill.
- battle_consume_ammo(sd, skillid, skilllv);
+ if( sd && !(flag&1) )
+ {
+ if( sd->state.arrow_atk ) //Consume arrow on last invocation to this skill.
+ battle_consume_ammo(sd, skillid, skilllv);
+ if( !sd->state.skillonskill )
+ skill_onskillusage(sd, bl, skillid, tick);
+ }
+
return 0;
}
@@ -5408,8 +5491,13 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
mobskill_event(dstmd, src, tick, MSC_SKILLUSED|(skillid<<16));
}
- if (sd && !(flag&1) && sd->state.arrow_atk) //Consume arrow on last invocation to this skill.
- battle_consume_ammo(sd, skillid, skilllv);
+ if( sd && !(flag&1) )
+ {
+ if( sd->state.arrow_atk ) //Consume arrow on last invocation to this skill.
+ battle_consume_ammo(sd, skillid, skilllv);
+ if( !sd->state.skillonskill )
+ skill_onskillusage(sd, bl, skillid, tick);
+ }
map_freeblock_unlock();
return 0;
@@ -6182,9 +6270,15 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
if (sc && sc->data[SC_MAGICPOWER])
status_change_end(src,SC_MAGICPOWER,-1);
- if (sd && !(flag&1) && sd->state.arrow_atk) //Consume arrow if a ground skill was not invoked. [Skotlex]
- battle_consume_ammo(sd, skillid, skilllv);
-
+ if( sd )
+ {
+ if( sd->state.arrow_atk && !(flag&1) ) //Consume arrow if a ground skill was not invoked. [Skotlex]
+ battle_consume_ammo(sd, skillid, skilllv);
+
+ if( !sd->state.skillonskill )
+ skill_onskillusage(sd, NULL, skillid, tick);
+ }
+
return 0;
}
@@ -8547,8 +8641,8 @@ int skill_castfix (struct block_list *bl, int skill_id, int skill_lv)
}
}
- if( sc && sc->count && sc->data[SC_SKILLCASTRATE] && sc->data[SC_SKILLCASTRATE]->val1 == skill_id )
- time += time * sc->data[SC_SKILLCASTRATE]->val2 / 100;
+ if( sc && sc->count && sc->data[SC_SKILLCASTRATE] && (sc->data[SC_SKILLCASTRATE]->val1 == skill_id || sc->data[SC_SKILLCASTRATE]->val2 == skill_id || sc->data[SC_SKILLCASTRATE]->val3 == skill_id) )
+ time += time * sc->data[SC_SKILLCASTRATE]->val4 / 100;
// config cast time multiplier
if (battle_config.cast_rate != 100)
diff --git a/src/map/status.c b/src/map/status.c
index 10eb77053..ae0da921f 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -193,7 +193,7 @@ void initChangeTables(void)
set_sc( MG_ENERGYCOAT , SC_ENERGYCOAT , SI_ENERGYCOAT , SCB_NONE );
set_sc( NPC_EMOTION , SC_MODECHANGE , SI_BLANK , SCB_MODE );
add_sc( NPC_EMOTION_ON , SC_MODECHANGE );
- set_sc( NPC_ATTRICHANGE , SC_ELEMENTALCHANGE , SI_BLANK , SCB_DEF_ELE );
+ set_sc( NPC_ATTRICHANGE , SC_ELEMENTALCHANGE , SI_ARMOR_RESIST , SCB_DEF_ELE );
add_sc( NPC_CHANGEWATER , SC_ELEMENTALCHANGE );
add_sc( NPC_CHANGEGROUND , SC_ELEMENTALCHANGE );
add_sc( NPC_CHANGEFIRE , SC_ELEMENTALCHANGE );
@@ -529,6 +529,7 @@ void initChangeTables(void)
StatusChangeFlagTable[SC_ARMOR_RESIST] |= SCB_PC;
StatusChangeFlagTable[SC_SPCOST_RATE] |= SCB_PC;
StatusChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED;
+ StatusChangeFlagTable[SC_ITEMSCRIPT] |= SCB_PC;
// Mercenary Bonus Effects
StatusChangeFlagTable[SC_MERC_FLEEUP] |= SCB_FLEE;
StatusChangeFlagTable[SC_MERC_ATKUP] |= SCB_WATK;
@@ -1749,8 +1750,10 @@ int status_calc_pc(struct map_session_data* sd,int first)
//zero up structures...
memset(&sd->autospell,0,sizeof(sd->autospell)
+ sizeof(sd->autospell2)
+ + sizeof(sd->autospell3)
+ sizeof(sd->addeff)
+ sizeof(sd->addeff2)
+ + sizeof(sd->addeff3)
+ sizeof(sd->skillatk)
+ sizeof(sd->skillheal)
+ sizeof(sd->skillheal2)
@@ -1769,6 +1772,7 @@ int status_calc_pc(struct map_session_data* sd,int first)
// clear autoscripts...
pc_autoscript_clear(sd->autoscript, ARRAYLENGTH(sd->autoscript));
pc_autoscript_clear(sd->autoscript2, ARRAYLENGTH(sd->autoscript2));
+ pc_autoscript_clear(sd->autoscript3, ARRAYLENGTH(sd->autoscript3));
// vars zeroing. ints, shorts, chars. in that order.
memset (&sd->arrow_atk, 0,sizeof(sd->arrow_atk)
@@ -1966,6 +1970,13 @@ int status_calc_pc(struct map_session_data* sd,int first)
}
}
+ if( sc->count && sc->data[SC_ITEMSCRIPT] )
+ {
+ struct item_data *data = itemdb_exists(sc->data[SC_ITEMSCRIPT]->val1);
+ if( data && data->script )
+ run_script(data->script,0,sd->bl.id,0);
+ }
+
if( sd->pd )
{ // Pet Bonus
struct pet_data *pd = sd->pd;
diff --git a/src/map/status.h b/src/map/status.h
index d3301bd37..0ac17016f 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -309,6 +309,7 @@ typedef enum sc_type {
SC_DEFRATIOATK,
SC_HPDRAIN,
SC_SKILLATKBONUS,
+ SC_ITEMSCRIPT,
SC_MAX, //Automatically updated max, used in for's to check we are within bounds.
} sc_type;
@@ -488,7 +489,9 @@ enum si_type {
SI_INCHEALRATE = 293,
SI_HPREGEN = 294,
// 295 Sword ?
- SI_SPCOST_RATE = 300,
+ // 296 4 chars up ?
+ SI_SPCOST_RATE = 298,
+ // 300 Stars ?
SI_COMMONSC_RESIST = 301,
SI_ARMOR_RESIST = 302,
};
diff --git a/src/map/unit.c b/src/map/unit.c
index dce211fc9..194145e58 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -1932,6 +1932,7 @@ int unit_free(struct block_list *bl, int clrtype)
pc_delinvincibletimer(sd);
pc_autoscript_clear(sd->autoscript, ARRAYLENGTH(sd->autoscript));
pc_autoscript_clear(sd->autoscript2, ARRAYLENGTH(sd->autoscript2));
+ pc_autoscript_clear(sd->autoscript3, ARRAYLENGTH(sd->autoscript3));
if( sd->followtimer != -1 )
pc_stop_following(sd);