aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/master/2021_04_11_00_world_shaman_spells.sql11
-rw-r--r--src/server/game/Entities/Item/ItemTemplate.h4
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp14
-rw-r--r--src/server/game/Entities/Unit/Unit.h1
-rw-r--r--src/server/scripts/Spells/spell_shaman.cpp186
5 files changed, 191 insertions, 25 deletions
diff --git a/sql/updates/world/master/2021_04_11_00_world_shaman_spells.sql b/sql/updates/world/master/2021_04_11_00_world_shaman_spells.sql
new file mode 100644
index 00000000000..fdcf2fc855d
--- /dev/null
+++ b/sql/updates/world/master/2021_04_11_00_world_shaman_spells.sql
@@ -0,0 +1,11 @@
+-- Update various shaman spells
+UPDATE `creature_template` SET `spell1` = 192226 WHERE `entry` = 97369; -- Liquid Magma Totem
+UPDATE `creature_template` SET `spell1` = 8145 WHERE `entry` = 5913; -- Tremor Totem
+UPDATE `creature_template` SET `spell1` = 118905 WHERE `entry` = 61245; -- Capacitator
+
+DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_sha_healing_rain', 'spell_sha_liquid_magma_totem', 'spell_sha_flametongue_weapon', 'spell_sha_flametongue_weapon_aura');
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(73920, 'spell_sha_healing_rain'),
+(192223, 'spell_sha_liquid_magma_totem'),
+(318038, 'spell_sha_flametongue_weapon'),
+(319778, 'spell_sha_flametongue_weapon_aura');
diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h
index 990ee108dc6..cdee1d0265d 100644
--- a/src/server/game/Entities/Item/ItemTemplate.h
+++ b/src/server/game/Entities/Item/ItemTemplate.h
@@ -817,9 +817,11 @@ struct TC_GAME_API ItemTemplate
bool IsConjuredConsumable() const { return GetClass() == ITEM_CLASS_CONSUMABLE && (GetFlags() & ITEM_FLAG_CONJURED); }
bool IsCraftingReagent() const { return (GetFlags2() & ITEM_FLAG2_USED_IN_A_TRADESKILL) != 0; }
+ bool IsWeapon() const { return GetClass() == ITEM_CLASS_WEAPON; }
+
bool IsRangedWeapon() const
{
- return GetClass() == ITEM_CLASS_WEAPON ||
+ return IsWeapon() ||
GetSubClass() == ITEM_SUBCLASS_WEAPON_BOW ||
GetSubClass() == ITEM_SUBCLASS_WEAPON_GUN ||
GetSubClass() == ITEM_SUBCLASS_WEAPON_CROSSBOW;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index ffa959fedc5..1e2396560da 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -1130,6 +1130,20 @@ void Unit::CastSpell(GameObject* go, uint32 spellId, bool triggered, Item* castI
CastSpell(targets, spellInfo, nullptr, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster);
}
+void Unit::CastSpell(Item* target, uint32 spellId, bool triggered, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster)
+{
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID());
+ if (!spellInfo)
+ {
+ TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s", spellId, GetGUID().ToString().c_str());
+ return;
+ }
+ SpellCastTargets targets;
+ targets.SetItemTarget(target);
+
+ CastSpell(targets, spellInfo, nullptr, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster);
+}
+
void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType, bool crit)
{
if (damage < 0)
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 36f5f01bc41..d950b89122a 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1335,6 +1335,7 @@ class TC_GAME_API Unit : public WorldObject
void CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
void CastSpell(float x, float y, float z, uint32 spellId, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
void CastSpell(GameObject* go, uint32 spellId, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
+ void CastSpell(Item* target, uint32 spellId, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
void CastCustomSpell(Unit* victim, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
void CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* victim, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
void CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* victim = nullptr, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp
index e2052359cc0..adef5e55ed6 100644
--- a/src/server/scripts/Spells/spell_shaman.cpp
+++ b/src/server/scripts/Spells/spell_shaman.cpp
@@ -25,6 +25,7 @@
#include "CellImpl.h"
#include "CreatureAIImpl.h" // for RAND()
#include "GridNotifiersImpl.h"
+#include "Item.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "SpellAuraEffects.h"
@@ -52,14 +53,19 @@ enum ShamanSpells
SPELL_SHAMAN_FLAME_SHOCK = 8050,
SPELL_SHAMAN_FLAME_SHOCK_MAELSTROM = 188389,
SPELL_SHAMAN_FLAMETONGUE_ATTACK = 10444,
+ SPELL_SHAMAN_FLAMETONGUE_WEAPON_ENCHANT = 334294,
+ SPELL_SHAMAN_FLAMETONGUE_WEAPON_AURA = 319778,
SPELL_SHAMAN_GATHERING_STORMS = 198299,
SPELL_SHAMAN_GATHERING_STORMS_BUFF = 198300,
+ SPELL_SHAMAN_HEALING_RAIN_VISUAL = 147490,
+ SPELL_SHAMAN_HEALING_RAIN_HEAL = 73921,
SPELL_SHAMAN_ITEM_LIGHTNING_SHIELD = 23552,
SPELL_SHAMAN_ITEM_LIGHTNING_SHIELD_DAMAGE = 27635,
SPELL_SHAMAN_ITEM_MANA_SURGE = 23571,
SPELL_SHAMAN_LAVA_BURST = 51505,
SPELL_SHAMAN_LAVA_BURST_BONUS_DAMAGE = 71824,
SPELL_SHAMAN_LAVA_SURGE = 77762,
+ SPELL_SHAMAN_LIQUID_MAGMA_HIT = 192231,
SPELL_SHAMAN_PATH_OF_FLAMES_SPREAD = 210621,
SPELL_SHAMAN_PATH_OF_FLAMES_TALENT = 201909,
SPELL_SHAMAN_POWER_SURGE = 40466,
@@ -69,7 +75,7 @@ enum ShamanSpells
SPELL_SHAMAN_TOTEMIC_POWER_SPELL_POWER = 28825,
SPELL_SHAMAN_TOTEMIC_POWER_ATTACK_POWER = 28826,
SPELL_SHAMAN_TOTEMIC_POWER_ARMOR = 28827,
- SPELL_SHAMAN_WINDFURY_ATTACK = 25504
+ SPELL_SHAMAN_WINDFURY_ATTACK = 25504,
};
enum MiscSpells
@@ -79,6 +85,11 @@ enum MiscSpells
SPELL_PET_NETHERWINDS_FATIGUED = 160455
};
+enum MiscNpcs
+{
+ NPC_HEALING_RAIN_INVISIBLE_STALKER = 73400,
+};
+
// 108281 - Ancestral Guidance
class spell_sha_ancestral_guidance : public SpellScriptLoader
{
@@ -415,39 +426,129 @@ public:
}
};
-// 194084 - Flametongue
-class spell_sha_flametongue : public SpellScriptLoader
+// 318038 - Flametongue Weapon
+class spell_sha_flametongue_weapon : public SpellScript
+{
+ PrepareSpellScript(spell_sha_flametongue_weapon);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SHAMAN_FLAMETONGUE_WEAPON_ENCHANT });
+ }
+
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
+
+ void HandleEffectHitTarget(SpellEffIndex /*effIndex*/)
+ {
+ Player* player = GetCaster()->ToPlayer();
+ uint8 slot = EQUIPMENT_SLOT_MAINHAND;
+ if (player->GetPrimarySpecialization() == TALENT_SPEC_SHAMAN_ENHANCEMENT)
+ slot = EQUIPMENT_SLOT_OFFHAND;
+
+ Item* targetItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot);
+ if (!targetItem || !targetItem->GetTemplate()->IsWeapon())
+ return;
+
+ player->CastSpell(targetItem, SPELL_SHAMAN_FLAMETONGUE_WEAPON_ENCHANT, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_sha_flametongue_weapon::HandleEffectHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+};
+
+// 319778 - Flametongue - SPELL_SHAMAN_FLAMETONGUE_WEAPON_AURA
+class spell_sha_flametongue_weapon_aura : public AuraScript
+{
+ PrepareAuraScript(spell_sha_flametongue_weapon_aura);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SHAMAN_FLAMETONGUE_ATTACK });
+ }
+
+ void HandleEffectProc(AuraEffect* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+
+ Unit* attacker = eventInfo.GetActor();
+ int32 damage = std::max(1, int32(attacker->GetTotalAttackPowerValue(BASE_ATTACK) * 0.0264f));
+ attacker->CastCustomSpell(SPELL_SHAMAN_FLAMETONGUE_ATTACK, SPELLVALUE_BASE_POINT0, damage, eventInfo.GetActionTarget(), TRIGGERED_FULL_MASK, nullptr, aurEff);
+ }
+
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_sha_flametongue_weapon_aura::HandleEffectProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
+};
+
+// 73920 - Healing Rain (Aura)
+class spell_sha_healing_rain_aura : public AuraScript
{
public:
- spell_sha_flametongue() : SpellScriptLoader("spell_sha_flametongue") { }
+ static constexpr const char ScriptName[] = "spell_sha_healing_rain";
- class spell_sha_flametongue_AuraScript : public AuraScript
+ void SetVisualDummy(TempSummon* summon)
{
- PrepareAuraScript(spell_sha_flametongue_AuraScript);
+ _visualDummy = summon->GetGUID();
+ summon->GetPosition(_x, _y, _z);
+ }
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_SHAMAN_FLAMETONGUE_ATTACK });
- }
+private:
+ PrepareAuraScript(spell_sha_healing_rain_aura);
- void HandleEffectProc(AuraEffect* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
+ void HandleEffectPeriodic(AuraEffect const* aurEff)
+ {
+ GetTarget()->CastSpell(_x, _y, _z, SPELL_SHAMAN_HEALING_RAIN_HEAL, true, nullptr, aurEff);
+ }
- Unit* attacker = eventInfo.GetActor();
- int32 damage = int32(attacker->GetTotalAttackPowerValue(BASE_ATTACK) * 0.125f / 2600 * attacker->GetBaseAttackTime(BASE_ATTACK));
- attacker->CastCustomSpell(SPELL_SHAMAN_FLAMETONGUE_ATTACK, SPELLVALUE_BASE_POINT0, damage, eventInfo.GetActionTarget(), TRIGGERED_FULL_MASK, nullptr, aurEff);
- }
+ void HandleEffecRemoved(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Creature* summon = ObjectAccessor::GetCreature(*GetTarget(), _visualDummy))
+ summon->DespawnOrUnsummon();
+ }
- void Register() override
+ void Register() override
+ {
+ OnEffectRemove += AuraEffectRemoveFn(spell_sha_healing_rain_aura::HandleEffecRemoved, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_sha_healing_rain_aura::HandleEffectPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
+ }
+
+ ObjectGuid _visualDummy;
+ float _x = 0.0f, _y = 0.0f, _z = 0.0f;
+};
+
+// 73920 - Healing Rain
+class spell_sha_healing_rain : public SpellScript
+{
+ PrepareSpellScript(spell_sha_healing_rain);
+
+ void InitializeVisualStalker()
+ {
+ if (Aura* aura = GetHitAura())
{
- OnEffectProc += AuraEffectProcFn(spell_sha_flametongue_AuraScript::HandleEffectProc, EFFECT_0, SPELL_AURA_DUMMY);
+ if (WorldLocation const* dest = GetExplTargetDest())
+ {
+ int32 duration = GetSpellInfo()->CalcDuration(GetOriginalCaster());
+ TempSummon* summon = GetCaster()->GetMap()->SummonCreature(NPC_HEALING_RAIN_INVISIBLE_STALKER, *dest, nullptr, duration, GetOriginalCaster());
+ if (!summon)
+ return;
+
+ summon->CastSpell(summon, SPELL_SHAMAN_HEALING_RAIN_VISUAL, true);
+
+ if (spell_sha_healing_rain_aura* script = aura->GetScript<spell_sha_healing_rain_aura>(spell_sha_healing_rain_aura::ScriptName))
+ script->SetVisualDummy(summon);
+ }
}
- };
+ }
- AuraScript* GetAuraScript() const override
+ void Register() override
{
- return new spell_sha_flametongue_AuraScript();
+ OnHit += SpellHitFn(spell_sha_healing_rain::InitializeVisualStalker);
}
};
@@ -474,7 +575,7 @@ class spell_sha_healing_stream_totem_heal : public SpellScriptLoader
targets.push_back(GetOriginalCaster());
}
- void Register()
+ void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sha_healing_stream_totem_heal_SpellScript::SelectTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY);
}
@@ -881,6 +982,40 @@ class spell_sha_lava_surge_proc : public SpellScriptLoader
}
};
+// 192223 - Liquid Magma Totem (erupting hit spell)
+class spell_sha_liquid_magma_totem : public SpellScript
+{
+ PrepareSpellScript(spell_sha_liquid_magma_totem);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SHAMAN_LIQUID_MAGMA_HIT });
+ }
+
+ void HandleEffectHitTarget(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* hitUnit = GetHitUnit())
+ GetCaster()->CastSpell(hitUnit, SPELL_SHAMAN_LIQUID_MAGMA_HIT, true);
+ }
+
+ void HandleTargetSelect(std::list<WorldObject*>& targets)
+ {
+ // choose one random target from targets
+ if (targets.size() > 1)
+ {
+ WorldObject* selected = Trinity::Containers::SelectRandomContainerElement(targets);
+ targets.clear();
+ targets.push_back(selected);
+ }
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sha_liquid_magma_totem::HandleTargetSelect, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_sha_liquid_magma_totem::HandleEffectHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+};
+
// 210621 - Path of Flames Spread
class spell_sha_path_of_flames_spread : public SpellScriptLoader
{
@@ -1293,7 +1428,9 @@ void AddSC_shaman_spell_scripts()
new spell_sha_earthen_rage_passive();
new spell_sha_earthen_rage_proc_aura();
new spell_sha_elemental_blast();
- new spell_sha_flametongue();
+ RegisterSpellScript(spell_sha_flametongue_weapon);
+ RegisterAuraScript(spell_sha_flametongue_weapon_aura);
+ RegisterSpellAndAuraScriptPair(spell_sha_healing_rain, spell_sha_healing_rain_aura);
new spell_sha_healing_stream_totem_heal();
new spell_sha_heroism();
new spell_sha_item_lightning_shield();
@@ -1305,6 +1442,7 @@ void AddSC_shaman_spell_scripts()
new spell_sha_lava_burst();
new spell_sha_lava_surge();
new spell_sha_lava_surge_proc();
+ RegisterSpellScript(spell_sha_liquid_magma_totem);
new spell_sha_path_of_flames_spread();
new spell_sha_tidal_waves();
new spell_sha_t3_6p_bonus();