aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormegamage <none@none>2009-03-16 12:00:14 -0600
committermegamage <none@none>2009-03-16 12:00:14 -0600
commit3eba06e4ad7c9b92babd3df14d0602212e60b7cc (patch)
tree2dde1616704447c9c2a0d0ab0c4d6cc523a2842f /src
parent2453f2212324d656676693fd2b420290797a9ebf (diff)
*Use SpellCastResult and finaly fix SPELL_CAST_OK value (255 custom value now). By VladimirMangos.
--HG-- branch : trunk
Diffstat (limited to 'src')
-rw-r--r--src/game/Pet.cpp2
-rw-r--r--src/game/PetHandler.cpp10
-rw-r--r--src/game/Player.cpp6
-rw-r--r--src/game/SharedDefines.h7
-rw-r--r--src/game/Spell.cpp348
-rw-r--r--src/game/Spell.h22
-rw-r--r--src/game/SpellEffects.cpp6
-rw-r--r--src/game/SpellMgr.cpp28
-rw-r--r--src/game/SpellMgr.h4
-rw-r--r--src/game/Unit.cpp7
-rw-r--r--src/game/Unit.h2
11 files changed, 216 insertions, 226 deletions
diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp
index 11f1ba5d236..32ffd80801b 100644
--- a/src/game/Pet.cpp
+++ b/src/game/Pet.cpp
@@ -304,7 +304,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
AIM_Initialize();
map->Add((Creature*)this);
- // Spells should be loaded after pet is added to map, because in CanCast is check on it
+ // Spells should be loaded after pet is added to map, because in CheckCast is check on it
_LoadSpells();
_LoadSpellCooldowns();
diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp
index 11caeb74a55..9f9cb3a33a3 100644
--- a/src/game/PetHandler.cpp
+++ b/src/game/PetHandler.cpp
@@ -207,7 +207,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
Spell *spell = new Spell(pet, spellInfo, false);
- int16 result = spell->PetCanCast(unit_target);
+ SpellCastResult result = spell->CheckPetCast(unit_target);
//auto turn to target unless possessed
if(result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->isPossessed())
@@ -218,10 +218,10 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
if(Unit* powner = pet->GetCharmerOrOwner())
if(powner->GetTypeId() == TYPEID_PLAYER)
pet->SendUpdateToPlayer((Player*)powner);
- result = -1;
+ result = SPELL_CAST_OK;
}
- if(result == -1)
+ if(result == SPELL_CAST_OK)
{
((Creature*)pet)->AddCreatureSpellCooldown(spellid);
if (((Creature*)pet)->isPet())
@@ -624,8 +624,8 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
spell->m_cast_count = cast_count; // probably pending spell cast
spell->m_targets = targets;
- int16 result = spell->PetCanCast(NULL);
- if(result == -1)
+ SpellCastResult result = spell->CheckPetCast(NULL);
+ if(result == SPELL_CAST_OK)
{
if(caster->GetTypeId() == TYPEID_UNIT)
{
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 2fdf78e4a11..badeca1fa0e 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -7178,7 +7178,7 @@ void Player::ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply
if(apply)
{
// Cannot be used in this stance/form
- if(GetErrorAtShapeshiftedCast(spellInfo, m_form)!=0)
+ if(GetErrorAtShapeshiftedCast(spellInfo, m_form) != SPELL_CAST_OK)
return;
if(form_change) // check aura active state from other form
@@ -7212,7 +7212,7 @@ void Player::ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply
if(form_change) // check aura compatibility
{
// Cannot be used in this stance/form
- if(GetErrorAtShapeshiftedCast(spellInfo, m_form)==0)
+ if(GetErrorAtShapeshiftedCast(spellInfo, m_form)==SPELL_CAST_OK)
return; // and remove only not compatible at form change
}
@@ -19894,7 +19894,7 @@ void Player::UpdateAreaDependentAuras( uint32 newArea )
for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
{
// use m_zoneUpdateId for speed: UpdateArea called from UpdateZone or instead UpdateZone in both cases m_zoneUpdateId up-to-date
- if(spellmgr.GetSpellAllowedInLocationError(iter->second->GetSpellProto(),GetMapId(),m_zoneUpdateId,newArea,this)!=0)
+ if(spellmgr.GetSpellAllowedInLocationError(iter->second->GetSpellProto(),GetMapId(),m_zoneUpdateId,newArea,this) != SPELL_CAST_OK)
RemoveAura(iter);
else
++iter;
diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h
index ba165d3053a..f71f5655e25 100644
--- a/src/game/SharedDefines.h
+++ b/src/game/SharedDefines.h
@@ -695,8 +695,7 @@ enum SpellEffects
enum SpellCastResult
{
- SPELL_CAST_OK = 0, //FIXME: used as success result currently
- SPELL_FAILED_AFFECTING_COMBAT = 0, //FIXME: used as success result currently
+ SPELL_FAILED_AFFECTING_COMBAT = 0,
SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 1,
SPELL_FAILED_ALREADY_AT_FULL_MANA = 2,
SPELL_FAILED_ALREADY_AT_FULL_POWER = 3,
@@ -877,7 +876,9 @@ enum SpellCastResult
SPELL_FAILED_ITEM_AT_MAX_CHARGES = 178,
SPELL_FAILED_NOT_IN_BARBERSHOP = 179,
SPELL_FAILED_FISHING_TOO_LOW = 180,
- SPELL_FAILED_UNKNOWN = 181
+ SPELL_FAILED_UNKNOWN = 181,
+
+ SPELL_CAST_OK = 255 //custom value, don't must be send to client
};
// Spell aura states
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index bfc58631079..57bcebcef62 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -627,7 +627,7 @@ void Spell::FillTargetMap()
for (std::list<Unit*>::iterator itr = tmpUnitMap.begin() ; itr != tmpUnitMap.end();)
{
- if(!CheckTarget(*itr, i, false ))
+ if(!CheckTarget(*itr, i))
{
itr = tmpUnitMap.erase(itr);
continue;
@@ -2060,8 +2060,8 @@ void Spell::prepare(SpellCastTargets const* targets, Aura* triggeredByAura)
// Fill cost data
m_powerCost = CalculatePowerCost();
- uint8 result = CanCast(true);
- if(result != 0 && !IsAutoRepeat()) //always cast autorepeat dummy for triggering
+ SpellCastResult result = CheckCast(true);
+ if(result != SPELL_CAST_OK && !IsAutoRepeat()) //always cast autorepeat dummy for triggering
{
if(triggeredByAura)
{
@@ -2076,7 +2076,7 @@ void Spell::prepare(SpellCastTargets const* targets, Aura* triggeredByAura)
// Prepare data for triggers
prepareDataForTriggerSystem();
- // calculate cast time (calculated after first CanCast check to prevent charge counting for first CanCast fail)
+ // calculate cast time (calculated after first CheckCast check to prevent charge counting for first CheckCast fail)
m_casttime = GetSpellCastTime(m_spellInfo, this);
// set timer base at cast time
@@ -2157,8 +2157,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();
@@ -2175,8 +2173,8 @@ void Spell::cast(bool skipCheck)
if(!m_IsTriggeredSpell)
{
- castResult = CheckPower();
- if(castResult != 0)
+ SpellCastResult castResult = CheckPower();
+ if(castResult != SPELL_CAST_OK)
{
SendCastResult(castResult);
finish(false);
@@ -2188,8 +2186,8 @@ void Spell::cast(bool skipCheck)
// triggered cast called from Spell::prepare where it was already checked
if(!skipCheck)
{
- castResult = CanCast(false);
- if(castResult != 0)
+ SpellCastResult castResult = CheckCast(false);
+ if(castResult != SPELL_CAST_OK)
{
SendCastResult(castResult);
finish(false);
@@ -2634,65 +2632,65 @@ void Spell::finish(bool ok)
m_caster->AttackStop();
}
-void Spell::SendCastResult(uint8 result)
+void Spell::SendCastResult(SpellCastResult result)
{
+ if(result == SPELL_CAST_OK)
+ return;
+
if (m_caster->GetTypeId() != TYPEID_PLAYER)
return;
if(((Player*)m_caster)->GetSession()->PlayerLoading()) // don't send cast results at loading time
return;
- if(result != 0)
+ WorldPacket data(SMSG_CAST_FAILED, (4+1+1));
+ data << uint8(m_cast_count); // single cast or multi 2.3 (0/1)
+ data << uint32(m_spellInfo->Id);
+ data << uint8(result); // problem
+ switch (result)
{
- WorldPacket data(SMSG_CAST_FAILED, (4+1+1));
- data << uint8(m_cast_count); // single cast or multi 2.3 (0/1)
- data << uint32(m_spellInfo->Id);
- data << uint8(result); // problem
- switch (result)
- {
- case SPELL_FAILED_REQUIRES_SPELL_FOCUS:
- data << uint32(m_spellInfo->RequiresSpellFocus);
- break;
- case SPELL_FAILED_REQUIRES_AREA:
- // hardcode areas limitation case
- switch(m_spellInfo->Id)
- {
- case 41617: // Cenarion Mana Salve
- case 41619: // Cenarion Healing Salve
- data << uint32(3905);
- break;
- case 41618: // Bottled Nethergon Energy
- case 41620: // Bottled Nethergon Vapor
- data << uint32(3842);
- break;
- case 45373: // Bloodberry Elixir
- data << uint32(4075);
- break;
- default: // default case (don't must be)
- data << uint32(0);
- break;
- }
- break;
- case SPELL_FAILED_TOTEMS:
- if(m_spellInfo->Totem[0])
- data << uint32(m_spellInfo->Totem[0]);
- if(m_spellInfo->Totem[1])
- data << uint32(m_spellInfo->Totem[1]);
- break;
- case SPELL_FAILED_TOTEM_CATEGORY:
- if(m_spellInfo->TotemCategory[0])
- data << uint32(m_spellInfo->TotemCategory[0]);
- if(m_spellInfo->TotemCategory[1])
- data << uint32(m_spellInfo->TotemCategory[1]);
- break;
- case SPELL_FAILED_EQUIPPED_ITEM_CLASS:
- data << uint32(m_spellInfo->EquippedItemClass);
- data << uint32(m_spellInfo->EquippedItemSubClassMask);
- //data << uint32(m_spellInfo->EquippedItemInventoryTypeMask);
- break;
- }
- ((Player*)m_caster)->GetSession()->SendPacket(&data);
+ case SPELL_FAILED_REQUIRES_SPELL_FOCUS:
+ data << uint32(m_spellInfo->RequiresSpellFocus);
+ break;
+ case SPELL_FAILED_REQUIRES_AREA:
+ // hardcode areas limitation case
+ switch(m_spellInfo->Id)
+ {
+ case 41617: // Cenarion Mana Salve
+ case 41619: // Cenarion Healing Salve
+ data << uint32(3905);
+ break;
+ case 41618: // Bottled Nethergon Energy
+ case 41620: // Bottled Nethergon Vapor
+ data << uint32(3842);
+ break;
+ case 45373: // Bloodberry Elixir
+ data << uint32(4075);
+ break;
+ default: // default case (don't must be)
+ data << uint32(0);
+ break;
+ }
+ break;
+ case SPELL_FAILED_TOTEMS:
+ if(m_spellInfo->Totem[0])
+ data << uint32(m_spellInfo->Totem[0]);
+ if(m_spellInfo->Totem[1])
+ data << uint32(m_spellInfo->Totem[1]);
+ break;
+ case SPELL_FAILED_TOTEM_CATEGORY:
+ if(m_spellInfo->TotemCategory[0])
+ data << uint32(m_spellInfo->TotemCategory[0]);
+ if(m_spellInfo->TotemCategory[1])
+ data << uint32(m_spellInfo->TotemCategory[1]);
+ break;
+ case SPELL_FAILED_EQUIPPED_ITEM_CLASS:
+ data << uint32(m_spellInfo->EquippedItemClass);
+ data << uint32(m_spellInfo->EquippedItemSubClassMask);
+ //data << uint32(m_spellInfo->EquippedItemInventoryTypeMask);
+ break;
}
+ ((Player*)m_caster)->GetSession()->SendPacket(&data);
}
void Spell::SendSpellStart()
@@ -3280,30 +3278,28 @@ void Spell::TakeAmmo()
}
}
-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
@@ -3311,23 +3307,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()
@@ -3498,7 +3488,7 @@ void Spell::TriggerSpell()
}
}
-uint8 Spell::CanCast(bool strict)
+SpellCastResult Spell::CheckCast(bool strict)
{
// check cooldowns to prevent cheating
if(m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->HasSpellCooldown(m_spellInfo->Id))
@@ -3535,7 +3525,8 @@ uint8 Spell::CanCast(bool strict)
if (checkForm)
{
// Cannot be used in this stance/form
- if(uint8 shapeError = GetErrorAtShapeshiftedCast(m_spellInfo, m_caster->m_form))
+ SpellCastResult shapeError = GetErrorAtShapeshiftedCast(m_spellInfo, m_caster->m_form);
+ if(shapeError != SPELL_CAST_OK)
return shapeError;
if ((m_spellInfo->Attributes & SPELL_ATTR_ONLY_STEALTHED) && !(m_caster->HasStealthAura()))
@@ -3582,9 +3573,7 @@ uint8 Spell::CanCast(bool strict)
return SPELL_FAILED_MOVING;
}
- Unit *target = m_targets.getUnitTarget();
-
- if(target)
+ if(Unit *target = m_targets.getUnitTarget())
{
if (reqAuraState)
{
@@ -3615,14 +3604,10 @@ uint8 Spell::CanCast(bool strict)
// auto selection spell rank implemented in WorldSession::HandleCastSpellOpcode
// this case can be triggered if rank not found (too low-level target for first rank)
if(m_caster->GetTypeId() == TYPEID_PLAYER && !IsPassiveSpell(m_spellInfo->Id) && !m_CastItem)
- {
for(int i=0;i<3;i++)
- {
if(IsPositiveEffect(m_spellInfo->Id, i) && m_spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA)
if(target->getLevel() + 10 < m_spellInfo->spellLevel)
return SPELL_FAILED_LOWLEVEL;
- }
- }
}
else if (m_caster->GetTypeId()==TYPEID_PLAYER) // Target - is player caster
{
@@ -3688,10 +3673,8 @@ uint8 Spell::CanCast(bool strict)
}
if(IsPositiveSpell(m_spellInfo->Id))
- {
if(target->IsImmunedToSpell(m_spellInfo))
return SPELL_FAILED_TARGET_AURASTATE;
- }
//Must be behind the target.
if( m_spellInfo->AttributesEx2 == 0x100000 && (m_spellInfo->AttributesEx & 0x200) == 0x200 && target->HasInArc(M_PI, m_caster)
@@ -3713,10 +3696,9 @@ uint8 Spell::CanCast(bool strict)
// check if target is in combat
if (target != m_caster && (m_spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_IN_COMBAT_TARGET) && target->isInCombat())
- {
return SPELL_FAILED_TARGET_AFFECTING_COMBAT;
- }
}
+
// Spell casted only on battleground
if((m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_BATTLEGROUND) && m_caster->GetTypeId()==TYPEID_PLAYER)
if(!((Player*)m_caster)->InBattleGround())
@@ -3735,9 +3717,10 @@ uint8 Spell::CanCast(bool strict)
uint32 zone, area;
m_caster->GetZoneAndAreaId(zone,area);
- if (uint8 res= spellmgr.GetSpellAllowedInLocationError(m_spellInfo,m_caster->GetMapId(),zone,area,
- m_caster->GetTypeId()==TYPEID_PLAYER ? ((Player*)m_caster) : NULL))
- return res;
+ SpellCastResult locRes= spellmgr.GetSpellAllowedInLocationError(m_spellInfo,m_caster->GetMapId(),zone,area,
+ m_caster->GetTypeId()==TYPEID_PLAYER ? ((Player*)m_caster) : NULL);
+ if(locRes != SPELL_CAST_OK)
+ return locRes;
// not let players cast spells at mount (and let do it to creatures)
if( m_caster->IsMounted() && m_caster->GetTypeId()==TYPEID_PLAYER && !m_IsTriggeredSpell &&
@@ -3751,11 +3734,14 @@ 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)
+ if(m_UniqueTargetInfo.empty()) // skip second CheckCast apply (for delayed spells for example)
{
for(uint8 j = 0; j < 3; j++)
{
@@ -3891,13 +3877,16 @@ 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())
+ castResult = CheckPower();
+ if(castResult != SPELL_CAST_OK)
return castResult;
- if(uint8 castResult = CheckCasterAuras())
+ castResult = CheckCasterAuras();
+ if(castResult != SPELL_CAST_OK)
return castResult;
}
@@ -3922,7 +3911,7 @@ uint8 Spell::CanCast(bool strict)
{
// spell different for friends and enemies
// hart version required facing
- if(m_targets.getUnitTarget() && !m_caster->IsFriendlyTo(m_targets.getUnitTarget()) && !m_caster->HasInArc( M_PI, target ))
+ if(m_targets.getUnitTarget() && !m_caster->IsFriendlyTo(m_targets.getUnitTarget()) && !m_caster->HasInArc( M_PI, m_targets.getUnitTarget() ))
return SPELL_FAILED_UNIT_NOT_INFRONT;
}
else if (m_spellInfo->Id == 19938) // Awaken Peon
@@ -4332,10 +4321,10 @@ uint8 Spell::CanCast(bool strict)
}
// all ok
- return 0;
+ return SPELL_CAST_OK;
}
-int16 Spell::PetCanCast(Unit* target)
+SpellCastResult Spell::CheckPetCast(Unit* target)
{
if(!m_caster->isAlive())
return SPELL_FAILED_CASTER_DEAD;
@@ -4383,20 +4372,16 @@ int16 Spell::PetCanCast(Unit* target)
return SPELL_FAILED_NOT_READY;
}
- uint16 result = CanCast(true);
- if(result != 0)
- return result;
- else
- return -1; //this allows to check spell fail 0, in combat
+ return CheckCast(true);
}
-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;
@@ -4421,7 +4406,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))
@@ -4485,7 +4470,7 @@ uint8 Spell::CheckCasterAuras() const
else
return prevented_reason;
}
- return 0; // all ok
+ return SPELL_CAST_OK;
}
bool Spell::CanAutoCast(Unit* target)
@@ -4514,9 +4499,9 @@ bool Spell::CanAutoCast(Unit* target)
}
}
- int16 result = PetCanCast(target);
+ SpellCastResult result = CheckPetCast(target);
- if(result == -1 || result == SPELL_FAILED_UNIT_NOT_INFRONT)
+ if(result == SPELL_CAST_OK || result == SPELL_FAILED_UNIT_NOT_INFRONT)
{
FillTargetMap();
//check if among target units, our WANTED target is as well (->only self cast spells return false)
@@ -4527,12 +4512,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;
// i do not know why we need this
/*if (strict) //add radius of caster
@@ -4583,7 +4569,7 @@ uint8 Spell::CheckRange(bool strict)
return SPELL_FAILED_TOO_CLOSE;
}
- return 0; // ok
+ return SPELL_CAST_OK;
}
int32 Spell::CalculatePowerCost()
@@ -4654,18 +4640,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 )
@@ -4674,8 +4660,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
@@ -4683,15 +4669,14 @@ 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;
if(!m_CastItem)
@@ -4701,77 +4686,72 @@ uint8 Spell::CheckItems()
}
else
{
- 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++)
+ 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())
+ {
+ // 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)
+ // 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;
+
+ if (m_spellInfo->Effect[i] == SPELL_EFFECT_HEAL)
{
- if(m_CastItem->GetSpellCharges(i)==0)
- return SPELL_FAILED_NO_CHARGES_REMAIN;
+ if (m_targets.getUnitTarget()->GetHealth() == m_targets.getUnitTarget()->GetMaxHealth())
+ {
+ failReason = SPELL_FAILED_ALREADY_AT_FULL_HEALTH;
+ continue;
+ }
+ else
+ {
+ failReason = SPELL_CAST_OK;
+ break;
+ }
}
- }
- 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++)
+ // Mana Potion, Rage Potion, Thistle Tea(Rogue), ...
+ if (m_spellInfo->Effect[i] == SPELL_EFFECT_ENERGIZE)
{
- // 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_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
+ {
+ failReason = SPELL_FAILED_ALREADY_AT_FULL_POWER;
continue;
+ }
- if (m_spellInfo->Effect[i] == SPELL_EFFECT_HEAL)
+ Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
+ if (m_targets.getUnitTarget()->GetPower(power) == m_targets.getUnitTarget()->GetMaxPower(power))
{
- if (m_targets.getUnitTarget()->GetHealth() == m_targets.getUnitTarget()->GetMaxHealth())
- {
- failReason = (uint8)SPELL_FAILED_ALREADY_AT_FULL_HEALTH;
- continue;
- }
- else
- {
- failReason = 0;
- break;
- }
+ failReason = SPELL_FAILED_ALREADY_AT_FULL_POWER;
+ continue;
}
-
- // 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;
}
}
- if (failReason)
- return failReason;
}
+ if (failReason != SPELL_CAST_OK)
+ return failReason;
}
}
+ // check target item
if(m_targets.getItemTargetGUID())
{
if(m_caster->GetTypeId() != TYPEID_PLAYER)
@@ -4790,6 +4770,7 @@ uint8 Spell::CheckItems()
return SPELL_FAILED_EQUIPPED_ITEM_CLASS;
}
+ // check spell focus object
if(m_spellInfo->RequiresSpellFocus)
{
CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
@@ -4805,11 +4786,12 @@ uint8 Spell::CheckItems()
cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
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++)
@@ -4817,8 +4799,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 )
@@ -4838,10 +4820,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)
{
@@ -4856,9 +4839,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)
{
@@ -4874,8 +4857,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])
@@ -5077,7 +5061,7 @@ uint8 Spell::CheckItems()
}
}
- return uint8(0);
+ return SPELL_CAST_OK;
}
void Spell::Delayed() // only called in DealDamage()
@@ -5236,7 +5220,7 @@ CurrentSpellTypes Spell::GetCurrentContainer()
return(CURRENT_GENERIC_SPELL);
}
-bool Spell::CheckTarget( Unit* target, uint32 eff, bool hitPhase )
+bool Spell::CheckTarget( Unit* target, uint32 eff )
{
// Check targets for creature type mask and remove not appropriate (skip explicit self target case, maybe need other explicit targets)
if(m_spellInfo->EffectImplicitTargetA[eff]!=TARGET_SELF)
diff --git a/src/game/Spell.h b/src/game/Spell.h
index 0e87a0a01e3..66b98e7d566 100644
--- a/src/game/Spell.h
+++ b/src/game/Spell.h
@@ -365,14 +365,14 @@ class Spell
void finish(bool ok = true);
void TakePower();
void TakeAmmo();
- uint8 CheckRuneCost(uint32 runeCostID);
+
void TakeRunePower();
void TakeReagents();
void TakeCastItem();
void TriggerSpell();
- uint8 CanCast(bool strict);
- int16 PetCanCast(Unit* target);
- bool CanAutoCast(Unit* target);
+
+ SpellCastResult CheckCast(bool strict);
+ SpellCastResult CheckPetCast(Unit* target);
// handlers
void handle_immediate();
@@ -381,10 +381,11 @@ class Spell
void _handle_immediate_phase();
void _handle_finish_phase();
- uint8 CheckItems();
- uint8 CheckRange(bool strict);
- uint8 CheckPower();
- uint8 CheckCasterAuras() const;
+ SpellCastResult CheckItems();
+ SpellCastResult CheckRange(bool strict);
+ SpellCastResult CheckPower();
+ SpellCastResult CheckRuneCost(uint32 runeCostID);
+ SpellCastResult CheckCasterAuras() const;
int32 CalculateDamage(uint8 i, Unit* target) { return m_caster->CalculateSpellDamage(m_spellInfo,i,m_currentBasePoints[i],target); }
int32 CalculatePowerCost();
@@ -403,9 +404,10 @@ class Spell
void SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap);
Unit* SelectMagnetTarget();
- bool CheckTarget( Unit* target, uint32 eff, bool hitPhase );
+ bool CheckTarget( Unit* target, uint32 eff );
+ bool CanAutoCast(Unit* target);
- void SendCastResult(uint8 result);
+ void SendCastResult(SpellCastResult result);
void SendSpellStart();
void SendSpellGo();
void SendSpellCooldown();
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index 5cfb00588c5..309cf6e5816 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -3104,7 +3104,7 @@ void Spell::EffectOpenLock(uint32 effIndex)
if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK )
{
- //CanUseBattleGroundObject() already called in CanCast()
+ //CanUseBattleGroundObject() already called in CheckCast()
// in battleground check
if(BattleGround *bg = player->GetBattleGround())
{
@@ -3116,7 +3116,7 @@ void Spell::EffectOpenLock(uint32 effIndex)
}
else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
{
- //CanUseBattleGroundObject() already called in CanCast()
+ //CanUseBattleGroundObject() already called in CheckCast()
// in battleground check
if(BattleGround *bg = player->GetBattleGround())
{
@@ -3156,7 +3156,7 @@ void Spell::EffectOpenLock(uint32 effIndex)
SendLoot(guid, LOOT_SKINNING);
- // not allow use skill grou at item base open
+ // not allow use skill grow at item base open
if(!m_CastItem && skillId != SKILL_NONE)
{
// update skill if really known
diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index 109c846710a..5e21c4700c3 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -780,13 +780,13 @@ bool IsAuraAddedBySpell(uint32 auraType, uint32 spellId)
return false;
}
-uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form)
+SpellCastResult GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form)
{
// talents that learn spells can have stance requirements that need ignore
// (this requirement only for client-side stance show in talent description)
if( GetTalentSpellCost(spellInfo->Id) > 0 &&
(spellInfo->Effect[0]==SPELL_EFFECT_LEARN_SPELL || spellInfo->Effect[1]==SPELL_EFFECT_LEARN_SPELL || spellInfo->Effect[2]==SPELL_EFFECT_LEARN_SPELL) )
- return 0;
+ return SPELL_CAST_OK;
uint32 stanceMask = (form ? 1 << (form - 1) : 0);
@@ -794,7 +794,7 @@ uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form)
return SPELL_FAILED_NOT_SHAPESHIFT;
if (stanceMask & spellInfo->Stances) // can explicitly be casted in this stance
- return 0;
+ return SPELL_CAST_OK;
bool actAsShifted = false;
if (form > 0)
@@ -803,7 +803,7 @@ uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form)
if (!shapeInfo)
{
sLog.outError("GetErrorAtShapeshiftedCast: unknown shapeshift %u", form);
- return 0;
+ return SPELL_CAST_OK;
}
actAsShifted = !(shapeInfo->flags1 & 1); // shapeshift acts as normal form for spells
}
@@ -822,7 +822,7 @@ uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form)
return SPELL_FAILED_ONLY_SHAPESHIFT;
}
- return 0;
+ return SPELL_CAST_OK;
}
void SpellMgr::LoadSpellTargetPositions()
@@ -2759,7 +2759,7 @@ void SpellMgr::LoadSpellAreas()
sLog.outString( ">> Loaded %u spell area requirements", count );
}
-uint8 SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player)
+SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player)
{
// normal case
if( spellInfo->AreaGroupId > 0)
@@ -2785,7 +2785,7 @@ uint8 SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint
for(SpellAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
{
if(itr->second.IsFitToRequirements(player,zone_id,area_id))
- return 0;
+ return SPELL_CAST_OK;
}
return SPELL_FAILED_INCORRECT_AREA;
}
@@ -2795,9 +2795,9 @@ uint8 SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint
{
case 23333: // Warsong Flag
case 23335: // Silverwing Flag
- return map_id == 489 && player && player->InBattleGround() ? 0 : SPELL_FAILED_REQUIRES_AREA;
+ return map_id == 489 && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
case 34976: // Netherstorm Flag
- return map_id == 566 && player && player->InBattleGround() ? 0 : SPELL_FAILED_REQUIRES_AREA;
+ return map_id == 566 && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
case 2584: // Waiting to Resurrect
case 22011: // Spirit Heal Channel
case 22012: // Spirit Heal
@@ -2810,7 +2810,7 @@ uint8 SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint
if(!mapEntry)
return SPELL_FAILED_INCORRECT_AREA;
- return mapEntry->IsBattleGround() && player && player->InBattleGround() ? 0 : SPELL_FAILED_REQUIRES_AREA;
+ return mapEntry->IsBattleGround() && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
}
case 44521: // Preparation
{
@@ -2825,7 +2825,7 @@ uint8 SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint
return SPELL_FAILED_REQUIRES_AREA;
BattleGround* bg = player->GetBattleGround();
- return bg && bg->GetStatus()==STATUS_WAIT_JOIN ? 0 : SPELL_FAILED_REQUIRES_AREA;
+ return bg && bg->GetStatus()==STATUS_WAIT_JOIN ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
}
case 32724: // Gold Team (Alliance)
case 32725: // Green Team (Alliance)
@@ -2836,7 +2836,7 @@ uint8 SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint
if(!mapEntry)
return SPELL_FAILED_INCORRECT_AREA;
- return mapEntry->IsBattleArena() && player && player->InBattleGround() ? 0 : SPELL_FAILED_REQUIRES_AREA;
+ return mapEntry->IsBattleArena() && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
}
case 32727: // Arena Preparation
{
@@ -2851,11 +2851,11 @@ uint8 SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint
return SPELL_FAILED_REQUIRES_AREA;
BattleGround* bg = player->GetBattleGround();
- return bg && bg->GetStatus()==STATUS_WAIT_JOIN ? 0 : SPELL_FAILED_REQUIRES_AREA;
+ return bg && bg->GetStatus()==STATUS_WAIT_JOIN ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
}
}
- return 0;
+ return SPELL_CAST_OK;
}
void SpellMgr::LoadSkillLineAbilityMap()
diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h
index 8c2b5ccef93..9c671391bd5 100644
--- a/src/game/SpellMgr.h
+++ b/src/game/SpellMgr.h
@@ -285,7 +285,7 @@ inline bool IsAutoRepeatRangedSpell(SpellEntry const* spellInfo)
return (spellInfo->Attributes & SPELL_ATTR_RANGED) && (spellInfo->AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG);
}
-uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form);
+SpellCastResult GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form);
inline bool IsChanneledSpell(SpellEntry const* spellInfo)
{
@@ -915,7 +915,7 @@ class SpellMgr
return NULL;
}
- uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL);
+ SpellCastResult GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL);
SpellAreaMapBounds GetSpellAreaMapBounds(uint32 spell_id) const
{
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index edd099b63b7..d957988cc05 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -3385,7 +3385,7 @@ void Unit::_UpdateAutoRepeatSpell()
if (isAttackReady(RANGED_ATTACK))
{
// Check if able to cast
- if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->CanCast(true))
+ if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->CheckCast(true) != SPELL_CAST_OK)
{
InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
return;
@@ -11955,8 +11955,11 @@ Player* Unit::GetSpellModOwner() const
}
///----------Pet responses methods-----------------
-void Unit::SendPetCastFail(uint32 spellid, uint8 msg)
+void Unit::SendPetCastFail(uint32 spellid, SpellCastResult msg)
{
+ if(msg == SPELL_CAST_OK)
+ return;
+
Unit *owner = GetCharmerOrOwner();
if(!owner || owner->GetTypeId() != TYPEID_PLAYER)
return;
diff --git a/src/game/Unit.h b/src/game/Unit.h
index c3b786f2715..c977a1f1b0e 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -1516,7 +1516,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void ClearComboPointHolders();
///----------Pet responses methods-----------------
- void SendPetCastFail(uint32 spellid, uint8 msg);
+ void SendPetCastFail(uint32 spellid, SpellCastResult msg);
void SendPetActionFeedback (uint8 msg);
void SendPetTalk (uint32 pettalk);
void SendPetSpellCooldown (uint32 spellid, time_t cooltime);