diff --git a/conf/msg_conf/map_msg.conf b/conf/msg_conf/map_msg.conf index 23a0b9fd4f..cb4c527b8e 100644 --- a/conf/msg_conf/map_msg.conf +++ b/conf/msg_conf/map_msg.conf @@ -392,8 +392,8 @@ 377: -- Player %s has rejected the duel -- //etc 378: Eleanor is now in %s mode. -379: Able to use %.1f min later. -380: Able to use %d sec later. +379: Item Failed. [%s] is cooling down. Wait %.1f minutes. +380: Item Failed. [%s] is cooling down. Wait %.1f seconds. 381: Skill Failed. [%s] requires %dx %s. 382: You're too close to a stone or emperium to use this skill. 383: You cannot create a savepoint in an instance. diff --git a/db/pre-re/skill_db.txt b/db/pre-re/skill_db.txt index 812017e2c8..6899fb3ef1 100644 --- a/db/pre-re/skill_db.txt +++ b/db/pre-re/skill_db.txt @@ -228,7 +228,7 @@ 128,0,0,0,0,0,0,10,0,no,0,0,0,misc,0,0x0, HT_STEELCROW,Steel Crow 129,5,8,1,0,0x42,1,5,1:2:3:4:5,yes,0,0,0,misc,0,0x80, HT_BLITZBEAT,Blitz Beat 130,3:5:7:9,6,2,0,0x3,3,4,1,no,0,0,0,misc,0,0x0, HT_DETECTING,Detect -131,4:5:6:7:8,6,32,0,0x1,0,5,1,no,0,0,0,misc,0,0x2000, HT_SPRINGTRAP,Spring Trap +131,4:5:6:7:8,6,32,0,0x1,0,5,1,no,0,0,0,misc,0,0x0, HT_SPRINGTRAP,Spring Trap //**** // Assassin @@ -870,7 +870,7 @@ 1010,9,6,1,0,0x1,0,1,0,no,0,0x1,0,misc,0,0x0, BA_PANGVOICE,Pang Voice 1011,9,6,1,0,0x1,0,1,0,no,0,0x1,0,misc,0,0x0, DC_WINKCHARM,Wink of Charm 1012,0,0,0,0,0,0,1,0,no,0,0x1,0,weapon,0,0x4000, BS_UNFAIRLYTRICK,Unfair Trick -1013,0,6,4,0,0x3,2,1,0,no,0,0x1,0,weapon,0,0x0, BS_GREED,Greed +1013,0,6,4,0,0x3,2,1,0,no,0,0x1,0,weapon,0,0x2000, BS_GREED,Greed 1014,0,6,4,6,0x3,14,1,0,yes,0,0x1,0,magic,0,0x0, PR_REDEMPTIO,Redemptio 1015,9,6,16,0,0x1,0,1,1,no,0,0x401,0,weapon,0,0x0, MO_KITRANSLATION,Ki Translation 1016,-1,6,1,-1,0x2,1,1,1,no,0,0x1,0,weapon,5,0x0, MO_BALKYOUNG,Ki Explosion @@ -989,7 +989,7 @@ 2235,0,0,0,0,0,0,10,0,no,0,0,0,none,0,0x0, RA_RANGERMAIN,Ranger Main 2236,9,8,1,-1,0,0,10,1,yes,0,0,0,weapon,0,0x80, RA_AIMEDBOLT,Aimed Bolt 2237,9,6,2,0,0x3,3,1,1,no,0,0,0,none,0,0x2000, RA_DETONATOR,Detonator -2238,3,6,2,0,0x3,2,5,1,no,0,0x80,3,misc,0,0x0, RA_ELECTRICSHOCKER,Electric Shocker +2238,3,6,2,0,0x3,2,5,1,no,0,0x80,3,misc,0,0x2000, RA_ELECTRICSHOCKER,Electric Shocker 2239,3,6,2,0,0x42,3,5,1,no,0,0x80,3,misc,0,0x2800, RA_CLUSTERBOMB,Cluster Bomb 2240,0,6,4,0,0,0,1,1,no,0,0,0,none,0,0x0, RA_WUGMASTERY,Warg Mastery 2241,0,6,4,0,0,0,3,1,no,0,0,0,none,0,0x2000, RA_WUGRIDER,Warg Rider @@ -1000,10 +1000,10 @@ 2246,0,6,4,0,0x2,3:4:5:6:7,5,1,no,0,0,0,weapon,0,0x0, RA_SENSITIVEKEEN,Sensitive Keen 2247,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x42, RA_CAMOUFLAGE,Camouflage 2248,0,0,0,0,0,0,5,0,no,0,0,0,none,0,0x0, RA_RESEARCHTRAP,Research Trap -2249,3,6,2,3,0x43,2,1,1,no,0,0x80,1,misc,0,0x0, RA_MAGENTATRAP,Magenta Trap -2250,3,6,2,1,0x43,2,1,1,no,0,0x80,1,misc,0,0x0, RA_COBALTTRAP,Cobalt Trap -2251,3,6,2,2,0x43,2,1,1,no,0,0x80,1,misc,0,0x0, RA_MAIZETRAP,Maize Trap -2252,3,6,2,4,0x43,2,1,1,no,0,0x80,1,misc,0,0x0, RA_VERDURETRAP,Verdure Trap +2249,3,6,2,3,0x43,2,1,1,no,0,0x80,1,misc,0,0x2000, RA_MAGENTATRAP,Magenta Trap +2250,3,6,2,1,0x43,2,1,1,no,0,0x80,1,misc,0,0x2000, RA_COBALTTRAP,Cobalt Trap +2251,3,6,2,2,0x43,2,1,1,no,0,0x80,1,misc,0,0x2000, RA_MAIZETRAP,Maize Trap +2252,3,6,2,4,0x43,2,1,1,no,0,0x80,1,misc,0,0x2000, RA_VERDURETRAP,Verdure Trap 2253,3,6,2,3,0x42,2,5,1,no,0,0x80,2,misc,0,0x2800, RA_FIRINGTRAP,Firing Trap 2254,3,6,2,1,0x42,2,5,1,no,0,0x80,2,misc,0,0x2800, RA_ICEBOUNDTRAP,Icebound Trap diff --git a/db/pre-re/skill_unit_db.txt b/db/pre-re/skill_unit_db.txt index 8811a6a017..9031c3f2ed 100644 --- a/db/pre-re/skill_unit_db.txt +++ b/db/pre-re/skill_unit_db.txt @@ -151,8 +151,8 @@ 2482,0xe6,0x7f, 0, 1, 100,all, 0x000 //GN_WALLOFTHORN 2484,0x86, , 0, 1, 100,enemy, 0x080 //GN_CRAZYWEED_ATK 2485,0xe7, , 0, 2,2000,enemy, 0x098 //GN_DEMONIC_FIRE -2487,0xe8, , 2, 0, -1,all, 0x2000 //GN_FIRE_EXPANSION_SMOKE_POWDER -2488,0xe9, , 2, 0, -1,all, 0x2000 //GN_FIRE_EXPANSION_TEAR_GAS +2487,0xe8, , 2, 0, -1,enemy, 0x2000 //GN_FIRE_EXPANSION_SMOKE_POWDER +2488,0xe9, , 2, 0, -1,enemy, 0x2000 //GN_FIRE_EXPANSION_TEAR_GAS 2490,0xea, , 0, 1,1000,enemy, 0x002 //GN_HELLS_PLANT 2555,0x104, , 0, 1:2:2:3:3,500,enemy,0x6 //RL_B_TRAP diff --git a/db/re/skill_cast_db.txt b/db/re/skill_cast_db.txt index acb398bd7b..efb8d55eda 100644 --- a/db/re/skill_cast_db.txt +++ b/db/re/skill_cast_db.txt @@ -1575,7 +1575,7 @@ //-- SO_EARTH_INSIGNIA 2468,1000,0,0,60000,0,60000,1000 //-- SO_ELEMENTAL_SHIELD -5008,1000,0,0,0,0,10000,-1 +5008,1000,0,0,10000,0,10000,-1 //========================================== //==== Genetic skills ====================== diff --git a/db/re/skill_db.txt b/db/re/skill_db.txt index 92124a29ac..d0c9a017a5 100644 --- a/db/re/skill_db.txt +++ b/db/re/skill_db.txt @@ -228,7 +228,7 @@ 128,0,0,0,0,0,0,10,0,no,0,0,0,misc,0,0x0, HT_STEELCROW,Steel Crow 129,5,8,1,0,0x42,1,5,1:2:3:4:5,yes,0,0,0,misc,0,0x80, HT_BLITZBEAT,Blitz Beat 130,3:5:7:9,6,2,0,0x3,3,4,1,no,0,0,0,misc,0,0x0, HT_DETECTING,Detect -131,4:5:6:7:8,6,32,0,0x1,0,5,1,no,0,0,0,misc,0,0x2000, HT_SPRINGTRAP,Spring Trap +131,4:5:6:7:8,6,32,0,0x1,0,5,1,no,0,0,0,misc,0,0x0, HT_SPRINGTRAP,Spring Trap //**** // Assassin @@ -870,7 +870,7 @@ 1010,9,6,1,0,0x1,0,1,0,no,0,0x1,0,misc,0,0x0, BA_PANGVOICE,Pang Voice 1011,9,6,1,0,0x1,0,1,0,no,0,0x1,0,misc,0,0x0, DC_WINKCHARM,Wink of Charm 1012,0,0,0,0,0,0,1,0,no,0,0x1,0,weapon,0,0x4000, BS_UNFAIRLYTRICK,Unfair Trick -1013,0,6,4,0,0x3,2,1,0,no,0,0x1,0,weapon,0,0x0, BS_GREED,Greed +1013,0,6,4,0,0x3,2,1,0,no,0,0x1,0,weapon,0,0x2000, BS_GREED,Greed 1014,0,6,4,6,0x3,14,1,0,yes,0,0x1,0,magic,0,0x0, PR_REDEMPTIO,Redemptio 1015,9,6,16,0,0x1,0,1,1,no,0,0x401,0,weapon,0,0x0, MO_KITRANSLATION,Ki Translation 1016,-1,6,1,-1,0x2,1,1,1,no,0,0x1,0,weapon,5,0x0, MO_BALKYOUNG,Ki Explosion @@ -989,7 +989,7 @@ 2235,0,0,0,0,0,0,10,0,no,0,0,0,none,0,0x0, RA_RANGERMAIN,Ranger Main 2236,9,8,1,-1,0,0,10,1,yes,0,0,0,weapon,0,0x80, RA_AIMEDBOLT,Aimed Bolt 2237,9,6,2,0,0x3,3,1,1,no,0,0,0,none,0,0x2000, RA_DETONATOR,Detonator -2238,3,6,2,0,0x3,2,5,1,no,0,0x80,3,misc,0,0x0, RA_ELECTRICSHOCKER,Electric Shocker +2238,3,6,2,0,0x3,2,5,1,no,0,0x80,3,misc,0,0x2000, RA_ELECTRICSHOCKER,Electric Shocker 2239,3,6,2,0,0x42,3,5,1,no,0,0x80,3,misc,0,0x2800, RA_CLUSTERBOMB,Cluster Bomb 2240,0,6,4,0,0,0,1,1,no,0,0,0,none,0,0x0, RA_WUGMASTERY,Warg Mastery 2241,0,6,4,0,0,0,3,1,no,0,0,0,none,0,0x2000, RA_WUGRIDER,Warg Rider @@ -1000,10 +1000,10 @@ 2246,0,6,4,0,0x2,3:4:5:6:7,5,1,no,0,0,0,weapon,0,0x0, RA_SENSITIVEKEEN,Sensitive Keen 2247,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x42, RA_CAMOUFLAGE,Camouflage 2248,0,0,0,0,0,0,5,0,no,0,0,0,none,0,0x0, RA_RESEARCHTRAP,Research Trap -2249,3,6,2,3,0x43,2,1,1,no,0,0x80,1,misc,0,0x0, RA_MAGENTATRAP,Magenta Trap -2250,3,6,2,1,0x43,2,1,1,no,0,0x80,1,misc,0,0x0, RA_COBALTTRAP,Cobalt Trap -2251,3,6,2,2,0x43,2,1,1,no,0,0x80,1,misc,0,0x0, RA_MAIZETRAP,Maize Trap -2252,3,6,2,4,0x43,2,1,1,no,0,0x80,1,misc,0,0x0, RA_VERDURETRAP,Verdure Trap +2249,3,6,2,3,0x43,2,1,1,no,0,0x80,1,misc,0,0x2000, RA_MAGENTATRAP,Magenta Trap +2250,3,6,2,1,0x43,2,1,1,no,0,0x80,1,misc,0,0x2000, RA_COBALTTRAP,Cobalt Trap +2251,3,6,2,2,0x43,2,1,1,no,0,0x80,1,misc,0,0x2000, RA_MAIZETRAP,Maize Trap +2252,3,6,2,4,0x43,2,1,1,no,0,0x80,1,misc,0,0x2000, RA_VERDURETRAP,Verdure Trap 2253,3,6,2,3,0x42,2,5,1,no,0,0x80,2,misc,0,0x2800, RA_FIRINGTRAP,Firing Trap 2254,3,6,2,1,0x42,2,5,1,no,0,0x80,2,misc,0,0x2800, RA_ICEBOUNDTRAP,Icebound Trap diff --git a/db/re/skill_unit_db.txt b/db/re/skill_unit_db.txt index efb9205573..7605544ac6 100644 --- a/db/re/skill_unit_db.txt +++ b/db/re/skill_unit_db.txt @@ -153,8 +153,8 @@ 2482,0xe6,0x7f, 0, 1, 100,all, 0x000 //GN_WALLOFTHORN 2484,0x86, , 0, 1, 100,enemy, 0x080 //GN_CRAZYWEED_ATK 2485,0xe7, , 0, 2,2000,enemy, 0x098 //GN_DEMONIC_FIRE -2487,0xe8, , 2, 0, -1,all, 0x2000 //GN_FIRE_EXPANSION_SMOKE_POWDER -2488,0xe9, , 2, 0, -1,all, 0x2000 //GN_FIRE_EXPANSION_TEAR_GAS +2487,0xe8, , 2, 0, -1,enemy, 0x2000 //GN_FIRE_EXPANSION_SMOKE_POWDER +2488,0xe9, , 2, 0, -1,enemy, 0x2000 //GN_FIRE_EXPANSION_TEAR_GAS 2490,0xea, , 0, 1,1000,enemy, 0x002 //GN_HELLS_PLANT 2555,0x104, , 0, 1:2:2:3:3,500,enemy,0x6 //RL_B_TRAP diff --git a/src/map/battle.c b/src/map/battle.c index cdfb8bfe35..b43523c3c6 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -792,20 +792,29 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT ) { struct skill_unit_group* group = skill_id2group(sc->data[SC_SAFETYWALL]->val3); - //uint16 skill_id = sc->data[SC_SAFETYWALL]->val2; (safetywall or steinwand) + uint16 skill_id = sc->data[SC_SAFETYWALL]->val2; if (group) { - //in RE, SW possesses a lifetime equal to group val2, (3x caster hp, or homon formula) -#ifdef RENEWAL d->dmg_lv = ATK_BLOCK; + + if (skill_id == MH_STEINWAND) { + if (--group->val2 <= 0) + skill_delunitgroup(group); + if( (group->val3 - damage) > 0 ) + group->val3 -= (int)cap_value(damage, INT_MIN, INT_MAX); + else + skill_delunitgroup(group); + return 0; + } + //in RE, SW possesses a lifetime equal to group val2, (3x caster hp, or homon formula) +#ifdef RENEWAL if ( ( group->val2 - damage) > 0 ) { - group->val2 -= (int)cap_value(damage,INT_MIN,INT_MAX); + group->val2 -= (int)cap_value(damage, INT_MIN, INT_MAX); } else skill_delunitgroup(group); return 0; #else - if (--group->val2<=0) + if (--group->val2 <= 0) skill_delunitgroup(group); - d->dmg_lv = ATK_BLOCK; return 0; #endif } @@ -1493,6 +1502,10 @@ int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,in break; } + + if(sd->sc.data[SC_GN_CARTBOOST]) // cart boost adds mastery type damage + damage += 10*sd->sc.data[SC_GN_CARTBOOST]->val1; + return damage; } @@ -1853,6 +1866,26 @@ static int battle_skill_damage(struct block_list *src, struct block_list *target } #endif +/** + * Calculates Minstrel/Wanderer bonus for Chorus skills. + * @param sd Player who has Chorus skill active + * @return Bonus value based on party count + */ +static int battle_calc_chorusbonus(struct map_session_data *sd) { + int members = 0; + + if (!sd || !sd->status.party_id) + return 0; + + members = party_foreachsamemap(party_sub_count_class, sd, MAPID_THIRDMASK, MAPID_MINSTRELWANDERER); + + if (members < 3) + return 0; // Bonus remains 0 unless 3 or more Minstrels/Wanderers are in the party. + if (members > 7) + return 5; // Maximum effect possible from 7 or more Minstrels/Wanderers. + return members - 2; // Effect bonus from additional Minstrels/Wanderers if not above the max possible. +} + struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag); struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag); @@ -2531,11 +2564,6 @@ static struct Damage battle_calc_attack_masteries(struct Damage wd, struct block if (sc) { // Status change considered as masteries uint8 i; -#ifdef RENEWAL - if(sc->data[SC_NIBELUNGEN]) //With renewal, the level 4 weapon limitation has beed removed - ATK_ADD(wd.masteryAtk, wd.masteryAtk2, sc->data[SC_NIBELUNGEN]->val2); -#endif - if (sc->data[SC_MIRACLE]) i = 2; //Star anger else @@ -3418,9 +3446,13 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s break; case RA_WUGDASH:// ATK 300% skillratio += 200; + if (sc && sc->data[SC_DANCEWITHWUG]) + skillratio += 10 * sc->data[SC_DANCEWITHWUG]->val1 * (2 + battle_calc_chorusbonus(sd)); break; case RA_WUGSTRIKE: skillratio += -100 + 200 * skill_lv; + if (sc && sc->data[SC_DANCEWITHWUG]) + skillratio += 10 * sc->data[SC_DANCEWITHWUG]->val1 * (2 + battle_calc_chorusbonus(sd)); break; case RA_WUGBITE: skillratio += 300 + 200 * skill_lv; @@ -3905,11 +3937,15 @@ static int battle_calc_skill_constant_addition(struct Damage wd, struct block_li case RA_WUGDASH: if( sd && sd->weight ) atk = (sd->weight / 8) + (30 * pc_checkskill(sd,RA_TOOTHOFWUG)); + if (sc && sc->data[SC_DANCEWITHWUG]) + atk += 10 * sc->data[SC_DANCEWITHWUG]->val1 * (2 + battle_calc_chorusbonus(sd)); break; case RA_WUGSTRIKE: case RA_WUGBITE: if(sd) atk = (30 * pc_checkskill(sd, RA_TOOTHOFWUG)); + if (sc && sc->data[SC_DANCEWITHWUG]) + atk += 10 * sc->data[SC_DANCEWITHWUG]->val1 * (2 + battle_calc_chorusbonus(sd)); break; case GC_COUNTERSLASH: atk = sstatus->agi * 2 + (sd ? sd->status.job_level * 4 : 0); @@ -3949,27 +3985,14 @@ static int battle_calc_skill_constant_addition(struct Damage wd, struct block_li * Initial refactoring by Baalberith * Refined and optimized by helvetica */ -struct Damage battle_attack_sc_bonus(struct Damage wd, struct block_list *src, struct block_list *target, uint16 skill_id) +struct Damage battle_attack_sc_bonus(struct Damage wd, struct block_list *src, uint16 skill_id) { struct map_session_data *sd = BL_CAST(BL_PC, src); struct status_change *sc = status_get_sc(src); struct status_data *sstatus = status_get_status_data(src); -#ifdef RENEWAL - struct status_data *tstatus = status_get_status_data(target); -#endif - int chorusbonus = 0; if( sd ) { int type; - // Minstrel/Wanderer number check for chorus skills. - // Bonus remains 0 unless 3 or more Minstrels/Wanderers are in the party. - if( sd->status.party_id ) { - chorusbonus = party_foreachsamemap(party_sub_count_class, sd, MAPID_THIRDMASK, MAPID_MINSTRELWANDERER); - if( chorusbonus > 7 ) - chorusbonus = 5; // Maximum effect possible from 7 or more Minstrels/Wanderers - else if( chorusbonus > 2 ) - chorusbonus = chorusbonus - 2; // Effect bonus from additional Minstrels/Wanderers if not above the max possible. - } // Kagerou/Oboro Earth Charm effect +15% wATK ARR_FIND(1, 6, type, sd->talisman[type] > 0); @@ -3983,35 +4006,19 @@ struct Damage battle_attack_sc_bonus(struct Damage wd, struct block_list *src, s //The following are applied on top of current damage and are stackable. if (sc) { -#ifdef RENEWAL - if(sc->data[SC_WATK_ELEMENT]) - if(skill_id != ASC_METEORASSAULT) - ATK_ADDRATE(wd.weaponAtk, wd.weaponAtk2, sc->data[SC_WATK_ELEMENT]->val2); - if(sc->data[SC_IMPOSITIO]) - ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_IMPOSITIO]->val2); - if(sc->data[SC_VOLCANO]) - ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_VOLCANO]->val2); - if(sc->data[SC_DRUMBATTLE]) { - if(tstatus->size == SZ_SMALL) { - ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_DRUMBATTLE]->val2); - } else if(tstatus->size == SZ_MEDIUM) - ATK_ADD(wd.equipAtk, wd.equipAtk2, 10 * sc->data[SC_DRUMBATTLE]->val1); - } - if(sc->data[SC_MADNESSCANCEL]) - ATK_ADD(wd.equipAtk, wd.equipAtk2, 100); - if(sc->data[SC_GATLINGFEVER]) { - if(tstatus->size == SZ_SMALL) { - ATK_ADD(wd.equipAtk, wd.equipAtk2, 10 * sc->data[SC_GATLINGFEVER]->val1); - } else if(tstatus->size == SZ_MEDIUM) { - ATK_ADD(wd.equipAtk, wd.equipAtk2, 5 * sc->data[SC_GATLINGFEVER]->val1); - } else if(tstatus->size == SZ_BIG) - ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_GATLINGFEVER]->val1); - } -#endif #ifndef RENEWAL if( sc->data[SC_TRUESIGHT] ) ATK_ADDRATE(wd.damage, wd.damage2, 2*sc->data[SC_TRUESIGHT]->val1); #endif + if( sc->data[SC_GLOOMYDAY_SK] && + ( skill_id == LK_SPIRALPIERCE || skill_id == KN_BRANDISHSPEAR || + skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN || + skill_id == RK_HUNDREDSPEAR || skill_id == LG_SHIELDPRESS ) ) { + ATK_ADDRATE(wd.damage, wd.damage2, sc->data[SC_GLOOMYDAY_SK]->val2); +#ifdef RENEWAL + ATK_ADDRATE(wd.weaponAtk, wd.weaponAtk2, sc->data[SC_GLOOMYDAY_SK]->val2); +#endif + } if (sc->data[SC_SPIRIT]) { if(skill_id == AS_SONICBLOW && sc->data[SC_SPIRIT]->val2 == SL_ASSASIN){ ATK_ADDRATE(wd.damage, wd.damage2, map_flag_gvg(src->m)?25:100); //+25% dmg on woe/+100% dmg on nonwoe @@ -4067,93 +4074,7 @@ struct Damage battle_attack_sc_bonus(struct Damage wd, struct block_list *src, s #endif } } - if(sc->data[SC_FIGHTINGSPIRIT]) { - ATK_ADD(wd.damage, wd.damage2, sc->data[SC_FIGHTINGSPIRIT]->val1); -#ifdef RENEWAL - ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_FIGHTINGSPIRIT]->val1); -#endif - } - if(sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 3) { - ATK_ADD(wd.damage, wd.damage2, sc->data[SC_SHIELDSPELL_DEF]->val2); -#ifdef RENEWAL - ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_SHIELDSPELL_DEF]->val2); -#endif - } - if(sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1) { - ATK_ADD(wd.damage, wd.damage2, (10 + 10 * sc->data[SC_BANDING]->val1) * sc->data[SC_BANDING]->val2); -#ifdef RENEWAL - ATK_ADD(wd.equipAtk, wd.equipAtk2, (10 + 10 * sc->data[SC_BANDING]->val1) * sc->data[SC_BANDING]->val2); -#endif - } - if(sc->data[SC_INSPIRATION]) { - ATK_ADD(wd.damage, wd.damage2, 40 * sc->data[SC_INSPIRATION]->val1 + 3 * sc->data[SC_INSPIRATION]->val2); -#ifdef RENEWAL - ATK_ADD(wd.equipAtk, wd.equipAtk2, 40 * sc->data[SC_INSPIRATION]->val1 + 3 * sc->data[SC_INSPIRATION]->val2); -#endif - } - if(sc->data[SC_GT_CHANGE] && sc->data[SC_GT_CHANGE]->val2) { - struct block_list *bl; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5] - if( (bl = map_id2bl(sc->data[SC_GT_CHANGE]->val2)) ) { - ATK_ADD(wd.damage, wd.damage2, ( status_get_dex(bl)/4 + status_get_str(bl)/2 ) * sc->data[SC_GT_CHANGE]->val1 / 5 ); -#ifdef RENEWAL - ATK_ADD(wd.equipAtk, wd.equipAtk2, (status_get_dex(bl) / 4 + status_get_str(bl) / 2) * sc->data[SC_GT_CHANGE]->val1 / 5); -#endif - } - } - if(sc->data[SC_PYROTECHNIC_OPTION]) { - ATK_ADD(wd.damage, wd.damage2, sc->data[SC_PYROTECHNIC_OPTION]->val2); -#ifdef RENEWAL - ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_PYROTECHNIC_OPTION]->val2); -#endif - } - if(sc->data[SC_HEATER_OPTION]) { - ATK_ADD(wd.damage, wd.damage2, sc->data[SC_HEATER_OPTION]->val2); -#ifdef RENEWAL - ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_HEATER_OPTION]->val2); -#endif - } - if(sc->data[SC_TROPIC_OPTION]) { - ATK_ADD(wd.damage, wd.damage2, sc->data[SC_TROPIC_OPTION]->val2); -#ifdef RENEWAL - ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_TROPIC_OPTION]->val2); -#endif - } - if(sc->data[SC_GN_CARTBOOST]) { - ATK_ADD(wd.damage, wd.damage2, 10 * sc->data[SC_GN_CARTBOOST]->val1); -#ifdef RENEWAL - ATK_ADD(wd.equipAtk, wd.equipAtk2, 10 * sc->data[SC_GN_CARTBOOST]->val1); -#endif - } - if(sc->data[SC_RUSHWINDMILL]) { - ATK_ADD(wd.damage, wd.damage2, sc->data[SC_RUSHWINDMILL]->val3); -#ifdef RENEWAL - ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_RUSHWINDMILL]->val3); -#endif - } - if( sc->data[SC_GLOOMYDAY_SK] && - ( skill_id == LK_SPIRALPIERCE || skill_id == KN_BRANDISHSPEAR || - skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN || - skill_id == RK_HUNDREDSPEAR || skill_id == LG_SHIELDPRESS ) ) { - ATK_ADDRATE(wd.damage, wd.damage2, sc->data[SC_GLOOMYDAY_SK]->val2); - RE_ALLATK_ADDRATE(wd, sc->data[SC_GLOOMYDAY_SK]->val2); - } - if( sc->data[SC_DANCEWITHWUG] ) { - ATK_ADDRATE(wd.damage, wd.damage2, sc->data[SC_DANCEWITHWUG]->val1 * 2 * chorusbonus); -#ifdef RENEWAL - ATK_ADDRATE(wd.equipAtk, wd.equipAtk2, sc->data[SC_DANCEWITHWUG]->val1 * 2 * chorusbonus); -#endif - if( skill_id == RA_WUGSTRIKE || skill_id == RA_WUGBITE || skill_id == RA_WUGDASH ) { - ATK_ADDRATE(wd.damage, wd.damage2, sc->data[SC_DANCEWITHWUG]->val1 * 10 * chorusbonus); - RE_ALLATK_ADDRATE(wd, sc->data[SC_DANCEWITHWUG]->val1 * 10 * chorusbonus); - } - } - if(sc->data[SC_SATURDAYNIGHTFEVER]) { - ATK_ADD(wd.damage, wd.damage2, 100 * sc->data[SC_SATURDAYNIGHTFEVER]->val1); -#ifdef RENEWAL - ATK_ADD(wd.equipAtk, wd.equipAtk2, 100 * sc->data[SC_SATURDAYNIGHTFEVER]->val1); -#endif - } if(sc->data[SC_ZENKAI] && sstatus->rhw.ele == sc->data[SC_ZENKAI]->val2) { ATK_ADD(wd.damage, wd.damage2, 200); #ifdef RENEWAL @@ -4936,7 +4857,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl } // final attack bonuses that aren't affected by cards - wd = battle_attack_sc_bonus(wd, src, target, skill_id); + wd = battle_attack_sc_bonus(wd, src, skill_id); if (sd) { //monsters, homuns and pets have their damage computed directly wd.damage = wd.statusAtk + wd.weaponAtk + wd.equipAtk + wd.masteryAtk; @@ -6380,10 +6301,11 @@ int64 battle_calc_return_damage(struct block_list* bl, struct block_list *src, i struct map_session_data* sd; int64 rdamage = 0, damage = *dmg; int max_damage = status_get_max_hp(bl); - struct status_change* sc; + struct status_change *sc, *ssc; sd = BL_CAST(BL_PC, bl); sc = status_get_sc(bl); + ssc = status_get_sc(src); if (flag & BF_SHORT) {//Bounces back part of the damage. if ( !status_reflect && sd && sd->bonus.short_weapon_damage_return ) { @@ -6430,6 +6352,16 @@ int64 battle_calc_return_damage(struct block_list* bl, struct block_list *src, i } } + if (ssc && ssc->data[SC_INSPIRATION]) { + rdamage += damage / 100; +#ifdef RENEWAL + rdamage = cap_value(rdamage, 1, max_damage); +#else + if( rdamage < 1 ) + rdamage = 1; +#endif + } + if( sc && sc->data[SC_KYOMU] ) // Nullify reflecting ability rdamage = 0; diff --git a/src/map/clif.c b/src/map/clif.c index 175be79fe6..7cb7772088 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -10284,13 +10284,13 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, return; } + // Statuses that don't let the player sit / attack / talk with NPCs(targeted) + // (not all are included in pc_can_attack) if (sd->sc.count && (sd->sc.data[SC_TRICKDEAD] || (sd->sc.data[SC_AUTOCOUNTER] && action_type != 0x07) || sd->sc.data[SC_BLADESTOP] || - sd->sc.data[SC__MANHOLE] || - sd->sc.data[SC_CURSEDCIRCLE_ATKER] || - sd->sc.data[SC_CURSEDCIRCLE_TARGET] )) + sd->sc.data[SC__MANHOLE] )) return; pc_stop_walking(sd, 1); @@ -10313,9 +10313,6 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, if( sd->sc.option&OPTION_COSTUME ) return; - if( sd->sc.data[SC_BASILICA] || sd->sc.data[SC__SHADOWFORM] ) - return; - if (!battle_config.sdelay_attack_enable && pc_checkskill(sd, SA_FREECAST) <= 0) { if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) { clif_skill_fail(sd, 1, USESKILL_FAIL_SKILLINTERVAL, 0); diff --git a/src/map/pc.c b/src/map/pc.c index b74c4b590a..a2ef74b3a6 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -4725,11 +4725,11 @@ int pc_useitem(struct map_session_data *sd,int n) int e_tick = DIFF_TICK(sd->item_delay[i].tick, tick)/1000; char e_msg[100]; if( e_tick > 99 ) - sprintf(e_msg,msg_txt(sd,379), //Able to use %.1f min later. - (double)e_tick / 60); + sprintf(e_msg,msg_txt(sd,379), // Item Failed. [%s] is cooling down. Wait %.1f minutes. + itemdb_jname(sd->item_delay[i].nameid), (double)e_tick / 60); else - sprintf(e_msg,msg_txt(sd,380), //Able to use %d sec later. - e_tick+1); + sprintf(e_msg,msg_txt(sd,380), // Item Failed. [%s] is cooling down. Wait %d seconds. + itemdb_jname(sd->item_delay[i].nameid), e_tick+1); clif_colormes(sd,color_table[COLOR_YELLOW],e_msg); return 0; // Delay has not expired yet } @@ -8391,6 +8391,33 @@ bool pc_candrop(struct map_session_data *sd, struct item *item) return (itemdb_isdropable(item, pc_get_group_level(sd))); } +/** + * Determines whether a player can attack based on status changes + * Why not use status_check_skilluse? + * "src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack." + * Even ground-based attacks should be blocked by these statuses + * Called from unit_attack and unit_attack_timer_sub + * @retval true Can attack + **/ +bool pc_can_attack( struct map_session_data *sd, int target_id ) { + nullpo_retr(false, sd); + + if( sd->sc.data[SC_BASILICA] || + sd->sc.data[SC__SHADOWFORM] || + sd->sc.data[SC__MANHOLE] || + sd->sc.data[SC_CURSEDCIRCLE_ATKER] || + sd->sc.data[SC_CURSEDCIRCLE_TARGET] || + sd->sc.data[SC_CRYSTALIZE] || + sd->sc.data[SC_ALL_RIDING] || // The client doesn't let you, this is to make cheat-safe + sd->sc.data[SC_TRICKDEAD] || + (sd->sc.data[SC_VOICEOFSIREN] && sd->sc.data[SC_VOICEOFSIREN]->val2 == target_id) || + sd->sc.data[SC_BLADESTOP] || + sd->sc.data[SC_DEEPSLEEP] ) + return false; + + return true; +} + /*========================================== * Read ram register for player sd * get val (int) from reg for player sd diff --git a/src/map/pc.h b/src/map/pc.h index c407f1cc94..d243fb1df8 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -997,6 +997,7 @@ void pc_regen (struct map_session_data *sd, unsigned int diff_tick); void pc_setstand(struct map_session_data *sd); bool pc_candrop(struct map_session_data *sd,struct item *item); +bool pc_can_attack(struct map_session_data *sd, int target_id); int pc_jobid2mapid(unsigned short b_class); // Skotlex int pc_mapid2jobid(unsigned short class_, int sex); // Skotlex diff --git a/src/map/script.c b/src/map/script.c index 165d6f3cb4..be147613a1 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -4910,7 +4910,7 @@ BUILDIN_FUNC(prompt) sd->state.menu_or_input = 0; pc_setreg(sd, add_str("@menu"), 0xff); script_pushint(st, 0xff); - st->state = END; + st->state = RUN; } else {// return selected option diff --git a/src/map/skill.c b/src/map/skill.c index c33f60b6de..0869652691 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -2447,6 +2447,36 @@ static int skill_magic_reflect(struct block_list* src, struct block_list* bl, in return 0; } +/** + * Checks whether a skill can be used in combos or not + * @param skill_id: Target skill + * @return true: Skill is a combo, false: otherwise + * @author Panikon + **/ +bool skill_is_combo(int skill_id) { + switch(skill_id) { + case MO_CHAINCOMBO: + case MO_COMBOFINISH: + case CH_TIGERFIST: + case CH_CHAINCRUSH: + case MO_EXTREMITYFIST: + case TK_TURNKICK: + case TK_STORMKICK: + case TK_DOWNKICK: + case TK_COUNTER: + case TK_JUMPKICK: + case HT_POWER: + case GC_COUNTERSLASH: + case GC_WEAPONCRUSH: + case SR_FALLENEMPIRE: + case SR_DRAGONCOMBO: + case SR_TIGERCANNON: + case SR_GATEOFHELL: + return true; + } + return false; +} + /* * Combo handler, start stop combo status */ @@ -8843,32 +8873,33 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case WL_SUMMONWB: case WL_SUMMONSTONE: { - short element = 0, sctype = 0, pos = -1; + short element = 0, sctype = 0, pos = -1, j = 0; struct status_change *sc = status_get_sc(src); - if( !sc ) break; - for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) - { + if( !sc ) + break; + + for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) { if( !sctype && !sc->data[i] ) sctype = i; // Take the free SC - if( sc->data[i] ) + if( sc->data[i] ) { pos = max(sc->data[i]->val2,pos); + j++; + } } - if( !sctype ) - { + if( !sctype || j >= skill_lv ) { if( sd ) // No free slots to put SC clif_skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0); break; } pos++; // Used in val2 for SC. Indicates the order of this ball - switch( skill_id ) - { // Set val1. The SC element for this ball - case WL_SUMMONFB: element = WLS_FIRE; break; - case WL_SUMMONBL: element = WLS_WIND; break; - case WL_SUMMONWB: element = WLS_WATER; break; - case WL_SUMMONSTONE: element = WLS_STONE; break; + switch( skill_id ) { // Set val1. The SC element for this ball + case WL_SUMMONFB: element = WLS_FIRE; break; + case WL_SUMMONBL: element = WLS_WIND; break; + case WL_SUMMONWB: element = WLS_WATER; break; + case WL_SUMMONSTONE: element = WLS_STONE; break; } sc_start4(src,src,(enum sc_type)sctype,100,element,pos,skill_lv,0,skill_get_time(skill_id,skill_lv)); diff --git a/src/map/skill.h b/src/map/skill.h index b2c383e1ea..2b91718b86 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -1999,6 +1999,7 @@ int skill_elementalanalysis(struct map_session_data *sd, int n, uint16 skill_lv, int skill_changematerial(struct map_session_data *sd, int n, unsigned short *item_list); // Genetic Change Material. int skill_get_elemental_type(uint16 skill_id, uint16 skill_lv); +bool skill_is_combo(int skill_id); void skill_combo_toogle_inf(struct block_list* bl, uint16 skill_id, int inf); void skill_combo(struct block_list* src,struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int tick); diff --git a/src/map/status.c b/src/map/status.c index e7ebdc4f05..4ad0873967 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -240,12 +240,7 @@ void initChangeTables(void) add_sc( TF_POISON , SC_POISON ); set_sc( KN_TWOHANDQUICKEN , SC_TWOHANDQUICKEN , SI_TWOHANDQUICKEN , SCB_ASPD ); set_sc( KN_AUTOCOUNTER , SC_AUTOCOUNTER , SI_AUTOCOUNTER , SCB_NONE ); - set_sc( PR_IMPOSITIO , SC_IMPOSITIO , SI_IMPOSITIO , -#ifdef RENEWAL - SCB_NONE ); -#else - SCB_WATK ); -#endif + set_sc( PR_IMPOSITIO , SC_IMPOSITIO , SI_IMPOSITIO , SCB_WATK ); set_sc( PR_SUFFRAGIUM , SC_SUFFRAGIUM , SI_SUFFRAGIUM , SCB_NONE ); set_sc( PR_ASPERSIO , SC_ASPERSIO , SI_ASPERSIO , SCB_ATK_ELE ); set_sc( PR_BENEDICTIO , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE ); @@ -344,12 +339,7 @@ void initChangeTables(void) set_sc( SA_FROSTWEAPON , SC_WATERWEAPON , SI_WATERWEAPON , SCB_ATK_ELE ); set_sc( SA_LIGHTNINGLOADER , SC_WINDWEAPON , SI_WINDWEAPON , SCB_ATK_ELE ); set_sc( SA_SEISMICWEAPON , SC_EARTHWEAPON , SI_EARTHWEAPON , SCB_ATK_ELE ); - set_sc( SA_VOLCANO , SC_VOLCANO , SI_LANDENDOW , -#ifdef RENEWAL - SCB_NONE ); -#else - SCB_WATK ); -#endif + set_sc( SA_VOLCANO , SC_VOLCANO , SI_LANDENDOW , SCB_WATK ); set_sc( SA_DELUGE , SC_DELUGE , SI_LANDENDOW , SCB_MAXHP ); set_sc( SA_VIOLENTGALE , SC_VIOLENTGALE , SI_LANDENDOW , SCB_FLEE ); add_sc( SA_REVERSEORCISH , SC_ORCISH ); @@ -357,17 +347,8 @@ void initChangeTables(void) set_sc( BD_ENCORE , SC_DANCING , SI_BDPLAYING , SCB_SPEED|SCB_REGEN ); set_sc( BD_RICHMANKIM , SC_RICHMANKIM , SI_RICHMANKIM , SCB_NONE ); set_sc( BD_ETERNALCHAOS , SC_ETERNALCHAOS , SI_ETERNALCHAOS , SCB_DEF2 ); - set_sc( BD_DRUMBATTLEFIELD , SC_DRUMBATTLE , SI_DRUMBATTLEFIELD , SCB_DEF -#ifndef RENEWAL - |SCB_WATK -#endif - ); - set_sc( BD_RINGNIBELUNGEN , SC_NIBELUNGEN , SI_RINGNIBELUNGEN , -#ifdef RENEWAL - SCB_NONE ); -#else - SCB_WATK ); -#endif + set_sc( BD_DRUMBATTLEFIELD , SC_DRUMBATTLE , SI_DRUMBATTLEFIELD , SCB_WATK|SCB_DEF ); + set_sc( BD_RINGNIBELUNGEN , SC_NIBELUNGEN , SI_RINGNIBELUNGEN , SCB_WATK ); set_sc( BD_ROKISWEIL , SC_ROKISWEIL , SI_ROKISWEIL , SCB_NONE ); set_sc( BD_INTOABYSS , SC_INTOABYSS , SI_INTOABYSS , SCB_NONE ); set_sc( BD_SIEGFRIED , SC_SIEGFRIED , SI_SIEGFRIED , SCB_ALL ); @@ -392,12 +373,7 @@ void initChangeTables(void) add_sc( NPC_INVISIBLE , SC_CLOAKING ); set_sc( LK_AURABLADE , SC_AURABLADE , SI_AURABLADE , SCB_NONE ); set_sc( LK_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE ); - set_sc( LK_CONCENTRATION , SC_CONCENTRATION , SI_CONCENTRATION , -#ifndef RENEWAL - SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2 ); -#else - SCB_HIT|SCB_DEF ); -#endif + set_sc( LK_CONCENTRATION , SC_CONCENTRATION , SI_CONCENTRATION , SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2 ); set_sc( LK_TENSIONRELAX , SC_TENSIONRELAX , SI_TENSIONRELAX , SCB_REGEN ); set_sc( LK_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN ); set_sc( HP_ASSUMPTIO , SC_ASSUMPTIO , @@ -477,18 +453,10 @@ void initChangeTables(void) add_sc( GS_CRACKER , SC_STUN ); add_sc( GS_DISARM , SC_STRIPWEAPON ); add_sc( GS_PIERCINGSHOT , SC_BLEEDING ); - set_sc( GS_MADNESSCANCEL , SC_MADNESSCANCEL , SI_MADNESSCANCEL , SCB_ASPD -#ifndef RENEWAL - |SCB_BATK -#endif - ); + set_sc( GS_MADNESSCANCEL , SC_MADNESSCANCEL , SI_MADNESSCANCEL , SCB_BATK|SCB_ASPD ); set_sc( GS_ADJUSTMENT , SC_ADJUSTMENT , SI_ADJUSTMENT , SCB_HIT|SCB_FLEE ); set_sc( GS_INCREASING , SC_INCREASING , SI_ACCURACY , SCB_AGI|SCB_DEX|SCB_HIT ); - set_sc( GS_GATLINGFEVER , SC_GATLINGFEVER , SI_GATLINGFEVER , SCB_FLEE|SCB_SPEED|SCB_ASPD -#ifndef RENWAL - |SCB_BATK -#endif - ); + set_sc( GS_GATLINGFEVER , SC_GATLINGFEVER , SI_GATLINGFEVER , SCB_BATK|SCB_FLEE|SCB_SPEED|SCB_ASPD ); add_sc( NJ_TATAMIGAESHI , SC_TATAMIGAESHI ); set_sc( NJ_SUITON , SC_SUITON , SI_BLANK , SCB_AGI|SCB_SPEED ); add_sc( NJ_HYOUSYOURAKU , SC_FREEZE ); @@ -609,7 +577,7 @@ void initChangeTables(void) set_sc( RK_GIANTGROWTH , SC_GIANTGROWTH , SI_GIANTGROWTH , SCB_STR ); set_sc( RK_STONEHARDSKIN , SC_STONEHARDSKIN , SI_STONEHARDSKIN , SCB_DEF|SCB_MDEF ); set_sc( RK_VITALITYACTIVATION , SC_VITALITYACTIVATION , SI_VITALITYACTIVATION , SCB_REGEN ); - set_sc( RK_FIGHTINGSPIRIT , SC_FIGHTINGSPIRIT , SI_FIGHTINGSPIRIT , SCB_ASPD ); + set_sc( RK_FIGHTINGSPIRIT , SC_FIGHTINGSPIRIT , SI_FIGHTINGSPIRIT , SCB_WATK|SCB_ASPD ); set_sc( RK_ABUNDANCE , SC_ABUNDANCE , SI_ABUNDANCE , SCB_NONE ); set_sc( RK_CRUSHSTRIKE , SC_CRUSHSTRIKE , SI_CRUSHSTRIKE , SCB_NONE ); set_sc_with_vfx( RK_DRAGONBREATH_WATER , SC_FREEZING , SI_FROSTMISTY , SCB_ASPD|SCB_SPEED|SCB_DEF|SCB_DEF2 ); @@ -680,15 +648,10 @@ void initChangeTables(void) set_sc( LG_FORCEOFVANGUARD , SC_FORCEOFVANGUARD , SI_FORCEOFVANGUARD , SCB_MAXHP ); set_sc( LG_EXEEDBREAK , SC_EXEEDBREAK , SI_EXEEDBREAK , SCB_NONE ); set_sc( LG_PRESTIGE , SC_PRESTIGE , SI_PRESTIGE , SCB_DEF ); - set_sc( LG_BANDING , SC_BANDING , SI_BANDING , -#ifndef RENEWAL - SCB_DEF ); -#else - SCB_DEF2 ); -#endif + set_sc( LG_BANDING , SC_BANDING , SI_BANDING , SCB_DEF2|SCB_WATK ); set_sc( LG_PIETY , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE ); set_sc( LG_EARTHDRIVE , SC_EARTHDRIVE , SI_EARTHDRIVE , SCB_DEF|SCB_ASPD ); - set_sc( LG_INSPIRATION , SC_INSPIRATION , SI_INSPIRATION , SCB_MAXHP|SCB_HIT|SCB_VIT|SCB_AGI|SCB_STR|SCB_DEX|SCB_INT|SCB_LUK); + set_sc( LG_INSPIRATION , SC_INSPIRATION , SI_INSPIRATION , SCB_WATK|SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK|SCB_HIT|SCB_MAXHP); set_sc( LG_KINGS_GRACE , SC_KINGS_GRACE , SI_KINGS_GRACE , SCB_NONE ); /* Shadow Chaser */ @@ -718,7 +681,7 @@ void initChangeTables(void) set_sc( SR_LIGHTNINGWALK , SC_LIGHTNINGWALK , SI_LIGHTNINGWALK , SCB_NONE ); set_sc( SR_RAISINGDRAGON , SC_RAISINGDRAGON , SI_RAISINGDRAGON , SCB_REGEN|SCB_MAXHP|SCB_MAXSP ); set_sc( SR_GENTLETOUCH_ENERGYGAIN , SC_GT_ENERGYGAIN , SI_GENTLETOUCH_ENERGYGAIN , SCB_NONE ); - set_sc( SR_GENTLETOUCH_CHANGE , SC_GT_CHANGE , SI_GENTLETOUCH_CHANGE , SCB_MDEF|SCB_ASPD|SCB_MAXHP ); + set_sc( SR_GENTLETOUCH_CHANGE , SC_GT_CHANGE , SI_GENTLETOUCH_CHANGE , SCB_WATK|SCB_MDEF|SCB_ASPD|SCB_MAXHP ); set_sc( SR_GENTLETOUCH_REVITALIZE , SC_GT_REVITALIZE , SI_GENTLETOUCH_REVITALIZE , SCB_MAXHP|SCB_REGEN ); add_sc( SR_FLASHCOMBO , SC_FLASHCOMBO ); @@ -726,7 +689,7 @@ void initChangeTables(void) set_sc( WA_SWING_DANCE , SC_SWINGDANCE , SI_SWINGDANCE , SCB_SPEED|SCB_ASPD ); set_sc( WA_SYMPHONY_OF_LOVER , SC_SYMPHONYOFLOVER , SI_SYMPHONYOFLOVERS , SCB_MDEF ); set_sc( WA_MOONLIT_SERENADE , SC_MOONLITSERENADE , SI_MOONLITSERENADE , SCB_MATK ); - set_sc( MI_RUSH_WINDMILL , SC_RUSHWINDMILL , SI_RUSHWINDMILL , SCB_NONE ); + set_sc( MI_RUSH_WINDMILL , SC_RUSHWINDMILL , SI_RUSHWINDMILL , SCB_WATK ); set_sc( MI_ECHOSONG , SC_ECHOSONG , SI_ECHOSONG , SCB_DEF ); set_sc( MI_HARMONIZE , SC_HARMONIZE , SI_HARMONIZE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); set_sc_with_vfx( WM_POEMOFNETHERWORLD , SC_NETHERWORLD , SI_NETHERWORLD , SCB_NONE ); @@ -736,7 +699,7 @@ void initChangeTables(void) set_sc( WM_GLOOMYDAY , SC_GLOOMYDAY , SI_GLOOMYDAY , SCB_FLEE|SCB_SPEED|SCB_ASPD ); set_sc( WM_SONG_OF_MANA , SC_SONGOFMANA , SI_SONGOFMANA , SCB_NONE ); set_sc( WM_DANCE_WITH_WUG , SC_DANCEWITHWUG , SI_DANCEWITHWUG , SCB_ASPD ); - set_sc( WM_SATURDAY_NIGHT_FEVER , SC_SATURDAYNIGHTFEVER , SI_SATURDAYNIGHTFEVER , SCB_DEF|SCB_FLEE|SCB_REGEN ); + set_sc( WM_SATURDAY_NIGHT_FEVER , SC_SATURDAYNIGHTFEVER , SI_SATURDAYNIGHTFEVER , SCB_BATK|SCB_DEF|SCB_FLEE|SCB_REGEN ); set_sc( WM_LERADS_DEW , SC_LERADSDEW , SI_LERADSDEW , SCB_MAXHP ); set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SI_MELODYOFSINK , SCB_INT ); set_sc( WM_BEYOND_OF_WARCRY , SC_BEYONDOFWARCRY , SI_WARCRYOFBEYOND , SCB_STR|SCB_CRI|SCB_MAXHP ); @@ -781,9 +744,9 @@ void initChangeTables(void) set_sc( EL_SOLID_SKIN , SC_SOLID_SKIN_OPTION , SI_SOLID_SKIN_OPTION , SCB_DEF|SCB_MAXHP ); set_sc( EL_STONE_SHIELD , SC_STONE_SHIELD_OPTION , SI_STONE_SHIELD_OPTION , SCB_ALL ); set_sc( EL_POWER_OF_GAIA , SC_POWER_OF_GAIA , SI_POWER_OF_GAIA , SCB_MAXHP|SCB_DEF|SCB_SPEED ); - set_sc( EL_PYROTECHNIC , SC_PYROTECHNIC_OPTION , SI_PYROTECHNIC_OPTION , SCB_NONE ); - set_sc( EL_HEATER , SC_HEATER_OPTION , SI_HEATER_OPTION , SCB_NONE ); - set_sc( EL_TROPIC , SC_TROPIC_OPTION , SI_TROPIC_OPTION , SCB_NONE ); + set_sc( EL_PYROTECHNIC , SC_PYROTECHNIC_OPTION , SI_PYROTECHNIC_OPTION , SCB_WATK ); + set_sc( EL_HEATER , SC_HEATER_OPTION , SI_HEATER_OPTION , SCB_WATK ); + set_sc( EL_TROPIC , SC_TROPIC_OPTION , SI_TROPIC_OPTION , SCB_WATK ); set_sc( EL_AQUAPLAY , SC_AQUAPLAY_OPTION , SI_AQUAPLAY_OPTION , SCB_MATK ); set_sc( EL_COOLER , SC_COOLER_OPTION , SI_COOLER_OPTION , SCB_MATK ); set_sc( EL_CHILLY_AIR , SC_CHILLY_AIR_OPTION , SI_CHILLY_AIR_OPTION , SCB_MATK ); @@ -1081,6 +1044,7 @@ void initChangeTables(void) StatusChangeFlagTable[SC_PYREXIA] |= SCB_HIT|SCB_FLEE; StatusChangeFlagTable[SC_OBLIVIONCURSE] |= SCB_REGEN; StatusChangeFlagTable[SC_BANDING_DEFENCE] |= SCB_SPEED; + StatusChangeFlagTable[SC_SHIELDSPELL_DEF] |= SCB_WATK; StatusChangeFlagTable[SC_SHIELDSPELL_REF] |= SCB_DEF; StatusChangeFlagTable[SC_STOMACHACHE] |= SCB_STR|SCB_AGI|SCB_VIT|SCB_DEX|SCB_INT|SCB_LUK; StatusChangeFlagTable[SC_MYSTERIOUS_POWDER] |= SCB_MAXHP; @@ -2935,6 +2899,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) + sizeof(sd->skillfixcast) + sizeof(sd->skillvarcast) + sizeof(sd->skillfixcastrate) + + sizeof(sd->def_set_race) + + sizeof(sd->mdef_set_race) ); memset (&sd->bonus, 0,sizeof(sd->bonus)); @@ -4782,7 +4748,7 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang if(sc->data[SC_SAVAGE_STEAK]) str += sc->data[SC_SAVAGE_STEAK]->val1; if(sc->data[SC_INSPIRATION]) - str += sc->data[SC_INSPIRATION]->val2; + str += sc->data[SC_INSPIRATION]->val3; if(sc->data[SC_STOMACHACHE]) str -= sc->data[SC_STOMACHACHE]->val1; if(sc->data[SC_KYOUGAKU]) @@ -4846,7 +4812,7 @@ static unsigned short status_calc_agi(struct block_list *bl, struct status_chang if(sc->data[SC_DROCERA_HERB_STEAMED]) agi += sc->data[SC_DROCERA_HERB_STEAMED]->val1; if(sc->data[SC_INSPIRATION]) - agi += sc->data[SC_INSPIRATION]->val2; + agi += sc->data[SC_INSPIRATION]->val3; if(sc->data[SC_STOMACHACHE]) agi -= sc->data[SC_STOMACHACHE]->val1; if(sc->data[SC_KYOUGAKU]) @@ -4898,7 +4864,7 @@ static unsigned short status_calc_vit(struct block_list *bl, struct status_chang if(sc->data[SC_MINOR_BBQ]) vit += sc->data[SC_MINOR_BBQ]->val1; if(sc->data[SC_INSPIRATION]) - vit += sc->data[SC_INSPIRATION]->val2; + vit += sc->data[SC_INSPIRATION]->val3; if(sc->data[SC_STOMACHACHE]) vit -= sc->data[SC_STOMACHACHE]->val1; if(sc->data[SC_KYOUGAKU]) @@ -4959,14 +4925,14 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang int_ -= ((sc->data[SC_MARIONETTE]->val4)>>16)&0xFF; if(sc->data[SC_MARIONETTE2]) int_ += ((sc->data[SC_MARIONETTE2]->val4)>>16)&0xFF; + if(sc->data[SC_INSPIRATION]) + int_ += sc->data[SC_INSPIRATION]->val3; if(sc->data[SC_MELODYOFSINK]) int_ -= sc->data[SC_MELODYOFSINK]->val3; if(sc->data[SC_MANDRAGORA]) int_ -= 4 * sc->data[SC_MANDRAGORA]->val1; if(sc->data[SC_COCKTAIL_WARG_BLOOD]) int_ += sc->data[SC_COCKTAIL_WARG_BLOOD]->val1; - if(sc->data[SC_INSPIRATION]) - int_ += sc->data[SC_INSPIRATION]->val2; if(sc->data[SC_STOMACHACHE]) int_ -= sc->data[SC_STOMACHACHE]->val1; if(sc->data[SC_KYOUGAKU]) @@ -5035,7 +5001,7 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang if(sc->data[SC_SIROMA_ICE_TEA]) dex += sc->data[SC_SIROMA_ICE_TEA]->val1; if(sc->data[SC_INSPIRATION]) - dex += sc->data[SC_INSPIRATION]->val2; + dex += sc->data[SC_INSPIRATION]->val3; if(sc->data[SC_STOMACHACHE]) dex -= sc->data[SC_STOMACHACHE]->val1; if(sc->data[SC_KYOUGAKU]) @@ -5090,7 +5056,7 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang if(sc->data[SC_PUTTI_TAILS_NOODLES]) luk += sc->data[SC_PUTTI_TAILS_NOODLES]->val1; if(sc->data[SC_INSPIRATION]) - luk += sc->data[SC_INSPIRATION]->val2; + luk += sc->data[SC_INSPIRATION]->val3; if(sc->data[SC_STOMACHACHE]) luk -= sc->data[SC_STOMACHACHE]->val1; if(sc->data[SC_KYOUGAKU]) @@ -5122,14 +5088,12 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan if(sc->data[SC_ATKPOTION]) batk += sc->data[SC_ATKPOTION]->val1; -#ifndef RENEWAL - if(sc->data[SC_MADNESSCANCEL]) - batk += 100; - if(sc->data[SC_GATLINGFEVER]) - batk += sc->data[SC_GATLINGFEVER]->val3; -#endif if(sc->data[SC_BATKFOOD]) batk += sc->data[SC_BATKFOOD]->val1; + if(sc->data[SC_GATLINGFEVER]) + batk += sc->data[SC_GATLINGFEVER]->val3; + if(sc->data[SC_MADNESSCANCEL]) + batk += 100; if(sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2) batk += 50; if(bl->type == BL_ELEM @@ -5152,10 +5116,8 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan batk += batk * sc->data[SC_INCATKRATE]->val1/100; if(sc->data[SC_PROVOKE]) batk += batk * sc->data[SC_PROVOKE]->val3/100; -#ifndef RENEWAL if(sc->data[SC_CONCENTRATION]) batk += batk * sc->data[SC_CONCENTRATION]->val2/100; -#endif if(sc->data[SC_SKE]) batk += batk * 3; if(sc->data[SC_BLOODLUST]) @@ -5171,6 +5133,8 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan batk += batk * sc->data[SC_FLEET]->val3/100; if(sc->data[SC__ENERVATION]) batk -= batk * sc->data[SC__ENERVATION]->val2 / 100; + if(sc->data[SC_SATURDAYNIGHTFEVER]) + batk += 100 * sc->data[SC_SATURDAYNIGHTFEVER]->val1; if( sc->data[SC_ZANGETSU] ) batk += sc->data[SC_ZANGETSU]->val2; if(sc->data[SC_EQC]) @@ -5197,18 +5161,22 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan if(!sc || !sc->count) return cap_value(watk,0,USHRT_MAX); - if(sc->data[SC_WATKFOOD]) - watk += sc->data[SC_WATKFOOD]->val1; -#ifndef RENEWAL if(sc->data[SC_IMPOSITIO]) watk += sc->data[SC_IMPOSITIO]->val2; - if(sc->data[SC_VOLCANO]) - watk += sc->data[SC_VOLCANO]->val2; + if(sc->data[SC_WATKFOOD]) + watk += sc->data[SC_WATKFOOD]->val1; if(sc->data[SC_DRUMBATTLE]) watk += sc->data[SC_DRUMBATTLE]->val2; + if(sc->data[SC_VOLCANO]) + watk += sc->data[SC_VOLCANO]->val2; + if(sc->data[SC_MERC_ATKUP]) + watk += sc->data[SC_MERC_ATKUP]->val2; + if(sc->data[SC_WATER_BARRIER]) + watk -= sc->data[SC_WATER_BARRIER]->val3; if(sc->data[SC_NIBELUNGEN]) { if (bl->type != BL_PC) watk += sc->data[SC_NIBELUNGEN]->val2; + #ifndef RENEWAL else { TBL_PC *sd = (TBL_PC*)bl; int index = sd->equip_index[sd->state.lr_flag?EQI_HAND_L:EQI_HAND_R]; @@ -5216,18 +5184,14 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4) watk += sc->data[SC_NIBELUNGEN]->val2; } + #endif } - if(sc->data[SC_CONCENTRATION]) - watk += watk * sc->data[SC_CONCENTRATION]->val2/100; -#endif - if(sc->data[SC_MERC_ATKUP]) - watk += sc->data[SC_MERC_ATKUP]->val2; - if(sc->data[SC_WATER_BARRIER]) - watk -= sc->data[SC_WATER_BARRIER]->val3; if(sc->data[SC_INCATKRATE]) watk += watk * sc->data[SC_INCATKRATE]->val1/100; if(sc->data[SC_PROVOKE]) watk += watk * sc->data[SC_PROVOKE]->val3/100; + if(sc->data[SC_CONCENTRATION]) + watk += watk * sc->data[SC_CONCENTRATION]->val2/100; if(sc->data[SC_SKE]) watk += watk * 3; if(sc->data[SC_FLEET]) @@ -5236,15 +5200,33 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan watk -= watk * 25/100; if(sc->data[SC_STRIPWEAPON] && bl->type != BL_PC) watk -= watk * sc->data[SC_STRIPWEAPON]->val2/100; + if(sc->data[SC_FIGHTINGSPIRIT]) + watk += sc->data[SC_FIGHTINGSPIRIT]->val1; + if(sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 3) + watk += sc->data[SC_SHIELDSPELL_DEF]->val2; + if(sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1) + watk += (10 + 10 * sc->data[SC_BANDING]->val1) * sc->data[SC_BANDING]->val2; + if(sc->data[SC_INSPIRATION]) + watk += 40 * sc->data[SC_INSPIRATION]->val1 + 3 * sc->data[SC_INSPIRATION]->val2; + if(sc->data[SC_GT_CHANGE] && sc->data[SC_GT_CHANGE]->val2) + watk += sc->data[SC_GT_CHANGE]->val2; if(sc->data[SC__ENERVATION]) watk -= watk * sc->data[SC__ENERVATION]->val2 / 100; if(sc->data[SC_STRIKING]) watk += sc->data[SC_STRIKING]->val2; + if(sc->data[SC_RUSHWINDMILL]) + watk += sc->data[SC_RUSHWINDMILL]->val3; if((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2) || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2) || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 2) || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2)) watk += watk / 10; + if(sc->data[SC_PYROTECHNIC_OPTION]) + watk += sc->data[SC_PYROTECHNIC_OPTION]->val2; + if(sc->data[SC_HEATER_OPTION]) + watk += sc->data[SC_HEATER_OPTION]->val2; + if(sc->data[SC_TROPIC_OPTION]) + watk += sc->data[SC_TROPIC_OPTION]->val2; if( sc && sc->data[SC_TIDAL_WEAPON] ) watk += watk * sc->data[SC_TIDAL_WEAPON]->val2 / 100; if(bl->type == BL_PC && sc->data[SC_PYROCLASTIC]) @@ -5422,7 +5404,7 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change if(sc->data[SC_CONCENTRATION]) hit += sc->data[SC_CONCENTRATION]->val3; if(sc->data[SC_INSPIRATION]) - hit += 5 * sc->data[SC_INSPIRATION]->val1 + sc->data[SC_INSPIRATION]->val3 / 2; + hit += 5 * sc->data[SC_INSPIRATION]->val1 + sc->data[SC_INSPIRATION]->val2 / 2; if(sc->data[SC_ADJUSTMENT]) hit -= 30; if(sc->data[SC_INCREASING]) @@ -5643,10 +5625,8 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc, def += sc->data[SC_SHIELDSPELL_REF]->val2; if( sc->data[SC_PRESTIGE] ) def += sc->data[SC_PRESTIGE]->val1; -#ifndef RENEWAL if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1 ) def += (5 + sc->data[SC_BANDING]->val1) * sc->data[SC_BANDING]->val2 / 10; -#endif if( sc->data[SC_ECHOSONG] ) def += def * sc->data[SC_ECHOSONG]->val3 / 100; if( sc->data[SC_SATURDAYNIGHTFEVER] ) @@ -5694,19 +5674,17 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change if(sc->data[SC_SUN_COMFORT]) def2 += sc->data[SC_SUN_COMFORT]->val2; -#ifdef RENEWAL if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1 ) def2 += (5 + sc->data[SC_BANDING]->val1) * sc->data[SC_BANDING]->val2; -#endif if(sc->data[SC_ANGELUS]) #ifdef RENEWAL /// The VIT stat bonus is boosted by angelus [RENEWAL] def2 += status_get_vit(bl) / 2 * sc->data[SC_ANGELUS]->val2/100; #else def2 += def2 * sc->data[SC_ANGELUS]->val2/100; +#endif if(sc->data[SC_CONCENTRATION]) def2 -= def2 * sc->data[SC_CONCENTRATION]->val4/100; -#endif if(sc->data[SC_POISON]) def2 -= def2 * 25/100; if(sc->data[SC_DPOISON]) @@ -8935,7 +8913,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty val2 = 5*val1; // def increase break; case SC_IMPOSITIO: - val2 = 5*val1; // Atk increase + val2 = 5*val1; // Watk increase break; case SC_MELTDOWN: val2 = 100*val1; // Chance to break weapon @@ -9478,8 +9456,8 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty break; case SC_INSPIRATION: if( sd ) { - val2 = status_get_lv(bl) / 10 + (sd?sd->status.job_level:50) / 5; // All stat bonus - val3 = (sd?sd->status.job_level:50); + val2 = (sd?sd->status.job_level:50); + val3 = status_get_lv(bl) / 10 + val2 / 5; //All stat bonus } val4 = tick / 5000; tick_time = 5000; // [GodLesZ] tick time @@ -9503,8 +9481,10 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty { // Take note there is no def increase as skill desc says. [malufett] struct block_list * src2; val3 = status->agi * val1 / 60; // ASPD increase: [(Target AGI x Skill Level) / 60] % - if( (src2 = map_id2bl(val2)) ) + if( (src2 = map_id2bl(val2)) ) { + val2 = (status_get_dex(src2) / 4 + status_get_str(src2) / 2) * val1 / 5; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5] val4 = ( 200/status_get_int(src2) ) * val1; // MDEF decrease: MDEF [(200 / Caster INT) x Skill Level] + } if( val4 < 0 ) val4 = 0; } diff --git a/src/map/unit.c b/src/map/unit.c index 3475528dbf..f0a845ff9b 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1142,6 +1142,7 @@ int unit_can_move(struct block_list *bl) { )) return 0; // Can't move + // Status changes that block movement if (sc) { if( sc->cant.move // status placed here are ones that cannot be cached by sc->cant.move for they depend on other conditions other than their availability || (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0) @@ -1268,7 +1269,9 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui sc = NULL; // Unneeded // temp: used to signal combo-skills right now. - if (sc && sc->data[SC_COMBO] && (sc->data[SC_COMBO]->val1 == skill_id || + if (sc && sc->data[SC_COMBO] && + skill_is_combo(skill_id) && + (sc->data[SC_COMBO]->val1 == skill_id || (sd?skill_check_condition_castbegin(sd,skill_id,skill_lv):0) )) { if (sc->data[SC_COMBO]->val2) @@ -1854,6 +1857,10 @@ int unit_attack(struct block_list *src,int target_id,int continuous) unit_stop_attack(src); return 0; } + if( !pc_can_attack(sd, target_id) ) { + unit_stop_attack(src); + return 0; + } } if( battle_check_target(src,target,BCT_ENEMY) <= 0 || !status_check_skilluse(src, target, 0, 0) ) { unit_unattackable(src); @@ -2066,7 +2073,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t #ifdef OFFICIAL_WALKPATH || !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) #endif - ) + || (sd && !pc_can_attack(sd, target->id)) ) return 0; // Can't attack under these conditions if (sd && &sd->sc && sd->sc.count && sd->sc.data[SC_HEAT_BARREL_AFTER])