mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 18:52:22 +00:00
[Spells] Rework of SPA 288 SE_SkillAttackProc (#1893)
* start * updated 288
This commit is contained in:
+58
-12
@@ -1603,29 +1603,26 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
///////////////////////////////////////////////////////////
|
||||
////// Send Attack Damage
|
||||
///////////////////////////////////////////////////////////
|
||||
if (my_hit.damage_done > 0 && aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_CHANCE] && aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SKILL] == my_hit.skill &&
|
||||
IsValidSpell(aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID])) {
|
||||
float chance = aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_CHANCE] / 1000.0f;
|
||||
if (zone->random.Roll(chance))
|
||||
SpellFinished(aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID], other, EQ::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID]].resist_difficulty);
|
||||
}
|
||||
other->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, my_hit.skill, true, -1, false, m_specialattacks);
|
||||
|
||||
if (IsDead()) return false;
|
||||
if (IsDead()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MeleeLifeTap(my_hit.damage_done);
|
||||
|
||||
CommonBreakInvisibleFromCombat();
|
||||
|
||||
if (GetTarget())
|
||||
if (GetTarget()) {
|
||||
TriggerDefensiveProcs(other, Hand, true, my_hit.damage_done);
|
||||
}
|
||||
|
||||
if (my_hit.damage_done > 0)
|
||||
if (my_hit.damage_done > 0) {
|
||||
return true;
|
||||
|
||||
else
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//used by complete heal and #heal
|
||||
@@ -4489,6 +4486,8 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon,
|
||||
}
|
||||
}
|
||||
|
||||
TryCastOnSkillUse(on, skillinuse);
|
||||
|
||||
if (HasSkillProcs() && hand != EQ::invslot::slotRange) { //We check ranged skill procs within the attack functions.
|
||||
TrySkillProc(on, skillinuse, 0, false, hand);
|
||||
}
|
||||
@@ -5272,6 +5271,53 @@ float Mob::GetSkillProcChances(uint16 ReuseTime, uint16 hand) {
|
||||
return ProcChance;
|
||||
}
|
||||
|
||||
void Mob::TryCastOnSkillUse(Mob *on, EQ::skills::SkillType skill) {
|
||||
|
||||
if (!spellbonuses.HasSkillAttackProc[skill] && !itembonuses.HasSkillAttackProc[skill] && !aabonuses.HasSkillAttackProc[skill]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!on) {
|
||||
SetTarget(nullptr);
|
||||
LogError("A null Mob object was passed to Mob::TryCastOnSkillUse for evaluation!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (on->HasDied()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (spellbonuses.HasSkillAttackProc[skill]) {
|
||||
for (int i = 0; i < MAX_CAST_ON_SKILL_USE i += 3) {
|
||||
if (spellbonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID] && skill == spellbonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SKILL]) {
|
||||
if (IsValidSpell(spellbonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]) && zone->random.Int(1, 1000) <= spellbonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_CHANCE]) {
|
||||
SpellFinished(spellbonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID], on, EQ::spells::CastingSlot::Item, 0, -1, spells[spellbonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]].resist_difficulty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (itembonuses.HasSkillAttackProc[skill]) {
|
||||
for (int i = 0; i < MAX_CAST_ON_SKILL_USE i += 3) {
|
||||
if (itembonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID] && skill == itembonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SKILL]) {
|
||||
if (IsValidSpell(itembonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]) && zone->random.Int(1, 1000) <= spellbonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_CHANCE]) {
|
||||
SpellFinished(itembonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID], on, EQ::spells::CastingSlot::Item, 0, -1, spells[itembonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]].resist_difficulty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aabonuses.HasSkillAttackProc[skill]) {
|
||||
for (int i = 0; i < MAX_CAST_ON_SKILL_USE i += 3) {
|
||||
if (IsValidSpell(aabonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]) && aabonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID] && skill == aabonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SKILL]) {
|
||||
if (zone->random.Int(1, 1000) <= aabonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_CHANCE]) {
|
||||
SpellFinished(aabonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID], on, EQ::spells::CastingSlot::Item, 0, -1, spells[aabonuses.SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]].resist_difficulty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) {
|
||||
|
||||
/*Dev Quote 2010: http://forums.station.sony.com/eq/posts/list.m?topic_id=161443
|
||||
|
||||
+27
-5
@@ -1207,11 +1207,18 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
}
|
||||
|
||||
case SE_SkillAttackProc: {
|
||||
// You can only have one of these per client. [AA Dragon Punch]
|
||||
newbon->SkillAttackProc[SBIndex::SKILLATK_PROC_CHANCE] = base_value; // Chance base 1000 = 100% proc rate
|
||||
newbon->SkillAttackProc[SBIndex::SKILLATK_PROC_SKILL] = limit_value; // Skill to Proc Off
|
||||
newbon->SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID] = rank.spell; // spell to proc
|
||||
break;
|
||||
for (int i = 0; i < MAX_CAST_ON_SKILL_USE i += 3) {
|
||||
if (!newbon->SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]) { // spell id
|
||||
newbon->SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID] = rank.spell; // spell to proc
|
||||
newbon->SkillAttackProc[i + SBIndex::SKILLATK_PROC_CHANCE] = base_value; // Chance base 1000 = 100% proc rate
|
||||
newbon->SkillAttackProc[i + SBIndex::SKILLATK_PROC_SKILL] = limit_value; // Skill to Proc Offr
|
||||
|
||||
if (limit_value < EQ::skills::HIGHEST_SKILL) {
|
||||
newbon->HasSkillAttackProc[limit_value] = true; //check first before looking for any effects.
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case SE_DamageModifier: {
|
||||
@@ -3578,6 +3585,21 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_SkillAttackProc: {
|
||||
for (int i = 0; i < MAX_CAST_ON_SKILL_USE i += 3) {
|
||||
if (!new_bonus->SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]) { // spell id
|
||||
new_bonus->SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID] = max_value; // spell to proc
|
||||
new_bonus->SkillAttackProc[i + SBIndex::SKILLATK_PROC_CHANCE] = effect_value; // Chance base 1000 = 100% proc rate
|
||||
new_bonus->SkillAttackProc[i + SBIndex::SKILLATK_PROC_SKILL] = limit_value; // Skill to Proc Offr
|
||||
|
||||
if (limit_value < EQ::skills::HIGHEST_SKILL) {
|
||||
new_bonus->HasSkillAttackProc[limit_value] = true; //check first before looking for any effects.
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case SE_PC_Pet_Rampage: {
|
||||
new_bonus->PC_Pet_Rampage[SBIndex::PET_RAMPAGE_CHANCE] += effect_value; //Chance to rampage
|
||||
if (new_bonus->PC_Pet_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] < limit_value)
|
||||
|
||||
+5
-4
@@ -572,6 +572,7 @@ struct StatBonuses {
|
||||
uint8 IncreaseRunSpeedCap; // Increase max run speed above cap.
|
||||
int32 DoubleSpecialAttack; // Chance to to perform a double special attack (ie flying kick 2x)
|
||||
int32 SkillAttackProc[3]; // [0] chance to proc [2] spell on [1] skill usage
|
||||
bool HasSkillAttackProc[EQ::skills::HIGHEST_SKILL + 1]; //check if any skill proc is present before assessing for all skill procs
|
||||
uint8 FrontalStunResist; // Chance to resist a frontal stun
|
||||
int32 BindWound; // Increase amount of HP by percent.
|
||||
int32 MaxBindWound; // Increase max amount of HP you can bind wound.
|
||||
@@ -671,9 +672,9 @@ namespace SBIndex {
|
||||
constexpr uint16 POSITION_FRONT = 1; // SPA 503-506
|
||||
constexpr uint16 PET_RAMPAGE_CHANCE = 0; // SPA 464,465
|
||||
constexpr uint16 PET_RAMPAGE_DMG_MOD = 1; // SPA 465,465
|
||||
constexpr uint16 SKILLATK_PROC_CHANCE = 0; // SPA 427
|
||||
constexpr uint16 SKILLATK_PROC_SKILL = 1; // SPA 427
|
||||
constexpr uint16 SKILLATK_PROC_SPELL_ID = 2; // SPA 427
|
||||
constexpr uint16 SKILLATK_PROC_SPELL_ID = 0; // SPA 288
|
||||
constexpr uint16 SKILLATK_PROC_CHANCE = 1; // SPA 288
|
||||
constexpr uint16 SKILLATK_PROC_SKILL = 2; // SPA 288
|
||||
constexpr uint16 SLAYUNDEAD_RATE_MOD = 0; // SPA 219
|
||||
constexpr uint16 SLAYUNDEAD_DMG_MOD = 1; // SPA 219
|
||||
constexpr uint16 DOUBLE_RIPOSTE_CHANCE = 0; // SPA 223
|
||||
@@ -692,7 +693,7 @@ namespace SBIndex {
|
||||
constexpr uint16 COMBAT_PROC_ORIGIN_ID = 0; // SPA
|
||||
constexpr uint16 COMBAT_PROC_SPELL_ID = 1; // SPA
|
||||
constexpr uint16 COMBAT_PROC_RATE_MOD = 2; // SPA
|
||||
constexpr uint16 COMBAT_PROC_REUSE_TIMER = 3; // SPA
|
||||
constexpr uint16 COMBAT_PROC_REUSE_TIMER = 3; // SPA
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -4242,6 +4242,8 @@ void Mob::TriggerDefensiveProcs(Mob *on, uint16 hand, bool FromSkillProc, int da
|
||||
break;
|
||||
}
|
||||
|
||||
TryCastOnSkillUse(on, skillinuse);
|
||||
|
||||
if (on->HasSkillProcs()) {
|
||||
on->TrySkillProc(this, skillinuse, 0, false, hand, true);
|
||||
}
|
||||
|
||||
+2
-1
@@ -1447,9 +1447,10 @@ protected:
|
||||
bool spawned;
|
||||
void CalcSpellBonuses(StatBonuses* newbon);
|
||||
virtual void CalcBonuses();
|
||||
void TrySkillProc(Mob *on, EQ::skills::SkillType skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false); // hand = SlotCharm?
|
||||
void TrySkillProc(Mob *on, EQ::skills::SkillType skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false); // hand if 0 means its a skill ability for proc rate checks, otherwise hand is passed.
|
||||
bool PassLimitToSkill(EQ::skills::SkillType skill, int32 spell_id, int proc_type, int aa_id=0);
|
||||
bool PassLimitClass(uint32 Classes_, uint16 Class_);
|
||||
void TryCastOnSkillUse(Mob *on, EQ::skills::SkillType skill);
|
||||
void TryDefensiveProc(Mob *on, uint16 hand = EQ::invslot::slotPrimary);
|
||||
void TryWeaponProc(const EQ::ItemInstance* inst, const EQ::ItemData* weapon, Mob *on, uint16 hand = EQ::invslot::slotPrimary);
|
||||
void TrySpellProc(const EQ::ItemInstance* inst, const EQ::ItemData* weapon, Mob *on, uint16 hand = EQ::invslot::slotPrimary);
|
||||
|
||||
+12
-16
@@ -196,14 +196,6 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 bas
|
||||
DoAttack(who, my_hit);
|
||||
|
||||
who->AddToHateList(this, hate, 0);
|
||||
if (my_hit.damage_done > 0 && aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_CHANCE] && aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SKILL] == skill &&
|
||||
IsValidSpell(aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID])) {
|
||||
float chance = aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_CHANCE] / 1000.0f;
|
||||
if (zone->random.Roll(chance))
|
||||
SpellFinished(aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID], who, EQ::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID]].resist_difficulty);
|
||||
}
|
||||
|
||||
who->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, skill, false);
|
||||
|
||||
// Make sure 'this' has not killed the target and 'this' is not dead (Damage shield ect).
|
||||
@@ -212,6 +204,8 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 bas
|
||||
if (HasDied())
|
||||
return;
|
||||
|
||||
TryCastOnSkillUse(who, skill);
|
||||
|
||||
if (HasSkillProcs()) {
|
||||
TrySkillProc(who, skill, ReuseTime * 1000);
|
||||
}
|
||||
@@ -916,6 +910,8 @@ void Mob::DoArcheryAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, co
|
||||
TryWeaponProc(Ammo, Ammo->GetItem(), other, EQ::invslot::slotRange);
|
||||
}
|
||||
|
||||
TryCastOnSkillUse(other, EQ::skills::SkillArchery);
|
||||
|
||||
// Skill Proc Attempt
|
||||
if (HasSkillProcs() && other && !other->HasDied()) {
|
||||
if (ReuseTime) {
|
||||
@@ -1279,6 +1275,8 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha
|
||||
TrySpellProc(nullptr, (const EQ::ItemData*)nullptr, other, EQ::invslot::slotRange);
|
||||
}
|
||||
|
||||
TryCastOnSkillUse(other, skillInUse);
|
||||
|
||||
if (HasSkillProcs() && other && !other->HasDied()) {
|
||||
TrySkillProc(other, skillInUse, 0, false, EQ::invslot::slotRange);
|
||||
}
|
||||
@@ -2046,6 +2044,8 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool FromSpell,
|
||||
MessageString(Chat::SpellFailure, FAILED_TAUNT);
|
||||
}
|
||||
|
||||
TryCastOnSkillUse(who, EQ::skills::SkillTaunt);
|
||||
|
||||
if (HasSkillProcs()) {
|
||||
TrySkillProc(who, EQ::skills::SkillTaunt, TauntReuseTime * 1000);
|
||||
}
|
||||
@@ -2101,6 +2101,8 @@ void Mob::InstillDoubt(Mob *who) {
|
||||
}*/
|
||||
}
|
||||
|
||||
TryCastOnSkillUse(who, EQ::skills::SkillIntimidation);
|
||||
|
||||
if (HasSkillProcs()) {
|
||||
TrySkillProc(who, EQ::skills::SkillIntimidation, InstillDoubtReuseTime * 1000);
|
||||
}
|
||||
@@ -2253,19 +2255,13 @@ void Mob::DoMeleeSkillAttackDmg(Mob *other, uint16 weapon_damage, EQ::skills::Sk
|
||||
}
|
||||
|
||||
other->AddToHateList(this, hate, 0);
|
||||
if (damage > 0 && aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_CHANCE] && aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SKILL] == skillinuse &&
|
||||
IsValidSpell(aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID])) {
|
||||
float chance = aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_CHANCE] / 1000.0f;
|
||||
if (zone->random.Roll(chance))
|
||||
SpellFinished(aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID], other, EQ::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID]].resist_difficulty);
|
||||
}
|
||||
|
||||
other->Damage(this, damage, SPELL_UNKNOWN, skillinuse);
|
||||
|
||||
if (HasDied())
|
||||
return;
|
||||
|
||||
TryCastOnSkillUse(other, skillinuse);
|
||||
|
||||
if (CanSkillProc && HasSkillProcs()) {
|
||||
TrySkillProc(other, skillinuse, ReuseTime);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user