Core/Spells: Don't ignore power costs and reagents for spells triggered by SPELL_EFFECT_TRIGGER_SPELL, SPELL_EFFECT_TRIGGER_MISSILE, SPELL_EFFECT_FORCE_CAST, SPELL_AURA_PERIODIC_TRIGGER_SPELL, SPELL_AURA_PROC_TRIGGER_SPELL and fixed implementation of SPELL_ATTR6_DO_NOT_CONSUME_RESOURCES
This commit is contained in:
@@ -161,12 +161,13 @@ TC_API_EXPORT EnumText EnumUtils<InventoryResult>::ToString(InventoryResult valu
|
||||
case EQUIP_ERR_CANT_DELETE_IN_ACCOUNT_BANK: return { "EQUIP_ERR_CANT_DELETE_IN_ACCOUNT_BANK", "EQUIP_ERR_CANT_DELETE_IN_ACCOUNT_BANK", "Items must be moved out of the Warband Bank to be deleted." };
|
||||
case EQUIP_ERR_BANK_NOT_ACCESSIBLE: return { "EQUIP_ERR_BANK_NOT_ACCESSIBLE", "EQUIP_ERR_BANK_NOT_ACCESSIBLE", "This character does not have access to this bank." };
|
||||
case EQUIP_ERR_CANT_TRADE_ACCOUNT_ITEM: return { "EQUIP_ERR_CANT_TRADE_ACCOUNT_ITEM", "EQUIP_ERR_CANT_TRADE_ACCOUNT_ITEM", "You can't trade an item from the Warband bank." };
|
||||
case EQUIP_ERR_ACCOUNT_MONEY_LOCKED: return { "EQUIP_ERR_ACCOUNT_MONEY_LOCKED", "EQUIP_ERR_ACCOUNT_MONEY_LOCKED", "You cannot withdraw or deposit gold from the warband bank currently; please try again later." };
|
||||
default: throw std::out_of_range("value");
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
TC_API_EXPORT size_t EnumUtils<InventoryResult>::Count() { return 130; }
|
||||
TC_API_EXPORT size_t EnumUtils<InventoryResult>::Count() { return 131; }
|
||||
|
||||
template <>
|
||||
TC_API_EXPORT InventoryResult EnumUtils<InventoryResult>::FromIndex(size_t index)
|
||||
@@ -303,6 +304,7 @@ TC_API_EXPORT InventoryResult EnumUtils<InventoryResult>::FromIndex(size_t index
|
||||
case 127: return EQUIP_ERR_CANT_DELETE_IN_ACCOUNT_BANK;
|
||||
case 128: return EQUIP_ERR_BANK_NOT_ACCESSIBLE;
|
||||
case 129: return EQUIP_ERR_CANT_TRADE_ACCOUNT_ITEM;
|
||||
case 130: return EQUIP_ERR_ACCOUNT_MONEY_LOCKED;
|
||||
default: throw std::out_of_range("index");
|
||||
}
|
||||
}
|
||||
@@ -442,6 +444,7 @@ TC_API_EXPORT size_t EnumUtils<InventoryResult>::ToIndex(InventoryResult value)
|
||||
case EQUIP_ERR_CANT_DELETE_IN_ACCOUNT_BANK: return 127;
|
||||
case EQUIP_ERR_BANK_NOT_ACCESSIBLE: return 128;
|
||||
case EQUIP_ERR_CANT_TRADE_ACCOUNT_ITEM: return 129;
|
||||
case EQUIP_ERR_ACCOUNT_MONEY_LOCKED: return 130;
|
||||
default: throw std::out_of_range("value");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -656,7 +656,7 @@ enum SpellAttr6 : uint32
|
||||
SPELL_ATTR6_NOT_AN_ATTACK = 0x00000004, /*NYI*/ // TITLE Not an Attack
|
||||
SPELL_ATTR6_CAN_ASSIST_IMMUNE_PC = 0x00000008, // TITLE Can Assist Immune PC
|
||||
SPELL_ATTR6_IGNORE_FOR_MOD_TIME_RATE = 0x00000010, /*NYI, time rate not implemented*/ // TITLE Ignore For Mod Time Rate
|
||||
SPELL_ATTR6_DO_NOT_CONSUME_RESOURCES = 0x00000020, // TITLE Do Not Consume Resources
|
||||
SPELL_ATTR6_DO_NOT_CONSUME_RESOURCES = 0x00000020, // TITLE Do Not Consume Resources DESCRIPTION Requires power/reagents to cast but doesn't consume them
|
||||
SPELL_ATTR6_FLOATING_COMBAT_TEXT_ON_CAST = 0x00000040, // TITLE Floating Combat Text On Cast (client only)
|
||||
SPELL_ATTR6_AURA_IS_WEAPON_PROC = 0x00000080, // TITLE Aura Is Weapon Proc
|
||||
SPELL_ATTR6_DO_NOT_CHAIN_TO_CROWD_CONTROLLED_TARGETS = 0x00000100, // TITLE Do Not Chain To Crowd-Controlled Targets DESCRIPTION Implicit targeting (chaining and area targeting) will not impact crowd controlled targets
|
||||
|
||||
@@ -1053,7 +1053,7 @@ TC_API_EXPORT EnumText EnumUtils<SpellAttr6>::ToString(SpellAttr6 value)
|
||||
case SPELL_ATTR6_NOT_AN_ATTACK: return { "SPELL_ATTR6_NOT_AN_ATTACK", "Not an Attack", "" };
|
||||
case SPELL_ATTR6_CAN_ASSIST_IMMUNE_PC: return { "SPELL_ATTR6_CAN_ASSIST_IMMUNE_PC", "Can Assist Immune PC", "" };
|
||||
case SPELL_ATTR6_IGNORE_FOR_MOD_TIME_RATE: return { "SPELL_ATTR6_IGNORE_FOR_MOD_TIME_RATE", "Ignore For Mod Time Rate", "" };
|
||||
case SPELL_ATTR6_DO_NOT_CONSUME_RESOURCES: return { "SPELL_ATTR6_DO_NOT_CONSUME_RESOURCES", "Do Not Consume Resources", "" };
|
||||
case SPELL_ATTR6_DO_NOT_CONSUME_RESOURCES: return { "SPELL_ATTR6_DO_NOT_CONSUME_RESOURCES", "Do Not Consume Resources", "Requires power/reagents to cast but doesn't consume them" };
|
||||
case SPELL_ATTR6_FLOATING_COMBAT_TEXT_ON_CAST: return { "SPELL_ATTR6_FLOATING_COMBAT_TEXT_ON_CAST", "Floating Combat Text On Cast (client only)", "" };
|
||||
case SPELL_ATTR6_AURA_IS_WEAPON_PROC: return { "SPELL_ATTR6_AURA_IS_WEAPON_PROC", "Aura Is Weapon Proc", "" };
|
||||
case SPELL_ATTR6_DO_NOT_CHAIN_TO_CROWD_CONTROLLED_TARGETS: return { "SPELL_ATTR6_DO_NOT_CHAIN_TO_CROWD_CONTROLLED_TARGETS", "Do Not Chain To Crowd-Controlled Targets", "Implicit targeting (chaining and area targeting) will not impact crowd controlled targets" };
|
||||
|
||||
@@ -5553,7 +5553,10 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster)
|
||||
{
|
||||
if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? caster : target)
|
||||
{
|
||||
triggerCaster->CastSpell(target, triggerSpellId, this);
|
||||
triggerCaster->CastSpell(target, triggerSpellId, CastSpellExtraArgsInit{
|
||||
.TriggerFlags = TRIGGERED_FULL_MASK & ~(TRIGGERED_IGNORE_POWER_COST | TRIGGERED_IGNORE_REAGENT_COST),
|
||||
.TriggeringAura = this
|
||||
});
|
||||
TC_LOG_DEBUG("spells.aura.effect", "AuraEffect::HandlePeriodicTriggerSpellAuraTick: Spell {} Trigger {}", GetId(), triggeredSpellInfo->Id);
|
||||
}
|
||||
}
|
||||
@@ -5575,6 +5578,7 @@ void AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit*
|
||||
if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? caster : target)
|
||||
{
|
||||
CastSpellExtraArgs args(this);
|
||||
args.SetTriggerFlags(TRIGGERED_FULL_MASK & ~(TRIGGERED_IGNORE_POWER_COST | TRIGGERED_IGNORE_REAGENT_COST));
|
||||
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
args.AddSpellMod(SpellValueMod(SPELLVALUE_BASE_POINT0 + i), GetAmount());
|
||||
triggerCaster->CastSpell(target, triggerSpellId, args);
|
||||
@@ -6131,7 +6135,9 @@ void AuraEffect::HandleProcTriggerSpellAuraProc(AuraApplication* aurApp, ProcEve
|
||||
if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty()))
|
||||
{
|
||||
TC_LOG_DEBUG("spells.aura.effect", "AuraEffect::HandleProcTriggerSpellAuraProc: Triggering spell {} from aura {} proc", triggeredSpellInfo->Id, GetId());
|
||||
triggerCaster->CastSpell(triggerTarget, triggeredSpellInfo->Id, CastSpellExtraArgs(this).SetTriggeringSpell(eventInfo.GetProcSpell()));
|
||||
triggerCaster->CastSpell(triggerTarget, triggeredSpellInfo->Id, CastSpellExtraArgs(this)
|
||||
.SetTriggeringSpell(eventInfo.GetProcSpell())
|
||||
.SetTriggerFlags(TRIGGERED_FULL_MASK & ~(TRIGGERED_IGNORE_POWER_COST | TRIGGERED_IGNORE_REAGENT_COST)));
|
||||
}
|
||||
else if (triggerSpellId && GetAuraType() != SPELL_AURA_DUMMY)
|
||||
TC_LOG_ERROR("spells.aura.effect.nospell","AuraEffect::HandleProcTriggerSpellAuraProc: Spell {} has non-existent spell {} in EffectTriggered[{}] and is therefore not triggered.", GetId(), triggerSpellId, GetEffIndex());
|
||||
@@ -6154,6 +6160,7 @@ void AuraEffect::HandleProcTriggerSpellWithValueAuraProc(AuraApplication* aurApp
|
||||
if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty()))
|
||||
{
|
||||
CastSpellExtraArgs args(this);
|
||||
args.SetTriggerFlags(TRIGGERED_FULL_MASK & ~(TRIGGERED_IGNORE_POWER_COST | TRIGGERED_IGNORE_REAGENT_COST));
|
||||
args.SetTriggeringSpell(eventInfo.GetProcSpell());
|
||||
args.AddSpellMod(SPELLVALUE_BASE_POINT0, GetAmount());
|
||||
triggerCaster->CastSpell(triggerTarget, triggerSpellId, args);
|
||||
|
||||
@@ -464,12 +464,15 @@ m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEven
|
||||
m_procCooldown(TimePoint::min()),
|
||||
m_lastProcAttemptTime(GameTime::Now() - Seconds(10)), m_lastProcSuccessTime(GameTime::Now() - Seconds(120)), m_scriptRef(this, NoopAuraDeleter())
|
||||
{
|
||||
for (SpellPowerEntry const* power : m_spellInfo->PowerCosts)
|
||||
if (power && (power->ManaPerSecond != 0 || power->PowerPctPerSecond > 0.0f))
|
||||
m_periodicCosts.push_back(power);
|
||||
if (!m_spellInfo->HasAttribute(SPELL_ATTR6_DO_NOT_CONSUME_RESOURCES))
|
||||
{
|
||||
for (SpellPowerEntry const* power : m_spellInfo->PowerCosts)
|
||||
if (power && (power->ManaPerSecond != 0 || power->PowerPctPerSecond > 0.0f))
|
||||
m_periodicCosts.push_back(power);
|
||||
|
||||
if (!m_periodicCosts.empty())
|
||||
m_timeCla = 1 * IN_MILLISECONDS;
|
||||
if (!m_periodicCosts.empty())
|
||||
m_timeCla = 1 * IN_MILLISECONDS;
|
||||
}
|
||||
|
||||
m_maxDuration = CalcMaxDuration(createInfo.Caster);
|
||||
m_duration = m_maxDuration;
|
||||
|
||||
@@ -5548,7 +5548,7 @@ void Spell::TakePower()
|
||||
if (!unitCaster)
|
||||
return;
|
||||
|
||||
if (m_CastItem || m_triggeredByAuraSpell)
|
||||
if (m_CastItem || m_spellInfo->HasAttribute(SPELL_ATTR6_DO_NOT_CONSUME_RESOURCES))
|
||||
return;
|
||||
|
||||
//Don't take power if the spell is cast while .cheat power is enabled.
|
||||
@@ -5605,7 +5605,7 @@ void Spell::RefundPower()
|
||||
if (!unitCaster)
|
||||
return;
|
||||
|
||||
if (m_CastItem || m_triggeredByAuraSpell)
|
||||
if (m_CastItem || m_spellInfo->HasAttribute(SPELL_ATTR6_DO_NOT_CONSUME_RESOURCES))
|
||||
return;
|
||||
|
||||
//Don't take power if the spell is cast while .cheat power is enabled.
|
||||
@@ -5707,7 +5707,7 @@ void Spell::TakeReagents()
|
||||
return;
|
||||
|
||||
// do not take reagents for these item casts
|
||||
if (m_CastItem && m_CastItem->GetTemplate()->HasFlag(ITEM_FLAG_NO_REAGENT_COST))
|
||||
if ((m_CastItem && m_CastItem->GetTemplate()->HasFlag(ITEM_FLAG_NO_REAGENT_COST)) || m_spellInfo->HasAttribute(SPELL_ATTR6_DO_NOT_CONSUME_RESOURCES))
|
||||
return;
|
||||
|
||||
Player* p_caster = m_caster->ToPlayer();
|
||||
|
||||
@@ -708,7 +708,7 @@ void Spell::EffectTriggerSpell()
|
||||
targets.Update(caster); // refresh pointers stored in targets
|
||||
|
||||
// original caster guid only for GO cast
|
||||
CastSpellExtraArgs args(TRIGGERED_FULL_MASK);
|
||||
CastSpellExtraArgs args(TRIGGERED_FULL_MASK & ~(TRIGGERED_IGNORE_POWER_COST | TRIGGERED_IGNORE_REAGENT_COST));
|
||||
args.SetOriginalCaster(originalCaster);
|
||||
args.OriginalCastId = originalCastId;
|
||||
args.OriginalCastItemLevel = itemLevel;
|
||||
@@ -777,7 +777,7 @@ void Spell::EffectTriggerMissileSpell()
|
||||
targets.SetGOTarget(go);
|
||||
}
|
||||
|
||||
CastSpellExtraArgs args(TRIGGERED_FULL_MASK);
|
||||
CastSpellExtraArgs args(TRIGGERED_FULL_MASK & ~(TRIGGERED_IGNORE_POWER_COST | TRIGGERED_IGNORE_REAGENT_COST));
|
||||
args.SetOriginalCaster(m_originalCasterGUID);
|
||||
args.SetTriggeringSpell(this);
|
||||
args.SetCustomArg(m_customArg);
|
||||
@@ -851,7 +851,7 @@ void Spell::EffectForceCast()
|
||||
return;
|
||||
}
|
||||
|
||||
CastSpellExtraArgs args(TRIGGERED_FULL_MASK);
|
||||
CastSpellExtraArgs args(TRIGGERED_FULL_MASK & ~(TRIGGERED_IGNORE_POWER_COST | TRIGGERED_IGNORE_REAGENT_COST));
|
||||
args.SetTriggeringSpell(this);
|
||||
if (effectInfo->Effect == SPELL_EFFECT_FORCE_CAST_WITH_VALUE)
|
||||
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
|
||||
Reference in New Issue
Block a user