diff options
author | zephyrus <zephyrus@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2009-01-25 19:50:02 +0000 |
---|---|---|
committer | zephyrus <zephyrus@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2009-01-25 19:50:02 +0000 |
commit | 922f62e89a8b3dae0f7e407fae044299988b9ece (patch) | |
tree | 08d5ac0db76899cd696d938b90ed26ab4deff209 /src | |
parent | 5601d184cad4fb9b4ed6c51e15305e5800b30718 (diff) | |
download | hercules-922f62e89a8b3dae0f7e407fae044299988b9ece.tar.gz hercules-922f62e89a8b3dae0f7e407fae044299988b9ece.tar.bz2 hercules-922f62e89a8b3dae0f7e407fae044299988b9ece.tar.xz hercules-922f62e89a8b3dae0f7e407fae044299988b9ece.zip |
- Implemented new item bonus scripts required for battlegrounds.
- Battlegrounds items rewards for Tierra Valley and Flavius done (but autoscript rate is suggested - 5%).
- Restricted trade/storage/drop for those items.
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@13490 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src')
-rw-r--r-- | src/map/battle.c | 132 | ||||
-rw-r--r-- | src/map/map.h | 4 | ||||
-rw-r--r-- | src/map/pc.c | 81 | ||||
-rw-r--r-- | src/map/pc.h | 7 | ||||
-rw-r--r-- | src/map/script.c | 19 | ||||
-rw-r--r-- | src/map/skill.c | 123 | ||||
-rw-r--r-- | src/map/status.c | 34 | ||||
-rw-r--r-- | src/map/status.h | 4 |
8 files changed, 267 insertions, 137 deletions
diff --git a/src/map/battle.c b/src/map/battle.c index 01f4c9b67..381dcd67e 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -1658,26 +1658,24 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo break; } - if(sd) + if( sd ) { if (skill_num && (i = pc_skillatk_bonus(sd, skill_num))) ATK_ADDRATE(i); - if(skill_num != PA_SACRIFICE && skill_num != MO_INVESTIGATE && - skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS && - skill_num != PA_SHIELDCHAIN - && !flag.cri) - { //Elemental/Racial adjustments - if(sd->right_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) || + if( skill_num != PA_SACRIFICE && skill_num != MO_INVESTIGATE && skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS && skill_num != PA_SHIELDCHAIN && !flag.cri ) + { //Elemental/Racial adjustments + if( sd->right_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) || sd->right_weapon.def_ratio_atk_race & (1<<tstatus->race) || sd->right_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS)) ) flag.pdef = 1; - if(sd->left_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) || + if( sd->left_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) || sd->left_weapon.def_ratio_atk_race & (1<<tstatus->race) || sd->left_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS)) - ) { //Pass effect onto right hand if configured so. [Skotlex] + ) + { //Pass effect onto right hand if configured so. [Skotlex] if (battle_config.left_cardfix_to_right && flag.rh) flag.pdef = 1; else @@ -1707,6 +1705,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo } } + if( sc && sc->count && sc->data[SC_DEFRATIOATK] && skill_num != PA_SACRIFICE && skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS && skill_num != PA_SHIELDCHAIN && !flag.cri ) + flag.pdef = flag.pdef2 = sc->data[SC_DEFRATIOATK]->val1; // Occult Impact Effect + if (!flag.idef || !flag.idef2) { //Defense reduction short vit_def; @@ -1875,7 +1876,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo } //Card Fix, sd side - if ((wd.damage || wd.damage2) && !(nk&NK_NO_CARDFIX_ATK)) + if( (wd.damage || wd.damage2) && !(nk&NK_NO_CARDFIX_ATK) ) { int cardfix = 1000, cardfix_ = 1000; int t_race2 = status_get_race2(target); @@ -1887,8 +1888,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->arrow_addsize[tstatus->size])/100; cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100; cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->arrow_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; - } else { //Melee attack - if(!battle_config.left_cardfix_to_right) + if( tstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->arrow_addrace[RC_NONDEMIHUMAN])/100; + } + else + { // Melee attack + if( !battle_config.left_cardfix_to_right ) { cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100; if (!(nk&NK_NO_ELEFIX)) @@ -1896,8 +1901,10 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size])/100; cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100; cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + if( tstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN])/100; - if (flag.lh) + if( flag.lh ) { cardfix_=cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100; if (!(nk&NK_NO_ELEFIX)) @@ -1905,51 +1912,60 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo cardfix_=cardfix_*(100+sd->left_weapon.addsize[tstatus->size])/100; cardfix_=cardfix_*(100+sd->left_weapon.addrace2[t_race2])/100; cardfix_=cardfix_*(100+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + if( tstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100; } - } else { + } + else + { cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->left_weapon.addrace[tstatus->race])/100; cardfix=cardfix*(100+sd->right_weapon.addele[tstatus->def_ele]+sd->left_weapon.addele[tstatus->def_ele])/100; cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->left_weapon.addsize[tstatus->size])/100; cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2]+sd->left_weapon.addrace2[t_race2])/100; cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + if( tstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100; } } - for(i=0;i<ARRAYLENGTH(sd->right_weapon.add_dmg) && sd->right_weapon.add_dmg[i].rate;i++) { - if(sd->right_weapon.add_dmg[i].class_ == t_class) { + for( i = 0; i < ARRAYLENGTH(sd->right_weapon.add_dmg) && sd->right_weapon.add_dmg[i].rate; i++ ) + { + if( sd->right_weapon.add_dmg[i].class_ == t_class ) + { cardfix=cardfix*(100+sd->right_weapon.add_dmg[i].rate)/100; break; } } - if (flag.lh) + if( flag.lh ) { - for(i=0;i<ARRAYLENGTH(sd->left_weapon.add_dmg) && sd->left_weapon.add_dmg[i].rate;i++) { - if(sd->left_weapon.add_dmg[i].class_ == t_class) { + for( i = 0; i < ARRAYLENGTH(sd->left_weapon.add_dmg) && sd->left_weapon.add_dmg[i].rate; i++ ) + { + if( sd->left_weapon.add_dmg[i].class_ == t_class ) + { cardfix_=cardfix_*(100+sd->left_weapon.add_dmg[i].rate)/100; break; } } } - if(wd.flag&BF_LONG) + if( wd.flag&BF_LONG ) cardfix=cardfix*(100+sd->long_attack_atk_rate)/100; - if (cardfix != 1000 || cardfix_ != 1000) + if( cardfix != 1000 || cardfix_ != 1000 ) ATK_RATE2(cardfix/10, cardfix_/10); //What happens if you use right-to-left and there's no right weapon, only left? } - if (skill_num == CR_SHIELDBOOMERANG || skill_num == PA_SHIELDCHAIN) { //Refine bonus applies after cards and elements. + if( skill_num == CR_SHIELDBOOMERANG || skill_num == PA_SHIELDCHAIN ) + { //Refine bonus applies after cards and elements. short index= sd->equip_index[EQI_HAND_L]; - if (index >= 0 && - sd->inventory_data[index] && - sd->inventory_data[index]->type == IT_ARMOR) + if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR ) ATK_ADD(10*sd->status.inventory[index].refine); } } //if (sd) //Card Fix, tsd sid - if (tsd && !(nk&NK_NO_CARDFIX_DEF)) + if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) { short s_race2,s_class; short cardfix=1000; @@ -1957,24 +1973,29 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo s_race2 = status_get_race2(src); s_class = status_get_class(src); - if (!(nk&NK_NO_ELEFIX)) + if( !(nk&NK_NO_ELEFIX) ) { cardfix=cardfix*(100-tsd->subele[s_ele])/100; - if (flag.lh && s_ele_ != s_ele) + if( flag.lh && s_ele_ != s_ele ) cardfix=cardfix*(100-tsd->subele[s_ele_])/100; } cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; - for(i=0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++) { - if(tsd->add_def[i].class_ == s_class) { + if( sstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; + + for( i = 0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++ ) + { + if( tsd->add_def[i].class_ == s_class ) + { cardfix=cardfix*(100-tsd->add_def[i].rate)/100; break; } } - if(wd.flag&BF_SHORT) + if( wd.flag&BF_SHORT ) cardfix=cardfix*(100-tsd->near_attack_def_rate)/100; else // BF_LONG (there's no other choice) cardfix=cardfix*(100-tsd->long_attack_def_rate)/100; @@ -1982,17 +2003,17 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo if( tsd->sc.data[SC_DEF_RATE] ) cardfix=cardfix*(100-tsd->sc.data[SC_DEF_RATE]->val1)/100; - if (cardfix != 1000) + if( cardfix != 1000 ) ATK_RATE(cardfix/10); } - if(flag.infdef) + if( flag.infdef ) { //Plants receive 1 damage when hit - if (flag.rh && (flag.hit || wd.damage>0)) + if( flag.rh && (flag.hit || wd.damage>0) ) wd.damage = 1; - if (flag.lh && (flag.hit || wd.damage2>0)) + if( flag.lh && (flag.hit || wd.damage2>0) ) wd.damage2 = 1; - if (!(battle_config.skill_min_damage&1)) + if( !(battle_config.skill_min_damage&1) ) //Do not return if you are supposed to deal greater damage to plants than 1. [Skotlex] return wd; } @@ -2430,9 +2451,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list MATK_RATE(cardfix/10); } - if (tsd && !(nk&NK_NO_CARDFIX_DEF)) - { //Target cards. - short s_race2=status_get_race2(src); + if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) + { // Target cards. + short s_race2 = status_get_race2(src); short s_class= status_get_class(src); int cardfix=1000; @@ -2442,6 +2463,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; + if( sstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; + for(i=0; i < ARRAYLENGTH(tsd->add_mdef) && tsd->add_mdef[i].rate;i++) { if(tsd->add_mdef[i].class_ == s_class) { cardfix=cardfix*(100-tsd->add_mdef[i].rate)/100; @@ -2662,7 +2686,8 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * } } - if(md.damage && tsd && !(nk&NK_NO_CARDFIX_DEF)){ + if( md.damage && tsd && !(nk&NK_NO_CARDFIX_DEF) ) + { int cardfix = 10000; int race2 = status_get_race2(src); if (!(nk&NK_NO_ELEFIX)) @@ -2671,6 +2696,9 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * cardfix=cardfix*(100-tsd->subrace2[race2])/100; cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; + if( sstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; + cardfix=cardfix*(100-tsd->misc_def_rate)/100; if(md.flag&BF_SHORT) cardfix=cardfix*(100-tsd->near_attack_def_rate)/100; @@ -3104,7 +3132,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f s_bl = src; switch( target->type ) - { //Checks on actual target + { // Checks on actual target case BL_PC: if (((TBL_PC*)target)->invincible_timer != -1 || pc_isinvisible((TBL_PC*)target)) return -1; //Cannot be targeted yet. @@ -3267,24 +3295,26 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f break; } - if ((flag&BCT_ALL) == BCT_ALL) { //All actually stands for all attackable chars - if (target->type&BL_CHAR) + if( (flag&BCT_ALL) == BCT_ALL ) + { //All actually stands for all attackable chars + if( target->type&BL_CHAR ) return 1; else return -1; - } else - if (flag == BCT_NOONE) //Why would someone use this? no clue. + } + else if( flag == BCT_NOONE ) //Why would someone use this? no clue. return -1; - if (t_bl == s_bl) - { //No need for further testing. + if( t_bl == s_bl ) + { //No need for further testing. state |= BCT_SELF|BCT_PARTY|BCT_GUILD; - if (state&BCT_ENEMY && strip_enemy) + if( state&BCT_ENEMY && strip_enemy ) state&=~BCT_ENEMY; return (flag&state)?1:-1; } - if (map_flag_vs(m)) { //Check rivalry settings. + if( map_flag_vs(m) ) + { //Check rivalry settings. if (flag&(BCT_PARTY|BCT_ENEMY)) { int s_party = status_get_party_id(s_bl); if ( @@ -3331,10 +3361,10 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f } } - if (!state) //If not an enemy, nor a guild, nor party, nor yourself, it's neutral. + if( !state ) //If not an enemy, nor a guild, nor party, nor yourself, it's neutral. state = BCT_NEUTRAL; //Alliance state takes precedence over enemy one. - else if (state&BCT_ENEMY && strip_enemy && state&(BCT_SELF|BCT_PARTY|BCT_GUILD)) + else if( state&BCT_ENEMY && strip_enemy && state&(BCT_SELF|BCT_PARTY|BCT_GUILD) ) state&=~BCT_ENEMY; return (flag&state)?1:-1; diff --git a/src/map/map.h b/src/map/map.h index 1504c773f..a401214c8 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -199,6 +199,7 @@ enum { RC_DRAGON, RC_BOSS, RC_NONBOSS, + RC_NONDEMIHUMAN, RC_MAX }; @@ -305,7 +306,8 @@ 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, //1086-1087 + SP_IGNORE_MDEF_RATE,SP_IGNORE_DEF_RATE,SP_SKILL_HEAL2, //1086-1088 + 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 diff --git a/src/map/pc.c b/src/map/pc.c index 08b511fc7..f094eafce 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1395,22 +1395,30 @@ 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 pc_autoscript_add(struct s_autoscript *scripts, int max, short rate, short flag, short target, struct script_code *script) { int i; ARR_FIND(0, max, i, scripts[i].script == NULL); - if (i == max) { + if( i == max ) + { ShowWarning("pc_autoscript_bonus: Reached max (%d) number of autoscripts per character!\n", max); return 0; } + 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; + 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; @@ -2408,7 +2416,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; ARR_FIND(0, ARRAYLENGTH(sd->skillheal), i, sd->skillheal[i].id == 0 || sd->skillheal[i].id == type2); if (i == ARRAYLENGTH(sd->skillheal)) - { //Better mention this so the array length can be updated. [Skotlex] + { // Better mention this so the array length can be updated. [Skotlex] ShowDebug("run_script: bonus2 bSkillHeal reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillheal), type2, val); break; } @@ -2419,6 +2427,22 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) sd->skillheal[i].val = val; } break; + case SP_SKILL_HEAL2: + if(sd->state.lr_flag == 2) + break; + ARR_FIND(0, ARRAYLENGTH(sd->skillheal2), i, sd->skillheal2[i].id == 0 || sd->skillheal2[i].id == type2); + if (i == ARRAYLENGTH(sd->skillheal2)) + { // Better mention this so the array length can be updated. [Skotlex] + ShowDebug("run_script: bonus2 bSkillHeal2 reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillheal2), type2, val); + break; + } + if (sd->skillheal2[i].id == type2) + sd->skillheal2[i].val += val; + else { + sd->skillheal2[i].id = type2; + sd->skillheal2[i].val = val; + } + break; case SP_ADD_SKILL_BLOW: if(sd->state.lr_flag == 2) break; @@ -5081,24 +5105,41 @@ int pc_resethate(struct map_session_data* sd) int pc_skillatk_bonus(struct map_session_data *sd, int skill_num) { - int i; - for (i = 0; i < ARRAYLENGTH(sd->skillatk) && sd->skillatk[i].id; i++) + int i, bonus = 0; + ARR_FIND(0, ARRAYLENGTH(sd->skillatk), i, sd->skillatk[i].id && sd->skillatk[i].id == skill_num); + if( i < ARRAYLENGTH(sd->skillatk) && sd->skillatk[i].id ) + bonus = sd->skillatk[i].val; + if( sd->sc.data[SC_SKILLATKBONUS] ) { - if (sd->skillatk[i].id == skill_num) - return sd->skillatk[i].val; + if( sd->sc.data[SC_SKILLATKBONUS]->val1 && sd->sc.data[SC_SKILLATKBONUS]->val1 == skill_num ) + bonus += sd->sc.data[SC_SKILLATKBONUS]->val4; + if( sd->sc.data[SC_SKILLATKBONUS]->val2 && sd->sc.data[SC_SKILLATKBONUS]->val2 == skill_num ) + bonus += sd->sc.data[SC_SKILLATKBONUS]->val4; + if( sd->sc.data[SC_SKILLATKBONUS]->val3 && sd->sc.data[SC_SKILLATKBONUS]->val3 == skill_num ) + bonus += sd->sc.data[SC_SKILLATKBONUS]->val4; } - return 0; + + return bonus; } int pc_skillheal_bonus(struct map_session_data *sd, int skill_num) { - int i; - for (i = 0; i < ARRAYLENGTH(sd->skillheal) && sd->skillheal[i].id; i++) - { - if (sd->skillheal[i].id == skill_num) - return sd->skillheal[i].val; - } - return 0; + int i, bonus = 0; + + ARR_FIND(0, ARRAYLENGTH(sd->skillheal), i, sd->skillheal[i].id == skill_num); + if( i < ARRAYLENGTH(sd->skillheal) ) bonus += sd->skillheal[i].val; + + return bonus; +} + +int pc_skillheal2_bonus(struct map_session_data *sd, int skill_num) +{ + int i, bonus = 0; + + ARR_FIND(0, ARRAYLENGTH(sd->skillheal2), i, sd->skillheal2[i].id == skill_num); + if( i < ARRAYLENGTH(sd->skillheal2) ) bonus += sd->skillheal2[i].val; + + return bonus; } void pc_respawn(struct map_session_data* sd, uint8 clrtype) diff --git a/src/map/pc.h b/src/map/pc.h index 87ecd3279..a22f0c5ad 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -62,7 +62,7 @@ struct s_add_drop { }; struct s_autoscript { - unsigned short rate, flag; + unsigned short rate, flag, target; struct script_code *script; }; @@ -212,7 +212,7 @@ struct map_session_data { struct { //skillatk raises bonus dmg% of skills, skillheal increases heal%, skillblown increases bonus blewcount for some skills. unsigned short id; short val; - } skillatk[MAX_PC_BONUS], skillheal[5], skillblown[MAX_PC_BONUS], skillcast[MAX_PC_BONUS]; + } skillatk[MAX_PC_BONUS], skillheal[5], skillheal2[5], skillblown[MAX_PC_BONUS], skillcast[MAX_PC_BONUS]; struct { short value; int rate; @@ -555,7 +555,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, struct script_code *script); +int pc_autoscript_add(struct s_autoscript *scripts, int max, short rate, short flag, short target, struct script_code *script); void pc_autoscript_clear(struct s_autoscript *scripts, int max); int pc_bonus(struct map_session_data*,int,int); @@ -602,6 +602,7 @@ int pc_useitem(struct map_session_data*,int); int pc_skillatk_bonus(struct map_session_data *sd, int skill_num); int pc_skillheal_bonus(struct map_session_data *sd, int skill_num); +int pc_skillheal2_bonus(struct map_session_data *sd, int skill_num); void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int hp, unsigned int sp); int pc_dead(struct map_session_data *sd,struct block_list *src); diff --git a/src/map/script.c b/src/map/script.c index 4dadb2775..5ce0c3409 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -6487,6 +6487,7 @@ BUILDIN_FUNC(bonus) case SP_AUTOSPELL_WHENHIT: case SP_SKILL_ATK: case SP_SKILL_HEAL: + case SP_SKILL_HEAL2: case SP_ADD_SKILL_BLOW: case SP_CASTRATE: // these bonuses support skill names @@ -6535,7 +6536,7 @@ BUILDIN_FUNC(bonus) /// Bonus script that has a chance of being executed on attack. BUILDIN_FUNC(bonusautoscript) { - int rate, flag = 0; + int rate, flag = 0, target = 0; const char *str; struct script_code *script; TBL_PC* sd; @@ -6548,10 +6549,12 @@ BUILDIN_FUNC(bonusautoscript) rate = script_getnum(st,3); if( script_hasdata(st,4) ) flag = script_getnum(st,4); + if( script_hasdata(st,5) ) + target = script_getnum(st,5); script = parse_script(str, "autoscript bonus", 0, 0); - if (!script) + if( !script ) return 1; - if (!pc_autoscript_add(sd->autoscript, ARRAYLENGTH(sd->autoscript), rate, flag, script)) + if( !pc_autoscript_add(sd->autoscript, ARRAYLENGTH(sd->autoscript), rate, flag, target, script) ) { script_free_code(script); return 1; @@ -6561,7 +6564,7 @@ BUILDIN_FUNC(bonusautoscript) /// Bonus script that has a chance of being executed when attacked. BUILDIN_FUNC(bonusautoscript2) { - int rate, flag = 0; + int rate, flag = 0, target = 0; const char *str; struct script_code *script; TBL_PC* sd; @@ -6574,10 +6577,12 @@ BUILDIN_FUNC(bonusautoscript2) rate = script_getnum(st,3); if( script_hasdata(st,4) ) flag = script_getnum(st,4); + if( script_hasdata(st,5) ) + target = script_getnum(st,5); script = parse_script(str, "autoscript2 bonus", 0, 0); if (!script) return 1; - if (!pc_autoscript_add(sd->autoscript2, ARRAYLENGTH(sd->autoscript2), rate, flag, script)) + if (!pc_autoscript_add(sd->autoscript2, ARRAYLENGTH(sd->autoscript2), rate, flag, target, script)) { script_free_code(script); return 1; @@ -13376,8 +13381,8 @@ struct script_function buildin_func[] = { BUILDIN_DEF2(bonus,"bonus3","ivii"), BUILDIN_DEF2(bonus,"bonus4","iviii"), BUILDIN_DEF2(bonus,"bonus5","iviiii"), - BUILDIN_DEF(bonusautoscript,"si?"), - BUILDIN_DEF(bonusautoscript2,"si?"), + BUILDIN_DEF(bonusautoscript,"si??"), + BUILDIN_DEF(bonusautoscript2,"si??"), 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 32f05a51a..579d27616 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -936,17 +936,18 @@ 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) { + if( sd && src != bl && sd->autoscript[0].script ) + { int i; - for (i = 0; i < ARRAYLENGTH(sd->autoscript) && sd->autoscript[i].script; 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) + if( rand()%1000 > sd->autoscript[i].rate ) continue; - run_script(sd->autoscript[i].script,0,sd->bl.id,0); + run_script(sd->autoscript[i].script,0,sd->autoscript[i].target?bl->id:src->id,0); break; //Have only one script execute at a time. } } @@ -1123,19 +1124,18 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * } } //Auto-script when attacked - if(dstsd && !status_isdead(bl) && src != bl && dstsd->autoscript2[0].script && - !(skillid && skill_get_nk(skillid)&NK_NO_DAMAGE)) + 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++) { - + 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) + if( rand()%1000 > dstsd->autoscript2[i].rate ) continue; - run_script(dstsd->autoscript2[i].script,0,dstsd->bl.id,0); + run_script(dstsd->autoscript2[i].script,0,dstsd->autoscript2[i].target?src->id:bl->id,0); break; //Have only one script execute at a time. } } @@ -2978,20 +2978,23 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in int heal = skill_calc_heal(src, bl, skilllv); int heal_get_jobexp; - if (status_isimmune(bl) || (dstmd && dstmd->class_ == MOBID_EMPERIUM)) + if( status_isimmune(bl) || (dstmd && dstmd->class_ == MOBID_EMPERIUM) ) heal=0; - if (sd) { - if ((i = pc_skillheal_bonus(sd, skillid))) + if( sd ) + { + if( (i = pc_skillheal_bonus(sd, skillid)) ) heal += heal * i / 100; - if (sd && dstsd && sd->status.partner_id == dstsd->status.char_id && - (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.sex == 0) + if( sd && dstsd && sd->status.partner_id == dstsd->status.char_id && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.sex == 0 ) heal = heal*2; } - if (tsc && tsc->count) + if( dstsd && (i = pc_skillheal2_bonus(dstsd, skillid)) ) + heal += heal * i / 100; + + if( tsc && tsc->count ) { - if (tsc->data[SC_KAITE] && !(sstatus->mode&MD_BOSS) - ) { //Bounce back heal + if( tsc->data[SC_KAITE] && !(sstatus->mode&MD_BOSS) ) + { //Bounce back heal if (--tsc->data[SC_KAITE]->val2 <= 0) status_change_end(bl, SC_KAITE, -1); if (src == bl) @@ -4231,25 +4234,30 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case AM_POTIONPITCHER: { int i,x,hp = 0,sp = 0,bonus=100; - if(sd) { + if( sd ) + { x = skilllv%11 - 1; i = pc_search_inventory(sd,skill_db[skillid].itemid[x]); - if(i < 0 || skill_db[skillid].itemid[x] <= 0) { + if( i < 0 || skill_db[skillid].itemid[x] <= 0 ) + { clif_skill_fail(sd,skillid,0,0); map_freeblock_unlock(); return 1; } - if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill_db[skillid].amount[x]) { + if( sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill_db[skillid].amount[x] ) + { clif_skill_fail(sd,skillid,0,0); map_freeblock_unlock(); return 1; } - if(skillid == AM_BERSERKPITCHER) { //Does not override use-level, and cannot be used on bows. - if (dstsd && (dstsd->status.base_level<(unsigned int)sd->inventory_data[i]->elv || dstsd->weapontype1 == W_BOW)) { + if( skillid == AM_BERSERKPITCHER ) + { //Does not override use-level, and cannot be used on bows. + if( dstsd && (dstsd->status.base_level<(unsigned int)sd->inventory_data[i]->elv || dstsd->weapontype1 == W_BOW) ) + { clif_skill_fail(sd,skillid,0,0); map_freeblock_unlock(); return 1; - } + } } potion_flag = 1; potion_hp = potion_sp = potion_per_hp = potion_per_sp = 0; @@ -4257,27 +4265,32 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in run_script(sd->inventory_data[i]->script,0,sd->bl.id,0); pc_delitem(sd,i,skill_db[skillid].amount[x],0); potion_flag = potion_target = 0; - if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_ALCHEMIST) + if( sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_ALCHEMIST ) bonus += sd->status.base_level; - if(potion_per_hp > 0 || potion_per_sp > 0) { + if( potion_per_hp > 0 || potion_per_sp > 0 ) + { hp = tstatus->max_hp * potion_per_hp / 100; hp = hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; - if(dstsd) { + if( dstsd ) + { sp = dstsd->status.max_sp * potion_per_sp / 100; sp = sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; } } - else { - if(potion_hp > 0) { + else + { + if( potion_hp > 0 ) + { hp = potion_hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; hp = hp * (100 + (tstatus->vit<<1)) / 100; - if(dstsd) + if( dstsd ) hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100; } - if(potion_sp > 0) { + if( potion_sp > 0 ) + { sp = potion_sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; sp = sp * (100 + (tstatus->int_<<1)) / 100; - if(dstsd) + if( dstsd ) sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10) / 100; } } @@ -4288,27 +4301,33 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in sp += sp * sd->itemgrouphealrate[IG_POTION] / 100; } - if ((i = pc_skillheal_bonus(sd, skillid))) + if( (i = pc_skillheal_bonus(sd, skillid)) ) { hp += hp * i / 100; sp += sp * i / 100; } } - else { + else + { hp = (1 + rand()%400) * (100 + skilllv*10) / 100; hp = hp * (100 + (tstatus->vit<<1)) / 100; - if(dstsd) + if( dstsd ) hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100; } - if (tsc && tsc->data[SC_CRITICALWOUND]) + if( dstsd && (i = pc_skillheal2_bonus(dstsd, skillid)) ) + { + hp += hp * i / 100; + sp += sp * i / 100; + } + if( tsc && tsc->data[SC_CRITICALWOUND] ) { hp -= hp * tsc->data[SC_CRITICALWOUND]->val2 / 100; sp -= sp * tsc->data[SC_CRITICALWOUND]->val2 / 100; } clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(hp > 0 || (skillid == AM_POTIONPITCHER && sp <= 0)) + if( hp > 0 || (skillid == AM_POTIONPITCHER && sp <= 0) ) clif_skill_nodamage(NULL,bl,AL_HEAL,hp,1); - if(sp > 0) + if( sp > 0 ) clif_skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1); status_heal(bl,hp,sp,0); } @@ -5295,6 +5314,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in i = skill_calc_heal( src, bl, 1+rand()%skilllv); if (sd && (rnd = pc_skillheal_bonus(sd, skillid)) > 0) i += i * rnd / 100; + if (dstsd && (rnd = pc_skillheal2_bonus(dstsd, skillid)) > 0) + i += i * rnd / 100; //Eh? why double skill packet? clif_skill_nodamage(src,bl,AL_HEAL,i,1); clif_skill_nodamage(src,bl,skillid,i,1); @@ -6981,6 +7002,9 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns if( tsc->data[SC_CRITICALWOUND] ) heal -= heal * tsc->data[SC_CRITICALWOUND]->val2 / 100; } + if( tsd ) + heal += heal * pc_skillheal2_bonus(tsd, sg->skill_id) / 100; + if( bl->type == BL_MER ) heal /= 2; if( status_isimmune(bl) ) @@ -8445,35 +8469,42 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in *------------------------------------------*/ int skill_castfix (struct block_list *bl, int skill_id, int skill_lv) { - int time = skill_get_cast(skill_id, skill_lv); + int time = skill_get_cast(skill_id, skill_lv); struct map_session_data *sd; + struct status_change *sc; nullpo_retr(0, bl); sd = BL_CAST(BL_PC, bl); + sc = status_get_sc(bl); // calculate base cast time (reduced by dex) - if (!(skill_get_castnodex(skill_id, skill_lv)&1)) { + if( !(skill_get_castnodex(skill_id, skill_lv)&1) ) + { int scale = battle_config.castrate_dex_scale - status_get_dex(bl); - if (scale > 0) // not instant cast + if( scale > 0 ) // not instant cast time = time * scale / battle_config.castrate_dex_scale; else return 0; // instant cast } // calculate cast time reduced by item/card bonuses - if (!(skill_get_castnodex(skill_id, skill_lv)&4) && sd) + if( !(skill_get_castnodex(skill_id, skill_lv)&4) && sd ) { int i; - if (sd->castrate != 100) + if( sd->castrate != 100 ) time = time * sd->castrate / 100; - for(i = 0; i < ARRAYLENGTH(sd->skillcast) && sd->skillcast[i].id; i++) + for( i = 0; i < ARRAYLENGTH(sd->skillcast) && sd->skillcast[i].id; i++ ) { - if (sd->skillcast[i].id == skill_id) + if( sd->skillcast[i].id == skill_id ) { time+= time * sd->skillcast[i].val / 100; break; } } } + + if( sc && sc->count && sc->data[SC_SKILLCASTRATE] && sc->data[SC_SKILLCASTRATE]->val1 == skill_id ) + time += time * sc->data[SC_SKILLCASTRATE]->val2 / 100; + // config cast time multiplier if (battle_config.cast_rate != 100) time = time * battle_config.cast_rate / 100; diff --git a/src/map/status.c b/src/map/status.c index fcfc0fb7f..67f4a7c85 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1754,6 +1754,7 @@ int status_calc_pc(struct map_session_data* sd,int first) + sizeof(sd->addeff2) + sizeof(sd->skillatk) + sizeof(sd->skillheal) + + sizeof(sd->skillheal2) + sizeof(sd->hp_loss) + sizeof(sd->sp_loss) + sizeof(sd->hp_regen) @@ -5102,6 +5103,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val return 0; break; case SC_HPREGEN: + case SC_HPDRAIN: case SC_SPREGEN: case SC_BOSSMAPINFO: case SC_STUN: @@ -5432,6 +5434,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val tick = 10000; break; case SC_HPREGEN: + case SC_HPDRAIN: case SC_SPREGEN: if( val1 == 0 ) return 0; // val1 = heal percent/amout @@ -7094,6 +7097,17 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr data) } break; + case SC_KNOWLEDGE: + if (!sd) break; + if(bl->m == sd->feel_map[0].m || + bl->m == sd->feel_map[1].m || + bl->m == sd->feel_map[2].m) + { //Timeout will be handled by pc_setpos + sce->timer = INVALID_TIMER; + return 0; + } + break; + case SC_BLEEDING: if (--(sce->val4) >= 0) { int flag; @@ -7107,14 +7121,16 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr data) } break; - case SC_KNOWLEDGE: - if (!sd) break; - if(bl->m == sd->feel_map[0].m || - bl->m == sd->feel_map[1].m || - bl->m == sd->feel_map[2].m) - { //Timeout will be handled by pc_setpos - sce->timer = INVALID_TIMER; - return 0; + case SC_HPDRAIN: + if( --(sce->val4) >= 0 ) + { + int flag, hp = (sce->val1 < 0) ? (int)(status->max_hp * -1 * sce->val1 / 100.) : sce->val1; + map_freeblock_lock(); + status_fix_damage(NULL, bl, hp, 0); + flag = !sc->data[type]; + map_freeblock_unlock(); + if( flag ) return 0; + sc_timer_next((sce->val2 * 1000) + tick, status_change_timer, bl->id, data); } break; @@ -7130,7 +7146,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr data) sp = (sce->val1 < 0) ? (int)(sd->status.max_sp * -1 * sce->val1 / 100.) : sce->val1 ; status_heal(bl, hp, sp, 2); - sc_timer_next((sce->val2 * 1000) + tick, status_change_timer, bl->id, data ); + sc_timer_next((sce->val2 * 1000) + tick, status_change_timer, bl->id, data); return 0; } break; diff --git a/src/map/status.h b/src/map/status.h index b4b6dde61..d3301bd37 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -305,6 +305,10 @@ typedef enum sc_type { SC_MERC_QUICKEN, SC_REBIRTH, + SC_SKILLCASTRATE, //285 + SC_DEFRATIOATK, + SC_HPDRAIN, + SC_SKILLATKBONUS, SC_MAX, //Automatically updated max, used in for's to check we are within bounds. } sc_type; |