summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/map/map.h6
-rw-r--r--src/map/pc.c30
-rw-r--r--src/map/pc.h3
-rw-r--r--src/map/script.c57
-rw-r--r--src/map/skill.c34
-rw-r--r--src/map/status.c7
-rw-r--r--src/map/unit.c4
7 files changed, 139 insertions, 2 deletions
diff --git a/src/map/map.h b/src/map/map.h
index 6eb92530e..95c1d120d 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -692,6 +692,12 @@ struct map_session_data {
int rate;
} itemhealrate[MAX_PC_BONUS];
// zeroed structures end here
+ // manually zeroed structures start here.
+ struct s_autoscript {
+ unsigned short rate, flag;
+ struct script_code *script;
+ } autoscript[5], autoscript2[5]; //Auto script on attack, when attacked
+ // manually zeroed structures end here.
// zeroed vars start here.
int arrow_atk,arrow_ele,arrow_cri,arrow_hit;
int nsshealhp,nsshealsp;
diff --git a/src/map/pc.c b/src/map/pc.c
index f039f8318..733f31d0a 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -1219,6 +1219,36 @@ 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, struct script_code *script)
+{
+ int i;
+ ARR_FIND(0, max, i, scripts[i].script == NULL);
+ if (i == max) {
+ if (battle_config.error_log)
+ ShowWarning("pc_autoscript_bonus: Reached max (%d) number of autoscripts per character!\n", max);
+ return 0;
+ }
+ scripts[i].script = script;
+ scripts[i].rate = rate;
+ //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;
+ }
+ scripts[i].flag = flag;
+ return 1;
+}
+
+void pc_autoscript_clear(struct s_autoscript *scripts, int max)
+{
+ int i;
+ for (i = 0; i < max && scripts[i].script; i++)
+ script_free_code(scripts[i].script);
+ memset(scripts, 0, i*sizeof(struct s_autoscript));
+}
+
static int pc_bonus_autospell_del(struct s_autospell *spell, int max, short id, short lv, short rate, short card_id)
{
int i, j;
diff --git a/src/map/pc.h b/src/map/pc.h
index 0d3b4d8d4..442c9e188 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -167,6 +167,9 @@ int pc_dropitem(struct map_session_data*,int,int);
int pc_updateweightstatus(struct map_session_data *sd);
+int pc_autoscript_add(struct s_autoscript *scripts, int max, short rate, short flag, struct script_code *script);
+void pc_autoscript_clear(struct s_autoscript *scripts, int max);
+
int pc_bonus(struct map_session_data*,int,int);
int pc_bonus2(struct map_session_data *sd,int,int,int);
int pc_bonus3(struct map_session_data *sd,int,int,int,int);
diff --git a/src/map/script.c b/src/map/script.c
index 458f57fb3..e1e3a02cf 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -3802,6 +3802,8 @@ BUILDIN_FUNC(bonus2);
BUILDIN_FUNC(bonus3);
BUILDIN_FUNC(bonus4);
BUILDIN_FUNC(bonus5);
+BUILDIN_FUNC(bonusautoscript);
+BUILDIN_FUNC(bonusautoscript2);
BUILDIN_FUNC(skill);
BUILDIN_FUNC(addtoskill); // [Valaris]
BUILDIN_FUNC(guildskill);
@@ -4134,6 +4136,8 @@ struct script_function buildin_func[] = {
BUILDIN_DEF2(bonus,"bonus3","iiii"),
BUILDIN_DEF2(bonus,"bonus4","iiiii"),
BUILDIN_DEF2(bonus,"bonus5","iiiiii"),
+ BUILDIN_DEF(bonusautoscript,"si?"),
+ BUILDIN_DEF(bonusautoscript2,"si?"),
BUILDIN_DEF(skill,"ii?"),
BUILDIN_DEF(addtoskill,"ii?"), // [Valaris]
BUILDIN_DEF(guildskill,"ii"),
@@ -7192,6 +7196,59 @@ BUILDIN_FUNC(bonus)
return 0;
}
+/// Bonus script that has a chance of being executed on attack.
+BUILDIN_FUNC(bonusautoscript)
+{
+ int rate, flag = 0;
+ const char *str;
+ struct script_code *script;
+ TBL_PC* sd;
+
+ sd = script_rid2sd(st);
+ if( sd == NULL )
+ return 1;// no player attached, report source
+
+ str = script_getstr(st,2);
+ rate = script_getnum(st,3);
+ if( script_hasdata(st,4) )
+ flag = script_getnum(st,4);
+ script = parse_script(str, "autoscript bonus", 0, 0);
+ if (!script)
+ return 1;
+ if (!pc_autoscript_add(sd->autoscript, ARRAYLENGTH(sd->autoscript), rate, flag, script))
+ {
+ script_free_code(script);
+ return 1;
+ }
+ return 0;
+}
+/// Bonus script that has a chance of being executed when attacked.
+BUILDIN_FUNC(bonusautoscript2)
+{
+ int rate, flag = 0;
+ const char *str;
+ struct script_code *script;
+ TBL_PC* sd;
+
+ sd = script_rid2sd(st);
+ if( sd == NULL )
+ return 1;// no player attached, report source
+
+ str = script_getstr(st,2);
+ rate = script_getnum(st,3);
+ if( script_hasdata(st,4) )
+ flag = script_getnum(st,4);
+ script = parse_script(str, "autoscript2 bonus", 0, 0);
+ if (!script)
+ return 1;
+ if (!pc_autoscript_add(sd->autoscript2, ARRAYLENGTH(sd->autoscript2), rate, flag, script))
+ {
+ script_free_code(script);
+ return 1;
+ }
+ return 0;
+}
+
/// Changes the level of a player skill.
/// <flag> defaults to 1
/// <flag>=0 : set the level of the skill
diff --git a/src/map/skill.c b/src/map/skill.c
index 2db05ed82..ab9368820 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -1508,6 +1508,22 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
}
}
+ //Auto-script when attacking
+ if(sd && src != bl && sd->autoscript[0].script) {
+ int i;
+ for (i = 0; i < ARRAYLENGTH(sd->autoscript) && sd->autoscript[i].script; i++) {
+
+ if(!(sd->autoscript[i].flag&attack_type&BF_WEAPONMASK &&
+ sd->autoscript[i].flag&attack_type&BF_RANGEMASK &&
+ sd->autoscript[i].flag&attack_type&BF_SKILLMASK))
+ continue; // one or more trigger conditions were not fulfilled
+ if (rand()%1000 > sd->autoscript[i].rate)
+ continue;
+ run_script(sd->autoscript[i].script,0,sd->bl.id,0);
+ break; //Have only one script execute at a time.
+ }
+ }
+
//Polymorph
if(sd && sd->classchange && attack_type&BF_WEAPON &&
dstmd && !(tstatus->mode&MD_BOSS) &&
@@ -1683,6 +1699,24 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
break; //trigger only one auto-spell per hit.
}
}
+ //Auto-script when attacked
+ if(dstsd && !status_isdead(bl) && src != bl && dstsd->autoscript2[0].script &&
+ !(skillid && skill_get_nk(skillid)&NK_NO_DAMAGE))
+ {
+ int i;
+ for (i = 0; i < ARRAYLENGTH(dstsd->autoscript2) && dstsd->autoscript2[i].script; i++) {
+
+ if(!(dstsd->autoscript2[i].flag&attack_type&BF_WEAPONMASK &&
+ dstsd->autoscript2[i].flag&attack_type&BF_RANGEMASK &&
+ dstsd->autoscript2[i].flag&attack_type&BF_SKILLMASK))
+ continue; // one or more trigger conditions were not fulfilled
+ if (rand()%1000 > dstsd->autoscript2[i].rate)
+ continue;
+ run_script(dstsd->autoscript2[i].script,0,dstsd->bl.id,0);
+ break; //Have only one script execute at a time.
+ }
+ }
+
return 0;
}
/*=========================================================================
diff --git a/src/map/status.c b/src/map/status.c
index 7148005c9..a8e360469 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -1642,7 +1642,7 @@ int status_calc_pc(struct map_session_data* sd,int first)
sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100;
sd->regen.state.block = 0;
- // zeroed arays, order follows the order in map.h.
+ // zeroed arrays, order follows the order in map.h.
// add new arrays to the end of zeroed area in map.h (see comments) and size here. [zzo]
memset (sd->param_bonus, 0, sizeof(sd->param_bonus)
+ sizeof(sd->param_equip)
@@ -1715,7 +1715,10 @@ int status_calc_pc(struct map_session_data* sd,int first)
+ sizeof(sd->add_drop)
+ sizeof(sd->itemhealrate)
);
-
+ // clear autoscripts...
+ pc_autoscript_clear(sd->autoscript, ARRAYLENGTH(sd->autoscript));
+ pc_autoscript_clear(sd->autoscript2, ARRAYLENGTH(sd->autoscript2));
+
// vars zeroing. ints, shorts, chars. in that order.
memset (&sd->arrow_atk, 0,sizeof(sd->arrow_atk)
+ sizeof(sd->arrow_ele)
diff --git a/src/map/unit.c b/src/map/unit.c
index 616781b7a..709886e76 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -1805,6 +1805,10 @@ int unit_free(struct block_list *bl, int clrtype)
status_change_end(bl,SC_STEELBODY,-1);
}
}
+
+ pc_autoscript_clear(sd->autoscript, ARRAYLENGTH(sd->autoscript));
+ pc_autoscript_clear(sd->autoscript2, ARRAYLENGTH(sd->autoscript2));
+
if (sd->followtimer != -1)
pc_stop_following(sd);
// Force exiting from duel and rejecting all duel invitations when player quit [LuzZza]