*Use SpellCastResult and finaly fix SPELL_CAST_OK value (255 custom value now). By VladimirMangos.

--HG--
branch : trunk
This commit is contained in:
megamage
2009-03-16 12:00:14 -06:00
parent 2453f22123
commit 3eba06e4ad
11 changed files with 220 additions and 230 deletions
+1 -1
View File
@@ -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();
+5 -5
View File
@@ -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)
{
+3 -3
View File
@@ -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;
+4 -3
View File
@@ -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
+170 -186
View File
@@ -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++)
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)
@@ -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)
+12 -10
View File
@@ -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();
+3 -3
View File
@@ -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
+14 -14
View File
@@ -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()
+2 -2
View File
@@ -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
{
+5 -2
View File
@@ -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;
+1 -1
View File
@@ -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);