diff options
-rw-r--r-- | Changelog-Trunk.txt | 6 | ||||
-rw-r--r-- | doc/script_commands.txt | 39 | ||||
-rw-r--r-- | src/map/map.h | 6 | ||||
-rw-r--r-- | src/map/pc.c | 30 | ||||
-rw-r--r-- | src/map/pc.h | 3 | ||||
-rw-r--r-- | src/map/script.c | 57 | ||||
-rw-r--r-- | src/map/skill.c | 34 | ||||
-rw-r--r-- | src/map/status.c | 7 | ||||
-rw-r--r-- | src/map/unit.c | 4 |
9 files changed, 184 insertions, 2 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 693b380c6..48c6cc7cd 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,6 +4,12 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. 2007/10/19 + * Added bonusautoscript and bonusautoscript2. These are used to attach a + script to a player which gets executed on attack (or when attacked). This + is very similar to the autospell bonuses, except that a script is executed + instead of a spell. See doc/script_commands for indepth description and + usage. NOTE that I am unable to test ingame, and even though I proofread + the code it could have bugs. Feel free to test and report. [Skotlex] * Applied some cleanups that should correct "Infinite Endure" ending sometimes. [Skotlex] 2007/10/18 diff --git a/doc/script_commands.txt b/doc/script_commands.txt index bf9343cfe..baa73a893 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -4285,6 +4285,45 @@ kind in 'doc/item_bonus.txt'. --------------------------------------- +*bonusautoscript <script>,<rate>{,<flag>} +*bonusautoscript2 <script>,<rate>{,<flag>} + +These commands are meant to be used in item scripts. They will probably work +outside item scripts, but the bonus will not persist for long. They, as +expected, refer only to an invoking character. + +What these commands do is 'attach' a script to the player which will get +executed on attack (or when attacked in the case of bonusautoscript2). Rate is +the trigger rate of the script (1000 = 100%). The optional argument flag is +used to classify the type of attack where the script can trigger (it shares +the same flags as the bAutoSpell bonus script): + +Range criteria: + BF_SHORT: Trigger on melee attack + BF_LONG: Trigger on ranged attack + Default: BF_SHORT+BF_LONG +Attack type criteria: + BF_WEAPON: Trigger on weapon skills + BF_MAGIC: Trigger on magic skills + BF_MISC: Trigger on misc skills + Default: BF_WEAPON +Skill criteria: + BF_NORMAL: Trigger on normal attacks + BF_SKILL: Trigger on skills + default: If the attack type is BF_WEAPON (only) BF_NORMAL is used, otherwise + BF_SKILL+BF_NORMAL is used. + +In both cases, when the script triggers, the attached player will be the one +who holds the bonus. There is currently no way of knowing within this script +who was the other character (the attacker in autoscript2, or the target in +autoscript). + +//Grants a 1% chance of starting the state "all stats +10" for 10 seconds when +//using weapon or misc attacks (both melee and ranged skills). + bonusautoscript "sc_start SC_INCALLSTATUS, 10, 10000;", 10, BF_WEAPON|BF_MISC; + +--------------------------------------- + *skill <skill id>,<level>{,<flag>}; *addtoskill <skill id>,<level>{,<flag>} 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] |