From 9a83b5ad626f8bfd4011277173e8bf385e4971fe Mon Sep 17 00:00:00 2001 From: skotlex Date: Fri, 19 Oct 2007 20:31:57 +0000 Subject: - Added bonusautoscript and bonusautoscript2. These are used to attach a script to a player which gets executed on attack (or when attacked). Required for several of the more recent items. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@11519 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/map.h | 6 ++++++ src/map/pc.c | 30 +++++++++++++++++++++++++++++ src/map/pc.h | 3 +++ src/map/script.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/map/skill.c | 34 +++++++++++++++++++++++++++++++++ src/map/status.c | 7 +++++-- src/map/unit.c | 4 ++++ 7 files changed, 139 insertions(+), 2 deletions(-) (limited to 'src/map') 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. /// defaults to 1 /// =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] -- cgit v1.2.3-60-g2f50