From c3c4b55d56bc72a77df54990832029a3280a72d2 Mon Sep 17 00:00:00 2001 From: skotlex Date: Tue, 4 Jul 2006 16:38:36 +0000 Subject: - Added structure s_addeffect to handle status change additions. Cleaned up relevant code. It is now possible to specify ANY status change, not just the basic ones. - Added support for bonus3 bAddEff/bAddEffWhenHit as follows: bonus3 bAddEff/bAddEffWhenHit, , , . Target flag is 0: Self. 1: Enemy. 2: Both. - Added these descriptions to doc/item_bonus.txt git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@7514 54d463be-8e91-2dee-dedb-b68131a5f0ec --- Changelog-Trunk.txt | 7 +++++ doc/item_bonus.txt | 11 ++++++-- src/map/map.h | 17 ++++++++---- src/map/pc.c | 79 +++++++++++++++++++++++++++++++++++++++-------------- src/map/skill.c | 71 +++++++++++++++++++++++++++++++++-------------- src/map/status.c | 8 ++---- 6 files changed, 139 insertions(+), 54 deletions(-) diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index c496c84c5..3a66e9c95 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,6 +4,13 @@ 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. 2006/07/04 + * Added structure s_addeffect to handle status change additions. Cleaned up + relevant code. It is now possible to specify ANY status change, not just + the basic ones. NOTE that the code is proof-read, but untested! [Skotlex] + * Added support for bonus3 bAddEff/bAddEffWhenHit as follows: [Skotlex] + bonus3 bAddEff/bAddEffWhenHit, , , . + Target flag is 0: Self. 1: Enemy. 2: Both. + * Added these descriptions to doc/item_bonus.txt [Skotlex] * Added a check when joining a chat to make sure the target object is of type BL_CHAT. [Skotlex] 2006/07/03 diff --git a/doc/item_bonus.txt b/doc/item_bonus.txt index b6a947646..bcc416b85 100644 --- a/doc/item_bonus.txt +++ b/doc/item_bonus.txt @@ -147,9 +147,9 @@ bonus bDamageWhenUnequip,n; You lose n HP when the item is unequipped bonus2 bCriticalAddRace,n,r; Critical + n vs. enemies of race r r: 0=Formless, 1=Undead, 2=Brute, 3=Plant, 4=Insect, 5=Fish, 6=Demon, 7=Demi-Human, 8=Angel, 9=Dragon, 10=Boss monster, 11=Other than (normal monster) boss monster bonus2 bHPLossRate,n,x; Lose n HP every x milliseconds -bonus2 bAddEffWhenHit,n,x; n% chance to cause x state to the enemy when +bonus2 bAddEffWhenHit,e,n; n% chance to cause e state to the enemy when being hit by physical damage -bonus2 bAddEffWhenHitShort,n,x; n% chance to cause x state to the enemy when +bonus2 bAddEffWhenHitShort,e,n; n% chance to cause x state to the enemy when being hit by physical close range damage bonus2 bSkillAtk,n,x; Increase damage of skill n by x% bonus2 bAddDamageByClass,n,x; When being hit by monster of class n increase @@ -208,3 +208,10 @@ bonus3 bAddMonsterDropItemGroup,n,x,y; y% chance to get an item of group type n 0=Formless, 1=Undead, 2=Brute, 3=Plant, 4=Insect, 5=Fish, 6=Demon, 7=Demi-Human, 8=Angel, 9=Dragon, 10=Boss monster, 11=Other than (normal monster) boss monster if 'y' is negative value, then it's a part of formula chance = -y*(killed_mob_level/10)+1 + +bonus3 bAddEff,e,x,i; Adds a x/10000 chance to cause effect e on + physical attack. i signals target: + 0: Self, 1: Target, 2: Both. +bonus3 bAddEffWhenHit,e,x,i; Adds a x/10000 chance to cause effect e when + physically attacked. i signals target: + 0: Self, 1: Target, 2: Both diff --git a/src/map/map.h b/src/map/map.h index 02e4d15fa..510c97f88 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -255,6 +255,13 @@ enum { MAX_ITEMGROUP, } item_group_list; +enum { + ATF_SELF=0x01, + ATF_TARGET=0x02, + ATF_SHORT=0x04, + ATF_LONG=0x08 +} auto_trigger_flag; + struct block_list { struct block_list *next,*prev; int id; @@ -610,8 +617,6 @@ struct map_session_data { int subrace[RC_MAX]; int subrace2[RC_MAX]; int subsize[3]; - int addeff[SC_COMMON_MAX-SC_COMMON_MIN+1]; - int addeff2[SC_COMMON_MAX-SC_COMMON_MIN+1]; int reseff[SC_COMMON_MAX-SC_COMMON_MIN+1]; int weapon_coma_ele[ELE_MAX]; int weapon_coma_race[RC_MAX]; @@ -620,22 +625,22 @@ struct map_session_data { int arrow_addele[ELE_MAX]; int arrow_addrace[RC_MAX]; int arrow_addsize[3]; - int arrow_addeff[SC_COMMON_MAX-SC_COMMON_MIN+1]; - int arrow_addeff2[SC_COMMON_MAX-SC_COMMON_MIN+1]; int magic_addele[ELE_MAX]; int magic_addrace[RC_MAX]; int magic_addsize[3]; int critaddrace[RC_MAX]; int expaddrace[RC_MAX]; int itemhealrate[MAX_ITEMGROUP]; - int addeff3[SC_COMMON_MAX-SC_COMMON_MIN+1]; - short addeff3_type[SC_COMMON_MAX-SC_COMMON_MIN+1]; short sp_gain_race[RC_MAX]; // zeroed arrays end here. // zeroed structures start here struct s_autospell{ short id, lv, rate, card_id; } autospell[MAX_PC_BONUS], autospell2[MAX_PC_BONUS]; + struct s_addeffect{ + short id, rate, arrow_rate; + unsigned char flag; + } addeff[MAX_PC_BONUS], addeff2[MAX_PC_BONUS]; struct { //skillatk raises bonus dmg% of skills, skillblown increases bonus blewcount for some skills. short id, val; } skillatk[MAX_PC_BONUS], skillblown[MAX_PC_BONUS]; diff --git a/src/map/pc.c b/src/map/pc.c index bd28d6f7a..935c3b3eb 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1171,6 +1171,29 @@ static int pc_bonus_autospell(struct s_autospell *spell, int max, short id, shor return 1; } +static int pc_bonus_addeff(struct s_addeffect *effect, int max, short id, short rate, short arrow_rate, unsigned char flag) { + int i; + + for (i = 0; i < max && effect[i].id; i++) { + if (effect[i].id == id && effect[i].flag == flag) + { + effect[i].rate += rate; + effect[i].arrow_rate += rate; + return 1; + } + } + if (i == max) { + if (battle_config.error_log) + ShowWarning("pc_bonus: Reached max (%d) number of add effects per character!\n", max); + return 0; + } + effect[i].id = id; + effect[i].rate = rate; + effect[i].arrow_rate = arrow_rate; + effect[i].flag = flag; + return 1; +} + static int pc_bonus_item_drop(struct s_add_drop *drop, short *count, short id, short group, int race, int rate) { int i; //Apply config rate adjustment settings. @@ -1815,24 +1838,22 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) sd->subrace[type2]+=val; break; case SP_ADDEFF: - if (type2 < SC_COMMON_MIN || type2 > SC_COMMON_MAX) { + if (type2 > SC_MAX) { ShowWarning("pc_bonus2 (Add Effect): %d is not supported.\n", type2); break; } - if(sd->state.lr_flag != 2) - sd->addeff[type2-SC_COMMON_MIN]+=val; - else - sd->arrow_addeff[type2-SC_COMMON_MIN]+=val; + pc_bonus_addeff(sd->addeff, MAX_PC_BONUS, type2, + sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, + ATF_SHORT|ATF_LONG|ATF_TARGET); break; case SP_ADDEFF2: - if (type2 < SC_COMMON_MIN || type2 > SC_COMMON_MAX) { + if (type2 > SC_MAX) { ShowWarning("pc_bonus2 (Add Effect2): %d is not supported.\n", type2); break; } - if(sd->state.lr_flag != 2) - sd->addeff2[type2-SC_COMMON_MIN]+=val; - else - sd->arrow_addeff2[type2-SC_COMMON_MIN]+=val; + pc_bonus_addeff(sd->addeff, MAX_PC_BONUS, type2, + sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, + ATF_SHORT|ATF_LONG|ATF_SELF); break; case SP_RESEFF: if (type2 < SC_COMMON_MIN || type2 > SC_COMMON_MAX) { @@ -2040,24 +2061,22 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) sd->critaddrace[type2] += val*10; break; case SP_ADDEFF_WHENHIT: - if (type2 < SC_COMMON_MIN || type2 > SC_COMMON_MAX) { + if (type2 > SC_MAX) { ShowWarning("pc_bonus2 (Add Effect when hit): %d is not supported.\n", type2); break; } - if(sd->state.lr_flag != 2) { - sd->addeff3[type2-SC_COMMON_MIN]+=val; - sd->addeff3_type[type2-SC_COMMON_MIN]=1; - } + if(sd->state.lr_flag != 2) + pc_bonus_addeff(sd->addeff2, MAX_PC_BONUS, type2, val, 0, + ATF_SHORT|ATF_LONG|ATF_TARGET); break; case SP_ADDEFF_WHENHIT_SHORT: - if (type2 < SC_COMMON_MIN || type2 > SC_COMMON_MAX) { + if (type2 > SC_MAX) { ShowWarning("pc_bonus2 (Add Effect when hit short): %d is not supported.\n", type2); break; } - if(sd->state.lr_flag != 2) { - sd->addeff3[type2-SC_COMMON_MIN]+=val; - sd->addeff3_type[type2-SC_COMMON_MIN]=0; - } + if(sd->state.lr_flag != 2) + pc_bonus_addeff(sd->addeff2, MAX_PC_BONUS, type2, val, 0, + ATF_SHORT|ATF_TARGET); break; case SP_SKILL_ATK: for (i = 0; i < MAX_PC_BONUS && sd->skillatk[i].id != 0 && sd->skillatk[i].id != type2; i++); @@ -2251,6 +2270,26 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) pc_bonus_item_drop(sd->add_drop, &sd->add_drop_count, 0, type2, 1< SC_MAX) { + ShowWarning("pc_bonus3 (Add Effect): %d is not supported.\n", type2); + break; + } + pc_bonus_addeff(sd->addeff, MAX_PC_BONUS, type2, + sd->state.lr_flag!=2?type3:0, sd->state.lr_flag==2?type3:0, + ATF_SHORT|ATF_LONG|(val?ATF_TARGET:ATF_SELF)|(val==2?ATF_SELF:0)); + break; + + case SP_ADDEFF_WHENHIT: + if (type2 > SC_MAX) { + ShowWarning("pc_bonus3 (Add Effect when hit): %d is not supported.\n", type2); + break; + } + if(sd->state.lr_flag != 2) + pc_bonus_addeff(sd->addeff2, MAX_PC_BONUS, type2, type3, 0, + ATF_SHORT|ATF_LONG|(val?ATF_TARGET:ATF_SELF)|(val==2?ATF_SELF:0)); + break; + default: if(battle_config.error_log) ShowWarning("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val); diff --git a/src/map/skill.c b/src/map/skill.c index 6e8e0702c..cd67cceb2 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1324,14 +1324,34 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int break; } - if(sd && skillid != MC_CARTREVOLUTION && skillid != AM_DEMONSTRATION && skillid != CR_REFLECTSHIELD && attack_type&BF_WEAPON){ /* カードによる追加効果 */ + if(sd && attack_type&BF_WEAPON && + skillid != MC_CARTREVOLUTION && + skillid != AM_DEMONSTRATION && + skillid != CR_REFLECTSHIELD + ){ //Trigger status effects int i, type; - for(i=SC_COMMON_MIN;i<=SC_COMMON_MAX;i++){ - type=i-SC_COMMON_MIN; - rate = sd->addeff[type]+(sd->state.arrow_atk?sd->arrow_addeff[type]:0); - if (!rate) - continue; //Code Speedup. - status_change_start(bl,i,rate,7,0,0,0,skill_get_time2(StatusSkillChangeTable[type],7),0); + for(i=0; i < MAX_PC_BONUS && sd->addeff[i].id; i++) + { + rate = sd->addeff[i].rate; + type = sd->state.arrow_atk; //Ranged? + if (type) + rate += sd->addeff[i].arrow_rate; + if (!rate) continue; + + if (!(sd->addeff[i].flag&ATF_LONG && sd->addeff[i].flag&ATF_SHORT)) + { //Trigger has range consideration. + if ((sd->addeff[i].flag&ATF_LONG && !type) || + (sd->addeff[i].flag&ATF_SHORT && type)) + continue; //Range Failed. + } + type = sd->addeff[i].id; + skill = skill_get_time2(StatusSkillChangeTable[type],7); + + if (sd->addeff[i].flag&ATF_TARGET) + status_change_start(bl,type,rate,7,0,0,0,skill,0); + + if (sd->addeff[i].flag&ATF_SELF) + status_change_start(src,type,rate,7,0,0,0,skill,0); } } @@ -1445,24 +1465,35 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * clif_skill_nodamage(src,bl,HW_SOULDRAIN,rate,1); status_heal(src, 0, status_get_lv(bl)*(95+15*rate)/100, 2); } - - if((sd||dstsd) && skillid != MC_CARTREVOLUTION && attack_type&BF_WEAPON){ /* カードによる追加効果 */ - int i, type; - for(i=SC_COMMON_MIN;i<=SC_COMMON_MAX;i++){ - type=i-SC_COMMON_MIN; + if(dstsd && attack_type&BF_WEAPON) + { //Counter effects. + int i, type, time; + for(i=0; i < MAX_PC_BONUS && dstsd->addeff2[i].id; i++) + { + rate = dstsd->addeff2[i].rate; + type = (sd && sd->state.arrow_atk) || (status_get_range(src)>2); + if (type) + rate+=dstsd->addeff2[i].arrow_rate; + if (!rate) continue; + if (!(dstsd->addeff2[i].flag&ATF_LONG && dstsd->addeff2[i].flag&ATF_SHORT)) + { //Trigger has range consideration. + if ((dstsd->addeff2[i].flag&ATF_LONG && !type) || + (dstsd->addeff2[i].flag&ATF_SHORT && type)) + continue; //Range Failed. + } + type = dstsd->addeff2[i].id; + time = skill_get_time2(StatusSkillChangeTable[type],7); - rate = sd?(sd->addeff2[type]+(sd->state.arrow_atk?sd->arrow_addeff2[type]:0)):0; - if (rate) //Self inflicted status from attacking. - status_change_start(src,i,rate,7,0,0,0,skill_get_time2(StatusSkillChangeTable[type],7),0); - - rate = dstsd?dstsd->addeff3[type]:0; - if (rate && (dstsd->addeff3_type[type] == 1 || ((sd && sd->state.arrow_atk) || (status_get_range(src)>2)))) - status_change_start(src,i,rate,7,0,0,0,skill_get_time2(StatusSkillChangeTable[type],7),0); + if (dstsd->addeff2[i].flag&ATF_TARGET) + status_change_start(src,type,rate,7,0,0,0,time,0); + + if (dstsd->addeff2[i].flag&ATF_SELF && !status_isdead(bl)) + status_change_start(bl,type,rate,7,0,0,0,time,0); } } - + //Trigger counter-spells to retaliate against damage causing skills. [Skotlex] if(dstsd && !status_isdead(bl) && src != bl && !(skillid && skill_get_nk(skillid)&NK_NO_DAMAGE)) { diff --git a/src/map/status.c b/src/map/status.c index 07e12d548..8d7acaf93 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1504,8 +1504,6 @@ int status_calc_pc(struct map_session_data* sd,int first) + sizeof(sd->subrace) + sizeof(sd->subrace2) + sizeof(sd->subsize) - + sizeof(sd->addeff) - + sizeof(sd->addeff2) + sizeof(sd->reseff) + sizeof(sd->weapon_coma_ele) + sizeof(sd->weapon_coma_race) @@ -1514,16 +1512,12 @@ int status_calc_pc(struct map_session_data* sd,int first) + sizeof(sd->arrow_addele) + sizeof(sd->arrow_addrace) + sizeof(sd->arrow_addsize) - + sizeof(sd->arrow_addeff) - + sizeof(sd->arrow_addeff2) + sizeof(sd->magic_addele) + sizeof(sd->magic_addrace) + sizeof(sd->magic_addsize) + sizeof(sd->critaddrace) + sizeof(sd->expaddrace) + sizeof(sd->itemhealrate) - + sizeof(sd->addeff3) - + sizeof(sd->addeff3_type) + sizeof(sd->sp_gain_race) ); @@ -1552,6 +1546,8 @@ 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->addeff) + + sizeof(sd->addeff2) + sizeof(sd->skillatk) + sizeof(sd->skillblown) + sizeof(sd->add_def) -- cgit v1.2.3-70-g09d2