aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells/SpellInfo.cpp
diff options
context:
space:
mode:
authorariel- <ariel-@users.noreply.github.com>2018-02-10 16:43:01 -0300
committerAriel Silva <ariel-@users.noreply.github.com>2018-03-09 14:41:28 -0300
commit45c5e1b9d63796d168339a44f63418f220cf2403 (patch)
treec5c2ef9917147e38779d1f94e6ffc38386b9b251 /src/server/game/Spells/SpellInfo.cpp
parent080d2c6cd439acb2059adc4e24a279de98aa0db6 (diff)
Core/Spells: rework part 5: GameObject casting
Closes #21330 Closes #18885 Ref #18752
Diffstat (limited to 'src/server/game/Spells/SpellInfo.cpp')
-rw-r--r--src/server/game/Spells/SpellInfo.cpp104
1 files changed, 62 insertions, 42 deletions
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index cf8ef564413..63dadd6ede3 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -395,16 +395,20 @@ bool SpellEffectInfo::IsUnitOwnedAuraEffect() const
return IsAreaAuraEffect() || Effect == SPELL_EFFECT_APPLY_AURA;
}
-int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const* /*target*/) const
+int32 SpellEffectInfo::CalcValue(WorldObject const* caster /*= nullptr*/, int32 const* bp /*= nullptr*/) const
{
float basePointsPerLevel = RealPointsPerLevel;
int32 basePoints = bp ? *bp : BasePoints;
int32 randomPoints = int32(DieSides);
+ Unit const* casterUnit = nullptr;
+ if (caster)
+ casterUnit = caster->ToUnit();
+
// base amount modification based on spell lvl vs caster lvl
- if (caster && basePointsPerLevel != 0.0f)
+ if (casterUnit && basePointsPerLevel != 0.0f)
{
- int32 level = int32(caster->getLevel());
+ int32 level = int32(casterUnit->getLevel());
if (level > int32(_spellInfo->MaxLevel) && _spellInfo->MaxLevel > 0)
level = int32(_spellInfo->MaxLevel);
else if (level < int32(_spellInfo->BaseLevel))
@@ -433,17 +437,21 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const
float value = float(basePoints);
// random damage
- if (caster)
+ if (casterUnit)
{
// bonus amount from combo points
- if (uint8 comboPoints = caster->GetComboPoints())
+ if (uint8 comboPoints = casterUnit->GetComboPoints())
value += PointsPerComboPoint * comboPoints;
+ }
+ if (caster)
value = caster->ApplyEffectModifiers(_spellInfo, _effIndex, value);
+ if (casterUnit)
+ {
// amount multiplication based on caster's level
- if (!caster->IsControlledByPlayer() &&
- _spellInfo->SpellLevel && _spellInfo->SpellLevel != caster->getLevel() &&
+ if (!casterUnit->IsControlledByPlayer() &&
+ _spellInfo->SpellLevel && _spellInfo->SpellLevel != casterUnit->getLevel() &&
!basePointsPerLevel && _spellInfo->HasAttribute(SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION))
{
bool canEffectScale = false;
@@ -487,7 +495,7 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const
if (canEffectScale)
{
GtNPCManaCostScalerEntry const* spellScaler = sGtNPCManaCostScalerStore.LookupEntry(_spellInfo->SpellLevel - 1);
- GtNPCManaCostScalerEntry const* casterScaler = sGtNPCManaCostScalerStore.LookupEntry(caster->getLevel() - 1);
+ GtNPCManaCostScalerEntry const* casterScaler = sGtNPCManaCostScalerStore.LookupEntry(casterUnit->getLevel() - 1);
if (spellScaler && casterScaler)
value *= casterScaler->ratio / spellScaler->ratio;
}
@@ -505,7 +513,7 @@ int32 SpellEffectInfo::CalcBaseValue(int32 value) const
return value - 1;
}
-float SpellEffectInfo::CalcValueMultiplier(Unit* caster, Spell* spell) const
+float SpellEffectInfo::CalcValueMultiplier(WorldObject* caster, Spell* spell /*= nullptr*/) const
{
float multiplier = ValueMultiplier;
if (Player* modOwner = (caster ? caster->GetSpellModOwner() : nullptr))
@@ -514,7 +522,7 @@ float SpellEffectInfo::CalcValueMultiplier(Unit* caster, Spell* spell) const
return multiplier;
}
-float SpellEffectInfo::CalcDamageMultiplier(Unit* caster, Spell* spell) const
+float SpellEffectInfo::CalcDamageMultiplier(WorldObject* caster, Spell* spell /*= nullptr*/) const
{
float multiplierPercent = DamageMultiplier * 100.0f;
if (Player* modOwner = (caster ? caster->GetSpellModOwner() : nullptr))
@@ -528,7 +536,7 @@ bool SpellEffectInfo::HasRadius() const
return RadiusEntry != nullptr;
}
-float SpellEffectInfo::CalcRadius(Unit* caster, Spell* spell) const
+float SpellEffectInfo::CalcRadius(WorldObject* caster /*= nullptr*/, Spell* spell /*= nullptr*/) const
{
if (!HasRadius())
return 0.0f;
@@ -536,8 +544,11 @@ float SpellEffectInfo::CalcRadius(Unit* caster, Spell* spell) const
float radius = RadiusEntry->RadiusMin;
if (caster)
{
- radius += RadiusEntry->RadiusPerLevel * caster->getLevel();
+ if (Unit* casterUnit = caster->ToUnit())
+ radius += RadiusEntry->RadiusPerLevel * casterUnit->getLevel();
+
radius = std::min(radius, RadiusEntry->RadiusMax);
+
if (Player* modOwner = caster->GetSpellModOwner())
modOwner->ApplySpellMod(_spellInfo->Id, SPELLMOD_RADIUS, radius, spell);
}
@@ -1619,7 +1630,7 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
return SPELL_CAST_OK;
}
-SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* target, bool implicit) const
+SpellCastResult SpellInfo::CheckTarget(WorldObject const* caster, WorldObject const* target, bool implicit /*= true*/) const
{
if (HasAttribute(SPELL_ATTR1_CANT_TARGET_SELF) && caster == target)
return SPELL_FAILED_BAD_TARGETS;
@@ -1721,7 +1732,7 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta
}
// check GM mode and GM invisibility - only for player casts (npc casts are controlled by AI) and negative spells
- if (unitTarget != caster && (caster->IsControlledByPlayer() || !IsPositive()) && unitTarget->GetTypeId() == TYPEID_PLAYER)
+ if (unitTarget != caster && (caster->GetAffectingPlayer() || !IsPositive()) && unitTarget->GetTypeId() == TYPEID_PLAYER)
{
if (!unitTarget->ToPlayer()->IsVisible())
return SPELL_FAILED_BM_OR_INVISGOD;
@@ -1741,13 +1752,16 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta
him, because it would be it's passenger, there's no such case where this gets to fail legitimacy, this problem
cannot be solved from within the check in other way since target type cannot be called for the spell currently
Spell examples: [ID - 52864 Devour Water, ID - 52862 Devour Wind, ID - 49370 Wyrmrest Defender: Destabilize Azure Dragonshrine Effect] */
- if (!caster->IsVehicle() && !(caster->GetCharmerOrOwner() == target))
+ if (Unit const* unitCaster = caster->ToUnit())
{
- if (TargetAuraState && !unitTarget->HasAuraState(AuraStateType(TargetAuraState), this, caster))
- return SPELL_FAILED_TARGET_AURASTATE;
+ if (!unitCaster->IsVehicle() && !(unitCaster->GetCharmerOrOwner() == target))
+ {
+ if (TargetAuraState && !unitTarget->HasAuraState(AuraStateType(TargetAuraState), this, unitCaster))
+ return SPELL_FAILED_TARGET_AURASTATE;
- if (TargetAuraStateNot && unitTarget->HasAuraState(AuraStateType(TargetAuraStateNot), this, caster))
- return SPELL_FAILED_TARGET_AURASTATE;
+ if (TargetAuraStateNot && unitTarget->HasAuraState(AuraStateType(TargetAuraStateNot), this, unitCaster))
+ return SPELL_FAILED_TARGET_AURASTATE;
+ }
}
if (TargetAuraSpell && !unitTarget->HasAura(sSpellMgr->GetSpellIdForDifficulty(TargetAuraSpell, caster)))
@@ -1763,7 +1777,7 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta
return SPELL_CAST_OK;
}
-SpellCastResult SpellInfo::CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget) const
+SpellCastResult SpellInfo::CheckExplicitTarget(WorldObject const* caster, WorldObject const* target, Item const* itemTarget /*= nullptr*/) const
{
uint32 neededTargets = GetExplicitTargetMask();
if (!target)
@@ -1778,19 +1792,20 @@ SpellCastResult SpellInfo::CheckExplicitTarget(Unit const* caster, WorldObject c
{
if (neededTargets & (TARGET_FLAG_UNIT_ENEMY | TARGET_FLAG_UNIT_ALLY | TARGET_FLAG_UNIT_RAID | TARGET_FLAG_UNIT_PARTY | TARGET_FLAG_UNIT_MINIPET | TARGET_FLAG_UNIT_PASSENGER))
{
+ Unit const* unitCaster = caster->ToUnit();
if (neededTargets & TARGET_FLAG_UNIT_ENEMY)
if (caster->IsValidAttackTarget(unitTarget, this))
return SPELL_CAST_OK;
- if (neededTargets & TARGET_FLAG_UNIT_ALLY
- || (neededTargets & TARGET_FLAG_UNIT_PARTY && caster->IsInPartyWith(unitTarget))
- || (neededTargets & TARGET_FLAG_UNIT_RAID && caster->IsInRaidWith(unitTarget)))
+ if ((neededTargets & TARGET_FLAG_UNIT_ALLY)
+ || ((neededTargets & TARGET_FLAG_UNIT_PARTY) && unitCaster && unitCaster->IsInPartyWith(unitTarget))
+ || ((neededTargets & TARGET_FLAG_UNIT_RAID) && unitCaster && unitCaster->IsInRaidWith(unitTarget)))
if (caster->IsValidAssistTarget(unitTarget, this))
return SPELL_CAST_OK;
- if (neededTargets & TARGET_FLAG_UNIT_MINIPET)
- if (unitTarget->GetGUID() == caster->GetCritterGUID())
+ if ((neededTargets & TARGET_FLAG_UNIT_MINIPET) && unitCaster)
+ if (unitTarget->GetGUID() == unitCaster->GetCritterGUID())
return SPELL_CAST_OK;
- if (neededTargets & TARGET_FLAG_UNIT_PASSENGER)
- if (unitTarget->IsOnVehicle(caster))
+ if ((neededTargets & TARGET_FLAG_UNIT_PASSENGER) && unitCaster)
+ if (unitTarget->IsOnVehicle(unitCaster))
return SPELL_CAST_OK;
return SPELL_FAILED_BAD_TARGETS;
}
@@ -3030,7 +3045,7 @@ uint32 SpellInfo::GetAllowedMechanicMask() const
return _allowedMechanicMask;
}
-float SpellInfo::GetMinRange(bool positive) const
+float SpellInfo::GetMinRange(bool positive /*= false*/) const
{
if (!RangeEntry)
return 0.0f;
@@ -3039,7 +3054,7 @@ float SpellInfo::GetMinRange(bool positive) const
return RangeEntry->minRangeHostile;
}
-float SpellInfo::GetMaxRange(bool positive, Unit* caster, Spell* spell) const
+float SpellInfo::GetMaxRange(bool positive /*= false*/, WorldObject* caster /*= nullptr*/, Spell* spell /*= nullptr*/) const
{
if (!RangeEntry)
return 0.0f;
@@ -3132,17 +3147,22 @@ uint32 SpellInfo::GetRecoveryTime() const
return RecoveryTime > CategoryRecoveryTime ? RecoveryTime : CategoryRecoveryTime;
}
-int32 SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask, Spell* spell) const
+int32 SpellInfo::CalcPowerCost(WorldObject const* caster, SpellSchoolMask schoolMask, Spell* spell) const
{
+ // gameobject casts don't use power
+ Unit const* unitCaster = caster->ToUnit();
+ if (!unitCaster)
+ return 0;
+
// Spell drain all exist power on cast (Only paladin lay of Hands)
if (HasAttribute(SPELL_ATTR1_DRAIN_ALL_POWER))
{
// If power type - health drain all
if (PowerType == POWER_HEALTH)
- return caster->GetHealth();
+ return unitCaster->GetHealth();
// Else drain all power
if (PowerType < MAX_POWERS)
- return caster->GetPower(Powers(PowerType));
+ return unitCaster->GetPower(Powers(PowerType));
TC_LOG_ERROR("spells", "SpellInfo::CalcPowerCost: Unknown power type '%d' in spell %d", PowerType, Id);
return 0;
}
@@ -3156,16 +3176,16 @@ int32 SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask, S
{
// health as power used
case POWER_HEALTH:
- powerCost += int32(CalculatePct(caster->GetCreateHealth(), ManaCostPercentage));
+ powerCost += int32(CalculatePct(unitCaster->GetCreateHealth(), ManaCostPercentage));
break;
case POWER_MANA:
- powerCost += int32(CalculatePct(caster->GetCreateMana(), ManaCostPercentage));
+ powerCost += int32(CalculatePct(unitCaster->GetCreateMana(), ManaCostPercentage));
break;
case POWER_RAGE:
case POWER_FOCUS:
case POWER_ENERGY:
case POWER_HAPPINESS:
- powerCost += int32(CalculatePct(caster->GetMaxPower(Powers(PowerType)), ManaCostPercentage));
+ powerCost += int32(CalculatePct(unitCaster->GetMaxPower(Powers(PowerType)), ManaCostPercentage));
break;
case POWER_RUNE:
case POWER_RUNIC_POWER:
@@ -3178,37 +3198,37 @@ int32 SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask, S
}
SpellSchools school = GetFirstSchoolInMask(schoolMask);
// Flat mod from caster auras by spell school
- powerCost += caster->GetInt32Value(UNIT_FIELD_POWER_COST_MODIFIER + school);
+ powerCost += unitCaster->GetInt32Value(UNIT_FIELD_POWER_COST_MODIFIER + school);
// Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost)
if (HasAttribute(SPELL_ATTR4_SPELL_VS_EXTEND_COST))
{
uint32 speed = 0;
- if (SpellShapeshiftEntry const* ss = sSpellShapeshiftStore.LookupEntry(caster->GetShapeshiftForm()))
+ if (SpellShapeshiftEntry const* ss = sSpellShapeshiftStore.LookupEntry(unitCaster->GetShapeshiftForm()))
speed = ss->attackSpeed;
else
- speed = caster->GetAttackTime(GetAttackType());
+ speed = unitCaster->GetAttackTime(GetAttackType());
powerCost += speed / 100;
}
// Apply cost mod by spell
- if (Player* modOwner = caster->GetSpellModOwner())
+ if (Player* modOwner = unitCaster->GetSpellModOwner())
modOwner->ApplySpellMod(Id, SPELLMOD_COST, powerCost, spell);
- if (!caster->IsControlledByPlayer())
+ if (!unitCaster->IsControlledByPlayer())
{
if (HasAttribute(SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION))
{
GtNPCManaCostScalerEntry const* spellScaler = sGtNPCManaCostScalerStore.LookupEntry(SpellLevel - 1);
- GtNPCManaCostScalerEntry const* casterScaler = sGtNPCManaCostScalerStore.LookupEntry(caster->getLevel() - 1);
+ GtNPCManaCostScalerEntry const* casterScaler = sGtNPCManaCostScalerStore.LookupEntry(unitCaster->getLevel() - 1);
if (spellScaler && casterScaler)
powerCost *= casterScaler->ratio / spellScaler->ratio;
}
}
// PCT mod from user auras by school
- powerCost = int32(powerCost * (1.0f + caster->GetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER + school)));
+ powerCost = int32(powerCost * (1.0f + unitCaster->GetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER + school)));
if (powerCost < 0)
powerCost = 0;
return powerCost;