mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 22:37:03 +00:00
[10701] Correct check percent spell costs in AI::CanCast
Also use uint32 for spell cost fields/results Signed-off-by: VladimirMangos <vladimir@getmangos.com>
This commit is contained in:
parent
a72930acc9
commit
b435aa350f
5 changed files with 41 additions and 39 deletions
|
|
@ -19,6 +19,7 @@
|
||||||
#include "CreatureAI.h"
|
#include "CreatureAI.h"
|
||||||
#include "Creature.h"
|
#include "Creature.h"
|
||||||
#include "DBCStores.h"
|
#include "DBCStores.h"
|
||||||
|
#include "Spell.h"
|
||||||
|
|
||||||
CreatureAI::~CreatureAI()
|
CreatureAI::~CreatureAI()
|
||||||
{
|
{
|
||||||
|
|
@ -46,7 +47,7 @@ CanCastResult CreatureAI::CanCastSpell(Unit* pTarget, const SpellEntry *pSpell,
|
||||||
return CAST_FAIL_STATE;
|
return CAST_FAIL_STATE;
|
||||||
|
|
||||||
// Check for power (also done by Spell::CheckCast())
|
// Check for power (also done by Spell::CheckCast())
|
||||||
if (m_creature->GetPower((Powers)pSpell->powerType) < pSpell->manaCost)
|
if (m_creature->GetPower((Powers)pSpell->powerType) < Spell::CalculatePowerCost(pSpell, m_creature))
|
||||||
return CAST_FAIL_POWER;
|
return CAST_FAIL_POWER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1390,7 +1390,7 @@ bool CreatureEventAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Trigge
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//Check for power
|
//Check for power
|
||||||
if (!Triggered && m_creature->GetPower((Powers)Spell->powerType) < Spell->manaCost)
|
if (!Triggered && m_creature->GetPower((Powers)Spell->powerType) < Spell::CalculatePowerCost(Spell, m_creature))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SpellRangeEntry const *TempRange = NULL;
|
SpellRangeEntry const *TempRange = NULL;
|
||||||
|
|
|
||||||
|
|
@ -2633,7 +2633,7 @@ void Spell::prepare(SpellCastTargets const* targets, Aura* triggeredByAura)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill cost data
|
// Fill cost data
|
||||||
m_powerCost = CalculatePowerCost();
|
m_powerCost = CalculatePowerCost(m_spellInfo, m_caster, this, m_CastItem);
|
||||||
|
|
||||||
SpellCastResult result = CheckCast(true);
|
SpellCastResult result = CheckCast(true);
|
||||||
if(result != SPELL_CAST_OK && !IsAutoRepeat()) //always cast autorepeat dummy for triggering
|
if(result != SPELL_CAST_OK && !IsAutoRepeat()) //always cast autorepeat dummy for triggering
|
||||||
|
|
@ -5616,69 +5616,70 @@ SpellCastResult Spell::CheckRange(bool strict)
|
||||||
return SPELL_CAST_OK;
|
return SPELL_CAST_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 Spell::CalculatePowerCost()
|
uint32 Spell::CalculatePowerCost(SpellEntry const* spellInfo, Unit* caster, Spell const* spell, Item* castItem)
|
||||||
{
|
{
|
||||||
// item cast not used power
|
// item cast not used power
|
||||||
if (m_CastItem)
|
if (castItem)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Spell drain all exist power on cast (Only paladin lay of Hands)
|
// Spell drain all exist power on cast (Only paladin lay of Hands)
|
||||||
if (m_spellInfo->AttributesEx & SPELL_ATTR_EX_DRAIN_ALL_POWER)
|
if (spellInfo->AttributesEx & SPELL_ATTR_EX_DRAIN_ALL_POWER)
|
||||||
{
|
{
|
||||||
// If power type - health drain all
|
// If power type - health drain all
|
||||||
if (m_spellInfo->powerType == POWER_HEALTH)
|
if (spellInfo->powerType == POWER_HEALTH)
|
||||||
return m_caster->GetHealth();
|
return caster->GetHealth();
|
||||||
// Else drain all power
|
// Else drain all power
|
||||||
if (m_spellInfo->powerType < MAX_POWERS)
|
if (spellInfo->powerType < MAX_POWERS)
|
||||||
return m_caster->GetPower(Powers(m_spellInfo->powerType));
|
return caster->GetPower(Powers(spellInfo->powerType));
|
||||||
sLog.outError("Spell::CalculateManaCost: Unknown power type '%d' in spell %d", m_spellInfo->powerType, m_spellInfo->Id);
|
sLog.outError("Spell::CalculateManaCost: Unknown power type '%d' in spell %d", spellInfo->powerType, spellInfo->Id);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base powerCost
|
// Base powerCost
|
||||||
int32 powerCost = m_spellInfo->manaCost;
|
int32 powerCost = spellInfo->manaCost;
|
||||||
// PCT cost from total amount
|
// PCT cost from total amount
|
||||||
if (m_spellInfo->ManaCostPercentage)
|
if (spellInfo->ManaCostPercentage)
|
||||||
{
|
{
|
||||||
switch (m_spellInfo->powerType)
|
switch (spellInfo->powerType)
|
||||||
{
|
{
|
||||||
// health as power used
|
// health as power used
|
||||||
case POWER_HEALTH:
|
case POWER_HEALTH:
|
||||||
powerCost += m_spellInfo->ManaCostPercentage * m_caster->GetCreateHealth() / 100;
|
powerCost += spellInfo->ManaCostPercentage * caster->GetCreateHealth() / 100;
|
||||||
break;
|
break;
|
||||||
case POWER_MANA:
|
case POWER_MANA:
|
||||||
powerCost += m_spellInfo->ManaCostPercentage * m_caster->GetCreateMana() / 100;
|
powerCost += spellInfo->ManaCostPercentage * caster->GetCreateMana() / 100;
|
||||||
break;
|
break;
|
||||||
case POWER_RAGE:
|
case POWER_RAGE:
|
||||||
case POWER_FOCUS:
|
case POWER_FOCUS:
|
||||||
case POWER_ENERGY:
|
case POWER_ENERGY:
|
||||||
case POWER_HAPPINESS:
|
case POWER_HAPPINESS:
|
||||||
powerCost += m_spellInfo->ManaCostPercentage * m_caster->GetMaxPower(Powers(m_spellInfo->powerType)) / 100;
|
powerCost += spellInfo->ManaCostPercentage * caster->GetMaxPower(Powers(spellInfo->powerType)) / 100;
|
||||||
break;
|
break;
|
||||||
case POWER_RUNE:
|
case POWER_RUNE:
|
||||||
case POWER_RUNIC_POWER:
|
case POWER_RUNIC_POWER:
|
||||||
DEBUG_LOG("Spell::CalculateManaCost: Not implemented yet!");
|
DEBUG_LOG("Spell::CalculateManaCost: Not implemented yet!");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sLog.outError("Spell::CalculateManaCost: Unknown power type '%d' in spell %d", m_spellInfo->powerType, m_spellInfo->Id);
|
sLog.outError("Spell::CalculateManaCost: Unknown power type '%d' in spell %d", spellInfo->powerType, spellInfo->Id);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SpellSchools school = GetFirstSchoolInMask(m_spellSchoolMask);
|
SpellSchools school = GetFirstSchoolInMask(spell ? spell->m_spellSchoolMask : GetSpellSchoolMask(spellInfo));
|
||||||
// Flat mod from caster auras by spell school
|
// Flat mod from caster auras by spell school
|
||||||
powerCost += m_caster->GetInt32Value(UNIT_FIELD_POWER_COST_MODIFIER + school);
|
powerCost += caster->GetInt32Value(UNIT_FIELD_POWER_COST_MODIFIER + school);
|
||||||
// Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost)
|
// Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost)
|
||||||
if ( m_spellInfo->AttributesEx4 & SPELL_ATTR_EX4_SPELL_VS_EXTEND_COST )
|
if (spellInfo->AttributesEx4 & SPELL_ATTR_EX4_SPELL_VS_EXTEND_COST)
|
||||||
powerCost += m_caster->GetAttackTime(OFF_ATTACK) / 100;
|
powerCost += caster->GetAttackTime(OFF_ATTACK) / 100;
|
||||||
// Apply cost mod by spell
|
// Apply cost mod by spell
|
||||||
if(Player* modOwner = m_caster->GetSpellModOwner())
|
if (spell)
|
||||||
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, powerCost, this);
|
if (Player* modOwner = caster->GetSpellModOwner())
|
||||||
|
modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COST, powerCost, spell);
|
||||||
|
|
||||||
if(m_spellInfo->Attributes & SPELL_ATTR_LEVEL_DAMAGE_CALCULATION)
|
if (spellInfo->Attributes & SPELL_ATTR_LEVEL_DAMAGE_CALCULATION)
|
||||||
powerCost = int32(powerCost/ (1.117f * m_spellInfo->spellLevel / m_caster->getLevel() -0.1327f));
|
powerCost = int32(powerCost/ (1.117f * spellInfo->spellLevel / caster->getLevel() -0.1327f));
|
||||||
|
|
||||||
// PCT mod from user auras by school
|
// PCT mod from user auras by school
|
||||||
powerCost = int32(powerCost * (1.0f + m_caster->GetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER + school)));
|
powerCost = int32(powerCost * (1.0f + caster->GetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER + school)));
|
||||||
if (powerCost < 0)
|
if (powerCost < 0)
|
||||||
powerCost = 0;
|
powerCost = 0;
|
||||||
return powerCost;
|
return powerCost;
|
||||||
|
|
@ -5702,7 +5703,7 @@ SpellCastResult Spell::CheckPower()
|
||||||
// health as power used - need check health amount
|
// health as power used - need check health amount
|
||||||
if (m_spellInfo->powerType == POWER_HEALTH)
|
if (m_spellInfo->powerType == POWER_HEALTH)
|
||||||
{
|
{
|
||||||
if((int32)m_caster->GetHealth() <= m_powerCost)
|
if (m_caster->GetHealth() <= m_powerCost)
|
||||||
return SPELL_FAILED_CASTER_AURASTATE;
|
return SPELL_FAILED_CASTER_AURASTATE;
|
||||||
return SPELL_CAST_OK;
|
return SPELL_CAST_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -5723,9 +5724,9 @@ SpellCastResult Spell::CheckPower()
|
||||||
|
|
||||||
// Check power amount
|
// Check power amount
|
||||||
Powers powerType = Powers(m_spellInfo->powerType);
|
Powers powerType = Powers(m_spellInfo->powerType);
|
||||||
if((int32)m_caster->GetPower(powerType) < m_powerCost)
|
if (m_caster->GetPower(powerType) < m_powerCost)
|
||||||
return SPELL_FAILED_NO_POWER;
|
return SPELL_FAILED_NO_POWER;
|
||||||
else
|
|
||||||
return SPELL_CAST_OK;
|
return SPELL_CAST_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -374,7 +374,7 @@ class Spell
|
||||||
SpellCastResult CheckCasterAuras() const;
|
SpellCastResult CheckCasterAuras() const;
|
||||||
|
|
||||||
int32 CalculateDamage(SpellEffectIndex i, Unit* target) { return m_caster->CalculateSpellDamage(target, m_spellInfo, i, &m_currentBasePoints[i]); }
|
int32 CalculateDamage(SpellEffectIndex i, Unit* target) { return m_caster->CalculateSpellDamage(target, m_spellInfo, i, &m_currentBasePoints[i]); }
|
||||||
int32 CalculatePowerCost();
|
static uint32 CalculatePowerCost(SpellEntry const* spellInfo, Unit* caster, Spell const* spell = NULL, Item* castItem = NULL);
|
||||||
|
|
||||||
bool HaveTargetsForEffect(SpellEffectIndex effect) const;
|
bool HaveTargetsForEffect(SpellEffectIndex effect) const;
|
||||||
void Delayed();
|
void Delayed();
|
||||||
|
|
@ -469,7 +469,7 @@ class Spell
|
||||||
// m_originalCasterGUID can store GO guid, and in this case this is visual caster
|
// m_originalCasterGUID can store GO guid, and in this case this is visual caster
|
||||||
WorldObject* GetCastingObject() const;
|
WorldObject* GetCastingObject() const;
|
||||||
|
|
||||||
int32 GetPowerCost() const { return m_powerCost; }
|
uint32 GetPowerCost() const { return m_powerCost; }
|
||||||
|
|
||||||
void UpdatePointers(); // must be used at call Spell code after time delay (non triggered spell cast/update spell call/etc)
|
void UpdatePointers(); // must be used at call Spell code after time delay (non triggered spell cast/update spell call/etc)
|
||||||
|
|
||||||
|
|
@ -506,7 +506,7 @@ class Spell
|
||||||
//Spell data
|
//Spell data
|
||||||
SpellSchoolMask m_spellSchoolMask; // Spell school (can be overwrite for some spells (wand shoot for example)
|
SpellSchoolMask m_spellSchoolMask; // Spell school (can be overwrite for some spells (wand shoot for example)
|
||||||
WeaponAttackType m_attackType; // For weapon based attack
|
WeaponAttackType m_attackType; // For weapon based attack
|
||||||
int32 m_powerCost; // Calculated spell cost initialized only in Spell::prepare
|
uint32 m_powerCost; // Calculated spell cost initialized only in Spell::prepare
|
||||||
int32 m_casttime; // Calculated spell cast time initialized only in Spell::prepare
|
int32 m_casttime; // Calculated spell cast time initialized only in Spell::prepare
|
||||||
bool m_canReflect; // can reflect this spell?
|
bool m_canReflect; // can reflect this spell?
|
||||||
bool m_autoRepeat;
|
bool m_autoRepeat;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "10700"
|
#define REVISION_NR "10701"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue