diff --git a/common/spdat.h b/common/spdat.h index aaa2dcc6e..c41c22347 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -609,7 +609,7 @@ typedef enum { #define SE_TradeSkillMastery 263 // implemented - lets you raise more than one tradeskill above master. #define SE_HastenedAASkill 264 // implemented #define SE_MasteryofPast 265 // implemented[AA] - Spells less than effect values level can not be fizzled -#define SE_ExtraAttackChance 266 // implemented - increase chance to score an extra attack with a 2-Handed Weapon. +#define SE_ExtraAttackChance 266 // implemented, @OffBonus, gives your double attacks a percent chance to perform an extra attack with 2-handed primary weapon, base: chance, limit: amt attacks, max: none #define SE_AddPetCommand 267 // implemented - sets command base2 to base1 #define SE_ReduceTradeskillFail 268 // implemented - reduces chance to fail with given tradeskill by a percent chance #define SE_MaxBindWound 269 // implemented[AA] - Increase max HP you can bind wound. @@ -841,8 +841,8 @@ typedef enum { //#define SE_Ff_DurationMax 495 // #define SE_Critical_Melee_Damage_Mod_Max 496 // implemented - increase or decrease by percent critical damage (not stackable) //#define SE_Ff_FocusCastProcNoBypass 497 // -//#define SE_AddExtraAttackPct_1h_Primary 498 // -//#define SE_AddExtraAttackPct_1h_Secondary 499 // +#define SE_AddExtraAttackPct_1h_Primary 498 // implemented, @OffBonus, gives your double attacks a percent chance to perform an extra attack with 1-handed primary weapon, base: chance, limit: amt attacks, max: none +#define SE_AddExtraAttackPct_1h_Secondary 499 //implemented, @OffBonus, gives your double attacks a percent chance to perform an extra attack with 1-handed secondary weapon, base: chance, limit: amt attacks, max: none //#define SE_Fc_CastTimeMod2 500 // //#define SE_Fc_CastTimeAmt 501 // #define SE_Fearstun 502 // implemented - Stun with a max level limit. Normal stun restrictions don't apply. diff --git a/zone/attack.cpp b/zone/attack.cpp index d09271c55..aa6c30bd4 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -5483,13 +5483,40 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) CheckIncreaseSkill(EQ::skills::SkillDoubleAttack, target, -10); if (CheckDoubleAttack()) { Attack(target, hand, false, false, IsFromSpell); - - // Modern AA description: Increases your chance of ... performing one additional hit with a 2-handed weapon when double attacking by 2%. + if (hand == EQ::invslot::slotPrimary) { - auto extraattackchance = aabonuses.ExtraAttackChance + spellbonuses.ExtraAttackChance + - itembonuses.ExtraAttackChance; - if (extraattackchance && HasTwoHanderEquipped() && zone->random.Roll(extraattackchance)) - Attack(target, hand, false, false, IsFromSpell); + + if (HasTwoHanderEquipped()) { + auto extraattackchance = aabonuses.ExtraAttackChance[0] + spellbonuses.ExtraAttackChance[0] + + itembonuses.ExtraAttackChance[0]; + if (extraattackchance && zone->random.Roll(extraattackchance)) { + auto extraattackamt = std::max({ aabonuses.ExtraAttackChance[1], spellbonuses.ExtraAttackChance[1], itembonuses.ExtraAttackChance[1] }); + for (int i = 0; i < extraattackamt; i++) { + Attack(target, hand, false, false, IsFromSpell); + } + } + } + else { + auto extraattackchance_primary = aabonuses.ExtraAttackChancePrimary[0] + spellbonuses.ExtraAttackChancePrimary[0] + + itembonuses.ExtraAttackChancePrimary[0]; + if (extraattackchance_primary && zone->random.Roll(extraattackchance_primary)) { + auto extraattackamt_primary = std::max({ aabonuses.ExtraAttackChancePrimary[1], spellbonuses.ExtraAttackChancePrimary[1], itembonuses.ExtraAttackChancePrimary[1] }); + for (int i = 0; i < extraattackamt_primary; i++) { + Attack(target, hand, false, false, IsFromSpell); + } + } + } + } + + if (hand == EQ::invslot::slotSecondary) { + auto extraattackchance_secondary = aabonuses.ExtraAttackChanceSecondary[0] + spellbonuses.ExtraAttackChanceSecondary[0] + + itembonuses.ExtraAttackChanceSecondary[0]; + if (extraattackchance_secondary && zone->random.Roll(extraattackchance_secondary)) { + auto extraattackamt_secondary = std::max({ aabonuses.ExtraAttackChanceSecondary[1], spellbonuses.ExtraAttackChanceSecondary[1], itembonuses.ExtraAttackChanceSecondary[1] }); + for (int i = 0; i < extraattackamt_secondary; i++) { + Attack(target, hand, false, false, IsFromSpell); + } + } } // you can only triple from the main hand diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 437468dcb..e52e61533 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -860,9 +860,6 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_MaxBindWound: newbon->MaxBindWound += base1; break; - case SE_ExtraAttackChance: - newbon->ExtraAttackChance += base1; - break; case SE_SeeInvis: newbon->SeeInvis = base1; break; @@ -984,7 +981,6 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_BlockBehind: newbon->BlockBehind += base1; break; - case SE_StrikeThrough: case SE_StrikeThrough2: newbon->StrikeThrough += base1; @@ -1572,6 +1568,34 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) newbon->Pet_Add_Atk += base1; break; + case SE_ExtraAttackChance: + { + if (newbon->ExtraAttackChance[0] < base1) { + newbon->ExtraAttackChance[0] = base1; + newbon->ExtraAttackChance[1] = base2 ? base2 : 1; + } + break; + } + + case SE_AddExtraAttackPct_1h_Primary: + { + if (newbon->ExtraAttackChancePrimary[0] < base1) { + newbon->ExtraAttackChancePrimary[0] = base1; + newbon->ExtraAttackChancePrimary[1] = base2 ? base2 : 1; + } + break; + } + + case SE_AddExtraAttackPct_1h_Secondary: + { + + if (newbon->ExtraAttackChanceSecondary[0] < base1) { + newbon->ExtraAttackChanceSecondary[0] = base1; + newbon->ExtraAttackChanceSecondary[1] = base2 ? base2 : 1; + } + break; + } + // to do case SE_PetDiscipline: break; @@ -2382,8 +2406,45 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne } case SE_ExtraAttackChance: - new_bonus->ExtraAttackChance += effect_value; + { + if (AdditiveWornBonus) { + new_bonus->ExtraAttackChance[0] += effect_value; + new_bonus->ExtraAttackChance[1] = base2 ? base2 : 1; + } + if (new_bonus->ExtraAttackChance[0] < effect_value) { + new_bonus->ExtraAttackChance[0] = effect_value; + new_bonus->ExtraAttackChance[1] = base2 ? base2 : 1; + } break; + } + + case SE_AddExtraAttackPct_1h_Primary: + { + if (AdditiveWornBonus) { + new_bonus->ExtraAttackChancePrimary[0] += effect_value; + new_bonus->ExtraAttackChancePrimary[1] = base2 ? base2 : 1; + } + + if (new_bonus->ExtraAttackChancePrimary[0] < effect_value) { + new_bonus->ExtraAttackChancePrimary[0] = effect_value; + new_bonus->ExtraAttackChancePrimary[1] = base2 ? base2 : 1; + } + break; + } + + case SE_AddExtraAttackPct_1h_Secondary: + { + if (AdditiveWornBonus) { + new_bonus->ExtraAttackChanceSecondary[0] += effect_value; + new_bonus->ExtraAttackChanceSecondary[1] = base2 ? base2 : 1; + } + + if (new_bonus->ExtraAttackChanceSecondary[0] < effect_value) { + new_bonus->ExtraAttackChanceSecondary[0] = effect_value; + new_bonus->ExtraAttackChanceSecondary[1] = base2 ? base2 : 1; + } + break; + } case SE_PercentXPIncrease: { @@ -4302,9 +4363,21 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) break; case SE_ExtraAttackChance: - spellbonuses.ExtraAttackChance = effect_value; - aabonuses.ExtraAttackChance = effect_value; - itembonuses.ExtraAttackChance = effect_value; + spellbonuses.ExtraAttackChance[0] = effect_value; + aabonuses.ExtraAttackChance[0] = effect_value; + itembonuses.ExtraAttackChance[0] = effect_value; + break; + + case SE_AddExtraAttackPct_1h_Primary: + spellbonuses.ExtraAttackChancePrimary[0] = effect_value; + aabonuses.ExtraAttackChancePrimary[0] = effect_value; + itembonuses.ExtraAttackChancePrimary[0] = effect_value; + break; + + case SE_AddExtraAttackPct_1h_Secondary: + spellbonuses.ExtraAttackChanceSecondary[0] = effect_value; + aabonuses.ExtraAttackChanceSecondary[0] = effect_value; + itembonuses.ExtraAttackChanceSecondary[0] = effect_value; break; case SE_PercentXPIncrease: diff --git a/zone/common.h b/zone/common.h index 16d762915..e2aa19af5 100644 --- a/zone/common.h +++ b/zone/common.h @@ -446,7 +446,9 @@ struct StatBonuses { int32 MinDamageModifier[EQ::skills::HIGHEST_SKILL + 2]; //i int32 ProcChance; // ProcChance/10 == % increase i = CombatEffects int32 ProcChanceSPA; // ProcChance from spell effects - int32 ExtraAttackChance; + int32 ExtraAttackChance[2]; // base chance(w/ 2H weapon)=0, amt of extra attacks=1 + int32 ExtraAttackChancePrimary[2]; // base chance=0, , amt of extra attacks=1 + int32 ExtraAttackChanceSecondary[2]; // base chance=0, , amt of extra attacks=1 int32 DoTShielding; int32 DivineSaveChance[2]; // Second Chance (base1 = chance, base2 = spell on trigger) uint32 DeathSave[4]; // Death Pact [0](value = 1 partial 2 = full) [1]=slot [2]=LvLimit [3]=HealAmt diff --git a/zone/lua_stat_bonuses.cpp b/zone/lua_stat_bonuses.cpp index b6561199b..c007e09ca 100644 --- a/zone/lua_stat_bonuses.cpp +++ b/zone/lua_stat_bonuses.cpp @@ -572,7 +572,7 @@ int32 Lua_StatBonuses::GetProcChanceSPA() const { int32 Lua_StatBonuses::GetExtraAttackChance() const { Lua_Safe_Call_Int(); - return self->ExtraAttackChance; + return self->ExtraAttackChance[0]; } int32 Lua_StatBonuses::GetDoTShielding() const { diff --git a/zone/merc.cpp b/zone/merc.cpp index 3b8631edd..62b02c8a0 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1624,7 +1624,7 @@ void Merc::AI_Process() { } } - int16 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance; + int16 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance[0] + itembonuses.ExtraAttackChance[0] + aabonuses.ExtraAttackChance[0]; if (GetTarget() && ExtraAttackChanceBonus) { if(zone->random.Roll(ExtraAttackChanceBonus)) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index eb75c7892..f39340876 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3214,6 +3214,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_Fc_Cast_Spell_On_Land: case SE_Ff_CasterClass: case SE_Ff_Same_Caster: + case SE_AddExtraAttackPct_1h_Primary: + case SE_AddExtraAttackPct_1h_Secondary: case SE_Skill_Base_Damage_Mod: { break;