mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 18:52:22 +00:00
[Spells] Throwing procs fixed and other proc updates (#1871)
* first updating sbindex defines * updates * updates * proctypes added for organization * debug * updates * range procs cleaned up * skill proc clean up * fix * remove debugs * [Spells] Throwing procs fixed and other proc updates * [Spells] Throwing procs fixed and other proc updates bot fix * [Spells] Throwing procs fixed and other proc updates proctype updates
This commit is contained in:
+108
-81
@@ -196,12 +196,12 @@ 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::SKILLPROC_CHANCE] && aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SKILL] == skill &&
|
||||
IsValidSpell(aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID])) {
|
||||
float chance = aabonuses.SkillAttackProc[SBIndex::SKILLPROC_CHANCE] / 1000.0f;
|
||||
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::SKILLPROC_SPELL_ID], who, EQ::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID]].resist_difficulty);
|
||||
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);
|
||||
@@ -212,11 +212,12 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 bas
|
||||
if (HasDied())
|
||||
return;
|
||||
|
||||
if (HasSkillProcs())
|
||||
if (HasSkillProcs()) {
|
||||
TrySkillProc(who, skill, ReuseTime * 1000);
|
||||
|
||||
if (my_hit.damage_done > 0 && HasSkillProcSuccess())
|
||||
}
|
||||
if (my_hit.damage_done > 0 && HasSkillProcSuccess()) {
|
||||
TrySkillProc(who, skill, ReuseTime * 1000, true);
|
||||
}
|
||||
}
|
||||
|
||||
// We should probably refactor this to take the struct not the packet
|
||||
@@ -798,7 +799,7 @@ void Mob::DoArcheryAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, co
|
||||
|
||||
const EQ::ItemInstance *_RangeWeapon = nullptr;
|
||||
const EQ::ItemInstance *_Ammo = nullptr;
|
||||
const EQ::ItemData *ammo_lost = nullptr;
|
||||
const EQ::ItemData *last_ammo_used = nullptr;
|
||||
|
||||
/*
|
||||
If LaunchProjectile is false this function will do archery damage on target,
|
||||
@@ -822,7 +823,7 @@ void Mob::DoArcheryAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, co
|
||||
if (!RangeWeapon && !Ammo && range_id && ammo_id) {
|
||||
if (IsClient()) {
|
||||
_RangeWeapon = CastToClient()->m_inv[EQ::invslot::slotRange];
|
||||
if (_RangeWeapon && _RangeWeapon->GetItem() &&
|
||||
if (_RangeWeapon && _RangeWeapon->GetItem() &&
|
||||
_RangeWeapon->GetItem()->ID == range_id)
|
||||
RangeWeapon = _RangeWeapon;
|
||||
|
||||
@@ -830,7 +831,7 @@ void Mob::DoArcheryAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, co
|
||||
if (_Ammo && _Ammo->GetItem() && _Ammo->GetItem()->ID == ammo_id)
|
||||
Ammo = _Ammo;
|
||||
else
|
||||
ammo_lost = database.GetItem(ammo_id);
|
||||
last_ammo_used = database.GetItem(ammo_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -900,34 +901,39 @@ void Mob::DoArcheryAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, co
|
||||
|
||||
other->Damage(this, TotalDmg, SPELL_UNKNOWN, EQ::skills::SkillArchery);
|
||||
|
||||
// Skill Proc Success
|
||||
if (TotalDmg > 0 && HasSkillProcSuccess() && other && !other->HasDied()) {
|
||||
if (ReuseTime)
|
||||
TrySkillProc(other, EQ::skills::SkillArchery, ReuseTime);
|
||||
else
|
||||
TrySkillProc(other, EQ::skills::SkillArchery, 0, true, EQ::invslot::slotRange);
|
||||
}
|
||||
// end of old fuck
|
||||
|
||||
if (LaunchProjectile)
|
||||
return; // Shouldn't reach this point durring initial launch phase, but just in case.
|
||||
|
||||
// Weapon Proc
|
||||
if (RangeWeapon && other && !other->HasDied())
|
||||
TryWeaponProc(RangeWeapon, other, EQ::invslot::slotRange);
|
||||
if (RangeWeapon && other && !other->HasDied()) {
|
||||
TryCombatProcs(RangeWeapon, other, EQ::invslot::slotRange);
|
||||
}
|
||||
|
||||
// Ammo Proc
|
||||
if (ammo_lost)
|
||||
TryWeaponProc(nullptr, ammo_lost, other, EQ::invslot::slotRange);
|
||||
else if (Ammo && other && !other->HasDied())
|
||||
TryWeaponProc(Ammo, other, EQ::invslot::slotRange);
|
||||
// Ammo Proc, do not try spell procs if from ammo.
|
||||
if (last_ammo_used) {
|
||||
TryWeaponProc(nullptr, last_ammo_used, other, EQ::invslot::slotRange);
|
||||
}
|
||||
else if (Ammo && other && !other->HasDied()) {
|
||||
TryWeaponProc(Ammo, Ammo->GetItem(), other, EQ::invslot::slotRange);
|
||||
}
|
||||
|
||||
// Skill Proc
|
||||
// Skill Proc Attempt
|
||||
if (HasSkillProcs() && other && !other->HasDied()) {
|
||||
if (ReuseTime)
|
||||
if (ReuseTime) {
|
||||
TrySkillProc(other, EQ::skills::SkillArchery, ReuseTime);
|
||||
else
|
||||
}
|
||||
else {
|
||||
TrySkillProc(other, EQ::skills::SkillArchery, 0, false, EQ::invslot::slotRange);
|
||||
}
|
||||
}
|
||||
|
||||
// Skill Proc Success ... can proc off hits OR misses
|
||||
if (HasSkillProcSuccess() && other && !other->HasDied()) {
|
||||
if (ReuseTime) {
|
||||
TrySkillProc(other, EQ::skills::SkillArchery, ReuseTime, true);
|
||||
}
|
||||
else {
|
||||
TrySkillProc(other, EQ::skills::SkillArchery, 0, true, EQ::invslot::slotRange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -991,7 +997,7 @@ bool Mob::TryProjectileAttack(Mob *other, const EQ::ItemData *item, EQ::skills::
|
||||
if (Ammo && Ammo->GetItem())
|
||||
ProjectileAtk[slot].ammo_id = Ammo->GetItem()->ID;
|
||||
|
||||
ProjectileAtk[slot].ammo_slot = 0;
|
||||
ProjectileAtk[slot].ammo_slot = AmmoSlot;
|
||||
ProjectileAtk[slot].skill = skillInUse;
|
||||
ProjectileAtk[slot].speed_mod = speed;
|
||||
|
||||
@@ -1268,15 +1274,18 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha
|
||||
|
||||
other->Damage(this, TotalDmg, SPELL_UNKNOWN, skillInUse);
|
||||
|
||||
if (TotalDmg > 0 && HasSkillProcSuccess() && !other->HasDied())
|
||||
TrySkillProc(other, skillInUse, 0, true, EQ::invslot::slotRange);
|
||||
|
||||
//try proc on hits and misses
|
||||
if(other && !other->HasDied())
|
||||
if (other && !other->HasDied()) {
|
||||
TrySpellProc(nullptr, (const EQ::ItemData*)nullptr, other, EQ::invslot::slotRange);
|
||||
}
|
||||
|
||||
if (HasSkillProcs() && other && !other->HasDied())
|
||||
if (HasSkillProcs() && other && !other->HasDied()) {
|
||||
TrySkillProc(other, skillInUse, 0, false, EQ::invslot::slotRange);
|
||||
}
|
||||
|
||||
if (HasSkillProcSuccess() && other && !other->HasDied()) {
|
||||
TrySkillProc(other, skillInUse, 0, true, EQ::invslot::slotRange);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51
|
||||
@@ -1294,7 +1303,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51
|
||||
|
||||
int ammo_slot = EQ::invslot::slotRange;
|
||||
const EQ::ItemInstance* RangeWeapon = m_inv[EQ::invslot::slotRange];
|
||||
|
||||
|
||||
if (!RangeWeapon || !RangeWeapon->IsClassCommon()) {
|
||||
LogCombat("Ranged attack canceled. Missing or invalid ranged weapon ([{}]) in slot [{}]", GetItemIDAt(EQ::invslot::slotRange), EQ::invslot::slotRange);
|
||||
Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing to throw!", GetItemIDAt(EQ::invslot::slotRange));
|
||||
@@ -1355,7 +1364,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51
|
||||
return;
|
||||
}
|
||||
|
||||
DoThrowingAttackDmg(other, RangeWeapon, item);
|
||||
DoThrowingAttackDmg(other, RangeWeapon, item, 0, 0, 0, 0, 0,ammo_slot);
|
||||
|
||||
// Consume Ammo, unless Ammo Consumption is disabled
|
||||
if (RuleB(Combat, ThrowingConsumesAmmo)) {
|
||||
@@ -1378,8 +1387,8 @@ void Mob::DoThrowingAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, c
|
||||
return;
|
||||
}
|
||||
|
||||
const EQ::ItemInstance *_RangeWeapon = nullptr;
|
||||
const EQ::ItemData *ammo_lost = nullptr;
|
||||
const EQ::ItemInstance *m_RangeWeapon = nullptr;//throwing weapon
|
||||
const EQ::ItemData *last_ammo_used = nullptr;
|
||||
|
||||
/*
|
||||
If LaunchProjectile is false this function will do archery damage on target,
|
||||
@@ -1394,12 +1403,14 @@ void Mob::DoThrowingAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, c
|
||||
} else {
|
||||
if (!RangeWeapon && range_id) {
|
||||
if (IsClient()) {
|
||||
_RangeWeapon = CastToClient()->m_inv[AmmoSlot];
|
||||
if (_RangeWeapon && _RangeWeapon->GetItem() &&
|
||||
_RangeWeapon->GetItem()->ID != range_id)
|
||||
RangeWeapon = _RangeWeapon;
|
||||
else
|
||||
ammo_lost = database.GetItem(range_id);
|
||||
m_RangeWeapon = CastToClient()->m_inv[AmmoSlot];
|
||||
|
||||
if (m_RangeWeapon && m_RangeWeapon->GetItem() && m_RangeWeapon->GetItem()->ID == range_id) {
|
||||
RangeWeapon = m_RangeWeapon;
|
||||
}
|
||||
else {
|
||||
last_ammo_used = database.GetItem(range_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1412,10 +1423,12 @@ void Mob::DoThrowingAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, c
|
||||
int WDmg = 0;
|
||||
|
||||
if (!weapon_damage) {
|
||||
if (IsClient() && RangeWeapon)
|
||||
if (IsClient() && RangeWeapon) {
|
||||
WDmg = GetWeaponDamage(other, RangeWeapon);
|
||||
else if (AmmoItem)
|
||||
}
|
||||
else if (AmmoItem) {
|
||||
WDmg = GetWeaponDamage(other, AmmoItem);
|
||||
}
|
||||
|
||||
if (LaunchProjectile) {
|
||||
TryProjectileAttack(other, AmmoItem, EQ::skills::SkillThrowing, WDmg, RangeWeapon,
|
||||
@@ -1426,8 +1439,9 @@ void Mob::DoThrowingAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, c
|
||||
WDmg = weapon_damage;
|
||||
}
|
||||
|
||||
if (focus) // From FcBaseEffects
|
||||
if (focus) { // no longer used, keep for quests
|
||||
WDmg += WDmg * focus / 100;
|
||||
}
|
||||
|
||||
int TotalDmg = 0;
|
||||
|
||||
@@ -1455,29 +1469,28 @@ void Mob::DoThrowingAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, c
|
||||
|
||||
other->Damage(this, TotalDmg, SPELL_UNKNOWN, EQ::skills::SkillThrowing);
|
||||
|
||||
if (TotalDmg > 0 && HasSkillProcSuccess() && other && !other->HasDied()) {
|
||||
if (ReuseTime)
|
||||
TrySkillProc(other, EQ::skills::SkillThrowing, ReuseTime);
|
||||
else
|
||||
TrySkillProc(other, EQ::skills::SkillThrowing, 0, true, EQ::invslot::slotRange);
|
||||
if (other && !other->HasDied()) {
|
||||
TryCombatProcs(RangeWeapon, other, EQ::invslot::slotRange, last_ammo_used);
|
||||
}
|
||||
// end old shit
|
||||
|
||||
if (LaunchProjectile)
|
||||
return;
|
||||
|
||||
// Throwing item Proc
|
||||
if (ammo_lost)
|
||||
TryWeaponProc(nullptr, ammo_lost, other, EQ::invslot::slotRange);
|
||||
else if (RangeWeapon && other && !other->HasDied())
|
||||
TryWeaponProc(RangeWeapon, other, EQ::invslot::slotRange);
|
||||
|
||||
if (HasSkillProcs() && other && !other->HasDied()) {
|
||||
if (ReuseTime)
|
||||
if (ReuseTime) {
|
||||
TrySkillProc(other, EQ::skills::SkillThrowing, ReuseTime);
|
||||
else
|
||||
}
|
||||
else {
|
||||
TrySkillProc(other, EQ::skills::SkillThrowing, 0, false, EQ::invslot::slotRange);
|
||||
}
|
||||
}
|
||||
|
||||
if (HasSkillProcSuccess() && other && !other->HasDied()) {
|
||||
if (ReuseTime) {
|
||||
TrySkillProc(other, EQ::skills::SkillThrowing, ReuseTime, true);
|
||||
}
|
||||
else {
|
||||
TrySkillProc(other, EQ::skills::SkillThrowing, 0, true, EQ::invslot::slotRange);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsClient()) {
|
||||
CastToClient()->CheckIncreaseSkill(EQ::skills::SkillThrowing, GetTarget());
|
||||
}
|
||||
@@ -1965,7 +1978,7 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool FromSpell,
|
||||
Mob *hate_top = who->GetHateMost();
|
||||
|
||||
int level_difference = GetLevel() - who->GetLevel();
|
||||
bool Success = false;
|
||||
bool success = false;
|
||||
|
||||
// Support for how taunt worked pre 2000 on LIVE - Can not taunt NPC over your level.
|
||||
if ((RuleB(Combat, TauntOverLevel) == false) && (level_difference < 0) ||
|
||||
@@ -1978,7 +1991,7 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool FromSpell,
|
||||
if ((hate_top && hate_top->GetHPRatio() >= 20) || hate_top == nullptr || chance_bonus) {
|
||||
// SE_Taunt this is flat chance
|
||||
if (chance_bonus) {
|
||||
Success = zone->random.Roll(chance_bonus);
|
||||
success = zone->random.Roll(chance_bonus);
|
||||
} else {
|
||||
float tauntchance = 50.0f;
|
||||
|
||||
@@ -2012,14 +2025,14 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool FromSpell,
|
||||
|
||||
tauntchance /= 100.0f;
|
||||
|
||||
Success = tauntchance > zone->random.Real(0, 1);
|
||||
success = tauntchance > zone->random.Real(0, 1);
|
||||
}
|
||||
|
||||
if (Success) {
|
||||
if (success) {
|
||||
if (hate_top && hate_top != this) {
|
||||
int newhate = (who->GetNPCHate(hate_top) - who->GetNPCHate(this)) + 1 + bonus_hate;
|
||||
who->CastToNPC()->AddToHateList(this, newhate);
|
||||
Success = true;
|
||||
success = true;
|
||||
} else {
|
||||
who->CastToNPC()->AddToHateList(this, 12);
|
||||
}
|
||||
@@ -2033,11 +2046,13 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool FromSpell,
|
||||
MessageString(Chat::SpellFailure, FAILED_TAUNT);
|
||||
}
|
||||
|
||||
if (HasSkillProcs())
|
||||
if (HasSkillProcs()) {
|
||||
TrySkillProc(who, EQ::skills::SkillTaunt, TauntReuseTime * 1000);
|
||||
}
|
||||
|
||||
if (Success && HasSkillProcSuccess())
|
||||
if (success && HasSkillProcSuccess()) {
|
||||
TrySkillProc(who, EQ::skills::SkillTaunt, TauntReuseTime * 1000, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::InstillDoubt(Mob *who) {
|
||||
@@ -2061,6 +2076,7 @@ void Mob::InstillDoubt(Mob *who) {
|
||||
|
||||
//I think this formula needs work
|
||||
int value = 0;
|
||||
bool success = false;
|
||||
|
||||
//user's bonus
|
||||
value += GetSkill(EQ::skills::SkillIntimidation) + GetCHA() / 4;
|
||||
@@ -2073,6 +2089,7 @@ void Mob::InstillDoubt(Mob *who) {
|
||||
//cast fear on them... should prolly be a different spell
|
||||
//and should be un-resistable.
|
||||
SpellOnTarget(229, who, 0, true, -2000);
|
||||
success = true;
|
||||
//is there a success message?
|
||||
} else {
|
||||
MessageString(Chat::LightBlue,NOT_SCARING);
|
||||
@@ -2083,6 +2100,14 @@ void Mob::InstillDoubt(Mob *who) {
|
||||
entity_list.AEAttack(target, 50);
|
||||
}*/
|
||||
}
|
||||
|
||||
if (HasSkillProcs()) {
|
||||
TrySkillProc(who, EQ::skills::SkillIntimidation, InstillDoubtReuseTime * 1000);
|
||||
}
|
||||
|
||||
if (success && HasSkillProcSuccess()) {
|
||||
TrySkillProc(who, EQ::skills::SkillIntimidation, InstillDoubtReuseTime * 1000, true);
|
||||
}
|
||||
}
|
||||
|
||||
int Mob::TryHeadShot(Mob *defender, EQ::skills::SkillType skillInUse)
|
||||
@@ -2228,12 +2253,12 @@ void Mob::DoMeleeSkillAttackDmg(Mob *other, uint16 weapon_damage, EQ::skills::Sk
|
||||
}
|
||||
|
||||
other->AddToHateList(this, hate, 0);
|
||||
if (damage > 0 && aabonuses.SkillAttackProc[SBIndex::SKILLPROC_CHANCE] && aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SKILL] == skillinuse &&
|
||||
IsValidSpell(aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID])) {
|
||||
float chance = aabonuses.SkillAttackProc[SBIndex::SKILLPROC_CHANCE] / 1000.0f;
|
||||
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::SKILLPROC_SPELL_ID], other, EQ::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID]].resist_difficulty);
|
||||
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);
|
||||
@@ -2241,11 +2266,13 @@ void Mob::DoMeleeSkillAttackDmg(Mob *other, uint16 weapon_damage, EQ::skills::Sk
|
||||
if (HasDied())
|
||||
return;
|
||||
|
||||
if (CanSkillProc && HasSkillProcs())
|
||||
if (CanSkillProc && HasSkillProcs()) {
|
||||
TrySkillProc(other, skillinuse, ReuseTime);
|
||||
}
|
||||
|
||||
if (CanSkillProc && (damage > 0) && HasSkillProcSuccess())
|
||||
if (CanSkillProc && (damage > 0) && HasSkillProcSuccess()) {
|
||||
TrySkillProc(other, skillinuse, ReuseTime, true);
|
||||
}
|
||||
}
|
||||
|
||||
bool Mob::CanDoSpecialAttack(Mob *other) {
|
||||
|
||||
Reference in New Issue
Block a user