[7465] More fixes in SPELL_CAST_OK use.

This commit is contained in:
VladimirMangos 2009-03-16 09:36:26 +03:00
parent 4aaf758ab7
commit 78879cc634
3 changed files with 108 additions and 108 deletions

View file

@ -2269,8 +2269,6 @@ void Spell::cast(bool skipCheck)
{
SetExecutedCurrently(true);
uint8 castResult = 0;
// update pointers base at GUIDs to prevent access to non-existed already object
UpdatePointers();
@ -2285,8 +2283,8 @@ void Spell::cast(bool skipCheck)
if(m_caster->GetTypeId() != TYPEID_PLAYER && m_targets.getUnitTarget() && m_targets.getUnitTarget() != m_caster)
m_caster->SetInFront(m_targets.getUnitTarget());
castResult = CheckPower();
if(castResult != 0)
uint8 castResult = CheckPower();
if(castResult != SPELL_CAST_OK)
{
SendCastResult(castResult);
finish(false);
@ -3375,30 +3373,28 @@ void Spell::TakePower()
m_caster->SetLastManaUse(getMSTime());
}
uint8 Spell::CheckRuneCost(uint32 runeCostID)
SpellCastResult Spell::CheckRuneCost(uint32 runeCostID)
{
if(m_caster->GetTypeId() != TYPEID_PLAYER)
return 0;
return SPELL_CAST_OK;
Player *plr = (Player*)m_caster;
if(plr->getClass() != CLASS_DEATH_KNIGHT)
return 0;
return SPELL_CAST_OK;
SpellRuneCostEntry const *src = sSpellRuneCostStore.LookupEntry(runeCostID);
if(!src)
return 0;
return SPELL_CAST_OK;
if(src->NoRuneCost())
return 0;
return SPELL_CAST_OK;
int32 runeCost[NUM_RUNE_TYPES]; // blood, frost, unholy, death
for(uint32 i = 0; i < RUNE_DEATH; ++i)
{
runeCost[i] = src->RuneCost[i];
}
runeCost[RUNE_DEATH] = MAX_RUNES; // calculated later
@ -3406,23 +3402,17 @@ uint8 Spell::CheckRuneCost(uint32 runeCostID)
{
uint8 rune = plr->GetCurrentRune(i);
if((plr->GetRuneCooldown(i) == 0) && (runeCost[rune] > 0))
{
runeCost[rune]--;
}
}
for(uint32 i = 0; i < RUNE_DEATH; ++i)
{
if(runeCost[i] > 0)
{
runeCost[RUNE_DEATH] += runeCost[i];
}
}
if(runeCost[RUNE_DEATH] > MAX_RUNES)
return SPELL_FAILED_NO_POWER; // not sure if result code is correct
return 0;
return SPELL_CAST_OK;
}
void Spell::TakeRunePower()
@ -3821,8 +3811,11 @@ uint8 Spell::CanCast(bool strict)
// always (except passive spells) check items (focus object can be required for any type casts)
if(!IsPassiveSpell(m_spellInfo->Id))
if(uint8 castResult = CheckItems())
{
SpellCastResult castResult = CheckItems();
if(castResult != SPELL_CAST_OK)
return castResult;
}
//ImpliciteTargetA-B = 38, If fact there is 0 Spell with ImpliciteTargetB=38
if(m_UniqueTargetInfo.empty()) // skip second canCast apply (for delayed spells for example)
@ -3960,17 +3953,24 @@ uint8 Spell::CanCast(bool strict)
}
if(!m_IsTriggeredSpell)
if(uint8 castResult = CheckRange(strict))
{
SpellCastResult castResult = CheckRange(strict);
if(castResult != SPELL_CAST_OK)
return castResult;
}
{
if(uint8 castResult = CheckPower())
SpellCastResult castResult = CheckPower();
if(castResult != SPELL_CAST_OK)
return castResult;
}
if(!m_IsTriggeredSpell) // triggered spell not affected by stun/etc
if(uint8 castResult = CheckCasterAuras())
{
SpellCastResult castResult = CheckCasterAuras();
if(castResult != SPELL_CAST_OK)
return castResult;
}
for (int i = 0; i < 3; i++)
{
@ -4472,13 +4472,13 @@ int16 Spell::PetCanCast(Unit* target)
return -1; //this allows to check spell fail 0, in combat
}
uint8 Spell::CheckCasterAuras() const
SpellCastResult Spell::CheckCasterAuras() const
{
// Flag drop spells totally immuned to caster auras
// FIXME: find more nice check for all totally immuned spells
// AttributesEx3 & 0x10000000?
if(m_spellInfo->Id==23336 || m_spellInfo->Id==23334 || m_spellInfo->Id==34991)
return 0;
return SPELL_CAST_OK;
uint8 school_immune = 0;
uint32 mechanic_immune = 0;
@ -4503,7 +4503,7 @@ uint8 Spell::CheckCasterAuras() const
}
//Check whether the cast should be prevented by any state you might have.
uint8 prevented_reason = 0;
SpellCastResult prevented_reason = SPELL_CAST_OK;
// Have to check if there is a stun aura. Otherwise will have problems with ghost aura apply while logging out
uint32 unitflag = m_caster->GetUInt32Value(UNIT_FIELD_FLAGS); // Get unit state
if(unitflag & UNIT_FLAG_STUNNED && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_STUNNED))
@ -4567,7 +4567,7 @@ uint8 Spell::CheckCasterAuras() const
else
return prevented_reason;
}
return 0; // all ok
return SPELL_CAST_OK;
}
bool Spell::CanAutoCast(Unit* target)
@ -4609,12 +4609,13 @@ bool Spell::CanAutoCast(Unit* target)
return false; //target invalid
}
uint8 Spell::CheckRange(bool strict)
SpellCastResult Spell::CheckRange(bool strict)
{
float range_mod;
// self cast doesn't need range checking -- also for Starshards fix
if (m_spellInfo->rangeIndex == 1) return 0;
if (m_spellInfo->rangeIndex == 1)
return SPELL_CAST_OK;
if (strict) //add radius of caster
range_mod = 1.25;
@ -4652,7 +4653,7 @@ uint8 Spell::CheckRange(bool strict)
return SPELL_FAILED_TOO_CLOSE;
}
return 0; // ok
return SPELL_CAST_OK;
}
int32 Spell::CalculatePowerCost()
@ -4723,18 +4724,18 @@ int32 Spell::CalculatePowerCost()
return powerCost;
}
uint8 Spell::CheckPower()
SpellCastResult Spell::CheckPower()
{
// item cast not used power
if(m_CastItem)
return 0;
return SPELL_CAST_OK;
// health as power used - need check health amount
if(m_spellInfo->powerType == POWER_HEALTH)
{
if(m_caster->GetHealth() <= m_powerCost)
return SPELL_FAILED_CASTER_AURASTATE;
return 0;
return SPELL_CAST_OK;
}
// Check valid power type
if( m_spellInfo->powerType >= MAX_POWERS )
@ -4743,8 +4744,8 @@ uint8 Spell::CheckPower()
return SPELL_FAILED_UNKNOWN;
}
uint8 failReason = CheckRuneCost(m_spellInfo->runeCostID);
if(failReason)
SpellCastResult failReason = CheckRuneCost(m_spellInfo->runeCostID);
if(failReason != SPELL_CAST_OK)
return failReason;
// Check power amount
@ -4752,90 +4753,85 @@ uint8 Spell::CheckPower()
if(m_caster->GetPower(powerType) < m_powerCost)
return SPELL_FAILED_NO_POWER;
else
return 0;
return SPELL_CAST_OK;
}
uint8 Spell::CheckItems()
SpellCastResult Spell::CheckItems()
{
if (m_caster->GetTypeId() != TYPEID_PLAYER)
return 0;
return SPELL_CAST_OK;
uint32 itemid, itemcount;
Player* p_caster = (Player*)m_caster;
// cast item checks
if(m_CastItem)
{
itemid = m_CastItem->GetEntry();
uint32 itemid = m_CastItem->GetEntry();
if( !p_caster->HasItemCount(itemid,1) )
return SPELL_FAILED_ITEM_NOT_READY;
else
ItemPrototype const *proto = m_CastItem->GetProto();
if(!proto)
return SPELL_FAILED_ITEM_NOT_READY;
for (int i = 0; i<5; i++)
if (proto->Spells[i].SpellCharges)
if(m_CastItem->GetSpellCharges(i)==0)
return SPELL_FAILED_NO_CHARGES_REMAIN;
// consumable cast item checks
if (proto->Class == ITEM_CLASS_CONSUMABLE && m_targets.getUnitTarget())
{
ItemPrototype const *proto = m_CastItem->GetProto();
if(!proto)
return SPELL_FAILED_ITEM_NOT_READY;
for (int i = 0; i<5; i++)
// such items should only fail if there is no suitable effect at all - see Rejuvenation Potions for example
SpellCastResult failReason = SPELL_CAST_OK;
for (int i = 0; i < 3; i++)
{
if (proto->Spells[i].SpellCharges)
{
if(m_CastItem->GetSpellCharges(i)==0)
return SPELL_FAILED_NO_CHARGES_REMAIN;
}
}
// skip check, pet not required like checks, and for TARGET_PET m_targets.getUnitTarget() is not the real target but the caster
if (m_spellInfo->EffectImplicitTargetA[i] == TARGET_PET)
continue;
uint32 ItemClass = proto->Class;
if (ItemClass == ITEM_CLASS_CONSUMABLE && m_targets.getUnitTarget())
{
// such items should only fail if there is no suitable effect at all - see Rejuvenation Potions for example
uint8 failReason = 0;
for (int i = 0; i < 3; i++)
if (m_spellInfo->Effect[i] == SPELL_EFFECT_HEAL)
{
// skip check, pet not required like checks, and for TARGET_PET m_targets.getUnitTarget() is not the real target but the caster
if (m_spellInfo->EffectImplicitTargetA[i] == TARGET_PET)
if (m_targets.getUnitTarget()->GetHealth() == m_targets.getUnitTarget()->GetMaxHealth())
{
failReason = SPELL_FAILED_ALREADY_AT_FULL_HEALTH;
continue;
if (m_spellInfo->Effect[i] == SPELL_EFFECT_HEAL)
{
if (m_targets.getUnitTarget()->GetHealth() == m_targets.getUnitTarget()->GetMaxHealth())
{
failReason = (uint8)SPELL_FAILED_ALREADY_AT_FULL_HEALTH;
continue;
}
else
{
failReason = 0;
break;
}
}
// Mana Potion, Rage Potion, Thistle Tea(Rogue), ...
if (m_spellInfo->Effect[i] == SPELL_EFFECT_ENERGIZE)
else
{
if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
{
failReason = (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER;
continue;
}
Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
if (m_targets.getUnitTarget()->GetPower(power) == m_targets.getUnitTarget()->GetMaxPower(power))
{
failReason = (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER;
continue;
}
else
{
failReason = 0;
break;
}
failReason = SPELL_CAST_OK;
break;
}
}
// Mana Potion, Rage Potion, Thistle Tea(Rogue), ...
if (m_spellInfo->Effect[i] == SPELL_EFFECT_ENERGIZE)
{
if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
{
failReason = SPELL_FAILED_ALREADY_AT_FULL_POWER;
continue;
}
Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
if (m_targets.getUnitTarget()->GetPower(power) == m_targets.getUnitTarget()->GetMaxPower(power))
{
failReason = SPELL_FAILED_ALREADY_AT_FULL_POWER;
continue;
}
else
{
failReason = SPELL_CAST_OK;
break;
}
}
if (failReason)
return failReason;
}
if (failReason != SPELL_CAST_OK)
return failReason;
}
}
// check target item
if(m_targets.getItemTargetGUID())
{
if(m_caster->GetTypeId() != TYPEID_PLAYER)
@ -4854,6 +4850,7 @@ uint8 Spell::CheckItems()
return SPELL_FAILED_EQUIPPED_ITEM_CLASS;
}
// check spell focus object
if(m_spellInfo->RequiresSpellFocus)
{
CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
@ -4869,11 +4866,12 @@ uint8 Spell::CheckItems()
cell_lock->Visit(cell_lock, object_checker, *m_caster->GetMap());
if(!ok)
return (uint8)SPELL_FAILED_REQUIRES_SPELL_FOCUS;
return SPELL_FAILED_REQUIRES_SPELL_FOCUS;
focusObject = ok; // game object found in range
}
// check reagents
if (!p_caster->CanNoReagentCast(m_spellInfo))
{
for(uint32 i=0;i<8;i++)
@ -4881,8 +4879,8 @@ uint8 Spell::CheckItems()
if(m_spellInfo->Reagent[i] <= 0)
continue;
itemid = m_spellInfo->Reagent[i];
itemcount = m_spellInfo->ReagentCount[i];
uint32 itemid = m_spellInfo->Reagent[i];
uint32 itemcount = m_spellInfo->ReagentCount[i];
// if CastItem is also spell reagent
if( m_CastItem && m_CastItem->GetEntry() == itemid )
@ -4902,10 +4900,11 @@ uint8 Spell::CheckItems()
}
}
if( !p_caster->HasItemCount(itemid,itemcount) )
return (uint8)SPELL_FAILED_ITEM_NOT_READY; //0x54
return SPELL_FAILED_ITEM_NOT_READY; //0x54
}
}
// check totem-item requirements (items presence in inventory)
uint32 totems = 2;
for(int i=0;i<2;++i)
{
@ -4920,9 +4919,9 @@ uint8 Spell::CheckItems()
totems -= 1;
}
if(totems != 0)
return (uint8)SPELL_FAILED_TOTEMS; //0x7C
return SPELL_FAILED_TOTEMS; //0x7C
//Check items for TotemCategory
// Check items for TotemCategory (items presence in inventory)
uint32 TotemCategory = 2;
for(int i=0;i<2;++i)
{
@ -4938,8 +4937,9 @@ uint8 Spell::CheckItems()
TotemCategory -= 1;
}
if(TotemCategory != 0)
return (uint8)SPELL_FAILED_TOTEM_CATEGORY; //0x7B
return SPELL_FAILED_TOTEM_CATEGORY; //0x7B
// special checks for spell effects
for(int i = 0; i < 3; i++)
{
switch (m_spellInfo->Effect[i])
@ -5141,7 +5141,7 @@ uint8 Spell::CheckItems()
}
}
return uint8(0);
return SPELL_CAST_OK;
}
void Spell::Delayed()