2010-10-07 15:35:36 +02:00
/*
2020-01-02 06:44:10 +01:00
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
2010-10-07 15:35:36 +02:00
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
2008-10-11 14:16:25 -05:00
*/
2009-10-17 15:51:44 -07:00
2017-05-21 23:18:43 +02:00
#include "Spell.h"
#include "AccountMgr.h"
#include "AreaTrigger.h"
2019-12-05 00:12:35 +01:00
#include "AzeriteEmpoweredItem.h"
2019-11-22 11:02:04 +01:00
#include "AzeriteItem.h"
2017-05-21 23:18:43 +02:00
#include "Battleground.h"
#include "BattlegroundMgr.h"
#include "BattlePetMgr.h"
2017-02-04 20:21:12 +01:00
#include "CellImpl.h"
2017-05-21 23:18:43 +02:00
#include "CombatLogPackets.h"
2017-06-04 16:51:47 +02:00
#include "CombatPackets.h"
2008-10-11 14:16:25 -05:00
#include "Common.h"
2017-05-21 23:18:43 +02:00
#include "Conversation.h"
#include "Creature.h"
#include "CreatureAI.h"
2021-08-07 19:40:34 +02:00
#include "CreatureTextMgr.h"
2010-06-08 17:01:03 -06:00
#include "DatabaseEnv.h"
2017-06-04 01:00:45 +02:00
#include "DB2Stores.h"
2017-05-21 23:18:43 +02:00
#include "DuelPackets.h"
2008-10-11 14:16:25 -05:00
#include "DynamicObject.h"
#include "GameObject.h"
2010-10-27 21:01:47 +02:00
#include "GameObjectAI.h"
2017-03-02 02:19:25 +01:00
#include "GameTime.h"
2017-05-21 23:18:43 +02:00
#include "Garrison.h"
#include "GossipDef.h"
2017-02-04 20:21:12 +01:00
#include "GridNotifiers.h"
2021-04-30 00:08:07 +02:00
#include "GridNotifiersImpl.h"
2017-05-21 23:18:43 +02:00
#include "Group.h"
#include "Guild.h"
2011-09-30 18:41:30 +02:00
#include "InstanceScript.h"
2017-06-04 01:00:45 +02:00
#include "Item.h"
2017-05-21 23:18:43 +02:00
#include "Language.h"
#include "Log.h"
#include "LootMgr.h"
2017-06-04 01:00:45 +02:00
#include "Map.h"
2017-05-21 23:18:43 +02:00
#include "MiscPackets.h"
2017-06-04 01:00:45 +02:00
#include "MotionMaster.h"
2017-05-21 23:18:43 +02:00
#include "ObjectMgr.h"
#include "Opcodes.h"
#include "OutdoorPvPMgr.h"
2012-09-03 20:30:30 +02:00
#include "PathGenerator.h"
2017-05-21 23:18:43 +02:00
#include "Pet.h"
2018-01-28 11:37:20 +01:00
#include "PhasingHandler.h"
2017-05-21 23:18:43 +02:00
#include "Player.h"
2012-11-20 12:30:30 +01:00
#include "ReputationMgr.h"
2021-10-11 12:59:19 +02:00
#include "SceneObject.h"
2017-05-21 23:18:43 +02:00
#include "ScriptMgr.h"
#include "SharedDefines.h"
#include "SkillExtraItems.h"
#include "SocialMgr.h"
#include "SpellAuraEffects.h"
#include "SpellAuras.h"
#include "SpellHistory.h"
#include "SpellMgr.h"
2015-03-10 16:29:52 +01:00
#include "SpellPackets.h"
2016-08-25 19:12:00 +02:00
#include "TalentPackets.h"
2017-05-21 23:18:43 +02:00
#include "TemporarySummon.h"
#include "Totem.h"
#include "Unit.h"
#include "Util.h"
#include "World.h"
#include "WorldPacket.h"
2017-06-04 01:00:45 +02:00
#include "WorldSession.h"
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
NonDefaultConstructible < SpellEffectHandlerFn > SpellEffectHandlers [ TOTAL_SPELL_EFFECTS ] =
2008-10-11 14:16:25 -05:00
{
& Spell :: EffectNULL , // 0
& Spell :: EffectInstaKill , // 1 SPELL_EFFECT_INSTAKILL
& Spell :: EffectSchoolDMG , // 2 SPELL_EFFECT_SCHOOL_DAMAGE
& Spell :: EffectDummy , // 3 SPELL_EFFECT_DUMMY
& Spell :: EffectUnused , // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , // 5 SPELL_EFFECT_5
2008-10-11 14:16:25 -05:00
& Spell :: EffectApplyAura , // 6 SPELL_EFFECT_APPLY_AURA
2011-09-13 14:15:35 +02:00
& Spell :: EffectEnvironmentalDMG , // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
2008-10-11 14:16:25 -05:00
& Spell :: EffectPowerDrain , // 8 SPELL_EFFECT_POWER_DRAIN
& Spell :: EffectHealthLeech , // 9 SPELL_EFFECT_HEALTH_LEECH
& Spell :: EffectHeal , // 10 SPELL_EFFECT_HEAL
2010-04-18 23:20:07 +02:00
& Spell :: EffectBind , // 11 SPELL_EFFECT_BIND
2008-10-11 14:16:25 -05:00
& Spell :: EffectNULL , // 12 SPELL_EFFECT_PORTAL
2021-03-28 02:22:34 +03:00
& Spell :: EffectTeleportToReturnPoint , // 13 SPELL_EFFECT_TELEPORT_TO_RETURN_POINT
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , // 14 SPELL_EFFECT_INCREASE_CURRENCY_CAP
2021-10-13 11:49:30 +02:00
& Spell :: EffectTeleportUnitsWithVisualLoadingScreen , // 15 SPELL_EFFECT_TELEPORT_WITH_SPELL_VISUAL_KIT_LOADING_SCREEN
2008-10-11 14:16:25 -05:00
& Spell :: EffectQuestComplete , // 16 SPELL_EFFECT_QUEST_COMPLETE
& Spell :: EffectWeaponDmg , // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
& Spell :: EffectResurrect , // 18 SPELL_EFFECT_RESURRECT
& Spell :: EffectAddExtraAttacks , // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
& Spell :: EffectUnused , // 20 SPELL_EFFECT_DODGE one spell: Dodge
& Spell :: EffectUnused , // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
& Spell :: EffectParry , // 22 SPELL_EFFECT_PARRY
& Spell :: EffectBlock , // 23 SPELL_EFFECT_BLOCK one spell: Block
& Spell :: EffectCreateItem , // 24 SPELL_EFFECT_CREATE_ITEM
& Spell :: EffectUnused , // 25 SPELL_EFFECT_WEAPON
& Spell :: EffectUnused , // 26 SPELL_EFFECT_DEFENSE one spell: Defense
& Spell :: EffectPersistentAA , // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
& Spell :: EffectSummonType , // 28 SPELL_EFFECT_SUMMON
2010-07-21 02:06:51 +02:00
& Spell :: EffectLeap , // 29 SPELL_EFFECT_LEAP
2008-10-11 14:16:25 -05:00
& Spell :: EffectEnergize , // 30 SPELL_EFFECT_ENERGIZE
& Spell :: EffectWeaponDmg , // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
& Spell :: EffectTriggerMissileSpell , // 32 SPELL_EFFECT_TRIGGER_MISSILE
& Spell :: EffectOpenLock , // 33 SPELL_EFFECT_OPEN_LOCK
& Spell :: EffectSummonChangeItem , // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
2018-03-10 00:58:48 -03:00
& Spell :: EffectUnused , // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
2008-10-11 14:16:25 -05:00
& Spell :: EffectLearnSpell , // 36 SPELL_EFFECT_LEARN_SPELL
& Spell :: EffectUnused , // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
& Spell :: EffectDispel , // 38 SPELL_EFFECT_DISPEL
& Spell :: EffectUnused , // 39 SPELL_EFFECT_LANGUAGE
& Spell :: EffectDualWield , // 40 SPELL_EFFECT_DUAL_WIELD
2009-04-11 22:41:15 -05:00
& Spell :: EffectJump , // 41 SPELL_EFFECT_JUMP
2010-07-19 21:24:09 +02:00
& Spell :: EffectJumpDest , // 42 SPELL_EFFECT_JUMP_DEST
2008-10-11 14:16:25 -05:00
& Spell :: EffectTeleUnitsFaceCaster , // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
& Spell :: EffectLearnSkill , // 44 SPELL_EFFECT_SKILL_STEP
2012-10-26 21:13:00 +02:00
& Spell :: EffectPlayMovie , // 45 SPELL_EFFECT_PLAY_MOVIE
2010-07-19 22:52:21 +02:00
& Spell :: EffectUnused , // 46 SPELL_EFFECT_SPAWN clientside, unit appears as if it was just spawned
2008-10-11 14:16:25 -05:00
& Spell :: EffectTradeSkill , // 47 SPELL_EFFECT_TRADE_SKILL
& Spell :: EffectUnused , // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
& Spell :: EffectUnused , // 49 SPELL_EFFECT_DETECT one spell: Detect
& Spell :: EffectTransmitted , // 50 SPELL_EFFECT_TRANS_DOOR
& Spell :: EffectUnused , // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , // 52 SPELL_EFFECT_SET_MAX_BATTLE_PET_COUNT
2008-10-11 14:16:25 -05:00
& Spell :: EffectEnchantItemPerm , // 53 SPELL_EFFECT_ENCHANT_ITEM
& Spell :: EffectEnchantItemTmp , // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
& Spell :: EffectTameCreature , // 55 SPELL_EFFECT_TAMECREATURE
& Spell :: EffectSummonPet , // 56 SPELL_EFFECT_SUMMON_PET
& Spell :: EffectLearnPetSpell , // 57 SPELL_EFFECT_LEARN_PET_SPELL
& Spell :: EffectWeaponDmg , // 58 SPELL_EFFECT_WEAPON_DAMAGE
2009-06-23 14:44:16 +02:00
& Spell :: EffectCreateRandomItem , // 59 SPELL_EFFECT_CREATE_RANDOM_ITEM create item base at spell specific loot
2008-10-11 14:16:25 -05:00
& Spell :: EffectProficiency , // 60 SPELL_EFFECT_PROFICIENCY
& Spell :: EffectSendEvent , // 61 SPELL_EFFECT_SEND_EVENT
& Spell :: EffectPowerBurn , // 62 SPELL_EFFECT_POWER_BURN
& Spell :: EffectThreat , // 63 SPELL_EFFECT_THREAT
& Spell :: EffectTriggerSpell , // 64 SPELL_EFFECT_TRIGGER_SPELL
2018-03-10 00:58:48 -03:00
& Spell :: EffectUnused , // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
2017-07-29 18:01:12 +02:00
& Spell :: EffectRechargeItem , // 66 SPELL_EFFECT_RECHARGE_ITEM
2008-10-11 14:16:25 -05:00
& Spell :: EffectHealMaxHealth , // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
& Spell :: EffectInterruptCast , // 68 SPELL_EFFECT_INTERRUPT_CAST
& Spell :: EffectDistract , // 69 SPELL_EFFECT_DISTRACT
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , // 70 SPELL_EFFECT_COMPLETE_AND_REWARD_WORLD_QUEST
2008-10-11 14:16:25 -05:00
& Spell :: EffectPickPocket , // 71 SPELL_EFFECT_PICKPOCKET
& Spell :: EffectAddFarsight , // 72 SPELL_EFFECT_ADD_FARSIGHT
2010-12-22 20:14:30 +02:00
& Spell :: EffectUntrainTalents , // 73 SPELL_EFFECT_UNTRAIN_TALENTS
2008-12-24 09:58:26 -06:00
& Spell :: EffectApplyGlyph , // 74 SPELL_EFFECT_APPLY_GLYPH
2008-10-11 14:16:25 -05:00
& Spell :: EffectHealMechanical , // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
& Spell :: EffectSummonObjectWild , // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
& Spell :: EffectScriptEffect , // 77 SPELL_EFFECT_SCRIPT_EFFECT
& Spell :: EffectUnused , // 78 SPELL_EFFECT_ATTACK
& Spell :: EffectSanctuary , // 79 SPELL_EFFECT_SANCTUARY
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , // 80 SPELL_EFFECT_MODIFY_FOLLOWER_ITEM_LEVEL
& Spell :: EffectNULL , // 81 SPELL_EFFECT_PUSH_ABILITY_TO_ACTION_BAR
2008-10-11 14:16:25 -05:00
& Spell :: EffectNULL , // 82 SPELL_EFFECT_BIND_SIGHT
& Spell :: EffectDuel , // 83 SPELL_EFFECT_DUEL
& Spell :: EffectStuck , // 84 SPELL_EFFECT_STUCK
& Spell :: EffectSummonPlayer , // 85 SPELL_EFFECT_SUMMON_PLAYER
& Spell :: EffectActivateObject , // 86 SPELL_EFFECT_ACTIVATE_OBJECT
2011-07-22 21:22:05 +02:00
& Spell :: EffectGameObjectDamage , // 87 SPELL_EFFECT_GAMEOBJECT_DAMAGE
& Spell :: EffectGameObjectRepair , // 88 SPELL_EFFECT_GAMEOBJECT_REPAIR
& Spell :: EffectGameObjectSetDestructionState , // 89 SPELL_EFFECT_GAMEOBJECT_SET_DESTRUCTION_STATE
2009-09-11 15:38:31 -07:00
& Spell :: EffectKillCreditPersonal , // 90 SPELL_EFFECT_KILL_CREDIT Kill credit but only for single person
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , // 91 SPELL_EFFECT_THREAT_ALL
2008-10-11 14:16:25 -05:00
& Spell :: EffectEnchantHeldItem , // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
2010-01-13 10:27:44 +01:00
& Spell :: EffectForceDeselect , // 93 SPELL_EFFECT_FORCE_DESELECT
2008-10-11 14:16:25 -05:00
& Spell :: EffectSelfResurrect , // 94 SPELL_EFFECT_SELF_RESURRECT
& Spell :: EffectSkinning , // 95 SPELL_EFFECT_SKINNING
2009-05-04 12:11:54 -05:00
& Spell :: EffectCharge , // 96 SPELL_EFFECT_CHARGE
2009-12-17 12:23:01 +01:00
& Spell :: EffectCastButtons , // 97 SPELL_EFFECT_CAST_BUTTON (totem bar since 3.2.2a)
2008-10-11 14:16:25 -05:00
& Spell :: EffectKnockBack , // 98 SPELL_EFFECT_KNOCK_BACK
& Spell :: EffectDisEnchant , // 99 SPELL_EFFECT_DISENCHANT
& Spell :: EffectInebriate , //100 SPELL_EFFECT_INEBRIATE
& Spell :: EffectFeedPet , //101 SPELL_EFFECT_FEED_PET
& Spell :: EffectDismissPet , //102 SPELL_EFFECT_DISMISS_PET
& Spell :: EffectReputation , //103 SPELL_EFFECT_REPUTATION
& Spell :: EffectSummonObject , //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //105 SPELL_EFFECT_SURVEY
2015-05-19 02:55:53 +01:00
& Spell :: EffectChangeRaidMarker , //106 SPELL_EFFECT_CHANGE_RAID_MARKER
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //107 SPELL_EFFECT_SHOW_CORPSE_LOOT
2008-10-11 14:16:25 -05:00
& Spell :: EffectDispelMechanic , //108 SPELL_EFFECT_DISPEL_MECHANIC
2014-01-17 17:54:52 +01:00
& Spell :: EffectResurrectPet , //109 SPELL_EFFECT_RESURRECT_PET
2008-10-11 14:16:25 -05:00
& Spell :: EffectDestroyAllTotems , //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
& Spell :: EffectDurabilityDamage , //111 SPELL_EFFECT_DURABILITY_DAMAGE
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //112 SPELL_EFFECT_112
2021-10-11 14:50:04 +02:00
& Spell :: EffectCancelConversation , //113 SPELL_EFFECT_CANCEL_CONVERSATION
2008-10-11 14:16:25 -05:00
& Spell :: EffectTaunt , //114 SPELL_EFFECT_ATTACK_ME
& Spell :: EffectDurabilityDamagePCT , //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
& Spell :: EffectSkinPlayerCorpse , //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
& Spell :: EffectSpiritHeal , //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
& Spell :: EffectSkill , //118 SPELL_EFFECT_SKILL professions and more
2018-03-10 00:58:48 -03:00
& Spell :: EffectUnused , //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //120 SPELL_EFFECT_TELEPORT_GRAVEYARD
2008-10-11 14:16:25 -05:00
& Spell :: EffectWeaponDmg , //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
& Spell :: EffectUnused , //122 SPELL_EFFECT_122 unused
& Spell :: EffectSendTaxi , //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
2010-08-09 02:31:42 +02:00
& Spell :: EffectPullTowards , //124 SPELL_EFFECT_PULL_TOWARDS
2008-10-11 14:16:25 -05:00
& Spell :: EffectModifyThreatPercent , //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
& Spell :: EffectStealBeneficialBuff , //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
& Spell :: EffectProspecting , //127 SPELL_EFFECT_PROSPECTING Prospecting spell
2018-03-10 00:58:48 -03:00
& Spell :: EffectUnused , //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
& Spell :: EffectUnused , //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
2008-12-17 20:07:25 -06:00
& Spell :: EffectRedirectThreat , //130 SPELL_EFFECT_REDIRECT_THREAT
2013-01-03 17:58:56 +01:00
& Spell :: EffectPlaySound , //131 SPELL_EFFECT_PLAY_SOUND sound id in misc value (SoundEntries.dbc)
2009-07-30 10:18:05 +08:00
& Spell :: EffectPlayMusic , //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
2008-10-11 14:16:25 -05:00
& Spell :: EffectUnlearnSpecialization , //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
& Spell :: EffectKillCredit , //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
& Spell :: EffectNULL , //135 SPELL_EFFECT_CALL_PET
& Spell :: EffectHealPct , //136 SPELL_EFFECT_HEAL_PCT
2009-06-08 21:19:34 +02:00
& Spell :: EffectEnergizePct , //137 SPELL_EFFECT_ENERGIZE_PCT
2010-07-19 21:24:09 +02:00
& Spell :: EffectLeapBack , //138 SPELL_EFFECT_LEAP_BACK Leap back
2010-07-04 19:16:40 +02:00
& Spell :: EffectQuestClear , //139 SPELL_EFFECT_CLEAR_QUEST Reset quest status (miscValue - quest ID)
2008-10-11 14:16:25 -05:00
& Spell :: EffectForceCast , //140 SPELL_EFFECT_FORCE_CAST
2011-09-25 13:29:17 +02:00
& Spell :: EffectForceCast , //141 SPELL_EFFECT_FORCE_CAST_WITH_VALUE
& Spell :: EffectTriggerSpell , //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
2018-03-10 00:58:48 -03:00
& Spell :: EffectUnused , //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
2010-07-20 04:29:17 +02:00
& Spell :: EffectKnockBack , //144 SPELL_EFFECT_KNOCK_BACK_DEST
2010-08-09 02:31:42 +02:00
& Spell :: EffectPullTowards , //145 SPELL_EFFECT_PULL_TOWARDS_DEST Black Hole Effect
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //146 SPELL_EFFECT_RESTORE_GARRISON_TROOP_VITALITY
2008-10-11 14:16:25 -05:00
& Spell :: EffectQuestFail , //147 SPELL_EFFECT_QUEST_FAIL quest fail
2011-09-25 13:29:17 +02:00
& Spell :: EffectTriggerMissileSpell , //148 SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE
2010-07-19 19:22:05 +02:00
& Spell :: EffectChargeDest , //149 SPELL_EFFECT_CHARGE_DEST
2010-07-20 16:11:49 +02:00
& Spell :: EffectQuestStart , //150 SPELL_EFFECT_QUEST_START
2008-10-11 14:16:25 -05:00
& Spell :: EffectTriggerRitualOfSummoning , //151 SPELL_EFFECT_TRIGGER_SPELL_2
2011-08-03 09:28:12 -07:00
& Spell :: EffectSummonRaFFriend , //152 SPELL_EFFECT_SUMMON_RAF_FRIEND summon Refer-a-Friend
2010-07-20 22:55:28 +02:00
& Spell :: EffectCreateTamedPet , //153 SPELL_EFFECT_CREATE_TAMED_PET misc value is creature entry
2010-08-08 19:45:53 +02:00
& Spell :: EffectDiscoverTaxi , //154 SPELL_EFFECT_DISCOVER_TAXI
2008-12-24 09:58:26 -06:00
& Spell :: EffectTitanGrip , //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
2009-02-03 19:12:17 -06:00
& Spell :: EffectEnchantItemPrismatic , //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
2009-06-23 14:44:16 +02:00
& Spell :: EffectCreateItem2 , //157 SPELL_EFFECT_CREATE_ITEM_2 create item or create item template and replace by some randon spell loot item
2009-01-22 22:44:27 -06:00
& Spell :: EffectMilling , //158 SPELL_EFFECT_MILLING milling
2009-06-11 00:45:59 -05:00
& Spell :: EffectRenamePet , //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
2016-04-16 15:24:57 +02:00
& Spell :: EffectForceCast , //160 SPELL_EFFECT_FORCE_CAST_2
2016-06-09 21:33:18 +02:00
& Spell :: EffectNULL , //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert)
2009-08-14 17:24:52 -07:00
& Spell :: EffectActivateSpec , //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //163 SPELL_EFFECT_OBLITERATE_ITEM
2010-07-20 04:29:17 +02:00
& Spell :: EffectRemoveAura , //164 SPELL_EFFECT_REMOVE_AURA
2012-12-31 02:10:04 +01:00
& Spell :: EffectDamageFromMaxHealthPCT , //165 SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT
2013-01-01 17:48:09 +01:00
& Spell :: EffectGiveCurrency , //166 SPELL_EFFECT_GIVE_CURRENCY
2016-04-13 20:24:51 +02:00
& Spell :: EffectUpdatePlayerPhase , //167 SPELL_EFFECT_UPDATE_PLAYER_PHASE
2015-01-05 14:58:17 +02:00
& Spell :: EffectNULL , //168 SPELL_EFFECT_ALLOW_CONTROL_PET
2015-04-06 14:01:39 +02:00
& Spell :: EffectDestroyItem , //169 SPELL_EFFECT_DESTROY_ITEM
2016-04-13 20:24:51 +02:00
& Spell :: EffectUpdateZoneAurasAndPhases , //170 SPELL_EFFECT_UPDATE_ZONE_AURAS_AND_PHASES
2021-01-23 17:44:47 +02:00
& Spell :: EffectSummonPersonalGameObject , //171 SPELL_EFFECT_SUMMON_PERSONAL_GAMEOBJECT
2013-01-01 21:57:31 +01:00
& Spell :: EffectResurrectWithAura , //172 SPELL_EFFECT_RESURRECT_WITH_AURA
2013-07-06 15:03:23 +02:00
& Spell :: EffectUnlockGuildVaultTab , //173 SPELL_EFFECT_UNLOCK_GUILD_VAULT_TAB
2020-06-22 11:04:57 +02:00
& Spell :: EffectApplyAura , //174 SPELL_EFFECT_APPLY_AURA_ON_PET
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //175 SPELL_EFFECT_175
2016-04-29 21:21:58 +02:00
& Spell :: EffectSanctuary , //176 SPELL_EFFECT_SANCTUARY_2
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //177 SPELL_EFFECT_DESPAWN_PERSISTENT_AREA_AURA
2012-08-18 13:39:41 -05:00
& Spell :: EffectUnused , //178 SPELL_EFFECT_178 unused
2013-05-26 04:47:10 +03:00
& Spell :: EffectCreateAreaTrigger , //179 SPELL_EFFECT_CREATE_AREATRIGGER
2015-01-05 14:58:17 +02:00
& Spell :: EffectNULL , //180 SPELL_EFFECT_UPDATE_AREATRIGGER
2015-01-30 23:58:16 +01:00
& Spell :: EffectRemoveTalent , //181 SPELL_EFFECT_REMOVE_TALENT
2016-08-09 17:21:19 +02:00
& Spell :: EffectNULL , //182 SPELL_EFFECT_DESPAWN_AREATRIGGER
2014-11-30 16:51:47 +01:00
& Spell :: EffectNULL , //183 SPELL_EFFECT_183
2015-01-05 14:58:17 +02:00
& Spell :: EffectNULL , //184 SPELL_EFFECT_REPUTATION
2014-11-30 16:51:47 +01:00
& Spell :: EffectNULL , //185 SPELL_EFFECT_185
& Spell :: EffectNULL , //186 SPELL_EFFECT_186
2015-01-05 14:58:17 +02:00
& Spell :: EffectNULL , //187 SPELL_EFFECT_RANDOMIZE_ARCHAEOLOGY_DIGSITES
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //188 SPELL_EFFECT_SUMMON_STABLED_PET_AS_GUARDIAN
2015-01-05 14:58:17 +02:00
& Spell :: EffectNULL , //189 SPELL_EFFECT_LOOT
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //190 SPELL_EFFECT_CHANGE_PARTY_MEMBERS
2015-01-05 14:58:17 +02:00
& Spell :: EffectNULL , //191 SPELL_EFFECT_TELEPORT_TO_DIGSITE
2015-09-09 14:52:32 +02:00
& Spell :: EffectUncageBattlePet , //192 SPELL_EFFECT_UNCAGE_BATTLEPET
2015-05-05 00:47:17 +02:00
& Spell :: EffectNULL , //193 SPELL_EFFECT_START_PET_BATTLE
2021-03-04 20:30:50 +01:00
& Spell :: EffectUnused , //194 SPELL_EFFECT_194
2021-03-04 20:31:08 +01:00
& Spell :: EffectPlaySceneScriptPackage , //195 SPELL_EFFECT_PLAY_SCENE_SCRIPT_PACKAGE
2021-10-11 12:59:19 +02:00
& Spell :: EffectCreateSceneObject , //196 SPELL_EFFECT_CREATE_SCENE_OBJECT
& Spell :: EffectCreatePrivateSceneObject , //197 SPELL_EFFECT_CREATE_PERSONAL_SCENE_OBJECT
2017-06-04 15:07:34 +02:00
& Spell :: EffectPlayScene , //198 SPELL_EFFECT_PLAY_SCENE
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //199 SPELL_EFFECT_DESPAWN_SUMMON
2015-09-09 14:52:32 +02:00
& Spell :: EffectHealBattlePetPct , //200 SPELL_EFFECT_HEAL_BATTLEPET_PCT
& Spell :: EffectEnableBattlePets , //201 SPELL_EFFECT_ENABLE_BATTLE_PETS
2018-03-10 00:58:48 -03:00
& Spell :: EffectUnused , //202 SPELL_EFFECT_APPLY_AREA_AURA_SUMMONS
2021-03-04 20:30:50 +01:00
& Spell :: EffectRemoveAura , //203 SPELL_EFFECT_REMOVE_AURA_2
2015-05-05 00:47:17 +02:00
& Spell :: EffectNULL , //204 SPELL_EFFECT_CHANGE_BATTLEPET_QUALITY
2017-12-17 14:40:04 +01:00
& Spell :: EffectLaunchQuestChoice , //205 SPELL_EFFECT_LAUNCH_QUEST_CHOICE
2016-06-02 17:07:07 +03:00
& Spell :: EffectNULL , //206 SPELL_EFFECT_ALTER_ITEM
2015-05-05 00:47:17 +02:00
& Spell :: EffectNULL , //207 SPELL_EFFECT_LAUNCH_QUEST_TASK
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //208 SPELL_EFFECT_SET_REPUTATION
& Spell :: EffectUnused , //209 SPELL_EFFECT_209
2015-05-08 00:03:15 +02:00
& Spell :: EffectLearnGarrisonBuilding , //210 SPELL_EFFECT_LEARN_GARRISON_BUILDING
2015-05-05 00:47:17 +02:00
& Spell :: EffectNULL , //211 SPELL_EFFECT_LEARN_GARRISON_SPECIALIZATION
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //212 SPELL_EFFECT_REMOVE_AURA_BY_SPELL_LABEL
& Spell :: EffectJumpDest , //213 SPELL_EFFECT_JUMP_DEST_2
2015-05-08 00:03:15 +02:00
& Spell :: EffectCreateGarrison , //214 SPELL_EFFECT_CREATE_GARRISON
2015-05-05 00:47:17 +02:00
& Spell :: EffectNULL , //215 SPELL_EFFECT_UPGRADE_CHARACTER_SPELLS
& Spell :: EffectNULL , //216 SPELL_EFFECT_CREATE_SHIPMENT
& Spell :: EffectNULL , //217 SPELL_EFFECT_UPGRADE_GARRISON
2014-11-30 16:51:47 +01:00
& Spell :: EffectNULL , //218 SPELL_EFFECT_218
2017-05-14 11:40:55 +02:00
& Spell :: EffectCreateConversation , //219 SPELL_EFFECT_CREATE_CONVERSATION
2015-05-17 18:06:28 +02:00
& Spell :: EffectAddGarrisonFollower , //220 SPELL_EFFECT_ADD_GARRISON_FOLLOWER
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //221 SPELL_EFFECT_ADD_GARRISON_MISSION
2015-10-16 22:54:46 +02:00
& Spell :: EffectCreateHeirloomItem , //222 SPELL_EFFECT_CREATE_HEIRLOOM_ITEM
2015-05-05 00:47:17 +02:00
& Spell :: EffectNULL , //223 SPELL_EFFECT_CHANGE_ITEM_BONUSES
2015-06-22 00:02:02 +02:00
& Spell :: EffectActivateGarrisonBuilding , //224 SPELL_EFFECT_ACTIVATE_GARRISON_BUILDING
2015-05-05 00:47:17 +02:00
& Spell :: EffectNULL , //225 SPELL_EFFECT_GRANT_BATTLEPET_LEVEL
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //226 SPELL_EFFECT_TRIGGER_ACTION_SET
2016-07-30 00:11:44 +02:00
& Spell :: EffectNULL , //227 SPELL_EFFECT_TELEPORT_TO_LFG_DUNGEON
2014-11-30 16:51:47 +01:00
& Spell :: EffectNULL , //228 SPELL_EFFECT_228
2015-05-05 00:47:17 +02:00
& Spell :: EffectNULL , //229 SPELL_EFFECT_SET_FOLLOWER_QUALITY
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //230 SPELL_EFFECT_230
2015-05-05 00:47:17 +02:00
& Spell :: EffectNULL , //231 SPELL_EFFECT_INCREASE_FOLLOWER_EXPERIENCE
& Spell :: EffectNULL , //232 SPELL_EFFECT_REMOVE_PHASE
& Spell :: EffectNULL , //233 SPELL_EFFECT_RANDOMIZE_FOLLOWER_ABILITIES
2014-11-30 16:51:47 +01:00
& Spell :: EffectNULL , //234 SPELL_EFFECT_234
2021-03-04 20:30:50 +01:00
& Spell :: EffectUnused , //235 SPELL_EFFECT_235
2015-05-05 00:47:17 +02:00
& Spell :: EffectNULL , //236 SPELL_EFFECT_GIVE_EXPERIENCE
& Spell :: EffectNULL , //237 SPELL_EFFECT_GIVE_RESTED_EXPERIENCE_BONUS
& Spell :: EffectNULL , //238 SPELL_EFFECT_INCREASE_SKILL
& Spell :: EffectNULL , //239 SPELL_EFFECT_END_GARRISON_BUILDING_CONSTRUCTION
2016-08-15 00:03:38 +02:00
& Spell :: EffectGiveArtifactPower , //240 SPELL_EFFECT_GIVE_ARTIFACT_POWER
2021-03-04 20:30:50 +01:00
& Spell :: EffectUnused , //241 SPELL_EFFECT_241
2016-08-15 00:03:38 +02:00
& Spell :: EffectGiveArtifactPowerNoBonus , //242 SPELL_EFFECT_GIVE_ARTIFACT_POWER_NO_BONUS
2016-04-07 21:36:36 +02:00
& Spell :: EffectApplyEnchantIllusion , //243 SPELL_EFFECT_APPLY_ENCHANT_ILLUSION
2015-05-05 00:47:17 +02:00
& Spell :: EffectNULL , //244 SPELL_EFFECT_LEARN_FOLLOWER_ABILITY
2015-10-16 22:54:46 +02:00
& Spell :: EffectUpgradeHeirloom , //245 SPELL_EFFECT_UPGRADE_HEIRLOOM
2015-05-05 00:47:17 +02:00
& Spell :: EffectNULL , //246 SPELL_EFFECT_FINISH_GARRISON_MISSION
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //247 SPELL_EFFECT_ADD_GARRISON_MISSION_SET
2015-05-05 00:47:17 +02:00
& Spell :: EffectNULL , //248 SPELL_EFFECT_FINISH_SHIPMENT
2016-08-09 17:21:19 +02:00
& Spell :: EffectNULL , //249 SPELL_EFFECT_FORCE_EQUIP_ITEM
2015-05-05 00:47:17 +02:00
& Spell :: EffectNULL , //250 SPELL_EFFECT_TAKE_SCREENSHOT
2015-07-18 00:45:21 +02:00
& Spell :: EffectNULL , //251 SPELL_EFFECT_SET_GARRISON_CACHE_SIZE
2016-07-30 00:11:44 +02:00
& Spell :: EffectTeleportUnits , //252 SPELL_EFFECT_TELEPORT_UNITS
2017-06-04 16:51:47 +02:00
& Spell :: EffectGiveHonor , //253 SPELL_EFFECT_GIVE_HONOR
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //254 SPELL_EFFECT_JUMP_CHARGE
2017-08-24 20:39:22 +02:00
& Spell :: EffectLearnTransmogSet , //255 SPELL_EFFECT_LEARN_TRANSMOG_SET
2021-03-04 20:30:50 +01:00
& Spell :: EffectUnused , //256 SPELL_EFFECT_256
& Spell :: EffectUnused , //257 SPELL_EFFECT_257
2019-02-04 16:47:41 +01:00
& Spell :: EffectNULL , //258 SPELL_EFFECT_MODIFY_KEYSTONE
2019-12-05 00:12:35 +01:00
& Spell :: EffectRespecAzeriteEmpoweredItem , //259 SPELL_EFFECT_RESPEC_AZERITE_EMPOWERED_ITEM
2019-02-04 16:47:41 +01:00
& Spell :: EffectNULL , //260 SPELL_EFFECT_SUMMON_STABLED_PET
& Spell :: EffectNULL , //261 SPELL_EFFECT_SCRAP_ITEM
2021-03-04 20:30:50 +01:00
& Spell :: EffectUnused , //262 SPELL_EFFECT_262
2019-06-08 13:19:48 +02:00
& Spell :: EffectNULL , //263 SPELL_EFFECT_REPAIR_ITEM
& Spell :: EffectNULL , //264 SPELL_EFFECT_REMOVE_GEM
2019-11-22 11:02:04 +01:00
& Spell :: EffectLearnAzeriteEssencePower , //265 SPELL_EFFECT_LEARN_AZERITE_ESSENCE_POWER
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //266 SPELL_EFFECT_SET_ITEM_BONUS_LIST_GROUP_ENTRY
2021-03-04 20:31:08 +01:00
& Spell :: EffectCreatePrivateConversation , //267 SPELL_EFFECT_CREATE_PRIVATE_CONVERSATION
2019-11-21 13:58:58 +01:00
& Spell :: EffectNULL , //268 SPELL_EFFECT_APPLY_MOUNT_EQUIPMENT
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //269 SPELL_EFFECT_INCREASE_ITEM_BONUS_LIST_GROUP_STEP
2019-11-21 13:58:58 +01:00
& Spell :: EffectNULL , //270 SPELL_EFFECT_270
2018-03-10 00:58:48 -03:00
& Spell :: EffectUnused , //271 SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM
2020-12-01 21:08:06 +01:00
& Spell :: EffectNULL , //272 SPELL_EFFECT_SET_COVENANT
& Spell :: EffectNULL , //273 SPELL_EFFECT_CRAFT_RUNEFORGE_LEGENDARY
2021-03-04 20:30:50 +01:00
& Spell :: EffectUnused , //274 SPELL_EFFECT_274
& Spell :: EffectUnused , //275 SPELL_EFFECT_275
2020-12-01 21:08:06 +01:00
& Spell :: EffectNULL , //276 SPELL_EFFECT_LEARN_TRANSMOG_ILLUSION
& Spell :: EffectNULL , //277 SPELL_EFFECT_SET_CHROMIE_TIME
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //278 SPELL_EFFECT_278
2020-12-01 21:08:06 +01:00
& Spell :: EffectNULL , //279 SPELL_EFFECT_LEARN_GARR_TALENT
2021-03-04 20:30:50 +01:00
& Spell :: EffectUnused , //280 SPELL_EFFECT_280
2020-12-01 21:08:06 +01:00
& Spell :: EffectNULL , //281 SPELL_EFFECT_LEARN_SOULBIND_CONDUIT
& Spell :: EffectNULL , //282 SPELL_EFFECT_CONVERT_ITEMS_TO_CURRENCY
2021-03-04 20:30:50 +01:00
& Spell :: EffectNULL , //283 SPELL_EFFECT_COMPLETE_CAMPAIGN
2021-08-07 19:40:34 +02:00
& Spell :: EffectSendChatMessage , //284 SPELL_EFFECT_SEND_CHAT_MESSAGE
& Spell :: EffectNULL , //285 SPELL_EFFECT_MODIFY_KEYSTONE_2
2021-11-01 22:17:12 +01:00
& Spell :: EffectNULL , //286 SPELL_EFFECT_GRANT_BATTLEPET_EXPERIENCE
& Spell :: EffectNULL , //287 SPELL_EFFECT_SET_GARRISON_FOLLOWER_LEVEL
2008-10-11 14:16:25 -05:00
};
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectNULL ()
2008-10-11 14:16:25 -05:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "spells" , "WORLD: Spell Effect DUMMY" );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectUnused ()
2008-10-11 14:16:25 -05:00
{
2010-02-05 00:31:28 +01:00
// NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN TRINITY
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectResurrectNew ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2013-06-11 19:54:27 -02:30
if ( ! unitTarget || unitTarget -> IsAlive ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( unitTarget -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! unitTarget -> IsInWorld ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-10-07 19:45:43 -05:00
Player * target = unitTarget -> ToPlayer ();
2009-10-17 15:51:44 -07:00
2014-05-25 21:52:27 +02:00
if ( target -> IsResurrectRequested ()) // already have one active request
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 health = damage ;
2014-12-19 23:52:29 +01:00
uint32 mana = effectInfo -> MiscValue ;
2021-08-28 18:30:45 +02:00
ExecuteLogEffectResurrect ( SpellEffectName ( effectInfo -> Effect ), target );
2013-01-01 21:57:31 +01:00
target -> SetResurrectRequestData ( m_caster , health , mana , 0 );
2011-10-07 19:45:43 -05:00
SendResurrectRequest ( target );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectInstaKill ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2013-06-11 19:54:27 -02:30
if ( ! unitTarget || ! unitTarget -> IsAlive ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2012-09-01 00:36:26 +01:00
if ( unitTarget -> GetTypeId () == TYPEID_PLAYER )
if ( unitTarget -> ToPlayer () -> GetCommandStatus ( CHEAT_GOD ))
return ;
2010-04-07 19:14:10 +02:00
if ( m_caster == unitTarget ) // prevent interrupt message
2008-10-11 14:16:25 -05:00
finish ();
2009-10-17 15:51:44 -07:00
2015-06-07 17:08:45 +02:00
WorldPackets :: CombatLog :: SpellInstakillLog data ;
data . Target = unitTarget -> GetGUID ();
data . Caster = m_caster -> GetGUID ();
data . SpellID = m_spellInfo -> Id ;
m_caster -> SendMessageToSet ( data . Write (), true );
2010-08-28 00:30:07 +02:00
2018-02-10 16:43:01 -03:00
Unit :: DealDamage ( unitCaster , unitTarget , unitTarget -> GetHealth (), nullptr , NODAMAGE , SPELL_SCHOOL_MASK_NORMAL , nullptr , false );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectEnvironmentalDMG ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2013-06-11 19:54:27 -02:30
if ( ! unitTarget || ! unitTarget -> IsAlive ())
2011-07-27 21:23:15 +02:00
return ;
2016-10-26 02:16:11 -03:00
// CalcAbsorbResist already in Player::EnvironmentalDamage
2011-07-27 21:23:15 +02:00
if ( unitTarget -> GetTypeId () == TYPEID_PLAYER )
2015-08-10 17:46:31 +02:00
unitTarget -> ToPlayer () -> EnvironmentalDamage ( DAMAGE_FIRE , damage );
2016-10-26 02:16:11 -03:00
else
{
2018-02-10 16:43:01 -03:00
DamageInfo damageInfo ( unitCaster , unitTarget , damage , m_spellInfo , m_spellInfo -> GetSchoolMask (), SPELL_DIRECT_DAMAGE , BASE_ATTACK );
2018-01-13 06:45:21 -03:00
Unit :: CalcAbsorbResist ( damageInfo );
2016-10-26 02:16:11 -03:00
2018-02-10 16:43:01 -03:00
SpellNonMeleeDamage log ( unitCaster , unitTarget , m_spellInfo , m_SpellVisual , m_spellInfo -> GetSchoolMask (), m_castId );
2018-10-04 18:50:21 +02:00
log . damage = damageInfo . GetDamage ();
log . originalDamage = damage ;
2016-10-26 02:16:11 -03:00
log . absorb = damageInfo . GetAbsorb ();
log . resist = damageInfo . GetResist ();
2015-08-08 15:15:14 +02:00
2018-02-10 16:43:01 -03:00
if ( unitCaster )
unitCaster -> SendSpellNonMeleeDamageLog ( & log );
2016-10-26 02:16:11 -03:00
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectSchoolDMG ()
2008-12-25 17:39:46 -06:00
{
2011-10-06 14:22:11 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET )
2011-09-25 13:29:17 +02:00
return ;
2009-10-17 15:51:44 -07:00
2013-06-11 19:54:27 -02:30
if ( unitTarget && unitTarget -> IsAlive ())
2008-10-11 14:16:25 -05:00
{
2012-08-30 22:44:33 +01:00
bool apply_direct_bonus = true ;
2017-01-01 03:05:33 +01:00
// Meteor like spells (divided damage to targets)
if ( m_spellInfo -> HasAttribute ( SPELL_ATTR0_CU_SHARE_DAMAGE ))
2008-10-11 14:16:25 -05:00
{
2017-01-01 03:05:33 +01:00
// divide to all targets
2021-08-28 19:51:29 +02:00
if ( int64 count = GetUnitTargetCountForEffect ( SpellEffIndex ( effectInfo -> EffectIndex )))
2017-01-01 03:05:33 +01:00
damage /= count ;
}
2009-10-17 15:51:44 -07:00
2017-01-01 03:05:33 +01:00
switch ( m_spellInfo -> SpellFamilyName )
{
case SPELLFAMILY_GENERIC :
{
2018-02-10 16:43:01 -03:00
///@todo: move those to scripts
2011-09-29 12:43:05 +02:00
switch ( m_spellInfo -> Id ) // better way to check unknown
2008-10-25 15:46:52 -05:00
{
2009-05-20 11:44:38 -05:00
// Consumption
2010-02-15 18:23:39 +01:00
case 28865 :
2018-02-10 16:43:01 -03:00
damage = 2750 ;
if ( m_caster -> GetMap () -> IsHeroic ())
damage = 4250 ;
2009-05-18 15:04:05 -05:00
break ;
2008-10-11 14:16:25 -05:00
// percent from health with min
2010-02-15 18:23:39 +01:00
case 25599 : // Thundercrash
2008-10-11 14:16:25 -05:00
{
damage = unitTarget -> GetHealth () / 2 ;
2010-04-07 19:14:10 +02:00
if ( damage < 200 )
2008-10-11 14:16:25 -05:00
damage = 200 ;
break ;
}
2008-11-24 15:15:09 -06:00
// arcane charge. must only affect demons (also undead?)
2010-02-15 18:23:39 +01:00
case 45072 :
2008-10-19 14:47:43 -05:00
{
2018-02-10 16:43:01 -03:00
if ( ! ( unitTarget -> GetCreatureTypeMask () & CREATURE_TYPEMASK_DEMON_OR_UNDEAD ))
2008-10-19 14:47:43 -05:00
return ;
break ;
}
2008-10-11 14:16:25 -05:00
}
break ;
}
case SPELLFAMILY_WARRIOR :
{
break ;
}
case SPELLFAMILY_WARLOCK :
{
break ;
}
2008-12-29 17:27:50 -06:00
case SPELLFAMILY_PRIEST :
{
break ;
}
2008-10-11 14:16:25 -05:00
case SPELLFAMILY_DRUID :
{
break ;
}
2009-07-06 00:51:50 +02:00
case SPELLFAMILY_DEATHKNIGHT :
{
break ;
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
if ( unitCaster && apply_direct_bonus )
2012-05-30 08:01:02 +02:00
{
2021-09-04 15:13:15 +02:00
uint32 bonus = unitCaster -> SpellDamageBonusDone ( unitTarget , m_spellInfo , ( uint32 ) damage , SPELL_DIRECT_DAMAGE , * effectInfo );
2014-12-19 18:55:09 +01:00
damage = bonus + uint32 ( bonus * variance );
2018-02-10 16:43:01 -03:00
damage = unitTarget -> SpellDamageBonusTaken ( unitCaster , m_spellInfo , ( uint32 ) damage , SPELL_DIRECT_DAMAGE );
2012-05-30 08:01:02 +02:00
}
2009-10-17 15:51:44 -07:00
2009-01-10 09:29:22 -06:00
m_damage += damage ;
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectDummy ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2009-10-15 11:50:11 -07:00
if ( ! unitTarget && ! gameObjTarget && ! itemTarget )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// pet auras
2017-04-28 18:11:23 -03:00
if ( m_caster -> GetTypeId () == TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
{
2021-08-28 19:51:29 +02:00
if ( PetAura const * petSpell = sSpellMgr -> GetPetAura ( m_spellInfo -> Id , effectInfo -> EffectIndex ))
2017-04-28 18:11:23 -03:00
{
m_caster -> ToPlayer () -> AddPetAura ( petSpell );
return ;
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-07-24 21:51:25 +02:00
// normal DB scripted effect
2021-08-28 19:51:29 +02:00
TC_LOG_DEBUG ( "spells" , "Spell ScriptStart spellid %u in EffectDummy(%u)" , m_spellInfo -> Id , effectInfo -> EffectIndex );
m_caster -> GetMap () -> ScriptsStart ( sSpellScripts , uint32 ( m_spellInfo -> Id | ( effectInfo -> EffectIndex << 24 )), m_caster , unitTarget );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectTriggerSpell ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET
&& effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH )
return ;
2014-12-19 23:52:29 +01:00
uint32 triggered_spell_id = effectInfo -> TriggerSpell ;
2009-10-17 15:51:44 -07:00
2013-03-08 21:41:30 +01:00
/// @todo move those to spell scripts
2014-12-19 23:52:29 +01:00
if ( effectInfo -> Effect == SPELL_EFFECT_TRIGGER_SPELL
2011-09-25 13:29:17 +02:00
&& effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET )
{
// special cases
2011-09-29 12:43:05 +02:00
switch ( triggered_spell_id )
2011-09-25 13:29:17 +02:00
{
// Demonic Empowerment -- succubus
case 54437 :
{
2017-02-04 23:50:32 +01:00
unitTarget -> RemoveMovementImpairingAuras ( true );
2011-09-25 13:29:17 +02:00
unitTarget -> RemoveAurasByType ( SPELL_AURA_MOD_STALKED );
unitTarget -> RemoveAurasByType ( SPELL_AURA_MOD_STUN );
// Cast Lesser Invisibility
2021-10-03 16:36:39 +02:00
unitTarget -> CastSpell ( unitTarget , 7870 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2011-09-27 00:36:23 +02:00
return ;
2011-09-25 13:29:17 +02:00
}
// Brittle Armor - (need add max stack of 24575 Brittle Armor)
case 29284 :
{
// Brittle Armor
2020-06-12 01:29:18 +02:00
SpellInfo const * spell = sSpellMgr -> GetSpellInfo ( 24575 , GetCastDifficulty ());
2011-09-25 13:29:17 +02:00
if ( ! spell )
return ;
for ( uint32 j = 0 ; j < spell -> StackAmount ; ++ j )
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( unitTarget , spell -> Id , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2011-09-25 13:29:17 +02:00
return ;
}
// Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
case 29286 :
{
// Mercurial Shield
2020-06-12 01:29:18 +02:00
SpellInfo const * spell = sSpellMgr -> GetSpellInfo ( 26464 , GetCastDifficulty ());
2011-09-25 13:29:17 +02:00
if ( ! spell )
return ;
for ( uint32 j = 0 ; j < spell -> StackAmount ; ++ j )
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( unitTarget , spell -> Id , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2011-09-25 13:29:17 +02:00
return ;
}
}
}
2008-10-11 14:16:25 -05:00
// normal case
2020-06-12 01:29:18 +02:00
SpellInfo const * spellInfo = sSpellMgr -> GetSpellInfo ( triggered_spell_id , GetCastDifficulty ());
2010-04-07 19:14:10 +02:00
if ( ! spellInfo )
2008-10-11 14:16:25 -05:00
{
2016-08-05 21:22:12 +02:00
TC_LOG_ERROR ( "spells.effecttriggerspell" , "Spell::EffectTriggerSpell spell %u tried to trigger unknown spell %u" , m_spellInfo -> Id , triggered_spell_id );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-09-25 13:29:17 +02:00
SpellCastTargets targets ;
if ( effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET )
{
2020-06-12 01:29:18 +02:00
if ( ! spellInfo -> NeedsToBeTriggeredByCaster ( m_spellInfo ))
2011-09-25 13:29:17 +02:00
return ;
targets . SetUnitTarget ( unitTarget );
}
else //if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH)
{
2020-06-12 01:29:18 +02:00
if ( spellInfo -> NeedsToBeTriggeredByCaster ( m_spellInfo ) && ( effectInfo -> GetProvidedTargetMask () & TARGET_FLAG_UNIT_MASK ))
2011-09-25 13:29:17 +02:00
return ;
2011-07-26 23:09:28 +02:00
2011-09-25 13:29:17 +02:00
if ( spellInfo -> GetExplicitTargetMask () & TARGET_FLAG_DEST_LOCATION )
targets . SetDst ( m_targets );
2014-01-27 20:26:34 +01:00
if ( Unit * target = m_targets . GetUnitTarget ())
targets . SetUnitTarget ( target );
else
2018-02-10 16:43:01 -03:00
{
if ( Unit * unit = m_caster -> ToUnit ())
targets . SetUnitTarget ( unit );
else if ( GameObject * go = m_caster -> ToGameObject ())
targets . SetGOTarget ( go );
}
2011-09-25 13:29:17 +02:00
}
2010-04-07 18:09:10 +02:00
2021-10-03 14:58:35 +02:00
CastSpellExtraArgs args ( TRIGGERED_FULL_MASK );
args . SetOriginalCaster ( m_originalCasterGUID );
2021-10-03 16:36:39 +02:00
args . SetOriginalCastId ( m_castId );
2011-09-25 13:29:17 +02:00
// set basepoints for trigger with value effect
2014-12-19 23:52:29 +01:00
if ( effectInfo -> Effect == SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE )
2017-12-30 20:28:41 +01:00
for ( uint32 i = 0 ; i < MAX_SPELL_EFFECTS ; ++ i )
2018-01-13 20:38:32 -03:00
args . AddSpellMod ( SpellValueMod ( SPELLVALUE_BASE_POINT0 + i ), damage );
2011-09-25 13:29:17 +02:00
// original caster guid only for GO cast
2021-10-03 19:58:03 +02:00
m_caster -> CastSpell ( std :: move ( targets ), spellInfo -> Id , args );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectTriggerMissileSpell ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET
&& effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2014-12-19 23:52:29 +01:00
uint32 triggered_spell_id = effectInfo -> TriggerSpell ;
2009-10-17 15:51:44 -07:00
2011-09-25 13:29:17 +02:00
// normal case
2020-06-12 01:29:18 +02:00
SpellInfo const * spellInfo = sSpellMgr -> GetSpellInfo ( triggered_spell_id , GetCastDifficulty ());
2010-04-07 19:14:10 +02:00
if ( ! spellInfo )
2008-10-11 14:16:25 -05:00
{
2016-08-05 21:22:12 +02:00
TC_LOG_ERROR ( "spells.effecttrigermissilespell" , "Spell::EffectTriggerMissileSpell spell %u tried to trigger unknown spell %u." , m_spellInfo -> Id , triggered_spell_id );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-09-25 13:29:17 +02:00
SpellCastTargets targets ;
if ( effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET )
{
2020-06-12 01:29:18 +02:00
if ( ! spellInfo -> NeedsToBeTriggeredByCaster ( m_spellInfo ))
2011-09-25 13:29:17 +02:00
return ;
targets . SetUnitTarget ( unitTarget );
}
else //if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT)
{
2020-06-12 01:29:18 +02:00
if ( spellInfo -> NeedsToBeTriggeredByCaster ( m_spellInfo ) && ( effectInfo -> GetProvidedTargetMask () & TARGET_FLAG_UNIT_MASK ))
2011-09-25 13:29:17 +02:00
return ;
if ( spellInfo -> GetExplicitTargetMask () & TARGET_FLAG_DEST_LOCATION )
targets . SetDst ( m_targets );
2018-02-10 16:43:01 -03:00
if ( Unit * unit = m_caster -> ToUnit ())
targets . SetUnitTarget ( unit );
else if ( GameObject * go = m_caster -> ToGameObject ())
targets . SetGOTarget ( go );
2011-09-25 13:29:17 +02:00
}
2021-10-03 14:58:35 +02:00
CastSpellExtraArgs args ( TRIGGERED_FULL_MASK );
args . SetOriginalCaster ( m_originalCasterGUID );
2021-10-03 16:36:39 +02:00
args . SetOriginalCastId ( m_castId );
2011-09-25 13:29:17 +02:00
// set basepoints for trigger with value effect
2014-12-19 23:52:29 +01:00
if ( effectInfo -> Effect == SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE )
2017-12-30 20:28:41 +01:00
for ( uint32 i = 0 ; i < MAX_SPELL_EFFECTS ; ++ i )
2018-01-13 20:38:32 -03:00
args . AddSpellMod ( SpellValueMod ( SPELLVALUE_BASE_POINT0 + i ), damage );
2009-10-17 15:51:44 -07:00
2011-09-25 13:29:17 +02:00
// original caster guid only for GO cast
2021-10-03 19:58:03 +02:00
m_caster -> CastSpell ( std :: move ( targets ), spellInfo -> Id , args );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectForceCast ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-07 22:59:46 +02:00
if ( ! unitTarget )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
uint32 triggered_spell_id = effectInfo -> TriggerSpell ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// normal case
2020-06-12 01:29:18 +02:00
SpellInfo const * spellInfo = sSpellMgr -> GetSpellInfo ( triggered_spell_id , GetCastDifficulty ());
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! spellInfo )
2008-10-11 14:16:25 -05:00
{
2016-02-20 13:23:35 +01:00
TC_LOG_ERROR ( "spells" , "Spell::EffectForceCast of spell %u: triggering unknown spell id %i." , m_spellInfo -> Id , triggered_spell_id );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
if ( effectInfo -> Effect == SPELL_EFFECT_FORCE_CAST && damage )
2009-08-15 20:36:21 -05:00
{
2011-01-12 22:50:51 +01:00
switch ( m_spellInfo -> Id )
2009-08-15 20:36:21 -05:00
{
2011-07-07 18:02:04 +02:00
case 52588 : // Skeletal Gryphon Escape
2010-02-20 23:57:54 +01:00
case 48598 : // Ride Flamebringer Cue
2010-04-07 18:09:10 +02:00
unitTarget -> RemoveAura ( damage );
2010-02-20 23:57:54 +01:00
break ;
case 52463 : // Hide In Mine Car
case 52349 : // Overtake
2017-12-30 20:28:41 +01:00
{
2021-10-03 14:58:35 +02:00
CastSpellExtraArgs args ( TRIGGERED_FULL_MASK );
args . SetOriginalCaster ( m_originalCasterGUID );
2021-10-03 16:36:39 +02:00
args . SetOriginalCastId ( m_castId );
2018-01-13 20:38:32 -03:00
args . AddSpellMod ( SPELLVALUE_BASE_POINT0 , damage );
2017-12-30 20:28:41 +01:00
unitTarget -> CastSpell ( unitTarget , spellInfo -> Id , args );
2010-02-20 23:57:54 +01:00
return ;
2017-12-30 20:28:41 +01:00
}
2009-08-15 20:36:21 -05:00
}
}
2010-07-19 22:52:21 +02:00
2014-07-23 17:24:50 +02:00
switch ( spellInfo -> Id )
{
case 72298 : // Malleable Goo Summon
2021-10-03 14:58:35 +02:00
unitTarget -> CastSpell ( unitTarget , spellInfo -> Id , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
2021-10-03 16:36:39 +02:00
. SetOriginalCaster ( m_originalCasterGUID )
. SetOriginalCastId ( m_castId ));
2014-07-23 17:24:50 +02:00
return ;
}
2017-12-30 20:28:41 +01:00
CastSpellExtraArgs args ( TRIGGERED_FULL_MASK );
2021-10-03 16:36:39 +02:00
args . SetOriginalCastId ( m_castId );
2014-12-19 23:52:29 +01:00
if ( effectInfo -> Effect == SPELL_EFFECT_FORCE_CAST_WITH_VALUE )
2017-12-30 20:28:41 +01:00
for ( uint32 i = 0 ; i < MAX_SPELL_EFFECTS ; ++ i )
2018-01-13 20:38:32 -03:00
args . AddSpellMod ( SpellValueMod ( SPELLVALUE_BASE_POINT0 + i ), damage );
2011-09-25 13:29:17 +02:00
2017-12-30 20:28:41 +01:00
unitTarget -> CastSpell ( m_caster , spellInfo -> Id , args );
2010-07-19 22:52:21 +02:00
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectTriggerRitualOfSummoning ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
uint32 triggered_spell_id = effectInfo -> TriggerSpell ;
2020-06-12 01:29:18 +02:00
SpellInfo const * spellInfo = sSpellMgr -> GetSpellInfo ( triggered_spell_id , GetCastDifficulty ());
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! spellInfo )
2008-10-11 14:16:25 -05:00
{
2016-02-20 13:23:35 +01:00
TC_LOG_ERROR ( "spells" , "EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i." , m_spellInfo -> Id , triggered_spell_id );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-09-25 13:29:17 +02:00
finish ();
2009-10-17 15:51:44 -07:00
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( nullptr , spellInfo -> Id , CastSpellExtraArgs ()
. SetOriginalCastId ( m_castId ));
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
inline void CalculateJumpSpeeds ( SpellEffectInfo const * effInfo , float dist , float & speedXY , float & speedZ )
{
if ( effInfo -> MiscValue )
speedZ = float ( effInfo -> MiscValue ) / 10 ;
else if ( effInfo -> MiscValueB )
speedZ = float ( effInfo -> MiscValueB ) / 10 ;
else
speedZ = 10.0f ;
speedXY = dist * 10.0f / speedZ ;
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectJump ()
2010-07-19 21:24:09 +02:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
if ( unitCaster -> IsInFlight ())
2010-07-19 21:24:09 +02:00
return ;
2011-09-25 13:29:17 +02:00
if ( ! unitTarget )
2010-07-19 21:24:09 +02:00
return ;
2011-09-25 13:29:17 +02:00
2010-07-19 21:24:09 +02:00
float speedXY , speedZ ;
2018-02-10 16:43:01 -03:00
CalculateJumpSpeeds ( effectInfo , unitCaster -> GetExactDist2d ( unitTarget ), speedXY , speedZ );
2017-02-18 21:55:28 +01:00
JumpArrivalCastArgs arrivalCast ;
arrivalCast . SpellId = effectInfo -> TriggerSpell ;
arrivalCast . Target = unitTarget -> GetGUID ();
2018-02-10 16:43:01 -03:00
unitCaster -> GetMotionMaster () -> MoveJump ( * unitTarget , speedXY , speedZ , EVENT_JUMP , false , & arrivalCast );
2010-07-19 21:24:09 +02:00
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectJumpDest ()
2009-03-12 14:50:14 -06:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
if ( unitCaster -> IsInFlight ())
2009-03-12 14:50:14 -06:00
return ;
2009-10-17 15:51:44 -07:00
2011-09-25 13:29:17 +02:00
if ( ! m_targets . HasDst ())
return ;
2010-07-19 21:24:09 +02:00
float speedXY , speedZ ;
2018-02-10 16:43:01 -03:00
CalculateJumpSpeeds ( effectInfo , unitCaster -> GetExactDist2d ( destTarget ), speedXY , speedZ );
2017-02-18 21:55:28 +01:00
JumpArrivalCastArgs arrivalCast ;
arrivalCast . SpellId = effectInfo -> TriggerSpell ;
2018-02-10 16:43:01 -03:00
unitCaster -> GetMotionMaster () -> MoveJump ( * destTarget , speedXY , speedZ , EVENT_JUMP , ! m_targets . GetObjectTargetGUID (). IsEmpty (), & arrivalCast );
2009-03-12 14:50:14 -06:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectTeleportUnits ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2013-06-11 19:54:27 -02:30
if ( ! unitTarget || unitTarget -> IsInFlight ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-11-01 15:08:12 -05:00
// If not exist data for dest location - return
2009-10-30 18:54:38 -07:00
if ( ! m_targets . HasDst ())
2008-11-01 15:08:12 -05:00
{
2016-02-20 13:23:35 +01:00
TC_LOG_ERROR ( "spells" , "Spell::EffectTeleportUnits - does not have a destination for spellId %u." , m_spellInfo -> Id );
2009-03-09 19:17:12 -06:00
return ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-03-09 19:17:12 -06:00
// Init dest coordinates
2018-02-04 22:47:53 -03:00
WorldLocation targetDest ( * destTarget );
if ( targetDest . GetMapId () == MAPID_INVALID )
targetDest . m_mapId = unitTarget -> GetMapId ();
if ( ! targetDest . GetOrientation () && m_targets . GetUnitTarget ())
targetDest . SetOrientation ( m_targets . GetUnitTarget () -> GetOrientation ());
Player * player = unitTarget -> ToPlayer ();
// Custom loading screen
if ( player )
2017-03-17 18:50:11 +01:00
if ( uint32 customLoadingScreenId = effectInfo -> MiscValue )
player -> SendDirectMessage ( WorldPackets :: Spells :: CustomLoadScreen ( m_spellInfo -> Id , customLoadingScreenId ). Write ());
2018-02-04 22:47:53 -03:00
if ( targetDest . GetMapId () == unitTarget -> GetMapId ())
unitTarget -> NearTeleportTo ( targetDest , unitTarget == m_caster );
else if ( player )
player -> TeleportTo ( targetDest , unitTarget == m_caster ? TELE_TO_SPELL : 0 );
2013-10-22 17:02:01 +02:00
else
{
2013-11-08 10:50:51 +01:00
TC_LOG_ERROR ( "spells" , "Spell::EffectTeleportUnits - spellId %u attempted to teleport creature to a different map." , m_spellInfo -> Id );
2013-10-22 17:02:01 +02:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-08-16 19:44:18 +02:00
// post effects for TARGET_DEST_DB
2018-02-04 22:47:53 -03:00
/// @todo: awful hacks, move this to spellscripts
2009-10-30 18:54:38 -07:00
switch ( m_spellInfo -> Id )
2008-10-11 14:16:25 -05:00
{
// Dimensional Ripper - Everlook
case 23442 :
{
int32 r = irand ( 0 , 119 );
2010-04-07 22:59:46 +02:00
if ( r >= 70 ) // 7/12 success
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
if ( r < 100 ) // 4/12 evil twin
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , 23445 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2008-10-11 14:16:25 -05:00
else // 1/12 fire
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , 23449 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2008-10-11 14:16:25 -05:00
}
return ;
}
// Ultrasafe Transporter: Toshley's Station
case 36941 :
{
2010-04-07 22:59:46 +02:00
if ( roll_chance_i ( 50 )) // 50% success
2008-10-11 14:16:25 -05:00
{
2009-05-31 15:56:51 -05:00
int32 rand_eff = urand ( 1 , 7 );
2010-04-07 22:59:46 +02:00
switch ( rand_eff )
2008-10-11 14:16:25 -05:00
{
case 1 :
// soul split - evil
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , 36900 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2008-10-11 14:16:25 -05:00
break ;
case 2 :
// soul split - good
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , 36901 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2008-10-11 14:16:25 -05:00
break ;
case 3 :
// Increase the size
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , 36895 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2008-10-11 14:16:25 -05:00
break ;
case 4 :
// Decrease the size
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , 36893 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2008-10-11 14:16:25 -05:00
break ;
case 5 :
// Transform
{
2010-04-07 22:59:46 +02:00
if ( m_caster -> ToPlayer () -> GetTeam () == ALLIANCE )
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , 36897 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2008-10-11 14:16:25 -05:00
else
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , 36899 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2008-10-11 14:16:25 -05:00
break ;
}
case 6 :
// chicken
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , 36940 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2008-10-11 14:16:25 -05:00
break ;
case 7 :
// evil twin
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , 23445 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2008-10-11 14:16:25 -05:00
break ;
}
}
return ;
}
// Dimensional Ripper - Area 52
case 36890 :
{
2010-04-07 22:59:46 +02:00
if ( roll_chance_i ( 50 )) // 50% success
2008-10-11 14:16:25 -05:00
{
2009-05-31 15:56:51 -05:00
int32 rand_eff = urand ( 1 , 4 );
2010-04-07 22:59:46 +02:00
switch ( rand_eff )
2008-10-11 14:16:25 -05:00
{
case 1 :
// soul split - evil
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , 36900 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2008-10-11 14:16:25 -05:00
break ;
case 2 :
// soul split - good
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , 36901 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2008-10-11 14:16:25 -05:00
break ;
case 3 :
// Increase the size
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , 36895 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2008-10-11 14:16:25 -05:00
break ;
case 4 :
2010-10-04 20:32:10 +02:00
// Transform
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
if ( m_caster -> ToPlayer () -> GetTeam () == ALLIANCE )
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , 36897 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2008-10-11 14:16:25 -05:00
else
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , 36899 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2008-10-11 14:16:25 -05:00
break ;
}
}
}
return ;
}
}
}
2009-10-17 15:51:44 -07:00
2021-10-13 11:49:30 +02:00
class DelayedSpellTeleportEvent : public BasicEvent
{
public :
explicit DelayedSpellTeleportEvent ( Unit * target , WorldLocation const & targetDest , uint32 options , uint32 spellId )
: _target ( target ), _targetDest ( targetDest ), _options ( options ), _spellId ( spellId ){ }
bool Execute ( uint64 /*e_time*/ , uint32 /*p_time*/ ) override
{
if ( _targetDest . GetMapId () == _target -> GetMapId ())
_target -> NearTeleportTo ( _targetDest , ( _options & TELE_TO_SPELL ) != 0 );
else if ( Player * player = _target -> ToPlayer ())
player -> TeleportTo ( _targetDest , _options );
else
TC_LOG_ERROR ( "spells" , "Spell::EffectTeleportUnitsWithVisualLoadingScreen - spellId %u attempted to teleport creature to a different map." , _spellId );
return true ;
}
private :
Unit * _target ;
WorldLocation _targetDest ;
uint32 _options ;
uint32 _spellId ;
};
void Spell :: EffectTeleportUnitsWithVisualLoadingScreen ()
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget )
return ;
// If not exist data for dest location - return
if ( ! m_targets . HasDst ())
{
TC_LOG_ERROR ( "spells" , "Spell::EffectTeleportUnitsWithVisualLoadingScreen - does not have a destination for spellId %u." , m_spellInfo -> Id );
return ;
}
// Init dest coordinates
WorldLocation targetDest ( * destTarget );
if ( targetDest . GetMapId () == MAPID_INVALID )
targetDest . m_mapId = unitTarget -> GetMapId ();
if ( ! targetDest . GetOrientation () && m_targets . GetUnitTarget ())
targetDest . SetOrientation ( m_targets . GetUnitTarget () -> GetOrientation ());
if ( effectInfo -> MiscValueB )
if ( Player * playerTarget = unitTarget -> ToPlayer ())
playerTarget -> SendDirectMessage ( WorldPackets :: Spells :: SpellVisualLoadScreen ( effectInfo -> MiscValueB , effectInfo -> MiscValue ). Write ());
unitTarget -> m_Events . AddEventAtOffset ( new DelayedSpellTeleportEvent ( unitTarget , targetDest , unitTarget == m_caster ? TELE_TO_SPELL : 0 , m_spellInfo -> Id ),
Milliseconds ( effectInfo -> MiscValue ));
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectApplyAura ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2018-01-27 03:45:40 -03:00
if ( ! _spellAura || ! unitTarget )
2010-01-10 01:23:15 +01:00
return ;
2018-01-27 03:45:40 -03:00
2018-03-10 00:58:48 -03:00
// register target/effect on aura
AuraApplication * aurApp = _spellAura -> GetApplicationOfTarget ( unitTarget -> GetGUID ());
if ( ! aurApp )
aurApp = unitTarget -> _CreateAuraApplication ( _spellAura , 1 << effectInfo -> EffectIndex );
else
aurApp -> UpdateApplyEffectMask ( aurApp -> GetEffectsToApply () | 1 << effectInfo -> EffectIndex );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectUnlearnSpecialization ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-07 19:14:10 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-12-10 15:40:55 +01:00
Player * player = unitTarget -> ToPlayer ();
2014-12-19 23:52:29 +01:00
uint32 spellToUnlearn = effectInfo -> TriggerSpell ;
2009-10-17 15:51:44 -07:00
2014-07-12 17:28:35 +02:00
player -> RemoveSpell ( spellToUnlearn );
2009-10-17 15:51:44 -07:00
2014-10-22 21:22:04 +02:00
TC_LOG_DEBUG ( "spells" , "Spell: %s has unlearned spell %u from %s" , player -> GetGUID (). ToString (). c_str (), spellToUnlearn , m_caster -> GetGUID (). ToString (). c_str ());
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectPowerDrain ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2014-12-19 23:52:29 +01:00
if ( effectInfo -> MiscValue < 0 || effectInfo -> MiscValue >= int8 ( MAX_POWERS ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
Powers powerType = Powers ( effectInfo -> MiscValue );
2018-01-03 16:39:00 +01:00
if ( ! unitTarget || ! unitTarget -> IsAlive () || unitTarget -> GetPowerType () != powerType || damage < 0 )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-08-26 19:07:55 +02:00
// add spell damage bonus
2018-02-10 16:43:01 -03:00
if ( unitCaster )
{
2021-09-04 15:13:15 +02:00
uint32 bonus = unitCaster -> SpellDamageBonusDone ( unitTarget , m_spellInfo , uint32 ( damage ), SPELL_DIRECT_DAMAGE , * effectInfo );
2018-02-10 16:43:01 -03:00
damage = bonus + uint32 ( bonus * variance );
damage = unitTarget -> SpellDamageBonusTaken ( unitCaster , m_spellInfo , uint32 ( damage ), SPELL_DIRECT_DAMAGE );
}
2009-10-17 15:51:44 -07:00
2012-12-20 19:22:14 +01:00
int32 newDamage = - ( unitTarget -> ModifyPower ( powerType , - damage ));
2009-10-17 15:51:44 -07:00
2012-12-20 19:22:14 +01:00
// Don't restore from self drain
2018-02-10 16:43:01 -03:00
float gainMultiplier = 0.f ;
if ( unitCaster && unitCaster != unitTarget )
2008-10-11 14:16:25 -05:00
{
2018-02-10 16:43:01 -03:00
gainMultiplier = effectInfo -> CalcValueMultiplier ( unitCaster , this );
int32 const gain = int32 ( newDamage * gainMultiplier );
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
unitCaster -> EnergizeBySpell ( unitCaster , m_spellInfo , gain , powerType );
2008-10-11 14:16:25 -05:00
}
2021-08-28 18:30:45 +02:00
ExecuteLogEffectTakeTargetPower ( SpellEffectName ( effectInfo -> Effect ), unitTarget , powerType , newDamage , gainMultiplier );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectSendEvent ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
// we do not handle a flag dropping or clicking on flag in battleground by sendevent system
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET
&& effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2010-01-21 23:57:14 +01:00
2020-08-14 17:06:03 +02:00
WorldObject * target = nullptr ;
2011-09-25 13:29:17 +02:00
2011-12-23 23:52:22 +01:00
// call events for object target if present
2011-09-25 13:29:17 +02:00
if ( effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET )
{
if ( unitTarget )
target = unitTarget ;
else if ( gameObjTarget )
target = gameObjTarget ;
}
2011-12-23 23:52:22 +01:00
else // if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT)
2011-09-25 13:29:17 +02:00
{
2011-12-23 23:52:22 +01:00
// let's prevent executing effect handler twice in case when spell effect is capable of targeting an object
// this check was requested by scripters, but it has some downsides:
// now it's impossible to script (using sEventScripts) a cast which misses all targets
// or to have an ability to script the moment spell hits dest (in a case when there are object targets present)
2014-12-19 23:52:29 +01:00
if ( effectInfo -> GetProvidedTargetMask () & ( TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT_MASK ))
2011-12-23 23:52:22 +01:00
return ;
// some spells have no target entries in dbc and they use focus target
2011-09-25 13:29:17 +02:00
if ( focusObject )
target = focusObject ;
2013-03-08 21:41:30 +01:00
/// @todo there should be a possibility to pass dest target to event script
2011-09-25 13:29:17 +02:00
}
2014-12-19 23:52:29 +01:00
TC_LOG_DEBUG ( "spells" , "Spell ScriptStart %u for spellid %u in EffectSendEvent " , effectInfo -> MiscValue , m_spellInfo -> Id );
2010-01-21 23:57:14 +01:00
2011-07-22 21:22:05 +02:00
if ( ZoneScript * zoneScript = m_caster -> GetZoneScript ())
2014-12-19 23:52:29 +01:00
zoneScript -> ProcessEvent ( target , effectInfo -> MiscValue );
2011-09-30 18:41:30 +02:00
else if ( InstanceScript * instanceScript = m_caster -> GetInstanceScript ()) // needed in case Player is the caster
2014-12-19 23:52:29 +01:00
instanceScript -> ProcessEvent ( target , effectInfo -> MiscValue );
2011-01-20 12:27:08 -03:00
2014-12-19 23:52:29 +01:00
m_caster -> GetMap () -> ScriptsStart ( sEventScripts , effectInfo -> MiscValue , m_caster , target );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectPowerBurn ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2014-12-19 23:52:29 +01:00
if ( effectInfo -> MiscValue < 0 || effectInfo -> MiscValue >= int8 ( MAX_POWERS ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
Powers powerType = Powers ( effectInfo -> MiscValue );
2018-01-03 16:39:00 +01:00
if ( ! unitTarget || ! unitTarget -> IsAlive () || unitTarget -> GetPowerType () != powerType || damage < 0 )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2012-12-20 19:22:14 +01:00
int32 newDamage = - ( unitTarget -> ModifyPower ( powerType , - damage ));
2009-10-17 15:51:44 -07:00
2010-08-26 19:07:55 +02:00
// NO - Not a typo - EffectPowerBurn uses effect value multiplier - not effect damage multiplier
2018-02-10 16:43:01 -03:00
float dmgMultiplier = effectInfo -> CalcValueMultiplier ( unitCaster , this );
2009-10-17 15:51:44 -07:00
2010-09-25 15:03:48 +02:00
// add log data before multiplication (need power amount, not damage)
2021-08-28 18:30:45 +02:00
ExecuteLogEffectTakeTargetPower ( SpellEffectName ( effectInfo -> Effect ), unitTarget , powerType , newDamage , 0.0f );
2009-10-17 15:51:44 -07:00
2018-02-01 13:10:51 -03:00
newDamage = int32 ( newDamage * dmgMultiplier );
2010-08-27 17:49:32 +02:00
2010-08-29 05:26:32 +02:00
m_damage += newDamage ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectHeal ()
2008-12-25 17:39:46 -06:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET )
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
if ( ! unitTarget || ! unitTarget -> IsAlive () || damage < 0 )
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
// Skip if m_originalCaster not available
if ( ! unitCaster )
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
int32 addhealth = damage ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
// Vessel of the Naaru (Vial of the Sunwell trinket)
///@todo: move this to scripts
if ( m_spellInfo -> Id == 45064 )
{
// Amount of heal - depends from stacked Holy Energy
int32 damageAmount = 0 ;
if ( AuraEffect const * aurEff = unitCaster -> GetAuraEffect ( 45062 , 0 ))
2014-12-19 18:55:09 +01:00
{
2018-02-10 16:43:01 -03:00
damageAmount += aurEff -> GetAmount ();
unitCaster -> RemoveAurasDueToSpell ( 45062 );
2014-12-19 18:55:09 +01:00
}
2012-05-30 08:01:02 +02:00
2018-02-10 16:43:01 -03:00
addhealth += damageAmount ;
}
// Runic Healing Injector (heal increased by 25% for engineers - 3.2.0 patch change)
else if ( m_spellInfo -> Id == 67489 )
{
if ( Player * player = unitCaster -> ToPlayer ())
if ( player -> HasSkill ( SKILL_ENGINEERING ))
AddPct ( addhealth , 25 );
}
// Death Pact - return pct of max health to caster
else if ( m_spellInfo -> SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellInfo -> SpellFamilyFlags [ 0 ] & 0x00080000 )
2021-09-04 15:13:15 +02:00
addhealth = unitCaster -> SpellHealingBonusDone ( unitTarget , m_spellInfo , int32 ( unitCaster -> CountPctFromMaxHealth ( damage )), HEAL , * effectInfo );
2018-02-10 16:43:01 -03:00
else
{
2021-09-04 15:13:15 +02:00
uint32 bonus = unitCaster -> SpellHealingBonusDone ( unitTarget , m_spellInfo , addhealth , HEAL , * effectInfo );
2018-02-10 16:43:01 -03:00
addhealth = bonus + uint32 ( bonus * variance );
}
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
addhealth = unitTarget -> SpellHealingBonusTaken ( unitCaster , m_spellInfo , addhealth , HEAL );
2010-06-20 00:37:02 +02:00
2018-02-10 16:43:01 -03:00
// Remove Grievious bite if fully healed
if ( unitTarget -> HasAura ( 48920 ) && ( unitTarget -> GetHealth () + addhealth >= unitTarget -> GetMaxHealth ()))
unitTarget -> RemoveAura ( 48920 );
m_healing += addhealth ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectHealPct ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2013-06-11 19:54:27 -02:30
if ( ! unitTarget || ! unitTarget -> IsAlive () || damage < 0 )
2010-08-28 23:01:04 +02:00
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
uint32 heal = unitTarget -> CountPctFromMaxHealth ( damage );
if ( unitCaster )
{
2021-09-04 15:13:15 +02:00
heal = unitCaster -> SpellHealingBonusDone ( unitTarget , m_spellInfo , heal , HEAL , * effectInfo );
2018-02-10 16:43:01 -03:00
heal = unitTarget -> SpellHealingBonusTaken ( unitCaster , m_spellInfo , heal , HEAL );
}
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
m_healing += heal ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectHealMechanical ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2013-06-11 19:54:27 -02:30
if ( ! unitTarget || ! unitTarget -> IsAlive () || damage < 0 )
2010-08-28 23:01:04 +02:00
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
uint32 heal = damage ;
if ( unitCaster )
2021-09-04 15:13:15 +02:00
heal = unitCaster -> SpellHealingBonusDone ( unitTarget , m_spellInfo , heal , HEAL , * effectInfo );
2009-10-17 15:51:44 -07:00
2014-12-19 18:55:09 +01:00
heal += uint32 ( heal * variance );
2018-02-10 16:43:01 -03:00
if ( unitCaster )
heal = unitTarget -> SpellHealingBonusTaken ( unitCaster , m_spellInfo , heal , HEAL );
2012-05-30 08:01:02 +02:00
2018-02-10 16:43:01 -03:00
m_healing += heal ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectHealthLeech ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2013-06-11 19:54:27 -02:30
if ( ! unitTarget || ! unitTarget -> IsAlive () || damage < 0 )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
uint32 bonus = 0 ;
if ( unitCaster )
2021-09-04 15:13:15 +02:00
bonus = unitCaster -> SpellDamageBonusDone ( unitTarget , m_spellInfo , uint32 ( damage ), SPELL_DIRECT_DAMAGE , * effectInfo );
2018-02-10 16:43:01 -03:00
2014-12-19 18:55:09 +01:00
damage = bonus + uint32 ( bonus * variance );
2018-02-10 16:43:01 -03:00
if ( unitCaster )
damage = unitTarget -> SpellDamageBonusTaken ( unitCaster , m_spellInfo , uint32 ( damage ), SPELL_DIRECT_DAMAGE );
2011-05-10 22:28:28 +07:00
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "spells" , "HealthLeech :%i" , damage );
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
float healMultiplier = effectInfo -> CalcValueMultiplier ( unitCaster , this );
2009-10-17 15:51:44 -07:00
2010-09-02 15:34:36 +02:00
m_damage += damage ;
// get max possible damage, don't count overkill for heal
uint32 healthGain = uint32 ( - unitTarget -> GetHealthGain ( - damage ) * healMultiplier );
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
if ( unitCaster && unitCaster -> IsAlive ())
2008-10-11 14:16:25 -05:00
{
2021-09-04 15:13:15 +02:00
healthGain = unitCaster -> SpellHealingBonusDone ( unitCaster , m_spellInfo , healthGain , HEAL , * effectInfo );
2018-02-10 16:43:01 -03:00
healthGain = unitCaster -> SpellHealingBonusTaken ( unitCaster , m_spellInfo , healthGain , HEAL );
2012-05-30 08:01:02 +02:00
2018-02-10 16:43:01 -03:00
HealInfo healInfo ( unitCaster , unitCaster , healthGain , m_spellInfo , m_spellSchoolMask );
unitCaster -> HealBySpell ( healInfo );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: DoCreateItem ( uint32 itemId , ItemContext context /*= ItemContext::NONE*/ , std :: vector < int32 > const & bonusListIDs /*= std::vector<int32>()*/ )
2008-10-11 14:16:25 -05:00
{
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
2009-10-17 15:51:44 -07:00
2011-09-25 13:29:17 +02:00
Player * player = unitTarget -> ToPlayer ();
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
uint32 newitemid = itemId ;
2011-09-15 14:08:17 +02:00
ItemTemplate const * pProto = sObjectMgr -> GetItemTemplate ( newitemid );
2010-04-07 19:14:10 +02:00
if ( ! pProto )
2008-10-11 14:16:25 -05:00
{
2020-08-14 17:06:03 +02:00
player -> SendEquipError ( EQUIP_ERR_ITEM_NOT_FOUND , nullptr , nullptr );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-04-14 12:22:35 +04:00
uint32 num_to_add = damage ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( num_to_add < 1 )
num_to_add = 1 ;
2009-01-03 11:06:51 -06:00
if ( num_to_add > pProto -> GetMaxStackSize ())
num_to_add = pProto -> GetMaxStackSize ();
2009-10-17 15:51:44 -07:00
2015-10-11 11:40:05 +02:00
/* == gem perfection handling == */
2017-04-06 23:39:34 +02:00
// this is bad, should be done using spell_loot_template (and conditions)
2015-10-11 11:40:05 +02:00
// the chance of getting a perfect result
float perfectCreateChance = 0.0f ;
// the resulting perfect item if successful
2021-08-28 19:51:29 +02:00
uint32 perfectItemType = itemId ;
2015-10-11 11:40:05 +02:00
// get perfection capability and chance
if ( CanCreatePerfectItem ( player , m_spellInfo -> Id , perfectCreateChance , perfectItemType ))
if ( roll_chance_f ( perfectCreateChance )) // if the roll succeeds...
newitemid = perfectItemType ; // the perfect item replaces the regular one
/* == gem perfection handling over == */
/* == profession specialization handling == */
2008-10-11 14:16:25 -05:00
// init items_count to 1, since 1 item will be created regardless of specialization
int items_count = 1 ;
// the chance to create additional items
float additionalCreateChance = 0.0f ;
// the maximum number of created additional items
uint8 additionalMaxNum = 0 ;
// get the chance and maximum number for creating extra items
2013-06-11 21:25:12 -02:30
if ( CanCreateExtraItems ( player , m_spellInfo -> Id , additionalCreateChance , additionalMaxNum ))
2008-10-11 14:16:25 -05:00
// roll with this chance till we roll not to create or we create the max num
2010-04-07 23:56:35 +02:00
while ( roll_chance_f ( additionalCreateChance ) && items_count <= additionalMaxNum )
2008-10-11 14:16:25 -05:00
++ items_count ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// really will be created more items
num_to_add *= items_count ;
2009-10-17 15:51:44 -07:00
2015-10-11 11:40:05 +02:00
/* == profession specialization handling over == */
2008-10-11 14:16:25 -05:00
// can the player store the new item?
ItemPosCountVec dest ;
uint32 no_space = 0 ;
2011-04-29 16:48:15 +06:00
InventoryResult msg = player -> CanStoreNewItem ( NULL_BAG , NULL_SLOT , dest , newitemid , num_to_add , & no_space );
2010-04-07 22:59:46 +02:00
if ( msg != EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
// convert to possible store amount
2012-08-20 15:54:55 +02:00
if ( msg == EQUIP_ERR_INV_FULL || msg == EQUIP_ERR_ITEM_MAX_COUNT )
2008-10-11 14:16:25 -05:00
num_to_add -= no_space ;
else
{
// if not created by another reason from full inventory or unique items amount limitation
2020-08-14 17:06:03 +02:00
player -> SendEquipError ( msg , nullptr , nullptr , newitemid );
2008-10-11 14:16:25 -05:00
return ;
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( num_to_add )
2008-10-11 14:16:25 -05:00
{
// create the new item and store it
2019-06-04 22:36:17 +02:00
Item * pItem = player -> StoreNewItem ( dest , newitemid , true , GenerateItemRandomBonusListId ( newitemid ), GuidSet (), context , bonusListIDs );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// was it successful? return error if not
2010-04-07 19:14:10 +02:00
if ( ! pItem )
2008-10-11 14:16:25 -05:00
{
2020-08-14 17:06:03 +02:00
player -> SendEquipError ( EQUIP_ERR_ITEM_NOT_FOUND , nullptr , nullptr );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// set the "Crafted by ..." property of the item
2014-12-21 13:35:43 +01:00
if ( pItem -> GetTemplate () -> GetClass () != ITEM_CLASS_CONSUMABLE && pItem -> GetTemplate () -> GetClass () != ITEM_CLASS_QUEST && newitemid != 6265 && newitemid != 6948 )
2019-06-03 20:40:34 +02:00
pItem -> SetCreator ( player -> GetGUID ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// send info to the client
2019-10-18 19:38:03 +02:00
player -> SendNewItem ( pItem , num_to_add , true , true );
2009-10-17 15:51:44 -07:00
2015-09-07 18:03:33 +02:00
if ( pItem -> GetQuality () > ITEM_QUALITY_EPIC || ( pItem -> GetQuality () == ITEM_QUALITY_EPIC && pItem -> GetItemLevel ( player ) >= MinNewsItemLevel ))
2012-11-07 23:21:19 +01:00
if ( Guild * guild = player -> GetGuild ())
2014-12-21 13:35:43 +01:00
guild -> AddGuildNews ( GUILD_NEWS_ITEM_CRAFTED , player -> GetGUID (), 0 , pProto -> GetId ());
2012-11-07 23:21:19 +01:00
2008-10-11 14:16:25 -05:00
// we succeeded in creating at least one item, so a levelup is possible
2019-10-18 19:38:03 +02:00
player -> UpdateCraftSkill ( m_spellInfo -> Id );
2009-04-06 21:14:51 +02:00
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectCreateItem ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2021-08-28 19:51:29 +02:00
DoCreateItem ( effectInfo -> ItemType , m_spellInfo -> HasAttribute ( SPELL_ATTR0_TRADESPELL ) ? ItemContext :: Trade_Skill : ItemContext :: NONE );
2021-08-28 18:30:45 +02:00
ExecuteLogEffectCreateItem ( SpellEffectName ( effectInfo -> Effect ), effectInfo -> ItemType );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectCreateItem2 ()
2009-02-05 23:02:07 -06:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
2009-05-24 11:17:41 -05:00
return ;
2011-09-25 13:29:17 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
Player * player = unitTarget -> ToPlayer ();
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
uint32 item_id = effectInfo -> ItemType ;
2019-11-23 00:03:42 +01:00
ItemContext context = m_spellInfo -> HasAttribute ( SPELL_ATTR0_TRADESPELL ) ? ItemContext :: Trade_Skill : ItemContext :: NONE ;
2009-10-17 15:51:44 -07:00
2010-04-11 11:24:05 +04:00
if ( item_id )
2021-08-28 19:51:29 +02:00
DoCreateItem ( item_id , context );
2009-10-17 15:51:44 -07:00
2009-05-24 11:17:41 -05:00
// special case: fake item replaced by generate using spell_loot_template
2011-07-26 23:09:28 +02:00
if ( m_spellInfo -> IsLootCrafting ())
2009-02-05 23:02:07 -06:00
{
2010-04-11 11:24:05 +04:00
if ( item_id )
{
2012-10-23 13:11:08 +02:00
if ( ! player -> HasItemCount ( item_id ))
2010-04-11 11:24:05 +04:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-11 11:24:05 +04:00
// remove reagent
uint32 count = 1 ;
player -> DestroyItemCount ( item_id , count , true );
2009-10-17 15:51:44 -07:00
2010-04-11 11:24:05 +04:00
// create some random items
2019-11-23 00:03:42 +01:00
player -> AutoStoreLoot ( m_spellInfo -> Id , LootTemplates_Spell , context );
2010-06-16 20:10:42 +02:00
}
else
2019-11-23 00:03:42 +01:00
player -> AutoStoreLoot ( m_spellInfo -> Id , LootTemplates_Spell , context ); // create some random items
2016-08-01 04:53:27 -03:00
player -> UpdateCraftSkill ( m_spellInfo -> Id );
2009-02-05 23:02:07 -06:00
}
2013-03-08 21:41:30 +01:00
/// @todo ExecuteLogEffectCreateItem(i, m_spellInfo->Effects[i].ItemType);
2009-02-05 23:02:07 -06:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectCreateRandomItem ()
2009-06-23 14:44:16 +02:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
2009-06-23 14:44:16 +02:00
return ;
2011-09-25 13:29:17 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
Player * player = unitTarget -> ToPlayer ();
2009-10-17 15:51:44 -07:00
2009-06-23 14:44:16 +02:00
// create some random items
2019-11-23 00:03:42 +01:00
player -> AutoStoreLoot ( m_spellInfo -> Id , LootTemplates_Spell , m_spellInfo -> HasAttribute ( SPELL_ATTR0_TRADESPELL ) ? ItemContext :: Trade_Skill : ItemContext :: NONE );
2013-03-08 21:41:30 +01:00
/// @todo ExecuteLogEffectCreateItem(i, m_spellInfo->Effects[i].ItemType);
2009-06-23 14:44:16 +02:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectPersistentAA ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
2018-01-27 03:45:40 -03:00
// only handle at last effect
2021-09-04 15:13:15 +02:00
for ( size_t i = effectInfo -> EffectIndex + 1 ; i < m_spellInfo -> GetEffects (). size (); ++ i )
if ( m_spellInfo -> GetEffect ( SpellEffIndex ( i )). IsEffect ( SPELL_EFFECT_PERSISTENT_AREA_AURA ))
return ;
2018-01-27 03:45:40 -03:00
ASSERT ( ! _dynObjAura );
2018-02-10 16:43:01 -03:00
float radius = effectInfo -> CalcRadius ( unitCaster );
2018-01-27 03:45:40 -03:00
// Caster not in world, might be spell triggered from aura removal
2018-02-10 16:43:01 -03:00
if ( ! unitCaster -> IsInWorld ())
2018-01-27 03:45:40 -03:00
return ;
DynamicObject * dynObj = new DynamicObject ( false );
2018-02-10 16:43:01 -03:00
if ( ! dynObj -> CreateDynamicObject ( unitCaster -> GetMap () -> GenerateLowGuid < HighGuid :: DynamicObject > (), unitCaster , m_spellInfo , * destTarget , radius , DYNAMIC_OBJECT_AREA_SPELL , m_SpellVisual ))
2009-08-27 16:41:10 -05:00
{
2018-01-27 03:45:40 -03:00
delete dynObj ;
return ;
}
2011-07-26 23:09:28 +02:00
2018-01-27 03:45:40 -03:00
AuraCreateInfo createInfo ( m_castId , m_spellInfo , GetCastDifficulty (), MAX_EFFECT_MASK , dynObj );
createInfo
2018-02-10 16:43:01 -03:00
. SetCaster ( unitCaster )
2018-01-27 03:45:40 -03:00
. SetBaseAmount ( m_spellValue -> EffectBasePoints )
. SetCastItem ( m_castItemGUID , m_castItemEntry , m_castItemLevel );
2011-04-19 15:14:50 +02:00
2018-01-27 03:45:40 -03:00
if ( Aura * aura = Aura :: TryCreate ( createInfo ))
{
_dynObjAura = aura -> ToDynObjAura ();
_dynObjAura -> _RegisterForTargets ();
2008-10-11 14:16:25 -05:00
}
2018-01-27 03:45:40 -03:00
else
return ;
2011-04-19 15:14:50 +02:00
2018-01-27 03:45:40 -03:00
ASSERT ( _dynObjAura -> GetDynobjOwner ());
2021-08-28 19:51:29 +02:00
_dynObjAura -> _ApplyEffectForTargets ( effectInfo -> EffectIndex );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectEnergize ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster || ! unitTarget )
2008-10-11 14:16:25 -05:00
return ;
2018-02-10 16:43:01 -03:00
2013-06-11 19:54:27 -02:30
if ( ! unitTarget -> IsAlive ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
if ( effectInfo -> MiscValue < 0 || effectInfo -> MiscValue >= int8 ( MAX_POWERS ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
Powers power = Powers ( effectInfo -> MiscValue );
2014-06-16 01:32:52 +02:00
if ( unitTarget -> GetMaxPower ( power ) == 0 )
return ;
2008-10-11 14:16:25 -05:00
// Some level depends spells
switch ( m_spellInfo -> Id )
{
2009-07-31 11:16:38 +08:00
case 24571 : // Blood Fury
2018-01-03 18:10:47 +01:00
// Instantly increases your rage by ${(300-10*$max(0,$PL-60))/10}.
2018-02-10 16:43:01 -03:00
damage -= 10 * std :: max ( 0 , std :: min ( 30 , unitCaster -> getLevel () - 60 ));
2008-10-11 14:16:25 -05:00
break ;
2009-07-31 11:16:38 +08:00
case 24532 : // Burst of Energy
2018-01-03 18:10:47 +01:00
// Instantly increases your energy by ${60-4*$max(0,$min(15,$PL-60))}.
2018-02-10 16:43:01 -03:00
damage -= 4 * std :: max ( 0 , std :: min ( 15 , unitCaster -> getLevel () - 60 ));
2009-08-13 14:36:50 +02:00
break ;
2011-11-02 19:23:59 +07:00
case 67490 : // Runic Mana Injector (mana gain increased by 25% for engineers - 3.2.0 patch change)
{
2018-02-10 16:43:01 -03:00
if ( Player * player = unitCaster -> ToPlayer ())
2011-11-03 17:08:30 +07:00
if ( player -> HasSkill ( SKILL_ENGINEERING ))
2012-10-02 12:17:42 +02:00
AddPct ( damage , 25 );
2011-11-02 19:23:59 +07:00
break ;
}
2008-10-11 14:16:25 -05:00
default :
break ;
}
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
unitCaster -> EnergizeBySpell ( unitTarget , m_spellInfo , damage , power );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectEnergizePct ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster || ! unitTarget )
2008-10-11 14:16:25 -05:00
return ;
2018-02-10 16:43:01 -03:00
2013-06-11 19:54:27 -02:30
if ( ! unitTarget -> IsAlive ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
if ( effectInfo -> MiscValue < 0 || effectInfo -> MiscValue >= int8 ( MAX_POWERS ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
Powers power = Powers ( effectInfo -> MiscValue );
2008-10-11 14:16:25 -05:00
uint32 maxPower = unitTarget -> GetMaxPower ( power );
2018-02-10 16:43:01 -03:00
if ( ! maxPower )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
uint32 const gain = CalculatePct ( maxPower , damage );
unitCaster -> EnergizeBySpell ( unitTarget , m_spellInfo , gain , power );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2014-09-14 16:14:12 +02:00
void Spell :: SendLoot ( ObjectGuid guid , LootType loottype )
2008-10-11 14:16:25 -05:00
{
2010-12-26 16:35:29 +01:00
Player * player = m_caster -> ToPlayer ();
2008-10-11 14:16:25 -05:00
if ( ! player )
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( gameObjTarget )
{
2011-01-18 20:02:28 +01:00
// Players shouldn't be able to loot gameobjects that are currently despawned
2013-06-11 21:25:12 -02:30
if ( ! gameObjTarget -> isSpawned () && ! player -> IsGameMaster ())
2011-01-18 20:02:28 +01:00
{
2016-08-11 09:10:20 +02:00
TC_LOG_ERROR ( "entities.player.cheat" , "Possible hacking attempt: Player %s [%s] tried to loot a gameobject [%s] which is on respawn times without being in GM mode!" ,
2014-10-22 21:22:04 +02:00
player -> GetName (). c_str (), player -> GetGUID (). ToString (). c_str (), gameObjTarget -> GetGUID (). ToString (). c_str ());
2011-01-18 20:02:28 +01:00
return ;
}
2010-12-26 16:35:29 +01:00
// special case, already has GossipHello inside so return and avoid calling twice
if ( gameObjTarget -> GetGoType () == GAMEOBJECT_TYPE_GOOBER )
{
2018-02-10 16:43:01 -03:00
gameObjTarget -> Use ( player );
2010-12-26 16:35:29 +01:00
return ;
}
2017-05-01 18:19:36 -03:00
player -> PlayerTalkClass -> ClearMenus ();
2017-06-06 20:36:01 +02:00
if ( gameObjTarget -> AI () -> GossipHello ( player ))
2012-09-22 21:28:37 +02:00
return ;
2010-10-27 21:01:47 +02:00
2008-10-11 14:16:25 -05:00
switch ( gameObjTarget -> GetGoType ())
{
case GAMEOBJECT_TYPE_DOOR :
case GAMEOBJECT_TYPE_BUTTON :
2012-01-22 20:36:01 -05:00
gameObjTarget -> UseDoorOrButton ( 0 , false , player );
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
case GAMEOBJECT_TYPE_QUESTGIVER :
2013-04-04 19:32:45 +02:00
player -> PrepareGossipMenu ( gameObjTarget , gameObjTarget -> GetGOInfo () -> questgiver . gossipID , true );
2012-01-05 21:41:17 -05:00
player -> SendPreparedGossip ( gameObjTarget );
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
case GAMEOBJECT_TYPE_SPELL_FOCUS :
// triggering linked GO
2014-10-30 20:02:42 +01:00
if ( uint32 trapEntry = gameObjTarget -> GetGOInfo () -> spellFocus . linkedTrap )
2018-02-10 16:43:01 -03:00
gameObjTarget -> TriggeringLinkedGameObject ( trapEntry , player );
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
case GAMEOBJECT_TYPE_CHEST :
2013-03-08 21:41:30 +01:00
/// @todo possible must be moved to loot release (in different from linked triggering)
2014-10-30 20:02:42 +01:00
if ( gameObjTarget -> GetGOInfo () -> chest . triggeredEvent )
2008-10-11 14:16:25 -05:00
{
2015-02-25 00:13:14 +01:00
TC_LOG_DEBUG ( "spells" , "Chest ScriptStart id %u for GO " UI64FMTD , gameObjTarget -> GetGOInfo () -> chest . triggeredEvent , gameObjTarget -> GetSpawnId ());
2014-10-30 20:02:42 +01:00
player -> GetMap () -> ScriptsStart ( sEventScripts , gameObjTarget -> GetGOInfo () -> chest . triggeredEvent , player , gameObjTarget );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// triggering linked GO
2014-10-30 20:02:42 +01:00
if ( uint32 trapEntry = gameObjTarget -> GetGOInfo () -> chest . linkedTrap )
2018-02-10 16:43:01 -03:00
gameObjTarget -> TriggeringLinkedGameObject ( trapEntry , player );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Don't return, let loots been taken
2009-05-03 22:21:46 -05:00
default :
break ;
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Send loot
player -> SendLoot ( guid , loottype );
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectOpenLock ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-12-22 20:18:34 +02:00
if ( m_caster -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "spells" , "WORLD: Open Lock - No Player Caster!" );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-09-25 13:29:17 +02:00
Player * player = m_caster -> ToPlayer ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 lockId = 0 ;
2014-09-14 16:14:12 +02:00
ObjectGuid guid ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Get lockId
2010-04-07 19:14:10 +02:00
if ( gameObjTarget )
2008-10-11 14:16:25 -05:00
{
2011-04-28 22:54:30 +02:00
GameObjectTemplate const * goInfo = gameObjTarget -> GetGOInfo ();
2013-03-08 21:41:30 +01:00
// Arathi Basin banner opening. /// @todo Verify correctness of this check
2010-08-30 15:25:15 +02:00
if (( goInfo -> type == GAMEOBJECT_TYPE_BUTTON && goInfo -> button . noDamageImmune ) ||
2014-10-30 20:02:42 +01:00
( goInfo -> type == GAMEOBJECT_TYPE_GOOBER && goInfo -> goober . requireLOS ))
2008-10-11 14:16:25 -05:00
{
2010-08-08 04:37:24 +02:00
//CanUseBattlegroundObject() already called in CheckCast()
2008-10-11 14:16:25 -05:00
// in battleground check
2011-09-15 14:08:17 +02:00
if ( Battleground * bg = player -> GetBattleground ())
2011-09-06 21:20:14 +01:00
{
bg -> EventPlayerClickedOnFlag ( player , gameObjTarget );
return ;
}
2008-10-11 14:16:25 -05:00
}
else if ( goInfo -> type == GAMEOBJECT_TYPE_FLAGSTAND )
{
2010-08-08 04:37:24 +02:00
//CanUseBattlegroundObject() already called in CheckCast()
2008-10-11 14:16:25 -05:00
// in battleground check
2011-09-15 14:08:17 +02:00
if ( Battleground * bg = player -> GetBattleground ())
2008-10-11 14:16:25 -05:00
{
2010-05-26 11:34:37 +02:00
if ( bg -> GetTypeID ( true ) == BATTLEGROUND_EY )
2008-10-11 14:16:25 -05:00
bg -> EventPlayerClickedOnFlag ( player , gameObjTarget );
return ;
}
2012-09-05 17:17:45 +02:00
}
else if ( m_spellInfo -> Id == 1842 && gameObjTarget -> GetGOInfo () -> type == GAMEOBJECT_TYPE_TRAP && gameObjTarget -> GetOwner ())
2010-03-26 22:04:38 -03:00
{
2010-05-23 18:20:10 -03:00
gameObjTarget -> SetLootState ( GO_JUST_DEACTIVATED );
return ;
2008-10-11 14:16:25 -05:00
}
2013-03-08 21:41:30 +01:00
/// @todo Add script for spell 41920 - Filling, becouse server it freze when use this spell
2008-10-14 11:57:03 -05:00
// handle outdoor pvp object opening, return true if go was registered for handling
// these objects must have been spawned by outdoorpvp!
2015-02-25 00:13:14 +01:00
else if ( gameObjTarget -> GetGOInfo () -> type == GAMEOBJECT_TYPE_GOOBER && sOutdoorPvPMgr -> HandleOpenGo ( player , gameObjTarget ))
2008-10-14 11:57:03 -05:00
return ;
2009-07-16 12:06:07 +08:00
lockId = goInfo -> GetLockId ();
2008-10-11 14:16:25 -05:00
guid = gameObjTarget -> GetGUID ();
}
2010-04-07 19:14:10 +02:00
else if ( itemTarget )
2008-10-11 14:16:25 -05:00
{
2014-12-21 13:35:43 +01:00
lockId = itemTarget -> GetTemplate () -> GetLockID ();
2008-10-11 14:16:25 -05:00
guid = itemTarget -> GetGUID ();
}
else
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "spells" , "WORLD: Open Lock - No GameObject/Item Target!" );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-03-15 17:54:24 -06:00
SkillType skillId = SKILL_NONE ;
int32 reqSkillValue = 0 ;
int32 skillValue ;
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
SpellCastResult res = CanOpenLock ( * effectInfo , lockId , skillId , reqSkillValue , skillValue );
2010-04-07 19:14:10 +02:00
if ( res != SPELL_CAST_OK )
2008-10-11 14:16:25 -05:00
{
2009-03-15 17:54:24 -06:00
SendCastResult ( res );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-08-04 10:34:30 +02:00
if ( gameObjTarget )
SendLoot ( guid , LOOT_SKINNING );
2012-09-05 17:17:45 +02:00
else if ( itemTarget )
2017-11-26 23:38:17 +01:00
{
2019-06-03 20:40:34 +02:00
itemTarget -> AddItemFlag ( ITEM_FIELD_FLAG_UNLOCKED );
2017-11-26 23:38:17 +01:00
itemTarget -> SetState ( ITEM_CHANGED , itemTarget -> GetOwner ());
}
2009-10-17 15:51:44 -07:00
2009-03-16 12:00:14 -06:00
// not allow use skill grow at item base open
2010-04-07 19:14:10 +02:00
if ( ! m_CastItem && skillId != SKILL_NONE )
2008-10-11 14:16:25 -05:00
{
2009-03-15 17:54:24 -06:00
// update skill if really known
2010-04-07 19:14:10 +02:00
if ( uint32 pureSkillValue = player -> GetPureSkillValue ( skillId ))
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( gameObjTarget )
2009-03-15 17:18:59 -06:00
{
2009-03-15 17:54:24 -06:00
// Allow one skill-up until respawned
2014-10-22 21:22:04 +02:00
if ( ! gameObjTarget -> IsInSkillupList ( player -> GetGUID ()) &&
2010-04-07 22:59:46 +02:00
player -> UpdateGatherSkill ( skillId , pureSkillValue , reqSkillValue ))
2014-10-22 21:22:04 +02:00
gameObjTarget -> AddToSkillupList ( player -> GetGUID ());
2009-03-15 17:54:24 -06:00
}
2010-04-07 19:14:10 +02:00
else if ( itemTarget )
2009-03-15 17:54:24 -06:00
{
// Do one skill-up
player -> UpdateGatherSkill ( skillId , pureSkillValue , reqSkillValue );
2009-03-15 17:18:59 -06:00
}
}
2008-10-11 14:16:25 -05:00
}
2021-08-28 18:30:45 +02:00
ExecuteLogEffectOpenLock ( SpellEffectName ( effectInfo -> Effect ), gameObjTarget ? ( Object * ) gameObjTarget : ( Object * ) itemTarget );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectSummonChangeItem ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
if ( m_caster -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-09-25 13:29:17 +02:00
Player * player = m_caster -> ToPlayer ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// applied only to using item
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
if ( ! m_CastItem )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// ... only to item in own inventory/bank/equip_slot
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
if ( m_CastItem -> GetOwnerGUID () != player -> GetGUID ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
uint32 newitemid = effectInfo -> ItemType ;
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
if ( ! newitemid )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint16 pos = m_CastItem -> GetPos ();
2009-10-17 15:51:44 -07:00
2019-11-23 00:03:42 +01:00
Item * pNewItem = Item :: CreateItem ( newitemid , 1 , m_CastItem -> GetContext (), player );
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
if ( ! pNewItem )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
for ( uint8 j = PERM_ENCHANTMENT_SLOT ; j <= TEMP_ENCHANTMENT_SLOT ; ++ j )
if ( m_CastItem -> GetEnchantmentId ( EnchantmentSlot ( j )))
2009-04-27 18:42:35 -05:00
pNewItem -> SetEnchantment ( EnchantmentSlot ( j ), m_CastItem -> GetEnchantmentId ( EnchantmentSlot ( j )), m_CastItem -> GetEnchantmentDuration ( EnchantmentSlot ( j )), m_CastItem -> GetEnchantmentCharges ( EnchantmentSlot ( j )));
2009-10-17 15:51:44 -07:00
2019-06-03 20:40:34 +02:00
if ( * m_CastItem -> m_itemData -> Durability < * m_CastItem -> m_itemData -> MaxDurability )
2008-10-11 14:16:25 -05:00
{
2019-06-03 20:40:34 +02:00
double lossPercent = 1 - * m_CastItem -> m_itemData -> Durability / double ( m_CastItem -> m_itemData -> MaxDurability );
2010-11-14 23:46:34 +02:00
player -> DurabilityLoss ( pNewItem , lossPercent );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
if ( player -> IsInventoryPos ( pos ))
2008-10-11 14:16:25 -05:00
{
ItemPosCountVec dest ;
2011-04-29 16:48:15 +06:00
InventoryResult msg = player -> CanStoreItem ( m_CastItem -> GetBagSlot (), m_CastItem -> GetSlot (), dest , pNewItem , true );
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
if ( msg == EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2009-05-31 15:56:51 -05:00
player -> DestroyItem ( m_CastItem -> GetBagSlot (), m_CastItem -> GetSlot (), true );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// prevent crash at access and unexpected charges counting with item update queue corrupt
2011-06-23 13:28:52 +02:00
if ( m_CastItem == m_targets . GetItemTarget ())
2020-08-14 17:06:03 +02:00
m_targets . SetItemTarget ( nullptr );
2009-10-17 15:51:44 -07:00
2020-08-14 17:06:03 +02:00
m_CastItem = nullptr ;
2014-09-14 16:14:12 +02:00
m_castItemGUID . Clear ();
2014-05-05 20:05:33 +02:00
m_castItemEntry = 0 ;
2015-11-24 00:16:42 +01:00
m_castItemLevel = - 1 ;
2009-10-17 15:51:44 -07:00
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
player -> StoreItem ( dest , pNewItem , true );
2016-11-18 03:42:01 -03:00
player -> SendNewItem ( pNewItem , 1 , true , false );
player -> ItemAddedQuestCheck ( newitemid , 1 );
2008-10-11 14:16:25 -05:00
return ;
}
}
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
else if ( player -> IsBankPos ( pos ))
2008-10-11 14:16:25 -05:00
{
ItemPosCountVec dest ;
2016-04-06 18:40:41 +02:00
if ( player -> CanBankItem ( m_CastItem -> GetBagSlot (), m_CastItem -> GetSlot (), dest , pNewItem , true ) == EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2009-05-31 15:56:51 -05:00
player -> DestroyItem ( m_CastItem -> GetBagSlot (), m_CastItem -> GetSlot (), true );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// prevent crash at access and unexpected charges counting with item update queue corrupt
2011-06-23 13:28:52 +02:00
if ( m_CastItem == m_targets . GetItemTarget ())
2020-08-14 17:06:03 +02:00
m_targets . SetItemTarget ( nullptr );
2009-10-17 15:51:44 -07:00
2020-08-14 17:06:03 +02:00
m_CastItem = nullptr ;
2014-09-14 16:14:12 +02:00
m_castItemGUID . Clear ();
2014-05-05 20:05:33 +02:00
m_castItemEntry = 0 ;
2015-11-24 00:16:42 +01:00
m_castItemLevel = - 1 ;
2009-10-17 15:51:44 -07:00
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
player -> BankItem ( dest , pNewItem , true );
2008-10-11 14:16:25 -05:00
return ;
}
}
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
else if ( player -> IsEquipmentPos ( pos ))
2008-10-11 14:16:25 -05:00
{
uint16 dest ;
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
player -> DestroyItem ( m_CastItem -> GetBagSlot (), m_CastItem -> GetSlot (), true );
2016-04-06 18:40:41 +02:00
InventoryResult msg = player -> CanEquipItem ( m_CastItem -> GetSlot (), dest , pNewItem , true );
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
2012-08-20 15:54:55 +02:00
if ( msg == EQUIP_ERR_OK || msg == EQUIP_ERR_CLIENT_LOCKED_OUT )
2008-10-11 14:16:25 -05:00
{
2012-08-20 15:54:55 +02:00
if ( msg == EQUIP_ERR_CLIENT_LOCKED_OUT ) dest = EQUIPMENT_SLOT_MAINHAND ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// prevent crash at access and unexpected charges counting with item update queue corrupt
2011-06-23 13:28:52 +02:00
if ( m_CastItem == m_targets . GetItemTarget ())
2020-08-14 17:06:03 +02:00
m_targets . SetItemTarget ( nullptr );
2009-10-17 15:51:44 -07:00
2020-08-14 17:06:03 +02:00
m_CastItem = nullptr ;
2014-09-14 16:14:12 +02:00
m_castItemGUID . Clear ();
2014-05-05 20:05:33 +02:00
m_castItemEntry = 0 ;
2015-11-24 00:16:42 +01:00
m_castItemLevel = - 1 ;
2009-10-17 15:51:44 -07:00
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
player -> EquipItem ( dest , pNewItem , true );
2008-10-11 14:16:25 -05:00
player -> AutoUnequipOffhandIfNeed ();
2016-11-18 03:42:01 -03:00
player -> SendNewItem ( pNewItem , 1 , true , false );
player -> ItemAddedQuestCheck ( newitemid , 1 );
2008-10-11 14:16:25 -05:00
return ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// fail
delete pNewItem ;
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectProficiency ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
if ( m_caster -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2011-09-25 13:29:17 +02:00
Player * p_target = m_caster -> ToPlayer ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 subClassMask = m_spellInfo -> EquippedItemSubClassMask ;
2010-04-07 19:14:10 +02:00
if ( m_spellInfo -> EquippedItemClass == ITEM_CLASS_WEAPON && ! ( p_target -> GetWeaponProficiency () & subClassMask ))
2008-10-11 14:16:25 -05:00
{
p_target -> AddWeaponProficiency ( subClassMask );
2009-05-31 15:56:51 -05:00
p_target -> SendProficiency ( ITEM_CLASS_WEAPON , p_target -> GetWeaponProficiency ());
2008-10-11 14:16:25 -05:00
}
2010-04-07 19:14:10 +02:00
if ( m_spellInfo -> EquippedItemClass == ITEM_CLASS_ARMOR && ! ( p_target -> GetArmorProficiency () & subClassMask ))
2008-10-11 14:16:25 -05:00
{
p_target -> AddArmorProficiency ( subClassMask );
2009-05-31 15:56:51 -05:00
p_target -> SendProficiency ( ITEM_CLASS_ARMOR , p_target -> GetArmorProficiency ());
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectSummonType ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2014-12-19 23:52:29 +01:00
uint32 entry = effectInfo -> MiscValue ;
2009-11-01 17:53:07 -08:00
if ( ! entry )
2009-03-20 14:01:46 -06:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
SummonPropertiesEntry const * properties = sSummonPropertiesStore . LookupEntry ( effectInfo -> MiscValueB );
2009-11-01 17:53:07 -08:00
if ( ! properties )
2009-03-25 16:20:30 -06:00
{
2016-02-20 13:23:35 +01:00
TC_LOG_ERROR ( "spells" , "EffectSummonType: Unhandled summon type %u." , effectInfo -> MiscValueB );
2009-03-25 16:20:30 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
WorldObject * caster = m_caster ;
if ( m_originalCaster )
caster = m_originalCaster ;
2009-10-17 15:51:44 -07:00
2021-03-28 18:20:57 +02:00
ObjectGuid privateObjectOwner = [ & ]()
{
if ( ! ( properties -> Flags & ( SUMMON_PROP_FLAG_PERSONAL_SPAWN | SUMMON_PROP_FLAG_PERSONAL_GROUP_SPAWN )))
return ObjectGuid :: Empty ;
2018-02-10 16:43:01 -03:00
if ( caster -> IsPrivateObject ())
return caster -> GetPrivateObjectOwner ();
2021-03-28 18:20:57 +02:00
if ( properties -> Flags & SUMMON_PROP_FLAG_PERSONAL_GROUP_SPAWN )
2018-02-10 16:43:01 -03:00
if ( caster -> IsPlayer () && m_originalCaster -> ToPlayer () -> GetGroup ())
return caster -> ToPlayer () -> GetGroup () -> GetGUID ();
2021-03-28 18:20:57 +02:00
2018-02-10 16:43:01 -03:00
return caster -> GetGUID ();
2021-03-28 18:20:57 +02:00
}();
2018-04-08 20:35:33 +02:00
2018-02-10 16:43:01 -03:00
int32 duration = m_spellInfo -> CalcDuration ( caster );
2009-10-17 15:51:44 -07:00
2020-08-14 17:06:03 +02:00
TempSummon * summon = nullptr ;
2009-10-17 15:51:44 -07:00
2012-02-09 20:26:30 +01:00
// determine how many units should be summoned
uint32 numSummons ;
// some spells need to summon many units, for those spells number of summons is stored in effect value
2012-02-10 11:32:33 +01:00
// however so far noone found a generic check to find all of those (there's no related data in summonproperties.dbc
2012-02-09 20:26:30 +01:00
// and in spell attributes, possibly we need to add a table for those)
// so here's a list of MiscValueB values, which is currently most generic check
2016-01-31 19:25:51 +01:00
switch ( effectInfo -> MiscValueB )
2012-02-09 20:26:30 +01:00
{
case 64 :
case 61 :
case 1101 :
case 66 :
case 648 :
case 2301 :
case 1061 :
case 1261 :
case 629 :
case 181 :
case 715 :
2012-02-17 11:44:34 +01:00
case 1562 :
case 833 :
case 1161 :
2014-08-02 05:17:42 +02:00
case 713 :
2012-02-09 20:26:30 +01:00
numSummons = ( damage > 0 ) ? damage : 1 ;
break ;
default :
numSummons = 1 ;
break ;
}
2018-03-12 18:20:26 +01:00
switch ( properties -> Control )
2008-10-11 14:16:25 -05:00
{
2011-04-22 12:05:15 +02:00
case SUMMON_CATEGORY_WILD :
case SUMMON_CATEGORY_ALLY :
2011-04-24 10:22:58 +02:00
case SUMMON_CATEGORY_UNK :
2018-02-10 16:43:01 -03:00
{
2009-07-22 17:10:30 +02:00
if ( properties -> Flags & 512 )
2009-07-22 20:22:36 +02:00
{
2021-08-28 18:30:45 +02:00
SummonGuardian ( effectInfo , entry , properties , numSummons , privateObjectOwner );
2009-07-22 17:10:30 +02:00
break ;
2009-07-22 20:22:36 +02:00
}
2018-02-10 16:43:01 -03:00
2020-04-07 17:27:40 +02:00
switch ( SummonTitle ( properties -> Title ))
2009-03-18 21:16:24 -06:00
{
2020-04-07 17:27:40 +02:00
case SummonTitle :: Pet :
case SummonTitle :: Guardian :
case SummonTitle :: Runeblade :
case SummonTitle :: Minion :
2021-08-28 18:30:45 +02:00
SummonGuardian ( effectInfo , entry , properties , numSummons , privateObjectOwner );
2009-03-18 21:16:24 -06:00
break ;
2018-02-10 16:43:01 -03:00
// Summons a vehicle, but doesn't force anyone to enter it (see SUMMON_CATEGORY_VEHICLE)
2020-04-07 17:27:40 +02:00
case SummonTitle :: Vehicle :
case SummonTitle :: Mount :
2018-02-10 16:43:01 -03:00
{
if ( ! unitCaster )
return ;
summon = unitCaster -> GetMap () -> SummonCreature ( entry , * destTarget , properties , duration , unitCaster , m_spellInfo -> Id );
2009-03-18 21:16:24 -06:00
break ;
2018-02-10 16:43:01 -03:00
}
2020-04-07 17:27:40 +02:00
case SummonTitle :: Lightwell :
case SummonTitle :: Totem :
2009-04-27 18:12:45 -05:00
{
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
summon = unitCaster -> GetMap () -> SummonCreature ( entry , * destTarget , properties , duration , unitCaster , m_spellInfo -> Id , 0 , privateObjectOwner );
2013-06-11 19:54:27 -02:30
if ( ! summon || ! summon -> IsTotem ())
2011-05-19 22:27:18 +02:00
return ;
2011-05-19 01:24:53 +07:00
2011-05-19 22:27:18 +02:00
if ( damage ) // if not spell info, DB values used
{
summon -> SetMaxHealth ( damage );
summon -> SetHealth ( damage );
2009-04-27 18:12:45 -05:00
}
2009-03-25 16:20:30 -06:00
break ;
2009-04-27 18:12:45 -05:00
}
2020-04-07 17:27:40 +02:00
case SummonTitle :: Companion :
2009-04-27 18:12:45 -05:00
{
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
summon = unitCaster -> GetMap () -> SummonCreature ( entry , * destTarget , properties , duration , unitCaster , m_spellInfo -> Id , 0 , privateObjectOwner );
2009-11-01 17:53:07 -08:00
if ( ! summon || ! summon -> HasUnitTypeMask ( UNIT_MASK_MINION ))
2009-04-27 18:12:45 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-01-06 20:30:11 +01:00
summon -> SelectLevel (); // some summoned creaters have different from 1 DB data for level/hp
2019-06-03 20:40:34 +02:00
summon -> SetNpcFlags ( NPCFlags ( summon -> GetCreatureTemplate () -> npcflag & 0xFFFFFFFF ));
summon -> SetNpcFlags2 ( NPCFlags2 ( summon -> GetCreatureTemplate () -> npcflag >> 32 ));
2017-07-09 02:07:29 +02:00
summon -> SetImmuneToAll ( true );
2009-10-17 15:51:44 -07:00
2009-05-12 10:11:54 -05:00
summon -> AI () -> EnterEvadeMode ();
2009-03-25 16:20:30 -06:00
break ;
2009-04-27 18:12:45 -05:00
}
2009-03-25 16:20:30 -06:00
default :
2009-04-27 18:12:45 -05:00
{
2014-12-19 23:52:29 +01:00
float radius = effectInfo -> CalcRadius ();
2009-10-17 15:51:44 -07:00
2011-04-22 12:05:15 +02:00
TempSummonType summonType = ( duration == 0 ) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN ;
2012-02-09 20:26:30 +01:00
for ( uint32 count = 0 ; count < numSummons ; ++ count )
2009-04-27 18:12:45 -05:00
{
2012-05-30 08:01:02 +02:00
Position pos ;
if ( count == 0 )
pos = * destTarget ;
else
// randomize position for multiple summons
2018-02-10 16:43:01 -03:00
pos = caster -> GetRandomPoint ( * destTarget , radius );
2009-10-17 15:51:44 -07:00
2018-04-03 08:28:41 -03:00
summon = caster -> SummonCreature ( entry , pos , summonType , duration , 0 , m_spellInfo -> Id , privateObjectOwner );
2009-07-22 22:52:05 +02:00
if ( ! summon )
continue ;
2011-04-22 12:05:15 +02:00
2018-03-12 18:20:26 +01:00
if ( properties -> Control == SUMMON_CATEGORY_ALLY )
2009-08-14 22:25:12 -05:00
{
2018-02-10 16:43:01 -03:00
summon -> SetOwnerGUID ( caster -> GetGUID ());
summon -> SetFaction ( caster -> GetFaction ());
2009-08-14 22:25:12 -05:00
}
2011-04-22 12:05:15 +02:00
2021-08-28 18:30:45 +02:00
ExecuteLogEffectSummonObject ( SpellEffectName ( effectInfo -> Effect ), summon );
2009-04-27 18:12:45 -05:00
}
2010-08-27 17:49:32 +02:00
return ;
2009-04-27 18:12:45 -05:00
}
2018-02-10 16:43:01 -03:00
}
2008-10-11 14:16:25 -05:00
break ;
2018-02-10 16:43:01 -03:00
}
2009-03-25 16:20:30 -06:00
case SUMMON_CATEGORY_PET :
2021-08-28 18:30:45 +02:00
SummonGuardian ( effectInfo , entry , properties , numSummons , privateObjectOwner );
2009-03-25 16:20:30 -06:00
break ;
2009-05-25 22:52:08 -05:00
case SUMMON_CATEGORY_PUPPET :
2018-02-10 16:43:01 -03:00
{
if ( ! unitCaster )
return ;
summon = unitCaster -> GetMap () -> SummonCreature ( entry , * destTarget , properties , duration , unitCaster , m_spellInfo -> Id , 0 , privateObjectOwner );
2009-03-25 16:20:30 -06:00
break ;
2018-02-10 16:43:01 -03:00
}
2011-04-24 10:22:58 +02:00
case SUMMON_CATEGORY_VEHICLE :
2018-02-10 16:43:01 -03:00
{
if ( ! unitCaster )
return ;
2011-04-22 12:05:15 +02:00
// Summoning spells (usually triggered by npc_spellclick) that spawn a vehicle and that cause the clicker
// to cast a ride vehicle spell on the summoned unit.
2018-02-10 16:43:01 -03:00
summon = unitCaster -> GetMap () -> SummonCreature ( entry , * destTarget , properties , duration , unitCaster , m_spellInfo -> Id );
2009-11-01 17:53:07 -08:00
if ( ! summon || ! summon -> IsVehicle ())
2009-04-27 18:12:45 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-04-22 12:05:15 +02:00
// The spell that this effect will trigger. It has SPELL_AURA_CONTROL_VEHICLE
2012-08-02 18:38:55 +02:00
uint32 spellId = VEHICLE_SPELL_RIDE_HARDCODED ;
2017-02-05 22:24:23 +01:00
int32 basePoints = effectInfo -> CalcValue ();
if ( basePoints > MAX_VEHICLE_SEATS )
{
2020-06-12 01:29:18 +02:00
SpellInfo const * spellInfo = sSpellMgr -> GetSpellInfo ( basePoints , GetCastDifficulty ());
if ( spellInfo && spellInfo -> HasAura ( SPELL_AURA_CONTROL_VEHICLE ))
2017-02-05 22:24:23 +01:00
spellId = spellInfo -> Id ;
}
2010-05-13 17:57:59 +02:00
2017-12-30 20:28:41 +01:00
CastSpellExtraArgs args ( TRIGGERED_FULL_MASK );
2021-10-03 16:36:39 +02:00
args . SetOriginalCastId ( m_castId );
2017-12-30 20:28:41 +01:00
2017-02-05 22:24:23 +01:00
// if we have small value, it indicates seat position
if ( basePoints > 0 && basePoints < MAX_VEHICLE_SEATS )
2018-01-13 20:38:32 -03:00
args . AddSpellMod ( SPELLVALUE_BASE_POINT0 , basePoints );
2017-12-30 20:28:41 +01:00
2018-02-10 16:43:01 -03:00
unitCaster -> CastSpell ( summon , spellId , args );
2011-02-26 23:00:09 +01:00
uint32 faction = properties -> Faction ;
if ( ! faction )
2018-02-10 16:43:01 -03:00
faction = unitCaster -> GetFaction ();
2011-02-26 23:00:09 +01:00
2017-04-28 02:24:04 -03:00
summon -> SetFaction ( faction );
2009-03-25 16:20:30 -06:00
break ;
2018-02-10 16:43:01 -03:00
}
2009-04-27 18:12:45 -05:00
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( summon )
2010-06-07 01:59:04 +02:00
{
2018-02-10 16:43:01 -03:00
summon -> SetCreatorGUID ( caster -> GetGUID ());
2021-08-28 18:30:45 +02:00
ExecuteLogEffectSummonObject ( SpellEffectName ( effectInfo -> Effect ), summon );
2010-06-07 01:59:04 +02:00
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectLearnSpell ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2009-11-01 17:53:07 -08:00
if ( ! unitTarget )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( unitTarget -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
{
2011-09-24 02:01:18 +02:00
if ( unitTarget -> ToPet ())
2021-08-28 19:51:29 +02:00
EffectLearnPetSpell ();
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-09-24 02:01:18 +02:00
Player * player = unitTarget -> ToPlayer ();
2009-10-17 15:51:44 -07:00
2021-10-16 13:22:42 +02:00
if ( m_CastItem && ! effectInfo -> TriggerSpell )
{
for ( ItemEffectEntry const * itemEffect : m_CastItem -> GetEffects ())
{
if ( itemEffect -> TriggerType != ITEM_SPELLTRIGGER_LEARN_SPELL_ID )
continue ;
2009-10-17 15:51:44 -07:00
2021-10-16 13:22:42 +02:00
player -> LearnSpell ( itemEffect -> SpellID , false );
2021-10-17 00:11:48 +02:00
if ( BattlePetSpeciesEntry const * speciesEntry = sSpellMgr -> GetBattlePetSpecies ( uint32 ( itemEffect -> SpellID )))
player -> GetSession () -> GetBattlePetMgr () -> AddPet ( speciesEntry -> ID , BattlePetMgr :: SelectPetDisplay ( speciesEntry ), BattlePetMgr :: RollPetBreed ( speciesEntry -> ID ), BattlePetMgr :: GetDefaultPetQuality ( speciesEntry -> ID ));
2021-10-16 13:22:42 +02:00
}
}
if ( effectInfo -> TriggerSpell )
{
player -> LearnSpell ( effectInfo -> TriggerSpell , false );
TC_LOG_DEBUG ( "spells" , "Spell: %s has learned spell %u from %s" , player -> GetGUID (). ToString (). c_str (), effectInfo -> TriggerSpell , m_caster -> GetGUID (). ToString (). c_str ());
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectDispel ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-07 19:14:10 +02:00
if ( ! unitTarget )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Create dispel mask by dispel type
2014-12-19 23:52:29 +01:00
uint32 dispel_type = effectInfo -> MiscValue ;
2011-07-26 23:09:28 +02:00
uint32 dispelMask = SpellInfo :: GetDispelMask ( DispelType ( dispel_type ));
2010-08-06 21:32:42 -07:00
2016-12-11 15:04:25 -03:00
DispelChargesList dispelList ;
unitTarget -> GetDispellableAuraList ( m_caster , dispelMask , dispelList , targetMissInfo == SPELL_MISS_REFLECT );
if ( dispelList . empty ())
2009-09-04 10:01:52 -05:00
return ;
2009-10-17 15:51:44 -07:00
2016-12-11 15:04:25 -03:00
size_t remaining = dispelList . size ();
2008-10-11 14:16:25 -05:00
// Ok if exist some buffs for dispel try dispel it
2016-12-11 15:04:25 -03:00
uint32 failCount = 0 ;
DispelChargesList successList ;
successList . reserve ( damage );
2016-03-18 23:53:29 +01:00
WorldPackets :: Spells :: DispelFailed dispelFailed ;
dispelFailed . CasterGUID = m_caster -> GetGUID ();
dispelFailed . VictimGUID = unitTarget -> GetGUID ();
dispelFailed . SpellID = m_spellInfo -> Id ;
2009-09-04 10:01:52 -05:00
// dispel N = damage buffs (or while exist buffs for dispel)
2016-12-11 15:04:25 -03:00
for ( int32 count = 0 ; count < damage && remaining > 0 ;)
2008-10-11 14:16:25 -05:00
{
2009-09-04 10:01:52 -05:00
// Random select buff for dispel
2016-12-11 15:04:25 -03:00
auto itr = dispelList . begin ();
std :: advance ( itr , urand ( 0 , remaining - 1 ));
2009-10-17 15:51:44 -07:00
2016-12-11 15:04:25 -03:00
if ( itr -> RollDispel ())
2008-10-11 14:16:25 -05:00
{
2016-12-11 15:04:25 -03:00
auto successItr = std :: find_if ( successList . begin (), successList . end (), [ & itr ]( DispelableAura & dispelAura ) -> bool
2008-10-11 14:16:25 -05:00
{
2016-12-11 15:04:25 -03:00
if ( dispelAura . GetAura () -> GetId () == itr -> GetAura () -> GetId ())
return true ;
return false ;
});
if ( successItr == successList . end ())
successList . emplace_back ( itr -> GetAura (), 0 , 1 );
2010-05-25 10:36:33 +02:00
else
2016-12-11 15:04:25 -03:00
successItr -> IncrementCharges ();
2016-03-18 23:53:29 +01:00
2016-12-11 15:04:25 -03:00
if ( ! itr -> DecrementCharge ())
{
-- remaining ;
std :: swap ( * itr , dispelList [ remaining ]);
}
2008-10-11 14:16:25 -05:00
}
2016-12-11 15:04:25 -03:00
else
{
++ failCount ;
dispelFailed . FailedSpells . push_back ( int32 ( itr -> GetAura () -> GetId ()));
}
++ count ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2016-03-18 23:53:29 +01:00
if ( ! dispelFailed . FailedSpells . empty ())
m_caster -> SendMessageToSet ( dispelFailed . Write (), true );
2009-10-17 15:51:44 -07:00
2016-12-11 15:04:25 -03:00
if ( successList . empty ())
2009-09-04 10:01:52 -05:00
return ;
2009-10-17 15:51:44 -07:00
2016-02-29 01:54:18 +00:00
WorldPackets :: CombatLog :: SpellDispellLog spellDispellLog ;
spellDispellLog . IsBreak = false ; // TODO: use me
spellDispellLog . IsSteal = false ;
spellDispellLog . TargetGUID = unitTarget -> GetGUID ();
spellDispellLog . CasterGUID = m_caster -> GetGUID ();
spellDispellLog . DispelledBySpellID = m_spellInfo -> Id ;
2016-12-11 15:04:25 -03:00
for ( DispelableAura const & dispelableAura : successList )
2016-02-29 01:54:18 +00:00
{
WorldPackets :: CombatLog :: SpellDispellData dispellData ;
2016-12-11 15:04:25 -03:00
dispellData . SpellID = dispelableAura . GetAura () -> GetId ();
2016-02-29 01:54:18 +00:00
dispellData . Harmful = false ; // TODO: use me
dispellData . Rolled = boost :: none ; // TODO: use me
dispellData . Needed = boost :: none ; // TODO: use me
2016-12-11 15:04:25 -03:00
unitTarget -> RemoveAurasDueToSpellByDispel ( dispelableAura . GetAura () -> GetId (), m_spellInfo -> Id , dispelableAura . GetAura () -> GetCasterGUID (), m_caster , dispelableAura . GetDispelCharges ());
2016-02-29 01:54:18 +00:00
spellDispellLog . DispellData . emplace_back ( dispellData );
}
m_caster -> SendMessageToSet ( spellDispellLog . Write (), true );
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
CallScriptSuccessfulDispel ( SpellEffIndex ( effectInfo -> EffectIndex ));
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectDualWield ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2008-10-29 20:00:21 -05:00
unitTarget -> SetCanDualWield ( true );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectDistract ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2008-10-11 14:16:25 -05:00
// Check for possible target
2017-07-01 20:18:02 +02:00
if ( ! unitTarget || unitTarget -> IsEngaged ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// target must be OK to do this
2012-02-03 19:12:41 +02:00
if ( unitTarget -> HasUnitState ( UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2018-06-03 10:06:57 -07:00
unitTarget -> GetMotionMaster () -> MoveDistract ( damage * IN_MILLISECONDS , unitTarget -> GetAbsoluteAngle ( destTarget ));
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectPickPocket ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2009-11-01 17:53:07 -08:00
if ( m_caster -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// victim must be creature and attackable
2009-11-01 17:53:07 -08:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_UNIT || m_caster -> IsFriendlyTo ( unitTarget ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// victim have to be alive and humanoid or undead
2013-06-11 19:54:27 -02:30
if ( unitTarget -> IsAlive () && ( unitTarget -> GetCreatureTypeMask () & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD ) != 0 )
2011-04-29 20:47:02 +02:00
m_caster -> ToPlayer () -> SendLoot ( unitTarget -> GetGUID (), LOOT_PICKPOCKETING );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectAddFarsight ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2018-02-10 16:43:01 -03:00
Player * player = m_caster -> ToPlayer ();
if ( ! player )
2008-11-14 20:40:35 -06:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
float radius = effectInfo -> CalcRadius ();
2017-01-29 00:00:43 +01:00
int32 duration = m_spellInfo -> CalcDuration ( m_caster );
2010-01-24 23:47:17 +01:00
// Caster not in world, might be spell triggered from aura removal
2018-02-10 16:43:01 -03:00
if ( ! player -> IsInWorld ())
2010-01-24 23:47:17 +01:00
return ;
2011-04-19 15:14:50 +02:00
2011-12-20 17:05:08 -05:00
DynamicObject * dynObj = new DynamicObject ( true );
2018-02-10 16:43:01 -03:00
if ( ! dynObj -> CreateDynamicObject ( player -> GetMap () -> GenerateLowGuid < HighGuid :: DynamicObject > (), player , m_spellInfo , * destTarget , radius , DYNAMIC_OBJECT_FARSIGHT_FOCUS , m_SpellVisual ))
2008-10-11 14:16:25 -05:00
{
delete dynObj ;
return ;
}
2011-04-19 15:14:50 +02:00
2010-01-10 01:23:15 +01:00
dynObj -> SetDuration ( duration );
2011-02-04 00:27:43 +01:00
dynObj -> SetCasterViewpoint ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectUntrainTalents ()
2010-12-22 20:14:30 +02:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-12-22 20:14:30 +02:00
if ( ! unitTarget || m_caster -> GetTypeId () == TYPEID_PLAYER )
return ;
2015-01-17 03:55:29 +01:00
unitTarget -> ToPlayer () -> SendRespecWipeConfirm ( m_caster -> GetGUID (), sWorld -> getBoolConfig ( CONFIG_NO_RESET_TALENT_COST ) ? 0 : unitTarget -> ToPlayer () -> GetNextResetTalentsCost ());
2010-12-22 20:14:30 +02:00
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectTeleUnitsFaceCaster ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2009-11-01 17:53:07 -08:00
if ( ! unitTarget )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2013-06-11 19:54:27 -02:30
if ( unitTarget -> IsInFlight ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
float dis = effectInfo -> CalcRadius ( m_caster );
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
float fx , fy , fz ;
2017-03-23 00:43:04 +01:00
m_caster -> GetClosePoint ( fx , fy , fz , unitTarget -> GetCombatReach (), dis );
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
unitTarget -> NearTeleportTo ( fx , fy , fz , - m_caster -> GetOrientation (), unitTarget == m_caster );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectLearnSkill ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2009-11-01 17:53:07 -08:00
if ( unitTarget -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2018-12-02 17:39:41 +01:00
if ( damage < 1 )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
uint32 skillid = effectInfo -> MiscValue ;
2016-01-24 15:56:10 +01:00
SkillRaceClassInfoEntry const * rcEntry = sDB2Manager . GetSkillRaceClassInfo ( skillid , unitTarget -> getRace (), unitTarget -> getClass ());
2014-06-25 20:34:10 +02:00
if ( ! rcEntry )
return ;
2015-07-05 01:18:57 +02:00
SkillTiersEntry const * tier = sObjectMgr -> GetSkillTier ( rcEntry -> SkillTierID );
2014-06-25 20:34:10 +02:00
if ( ! tier )
return ;
2010-03-07 15:20:19 +01:00
uint16 skillval = unitTarget -> ToPlayer () -> GetPureSkillValue ( skillid );
2018-12-02 17:39:41 +01:00
unitTarget -> ToPlayer () -> SetSkill ( skillid , damage , std :: max < uint16 > ( skillval , 1 ), tier -> Value [ damage - 1 ]);
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectPlayMovie ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2009-11-01 17:53:07 -08:00
if ( unitTarget -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
uint32 movieId = effectInfo -> MiscValue ;
if ( ! sMovieStore . LookupEntry ( movieId ))
return ;
unitTarget -> ToPlayer () -> SendMovieStart ( movieId );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectTradeSkill ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
if ( m_caster -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2011-07-26 23:09:28 +02:00
// uint32 skillid = m_spellInfo->Effects[i].MiscValue;
2010-03-07 15:20:19 +01:00
// uint16 skillmax = unitTarget->ToPlayer()->(skillid);
2011-09-25 13:29:17 +02:00
// m_caster->ToPlayer()->SetSkill(skillid, skillval?skillval:1, skillmax+75);
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectEnchantItemPerm ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2008-10-11 14:16:25 -05:00
if ( ! itemTarget )
return ;
2009-10-17 15:51:44 -07:00
2013-07-20 21:52:05 +02:00
Player * player = m_caster -> ToPlayer ();
if ( ! player )
return ;
2009-10-17 15:51:44 -07:00
2009-05-01 15:40:49 +02:00
// Handle vellums
2012-08-15 16:30:49 +01:00
if ( itemTarget -> IsVellum ())
2009-05-01 15:40:49 +02:00
{
// destroy one vellum from stack
2009-11-01 17:53:07 -08:00
uint32 count = 1 ;
2013-07-20 21:52:05 +02:00
player -> DestroyItemCount ( itemTarget , count , true );
unitTarget = player ;
2009-05-01 15:40:49 +02:00
// and add a scroll
2019-11-26 23:20:11 +01:00
damage = 1 ;
2021-08-28 19:51:29 +02:00
DoCreateItem ( effectInfo -> ItemType , m_spellInfo -> HasAttribute ( SPELL_ATTR0_TRADESPELL ) ? ItemContext :: Trade_Skill : ItemContext :: NONE );
2020-08-14 17:06:03 +02:00
itemTarget = nullptr ;
m_targets . SetItemTarget ( nullptr );
2009-05-01 15:40:49 +02:00
}
else
{
2009-05-01 17:21:16 +02:00
// do not increase skill if vellum used
2016-09-09 10:22:57 +02:00
if ( ! ( m_CastItem && m_CastItem -> GetTemplate () -> GetFlags () & ITEM_FLAG_NO_REAGENT_COST ))
2013-07-20 21:52:05 +02:00
player -> UpdateCraftSkill ( m_spellInfo -> Id );
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
uint32 enchant_id = effectInfo -> MiscValue ;
2009-05-01 15:40:49 +02:00
if ( ! enchant_id )
return ;
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
SpellItemEnchantmentEntry const * pEnchant = sSpellItemEnchantmentStore . LookupEntry ( enchant_id );
2010-04-07 19:14:10 +02:00
if ( ! pEnchant )
2009-05-01 15:40:49 +02:00
return ;
2010-10-07 14:00:52 +02:00
2009-05-01 15:40:49 +02:00
// item can be in trade slot and have owner diff. from caster
Player * item_owner = itemTarget -> GetOwner ();
2009-11-01 17:53:07 -08:00
if ( ! item_owner )
2009-05-01 15:40:49 +02:00
return ;
2009-10-17 15:51:44 -07:00
2013-09-27 12:46:01 +02:00
if ( item_owner != player && player -> GetSession () -> HasPermission ( rbac :: RBAC_PERM_LOG_GM_TRADE ))
2009-05-01 15:40:49 +02:00
{
2013-07-20 21:52:05 +02:00
sLog -> outCommand ( player -> GetSession () -> GetAccountId (), "GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)" ,
player -> GetName (). c_str (), player -> GetSession () -> GetAccountId (),
2014-12-21 13:35:43 +01:00
itemTarget -> GetTemplate () -> GetDefaultLocaleName (), itemTarget -> GetEntry (),
2012-10-24 13:29:34 +02:00
item_owner -> GetName (). c_str (), item_owner -> GetSession () -> GetAccountId ());
2009-05-01 15:40:49 +02:00
}
2009-10-17 15:51:44 -07:00
2009-05-01 15:40:49 +02:00
// remove old enchanting before applying new if equipped
2011-04-29 20:47:02 +02:00
item_owner -> ApplyEnchantment ( itemTarget , PERM_ENCHANTMENT_SLOT , false );
2009-10-17 15:51:44 -07:00
2013-05-25 11:09:21 +02:00
itemTarget -> SetEnchantment ( PERM_ENCHANTMENT_SLOT , enchant_id , 0 , 0 , m_caster -> GetGUID ());
2009-10-17 15:51:44 -07:00
2009-05-01 15:40:49 +02:00
// add new enchanting if equipped
2011-04-29 20:47:02 +02:00
item_owner -> ApplyEnchantment ( itemTarget , PERM_ENCHANTMENT_SLOT , true );
2010-09-21 21:55:16 +02:00
2012-06-23 12:31:46 +02:00
item_owner -> RemoveTradeableItem ( itemTarget );
2011-10-18 10:44:45 +02:00
itemTarget -> ClearSoulboundTradeable ( item_owner );
2009-05-01 15:40:49 +02:00
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectEnchantItemPrismatic ()
2009-02-03 19:12:17 -06:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2009-02-03 19:12:17 -06:00
if ( ! itemTarget )
return ;
2009-10-17 15:51:44 -07:00
2013-07-20 21:52:05 +02:00
Player * player = m_caster -> ToPlayer ();
if ( ! player )
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
uint32 enchantId = effectInfo -> MiscValue ;
2013-07-20 21:52:05 +02:00
if ( ! enchantId )
2009-02-03 19:12:17 -06:00
return ;
2009-10-17 15:51:44 -07:00
2013-07-20 21:52:05 +02:00
SpellItemEnchantmentEntry const * enchant = sSpellItemEnchantmentStore . LookupEntry ( enchantId );
if ( ! enchant )
2009-02-03 19:12:17 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-02-03 19:12:17 -06:00
// support only enchantings with add socket in this slot
{
bool add_socket = false ;
2010-09-28 08:21:51 +03:00
for ( uint8 i = 0 ; i < MAX_ITEM_ENCHANTMENT_EFFECTS ; ++ i )
2009-02-03 19:12:17 -06:00
{
2014-11-10 02:51:55 +02:00
if ( enchant -> Effect [ i ] == ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET )
2009-02-03 19:12:17 -06:00
{
add_socket = true ;
break ;
}
}
2010-04-07 19:14:10 +02:00
if ( ! add_socket )
2009-02-03 19:12:17 -06:00
{
2016-02-20 13:23:35 +01:00
TC_LOG_ERROR ( "spells" , "Spell::EffectEnchantItemPrismatic: attempt to apply the enchant spell %u with SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC (%u), but without ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET (%u), not supported yet." ,
2011-04-29 20:47:02 +02:00
m_spellInfo -> Id , SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC , ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET );
2009-02-03 19:12:17 -06:00
return ;
}
}
2009-10-17 15:51:44 -07:00
2009-02-03 19:12:17 -06:00
// item can be in trade slot and have owner diff. from caster
Player * item_owner = itemTarget -> GetOwner ();
2009-11-01 17:53:07 -08:00
if ( ! item_owner )
2009-02-03 19:12:17 -06:00
return ;
2009-10-17 15:51:44 -07:00
2013-09-27 12:46:01 +02:00
if ( item_owner != player && player -> GetSession () -> HasPermission ( rbac :: RBAC_PERM_LOG_GM_TRADE ))
2009-02-03 19:12:17 -06:00
{
2013-07-20 21:52:05 +02:00
sLog -> outCommand ( player -> GetSession () -> GetAccountId (), "GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)" ,
player -> GetName (). c_str (), player -> GetSession () -> GetAccountId (),
2014-12-21 13:35:43 +01:00
itemTarget -> GetTemplate () -> GetDefaultLocaleName (), itemTarget -> GetEntry (),
2012-10-24 13:29:34 +02:00
item_owner -> GetName (). c_str (), item_owner -> GetSession () -> GetAccountId ());
2009-02-03 19:12:17 -06:00
}
2009-10-17 15:51:44 -07:00
2009-02-03 19:12:17 -06:00
// remove old enchanting before applying new if equipped
2011-04-29 20:47:02 +02:00
item_owner -> ApplyEnchantment ( itemTarget , PRISMATIC_ENCHANTMENT_SLOT , false );
2009-10-17 15:51:44 -07:00
2013-07-20 21:52:05 +02:00
itemTarget -> SetEnchantment ( PRISMATIC_ENCHANTMENT_SLOT , enchantId , 0 , 0 , m_caster -> GetGUID ());
2009-10-17 15:51:44 -07:00
2009-02-03 19:12:17 -06:00
// add new enchanting if equipped
2011-04-29 20:47:02 +02:00
item_owner -> ApplyEnchantment ( itemTarget , PRISMATIC_ENCHANTMENT_SLOT , true );
2010-09-21 21:55:16 +02:00
2012-06-23 12:31:46 +02:00
item_owner -> RemoveTradeableItem ( itemTarget );
2011-10-18 10:44:45 +02:00
itemTarget -> ClearSoulboundTradeable ( item_owner );
2009-02-03 19:12:17 -06:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectEnchantItemTmp ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2021-02-28 19:10:27 +02:00
if ( ! itemTarget )
return ;
2013-07-20 21:52:05 +02:00
Player * player = m_caster -> ToPlayer ();
if ( ! player )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
uint32 enchant_id = effectInfo -> MiscValue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! enchant_id )
{
2021-08-28 19:51:29 +02:00
TC_LOG_ERROR ( "spells" , "Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) has enchanting id 0." , m_spellInfo -> Id , effectInfo -> EffectIndex );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
SpellItemEnchantmentEntry const * pEnchant = sSpellItemEnchantmentStore . LookupEntry ( enchant_id );
2009-11-01 17:53:07 -08:00
if ( ! pEnchant )
2008-10-11 14:16:25 -05:00
{
2021-08-28 19:51:29 +02:00
TC_LOG_ERROR ( "spells" , "Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) has a non-existing enchanting id %u " , m_spellInfo -> Id , effectInfo -> EffectIndex , enchant_id );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// select enchantment duration
uint32 duration ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// rogue family enchantments exception by duration
2009-11-01 17:53:07 -08:00
if ( m_spellInfo -> Id == 38615 )
2008-10-11 14:16:25 -05:00
duration = 1800 ; // 30 mins
// other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
2009-11-01 17:53:07 -08:00
else if ( m_spellInfo -> SpellFamilyName == SPELLFAMILY_ROGUE )
2008-10-11 14:16:25 -05:00
duration = 3600 ; // 1 hour
// shaman family enchantments
2009-11-01 17:53:07 -08:00
else if ( m_spellInfo -> SpellFamilyName == SPELLFAMILY_SHAMAN )
2015-07-07 12:13:14 +02:00
duration = 3600 ; // 30 mins
2008-10-11 14:16:25 -05:00
// other cases with this SpellVisual already selected
2016-06-29 19:49:23 +02:00
else if ( m_spellInfo -> GetSpellVisual () == 215 )
2008-10-11 14:16:25 -05:00
duration = 1800 ; // 30 mins
2010-05-24 13:56:21 +02:00
// some fishing pole bonuses except Glow Worm which lasts full hour
2016-06-29 19:49:23 +02:00
else if ( m_spellInfo -> GetSpellVisual () == 563 && m_spellInfo -> Id != 64401 )
2008-10-11 14:16:25 -05:00
duration = 600 ; // 10 mins
2009-11-01 17:53:07 -08:00
else if ( m_spellInfo -> Id == 29702 )
2008-10-11 14:16:25 -05:00
duration = 300 ; // 5 mins
2009-11-01 17:53:07 -08:00
else if ( m_spellInfo -> Id == 37360 )
2008-10-11 14:16:25 -05:00
duration = 300 ; // 5 mins
// default case
else
duration = 3600 ; // 1 hour
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// item can be in trade slot and have owner diff. from caster
Player * item_owner = itemTarget -> GetOwner ();
2009-11-01 17:53:07 -08:00
if ( ! item_owner )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2013-09-27 12:46:01 +02:00
if ( item_owner != player && player -> GetSession () -> HasPermission ( rbac :: RBAC_PERM_LOG_GM_TRADE ))
2008-11-25 16:36:50 -06:00
{
2013-07-20 21:52:05 +02:00
sLog -> outCommand ( player -> GetSession () -> GetAccountId (), "GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)" ,
player -> GetName (). c_str (), player -> GetSession () -> GetAccountId (),
2014-12-21 13:35:43 +01:00
itemTarget -> GetTemplate () -> GetDefaultLocaleName (), itemTarget -> GetEntry (),
2012-10-24 13:29:34 +02:00
item_owner -> GetName (). c_str (), item_owner -> GetSession () -> GetAccountId ());
2008-11-25 16:36:50 -06:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// remove old enchanting before applying new if equipped
2011-04-29 20:47:02 +02:00
item_owner -> ApplyEnchantment ( itemTarget , TEMP_ENCHANTMENT_SLOT , false );
2009-10-17 15:51:44 -07:00
2013-05-25 11:09:21 +02:00
itemTarget -> SetEnchantment ( TEMP_ENCHANTMENT_SLOT , enchant_id , duration * 1000 , 0 , m_caster -> GetGUID ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// add new enchanting if equipped
2009-05-31 15:56:51 -05:00
item_owner -> ApplyEnchantment ( itemTarget , TEMP_ENCHANTMENT_SLOT , true );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectTameCreature ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster || ! unitCaster -> GetPetGUID (). IsEmpty ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( ! unitTarget )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( unitTarget -> GetTypeId () != TYPEID_UNIT )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-03-07 18:30:53 +01:00
Creature * creatureTarget = unitTarget -> ToCreature ();
2009-10-17 15:51:44 -07:00
2013-06-11 18:39:51 -02:30
if ( creatureTarget -> IsPet ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
if ( unitCaster -> getClass () != CLASS_HUNTER )
2008-11-04 09:23:06 -06:00
return ;
2009-10-17 15:51:44 -07:00
2008-11-04 09:23:06 -06:00
// cast finish successfully
//SendChannelUpdate(0);
finish ();
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
Pet * pet = unitCaster -> CreateTamedPetFrom ( creatureTarget , m_spellInfo -> Id );
2009-11-01 17:53:07 -08:00
if ( ! pet ) // in very specific state like near world end/etc.
2009-06-02 17:40:22 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-06-18 17:05:01 -05:00
// "kill" original creature
2011-01-02 21:33:37 +01:00
creatureTarget -> DespawnOrUnsummon ();
2009-10-17 15:51:44 -07:00
2017-07-29 21:40:28 +02:00
uint8 level = ( creatureTarget -> GetLevelForTarget ( m_caster ) < ( m_caster -> GetLevelForTarget ( creatureTarget ) - 5 )) ? ( m_caster -> GetLevelForTarget ( creatureTarget ) - 5 ) : creatureTarget -> GetLevelForTarget ( m_caster );
2009-10-17 15:51:44 -07:00
2008-11-04 09:23:06 -06:00
// prepare visual effect for levelup
2019-06-03 20:40:34 +02:00
pet -> SetLevel ( level - 1 );
2009-10-17 15:51:44 -07:00
2008-11-04 09:23:06 -06:00
// add to world
2011-10-10 17:39:34 -04:00
pet -> GetMap () -> AddToMap ( pet -> ToCreature ());
2009-10-17 15:51:44 -07:00
2008-11-04 09:23:06 -06:00
// visual effect for levelup
2019-06-03 20:40:34 +02:00
pet -> SetLevel ( level );
2009-10-17 15:51:44 -07:00
2008-11-04 09:23:06 -06:00
// caster have pet now
2018-02-10 16:43:01 -03:00
unitCaster -> SetMinion ( pet , true );
2009-10-17 16:20:24 -07:00
2018-02-10 16:43:01 -03:00
if ( unitCaster -> GetTypeId () == TYPEID_PLAYER )
2008-11-04 09:23:06 -06:00
{
pet -> SavePetToDB ( PET_SAVE_AS_CURRENT );
2018-02-10 16:43:01 -03:00
unitCaster -> ToPlayer () -> PetSpellInitialize ();
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectSummonPet ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2020-08-14 17:06:03 +02:00
Player * owner = nullptr ;
2018-02-10 16:43:01 -03:00
if ( unitCaster )
2009-02-24 20:52:55 -06:00
{
2018-02-10 16:43:01 -03:00
owner = unitCaster -> ToPlayer ();
if ( ! owner && unitCaster -> IsTotem ())
owner = unitCaster -> GetCharmerOrOwnerPlayerOrPlayerItself ();
2009-02-24 20:52:55 -06:00
}
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
uint32 petentry = effectInfo -> MiscValue ;
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( ! owner )
2008-12-30 22:01:45 -06:00
{
2011-09-15 14:08:17 +02:00
SummonPropertiesEntry const * properties = sSummonPropertiesStore . LookupEntry ( 67 );
2010-04-07 19:14:10 +02:00
if ( properties )
2021-08-28 18:30:45 +02:00
SummonGuardian ( effectInfo , petentry , properties , 1 , ObjectGuid :: Empty );
2008-12-30 22:01:45 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-06-20 04:04:20 +07:00
Pet * OldSummon = owner -> GetPet ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// if pet requested type already exist
2009-11-01 17:53:07 -08:00
if ( OldSummon )
2008-10-11 14:16:25 -05:00
{
2009-11-01 17:53:07 -08:00
if ( petentry == 0 || OldSummon -> GetEntry () == petentry )
2008-10-11 14:16:25 -05:00
{
// pet in corpse state can't be summoned
2009-11-01 17:53:07 -08:00
if ( OldSummon -> isDead ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-07-30 20:04:28 +02:00
ASSERT ( OldSummon -> GetMap () == owner -> GetMap ());
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
//OldSummon->GetMap()->Remove(OldSummon->ToCreature(), false);
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
float px , py , pz ;
2017-03-23 00:43:04 +01:00
owner -> GetClosePoint ( px , py , pz , OldSummon -> GetCombatReach ());
2009-10-17 15:51:44 -07:00
2009-08-26 21:17:47 -05:00
OldSummon -> NearTeleportTo ( px , py , pz , OldSummon -> GetOrientation ());
//OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
//OldSummon->SetMap(owner->GetMap());
2010-03-07 18:30:53 +01:00
//owner->GetMap()->Add(OldSummon->ToCreature());
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
if ( owner -> GetTypeId () == TYPEID_PLAYER && OldSummon -> isControlled ())
2010-03-07 15:20:19 +01:00
owner -> ToPlayer () -> PetSpellInitialize ();
2009-11-01 17:53:07 -08:00
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( owner -> GetTypeId () == TYPEID_PLAYER )
2011-04-29 20:47:02 +02:00
owner -> ToPlayer () -> RemovePet ( OldSummon , ( OldSummon -> getPetType () == HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT ), false );
2008-10-11 14:16:25 -05:00
else
return ;
}
2009-10-17 15:51:44 -07:00
2009-02-24 20:52:55 -06:00
float x , y , z ;
2017-03-23 00:43:04 +01:00
owner -> GetClosePoint ( x , y , z , owner -> GetCombatReach ());
2009-02-24 20:52:55 -06:00
Pet * pet = owner -> SummonPet ( petentry , x , y , z , owner -> GetOrientation (), SUMMON_PET , 0 );
2009-11-01 17:53:07 -08:00
if ( ! pet )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( m_caster -> GetTypeId () == TYPEID_UNIT )
2008-10-11 14:16:25 -05:00
{
2018-02-10 16:43:01 -03:00
if ( m_caster -> ToCreature () -> IsTotem ())
2009-03-05 18:48:56 -06:00
pet -> SetReactState ( REACT_AGGRESSIVE );
2008-11-18 19:40:06 -06:00
else
2009-03-05 18:48:56 -06:00
pet -> SetReactState ( REACT_DEFENSIVE );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2019-06-03 20:40:34 +02:00
pet -> SetCreatedBySpell ( m_spellInfo -> Id );
2009-10-17 15:51:44 -07:00
2009-02-24 20:52:55 -06:00
// generate new name for summon pet
2020-09-04 13:38:24 +02:00
std :: string new_name = sObjectMgr -> GeneratePetName ( petentry );
2009-11-01 17:53:07 -08:00
if ( ! new_name . empty ())
2009-02-24 20:52:55 -06:00
pet -> SetName ( new_name );
2010-08-27 17:49:32 +02:00
2021-08-28 18:30:45 +02:00
ExecuteLogEffectSummonObject ( SpellEffectName ( effectInfo -> Effect ), pet );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectLearnPetSpell ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2011-09-24 02:01:18 +02:00
if ( ! unitTarget )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-09-24 02:01:18 +02:00
if ( unitTarget -> ToPlayer ())
{
2021-08-28 19:51:29 +02:00
EffectLearnSpell ();
2008-10-11 14:16:25 -05:00
return ;
2011-09-24 02:01:18 +02:00
}
Pet * pet = unitTarget -> ToPet ();
if ( ! pet )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2020-06-12 01:29:18 +02:00
SpellInfo const * learn_spellproto = sSpellMgr -> GetSpellInfo ( effectInfo -> TriggerSpell , DIFFICULTY_NONE );
2009-11-01 17:53:07 -08:00
if ( ! learn_spellproto )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
pet -> learnSpell ( learn_spellproto -> Id );
pet -> SavePetToDB ( PET_SAVE_AS_CURRENT );
2011-09-24 02:01:18 +02:00
pet -> GetOwner () -> PetSpellInitialize ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectTaunt ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
2008-10-11 14:16:25 -05:00
// this effect use before aura Taunt apply for prevent taunt already attacking target
// for spell as marked "non effective at already attacking target"
2018-01-03 20:04:19 +01:00
if ( ! unitTarget || ! unitTarget -> CanHaveThreatList ())
2008-10-11 14:16:25 -05:00
{
2009-04-17 18:08:52 -05:00
SendCastResult ( SPELL_FAILED_DONT_REPORT );
return ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2018-01-03 20:04:19 +01:00
ThreatManager & mgr = unitTarget -> GetThreatManager ();
2018-02-10 16:43:01 -03:00
if ( mgr . GetCurrentVictim () == unitCaster )
2009-04-17 18:08:52 -05:00
{
2018-01-03 20:04:19 +01:00
SendCastResult ( SPELL_FAILED_DONT_REPORT );
return ;
2015-06-29 19:53:28 +02:00
}
2009-10-17 15:51:44 -07:00
2018-01-03 20:04:19 +01:00
if ( ! mgr . IsThreatListEmpty ())
// Set threat equal to highest threat currently on target
2018-02-10 16:43:01 -03:00
mgr . MatchUnitThreatToHighestThreat ( unitCaster );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectWeaponDmg ()
2008-12-25 17:39:46 -06:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET )
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
2013-06-11 19:54:27 -02:30
if ( ! unitTarget || ! unitTarget -> IsAlive ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// multiple weapon dmg effect workaround
// execute only the last weapon damage
// and handle all effects at once
2021-08-28 19:53:53 +02:00
for ( size_t j = effectInfo -> EffectIndex + 1 ; j < m_spellInfo -> GetEffects (). size (); ++ j )
2008-10-11 14:16:25 -05:00
{
2021-09-04 15:13:15 +02:00
switch ( m_spellInfo -> GetEffect ( SpellEffIndex ( j )). Effect )
2008-10-11 14:16:25 -05:00
{
case SPELL_EFFECT_WEAPON_DAMAGE :
case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL :
case SPELL_EFFECT_NORMALIZED_WEAPON_DMG :
case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE :
2009-11-01 17:53:07 -08:00
return ; // we must calculate only at last weapon effect
2021-09-04 15:13:15 +02:00
default :
break ;
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// some spell specific modifiers
float totalDamagePercentMod = 1.0f ; // applied to final bonus+weapon damage
2008-12-17 23:27:01 -06:00
int32 fixed_bonus = 0 ;
2008-10-11 14:16:25 -05:00
int32 spell_bonus = 0 ; // bonus specific for spell
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
switch ( m_spellInfo -> SpellFamilyName )
2008-10-11 14:16:25 -05:00
{
case SPELLFAMILY_SHAMAN :
{
// Skyshatter Harness item set bonus
// Stormstrike
2018-02-10 16:43:01 -03:00
if ( AuraEffect * aurEff = unitCaster -> IsScriptOverriden ( m_spellInfo , 5634 ))
unitCaster -> CastSpell ( nullptr , 38430 , aurEff );
2008-12-17 23:27:01 -06:00
break ;
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-12-17 23:27:01 -06:00
bool normalized = false ;
2010-12-11 20:37:38 +06:00
float weaponDamagePercentMod = 1.0f ;
2021-09-04 15:13:15 +02:00
for ( SpellEffectInfo const & spellEffectInfo : m_spellInfo -> GetEffects ())
2008-10-11 14:16:25 -05:00
{
2021-09-04 15:13:15 +02:00
switch ( spellEffectInfo . Effect )
2008-10-11 14:16:25 -05:00
{
case SPELL_EFFECT_WEAPON_DAMAGE :
case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL :
2021-09-04 15:13:15 +02:00
fixed_bonus += CalculateDamage ( spellEffectInfo , unitTarget );
2008-10-11 14:16:25 -05:00
break ;
case SPELL_EFFECT_NORMALIZED_WEAPON_DMG :
2021-09-04 15:13:15 +02:00
fixed_bonus += CalculateDamage ( spellEffectInfo , unitTarget );
2008-10-11 14:16:25 -05:00
normalized = true ;
break ;
case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE :
2021-09-04 15:13:15 +02:00
ApplyPct ( weaponDamagePercentMod , CalculateDamage ( spellEffectInfo , unitTarget ));
2009-03-28 16:34:34 -06:00
break ;
2008-10-11 14:16:25 -05:00
default :
break ; // not weapon damage effect, just skip
}
}
2009-10-17 15:51:44 -07:00
2016-11-20 00:44:49 +01:00
// if (addPctMods) { percent mods are added in Unit::CalculateDamage } else { percent mods are added in Unit::MeleeDamageBonusDone }
// this distinction is neccessary to properly inform the client about his autoattack damage values from Script_UnitDamage
2018-01-08 20:31:21 +01:00
bool const addPctMods = ! m_spellInfo -> HasAttribute ( SPELL_ATTR6_IGNORE_CASTER_DAMAGE_MODIFIERS ) && ( m_spellSchoolMask & SPELL_SCHOOL_MASK_NORMAL );
2016-11-20 00:44:49 +01:00
if ( addPctMods )
2008-10-11 14:16:25 -05:00
{
UnitMods unitMod ;
2010-12-11 20:37:38 +06:00
switch ( m_attackType )
2008-10-11 14:16:25 -05:00
{
default :
case BASE_ATTACK : unitMod = UNIT_MOD_DAMAGE_MAINHAND ; break ;
case OFF_ATTACK : unitMod = UNIT_MOD_DAMAGE_OFFHAND ; break ;
case RANGED_ATTACK : unitMod = UNIT_MOD_DAMAGE_RANGED ; break ;
}
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
float weapon_total_pct = unitCaster -> GetPctModifierValue ( unitMod , TOTAL_PCT );
2010-04-07 19:14:10 +02:00
if ( fixed_bonus )
2008-12-17 23:27:01 -06:00
fixed_bonus = int32 ( fixed_bonus * weapon_total_pct );
2010-04-07 19:14:10 +02:00
if ( spell_bonus )
2008-12-17 23:27:01 -06:00
spell_bonus = int32 ( spell_bonus * weapon_total_pct );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
int32 weaponDamage = unitCaster -> CalculateDamage ( m_attackType , normalized , addPctMods );
2009-10-17 15:51:44 -07:00
2008-12-17 23:27:01 -06:00
// Sequence is important
2021-09-04 15:13:15 +02:00
for ( SpellEffectInfo const & spellEffectInfo : m_spellInfo -> GetEffects ())
2008-12-17 23:27:01 -06:00
{
// We assume that a spell have at most one fixed_bonus
// and at most one weaponDamagePercentMod
2021-09-04 15:13:15 +02:00
switch ( spellEffectInfo . Effect )
2008-12-17 23:27:01 -06:00
{
case SPELL_EFFECT_WEAPON_DAMAGE :
case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL :
case SPELL_EFFECT_NORMALIZED_WEAPON_DMG :
weaponDamage += fixed_bonus ;
break ;
case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE :
2016-11-20 00:44:49 +01:00
weaponDamage = int32 ( weaponDamage * weaponDamagePercentMod );
2018-02-04 21:28:15 -03:00
break ;
2008-12-17 23:27:01 -06:00
default :
break ; // not weapon damage effect, just skip
}
}
2009-10-17 15:51:44 -07:00
2016-11-20 00:44:49 +01:00
weaponDamage += spell_bonus ;
weaponDamage = int32 ( weaponDamage * totalDamagePercentMod );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// prevent negative damage
2018-02-04 21:28:15 -03:00
weaponDamage = std :: max ( weaponDamage , 0 );
2009-10-17 15:51:44 -07:00
2008-11-26 15:14:03 -06:00
// Add melee damage bonuses (also check for negative)
2018-02-10 16:43:01 -03:00
weaponDamage = unitCaster -> MeleeDamageBonusDone ( unitTarget , weaponDamage , m_attackType , SPELL_DIRECT_DAMAGE , m_spellInfo );
m_damage += unitTarget -> MeleeDamageBonusTaken ( unitCaster , weaponDamage , m_attackType , SPELL_DIRECT_DAMAGE , m_spellInfo );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectThreat ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster || ! unitCaster -> IsAlive ())
return ;
if ( ! unitTarget )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! unitTarget -> CanHaveThreatList ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
unitTarget -> GetThreatManager (). AddThreat ( unitCaster , float ( damage ), m_spellInfo , true );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectHealMaxHealth ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
2013-06-11 19:54:27 -02:30
if ( ! unitTarget || ! unitTarget -> IsAlive ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
int32 addhealth = 0 ;
2010-02-14 19:13:14 -07:00
2010-08-28 23:01:04 +02:00
// damage == 0 - heal for caster max health
if ( damage == 0 )
2018-02-10 16:43:01 -03:00
addhealth = unitCaster -> GetMaxHealth ();
2009-05-31 20:45:34 -05:00
else
addhealth = unitTarget -> GetMaxHealth () - unitTarget -> GetHealth ();
2010-08-28 23:01:04 +02:00
2012-05-30 08:01:02 +02:00
m_healing += addhealth ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectInterruptCast ()
2008-10-11 14:16:25 -05:00
{
2016-10-04 23:35:50 -03:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET )
2011-09-25 13:29:17 +02:00
return ;
2013-06-11 19:54:27 -02:30
if ( ! unitTarget || ! unitTarget -> IsAlive ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2013-03-08 21:41:30 +01:00
/// @todo not all spells that used this effect apply cooldown at school spells
2008-10-11 14:16:25 -05:00
// also exist case: apply cooldown to interrupted cast only and to all spells
2011-11-05 05:21:37 +07:00
// there is no CURRENT_AUTOREPEAT_SPELL spells that can be interrupted
for ( uint32 i = CURRENT_FIRST_NON_MELEE_SPELL ; i < CURRENT_AUTOREPEAT_SPELL ; ++ i )
2008-10-11 14:16:25 -05:00
{
2009-08-19 16:52:51 -05:00
if ( Spell * spell = unitTarget -> GetCurrentSpell ( CurrentSpellTypes ( i )))
2008-10-11 14:16:25 -05:00
{
2011-07-26 23:09:28 +02:00
SpellInfo const * curSpellInfo = spell -> m_spellInfo ;
2008-10-11 14:16:25 -05:00
// check if we can interrupt spell
2009-08-19 16:52:51 -05:00
if (( spell -> getState () == SPELL_STATE_CASTING
2011-11-05 05:33:52 +07:00
|| ( spell -> getState () == SPELL_STATE_PREPARING && spell -> GetCastTime () > 0.0f ))
2021-03-24 23:36:53 +01:00
&& curSpellInfo -> CanBeInterrupted ( m_caster , unitTarget ))
2008-10-11 14:16:25 -05:00
{
2018-02-10 16:43:01 -03:00
if ( unitCaster )
2008-12-15 09:55:57 -06:00
{
2012-08-03 01:27:39 +03:00
int32 duration = m_spellInfo -> GetDuration ();
2021-08-28 19:51:29 +02:00
unitTarget -> GetSpellHistory () -> LockSpellSchool ( curSpellInfo -> GetSchoolMask (), unitTarget -> ModSpellDuration ( m_spellInfo , unitTarget , duration , false , 1 << effectInfo -> EffectIndex ));
2019-08-01 15:23:08 -03:00
if ( m_spellInfo -> DmgClass == SPELL_DAMAGE_CLASS_MAGIC )
2018-02-10 16:43:01 -03:00
Unit :: ProcSkillsAndAuras ( unitCaster , unitTarget , PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG , PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG ,
2019-08-01 15:23:08 -03:00
PROC_SPELL_TYPE_MASK_ALL , PROC_SPELL_PHASE_HIT , PROC_HIT_INTERRUPT , nullptr , nullptr , nullptr );
else if ( m_spellInfo -> DmgClass == SPELL_DAMAGE_CLASS_MELEE )
2018-02-10 16:43:01 -03:00
Unit :: ProcSkillsAndAuras ( unitCaster , unitTarget , PROC_FLAG_DONE_SPELL_MELEE_DMG_CLASS , PROC_FLAG_TAKEN_SPELL_MELEE_DMG_CLASS ,
2019-08-01 15:23:08 -03:00
PROC_SPELL_TYPE_MASK_ALL , PROC_SPELL_PHASE_HIT , PROC_HIT_INTERRUPT , nullptr , nullptr , nullptr );
2008-12-15 09:55:57 -06:00
}
2021-08-28 18:30:45 +02:00
SendSpellInterruptLog ( unitTarget , curSpellInfo -> Id );
2009-08-19 16:52:51 -05:00
unitTarget -> InterruptSpell ( CurrentSpellTypes ( i ), false );
2008-10-11 14:16:25 -05:00
}
}
}
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectSummonObjectWild ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2008-10-11 14:16:25 -05:00
WorldObject * target = focusObject ;
2010-04-07 22:59:46 +02:00
if ( ! target )
2008-10-11 14:16:25 -05:00
target = m_caster ;
2009-10-17 15:51:44 -07:00
2009-05-31 15:56:51 -05:00
float x , y , z ;
2010-04-07 19:14:10 +02:00
if ( m_targets . HasDst ())
2012-05-30 08:01:02 +02:00
destTarget -> GetPosition ( x , y , z );
2008-10-11 14:16:25 -05:00
else
2017-03-23 00:43:04 +01:00
m_caster -> GetClosePoint ( x , y , z , DEFAULT_PLAYER_BOUNDING_RADIUS );
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
Map * map = target -> GetMap ();
2018-01-27 21:47:37 +01:00
Position pos = Position ( x , y , z , target -> GetOrientation ());
2017-06-04 01:00:45 +02:00
QuaternionData rot = QuaternionData :: fromEulerAnglesZYX ( target -> GetOrientation (), 0.f , 0.f );
2018-01-27 21:47:37 +01:00
GameObject * go = GameObject :: CreateGameObject ( effectInfo -> MiscValue , map , pos , rot , 255 , GO_STATE_READY );
if ( ! go )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2018-01-28 11:37:20 +01:00
PhasingHandler :: InheritPhaseShift ( go , m_caster );
2014-06-01 22:27:29 -05:00
2017-01-29 00:00:43 +01:00
int32 duration = m_spellInfo -> CalcDuration ( m_caster );
2009-10-17 15:51:44 -07:00
2018-01-27 21:47:37 +01:00
go -> SetRespawnTime ( duration > 0 ? duration / IN_MILLISECONDS : 0 );
go -> SetSpellId ( m_spellInfo -> Id );
2009-10-17 15:51:44 -07:00
2021-08-28 18:30:45 +02:00
ExecuteLogEffectSummonObject ( SpellEffectName ( effectInfo -> Effect ), go );
2010-08-27 17:49:32 +02:00
2009-08-08 12:25:20 -05:00
// Wild object not have owner and check clickable by players
2018-01-27 21:47:37 +01:00
map -> AddToMap ( go );
2009-10-17 15:51:44 -07:00
2018-01-27 21:47:37 +01:00
if ( go -> GetGoType () == GAMEOBJECT_TYPE_FLAGDROP )
2012-10-04 12:49:58 +02:00
if ( Player * player = m_caster -> ToPlayer ())
if ( Battleground * bg = player -> GetBattleground ())
2018-01-27 21:47:37 +01:00
bg -> SetDroppedFlagGUID ( go -> GetGUID (), player -> GetTeam () == ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE );
2009-10-17 15:51:44 -07:00
2018-01-27 21:47:37 +01:00
if ( GameObject * linkedTrap = go -> GetLinkedTrap ())
2008-10-11 14:16:25 -05:00
{
2018-01-28 11:37:20 +01:00
PhasingHandler :: InheritPhaseShift ( linkedTrap , m_caster );
2014-06-01 22:27:29 -05:00
2016-11-01 22:24:03 +01:00
linkedTrap -> SetRespawnTime ( duration > 0 ? duration / IN_MILLISECONDS : 0 );
linkedTrap -> SetSpellId ( m_spellInfo -> Id );
2009-10-17 15:51:44 -07:00
2021-08-28 18:30:45 +02:00
ExecuteLogEffectSummonObject ( SpellEffectName ( effectInfo -> Effect ), linkedTrap );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectScriptEffect ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2013-03-08 21:41:30 +01:00
/// @todo we must implement hunter pet summon at login there (spell 6962)
2018-02-10 16:43:01 -03:00
/// @todo: move this to scripts
2011-09-29 12:43:05 +02:00
switch ( m_spellInfo -> SpellFamilyName )
2008-10-11 14:16:25 -05:00
{
2009-01-20 19:59:43 -06:00
case SPELLFAMILY_GENERIC :
2008-12-06 14:01:44 -06:00
{
2011-09-29 12:43:05 +02:00
switch ( m_spellInfo -> Id )
2009-01-20 19:59:43 -06:00
{
2009-08-12 20:47:54 -05:00
case 55693 : // Remove Collapsing Cave Aura
2010-04-07 19:14:10 +02:00
if ( ! unitTarget )
2009-08-12 20:47:54 -05:00
return ;
2014-12-19 23:52:29 +01:00
unitTarget -> RemoveAurasDueToSpell ( effectInfo -> CalcValue ());
2009-08-12 20:47:54 -05:00
break ;
2009-01-20 19:59:43 -06:00
// Bending Shinbone
case 8856 :
{
2010-04-07 19:14:10 +02:00
if ( ! itemTarget && m_caster -> GetTypeId () != TYPEID_PLAYER )
2009-01-20 19:59:43 -06:00
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
uint32 const spell_id = roll_chance_i ( 20 ) ? 8854 : 8855 ;
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , spell_id , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2009-01-20 19:59:43 -06:00
return ;
}
// Brittle Armor - need remove one 24575 Brittle Armor aura
case 24590 :
2009-04-06 13:31:14 +02:00
unitTarget -> RemoveAuraFromStack ( 24575 );
2009-01-20 19:59:43 -06:00
return ;
// Mercurial Shield - need remove one 26464 Mercurial Shield aura
case 26465 :
2009-04-06 13:31:14 +02:00
unitTarget -> RemoveAuraFromStack ( 26464 );
2009-01-20 19:59:43 -06:00
return ;
// Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
case 22539 :
case 22972 :
case 22975 :
case 22976 :
case 22977 :
case 22978 :
case 22979 :
case 22980 :
case 22981 :
case 22982 :
case 22983 :
case 22984 :
case 22985 :
{
2013-06-11 19:54:27 -02:30
if ( ! unitTarget || ! unitTarget -> IsAlive ())
2009-01-20 19:59:43 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-01-20 19:59:43 -06:00
// Onyxia Scale Cloak
2010-04-07 19:14:10 +02:00
if ( unitTarget -> HasAura ( 22683 ))
2009-01-20 19:59:43 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-01-20 19:59:43 -06:00
// Shadow Flame
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( unitTarget , 22682 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2009-01-20 19:59:43 -06:00
return ;
}
// Mirren's Drinking Hat
case 29830 :
{
uint32 item = 0 ;
2010-04-07 22:59:46 +02:00
switch ( urand ( 1 , 6 ))
2009-01-20 19:59:43 -06:00
{
2009-05-31 15:56:51 -05:00
case 1 :
case 2 :
case 3 :
item = 23584 ; break ; // Loch Modan Lager
case 4 :
case 5 :
item = 23585 ; break ; // Stouthammer Lite
2009-01-20 19:59:43 -06:00
case 6 :
2009-05-31 15:56:51 -05:00
item = 23586 ; break ; // Aerie Peak Pale Ale
2009-01-20 19:59:43 -06:00
}
if ( item )
2021-08-28 19:51:29 +02:00
DoCreateItem ( item );
2009-01-20 19:59:43 -06:00
break ;
}
2012-06-03 02:35:00 +02:00
case 20589 : // Escape artist
case 30918 : // Improved Sprint
2009-12-24 13:01:39 +01:00
{
// Removes snares and roots.
2017-02-04 23:50:32 +01:00
unitTarget -> RemoveMovementImpairingAuras ( true );
2009-12-24 13:01:39 +01:00
break ;
}
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
// Plant Warmaul Ogre Banner
case 32307 :
2011-07-08 11:45:18 +02:00
if ( Player * caster = m_caster -> ToPlayer ())
2011-07-08 11:12:19 +02:00
{
caster -> RewardPlayerAndGroupAtEvent ( 18388 , unitTarget );
if ( Creature * target = unitTarget -> ToCreature ())
2017-02-05 15:39:22 +01:00
target -> DespawnOrUnsummon ();
2011-07-08 11:12:19 +02:00
}
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
break ;
2009-08-11 19:57:27 +02:00
// Mug Transformation
2009-01-20 19:59:43 -06:00
case 41931 :
{
2010-04-07 19:14:10 +02:00
if ( m_caster -> GetTypeId () != TYPEID_PLAYER )
2009-01-20 19:59:43 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-11-19 19:55:24 -08:00
uint8 bag = 19 ;
uint8 slot = 0 ;
2020-08-14 17:06:03 +02:00
Item * item = nullptr ;
2009-10-17 15:51:44 -07:00
2010-08-30 15:25:15 +02:00
while ( bag ) // 256 = 0 due to var type
2009-01-20 19:59:43 -06:00
{
2010-03-07 15:20:19 +01:00
item = m_caster -> ToPlayer () -> GetItemByPos ( bag , slot );
2012-05-30 08:01:02 +02:00
if ( item && item -> GetEntry () == 38587 )
break ;
2009-11-19 19:55:24 -08:00
++ slot ;
2009-01-20 19:59:43 -06:00
if ( slot == 39 )
{
slot = 0 ;
2009-11-19 19:55:24 -08:00
++ bag ;
2009-01-20 19:59:43 -06:00
}
}
2010-08-30 15:25:15 +02:00
if ( bag )
2009-01-20 19:59:43 -06:00
{
2011-04-29 20:47:02 +02:00
if ( m_caster -> ToPlayer () -> GetItemByPos ( bag , slot ) -> GetCount () == 1 ) m_caster -> ToPlayer () -> RemoveItem ( bag , slot , true );
else m_caster -> ToPlayer () -> GetItemByPos ( bag , slot ) -> SetCount ( m_caster -> ToPlayer () -> GetItemByPos ( bag , slot ) -> GetCount () - 1 );
2009-01-20 19:59:43 -06:00
// Spell 42518 (Braufest - Gratisprobe des Braufest herstellen)
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , 42518 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2009-01-20 19:59:43 -06:00
return ;
}
break ;
}
2009-11-19 19:55:24 -08:00
// Brutallus - Burn
case 45141 :
case 45151 :
{
//Workaround for Range ... should be global for every ScriptEffect
2014-12-19 23:52:29 +01:00
float radius = effectInfo -> CalcRadius ();
2009-11-19 19:55:24 -08:00
if ( unitTarget && unitTarget -> GetTypeId () == TYPEID_PLAYER && unitTarget -> GetDistance ( m_caster ) >= radius && ! unitTarget -> HasAura ( 46394 ) && unitTarget != m_caster )
2021-10-03 16:36:39 +02:00
unitTarget -> CastSpell ( unitTarget , 46394 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2009-11-19 19:55:24 -08:00
break ;
}
2009-01-20 19:59:43 -06:00
// Goblin Weather Machine
case 46203 :
{
2010-04-07 19:14:10 +02:00
if ( ! unitTarget )
2009-01-20 19:59:43 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-04-27 18:42:35 -05:00
uint32 spellId = 0 ;
2014-07-22 21:43:19 +02:00
switch ( rand32 () % 4 )
2009-01-20 19:59:43 -06:00
{
2009-01-21 16:18:57 -06:00
case 0 : spellId = 46740 ; break ;
case 1 : spellId = 46739 ; break ;
case 2 : spellId = 46738 ; break ;
case 3 : spellId = 46736 ; break ;
2009-01-20 19:59:43 -06:00
}
2021-10-03 16:36:39 +02:00
unitTarget -> CastSpell ( unitTarget , spellId , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2009-01-20 19:59:43 -06:00
break ;
}
2018-02-10 16:43:01 -03:00
// 5,000 Gold
2009-01-20 19:59:43 -06:00
case 46642 :
{
2010-04-07 19:14:10 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2009-01-20 19:59:43 -06:00
return ;
2009-10-17 15:51:44 -07:00
2010-03-07 15:20:19 +01:00
unitTarget -> ToPlayer () -> ModifyMoney ( 5000 * GOLD );
2009-01-20 19:59:43 -06:00
break ;
}
2009-08-11 19:57:27 +02:00
// Death Knight Initiate Visual
case 51519 :
{
2010-04-07 19:14:10 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_UNIT )
2009-08-11 19:57:27 +02:00
return ;
2009-10-17 15:51:44 -07:00
2009-08-11 19:57:27 +02:00
uint32 iTmpSpellId = 0 ;
switch ( unitTarget -> GetDisplayId ())
{
case 25369 : iTmpSpellId = 51552 ; break ; // bloodelf female
case 25373 : iTmpSpellId = 51551 ; break ; // bloodelf male
case 25363 : iTmpSpellId = 51542 ; break ; // draenei female
case 25357 : iTmpSpellId = 51541 ; break ; // draenei male
case 25361 : iTmpSpellId = 51537 ; break ; // dwarf female
case 25356 : iTmpSpellId = 51538 ; break ; // dwarf male
case 25372 : iTmpSpellId = 51550 ; break ; // forsaken female
case 25367 : iTmpSpellId = 51549 ; break ; // forsaken male
case 25362 : iTmpSpellId = 51540 ; break ; // gnome female
case 25359 : iTmpSpellId = 51539 ; break ; // gnome male
case 25355 : iTmpSpellId = 51534 ; break ; // human female
case 25354 : iTmpSpellId = 51520 ; break ; // human male
case 25360 : iTmpSpellId = 51536 ; break ; // nightelf female
case 25358 : iTmpSpellId = 51535 ; break ; // nightelf male
case 25368 : iTmpSpellId = 51544 ; break ; // orc female
case 25364 : iTmpSpellId = 51543 ; break ; // orc male
case 25371 : iTmpSpellId = 51548 ; break ; // tauren female
case 25366 : iTmpSpellId = 51547 ; break ; // tauren male
case 25370 : iTmpSpellId = 51545 ; break ; // troll female
case 25365 : iTmpSpellId = 51546 ; break ; // troll male
default : return ;
}
2009-10-17 15:51:44 -07:00
2021-10-03 16:36:39 +02:00
unitTarget -> CastSpell ( unitTarget , iTmpSpellId , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2010-03-07 18:30:53 +01:00
Creature * npc = unitTarget -> ToCreature ();
2013-02-18 12:24:18 +00:00
npc -> LoadEquipment ();
2009-08-11 19:57:27 +02:00
return ;
}
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
// Deathbolt from Thalgran Blightbringer
// reflected by Freya's Ward
// Retribution by Sevenfold Retribution
case 51854 :
{
2010-12-22 20:18:34 +02:00
if ( ! unitTarget )
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
return ;
if ( unitTarget -> HasAura ( 51845 ))
2021-10-03 16:36:39 +02:00
unitTarget -> CastSpell ( m_caster , 51856 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
else
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( unitTarget , 51855 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
break ;
}
2009-05-25 22:52:08 -05:00
// Summon Ghouls On Scarlet Crusade
case 51904 :
{
2010-04-07 19:14:10 +02:00
if ( ! m_targets . HasDst ())
2009-05-25 22:52:08 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
float radius = effectInfo -> CalcRadius ();
*Implement spells: 781, 13280, 32307, 40109, 47770, 47776, 49625, 49634, 51854, 64385, by Warhead
2009-10-31 04:28:02 -07:00
for ( uint8 i = 0 ; i < 15 ; ++ i )
2021-10-03 19:58:03 +02:00
m_caster -> CastSpell ( m_caster -> GetRandomPoint ( * destTarget , radius ), 54522 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
2021-10-03 16:36:39 +02:00
. SetOriginalCastId ( m_castId ));
2009-05-25 22:52:08 -05:00
break ;
2009-05-27 23:33:21 -05:00
}
2009-08-05 17:00:01 +02:00
case 52173 : // Coyote Spirit Despawn
case 60243 : // Blood Parrot Despawn
2015-08-12 14:05:14 +02:00
if ( unitTarget -> GetTypeId () == TYPEID_UNIT && unitTarget -> IsSummon ())
2010-03-27 16:08:14 +01:00
unitTarget -> ToTempSummon () -> UnSummon ();
2009-08-05 17:00:01 +02:00
return ;
2009-06-03 23:24:57 -05:00
case 52479 : // Gift of the Harvester
2018-02-10 16:43:01 -03:00
if ( unitTarget && unitCaster )
2021-10-03 16:36:39 +02:00
unitCaster -> CastSpell ( unitTarget , urand ( 0 , 1 ) ? damage : 52505 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2009-06-03 23:24:57 -05:00
return ;
2009-06-14 21:05:37 -05:00
case 53110 : // Devour Humanoid
2010-04-07 19:14:10 +02:00
if ( unitTarget )
2021-10-03 16:36:39 +02:00
unitTarget -> CastSpell ( m_caster , damage , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2009-06-14 21:05:37 -05:00
return ;
2011-11-12 02:36:18 +07:00
case 57347 : // Retrieving (Wintergrasp RP-GG pickup spell)
{
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_UNIT || m_caster -> GetTypeId () != TYPEID_PLAYER )
return ;
unitTarget -> ToCreature () -> DespawnOrUnsummon ();
return ;
}
case 57349 : // Drop RP-GG (Wintergrasp RP-GG at death drop spell)
{
if ( m_caster -> GetTypeId () != TYPEID_PLAYER )
return ;
// Delete item from inventory at death
m_caster -> ToPlayer () -> DestroyItemCount ( damage , 5 , true );
return ;
}
2009-03-29 17:18:51 -06:00
case 58418 : // Portal to Orgrimmar
case 58420 : // Portal to Stormwind
{
2021-08-28 19:51:29 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER || effectInfo -> EffectIndex != 0 )
2009-03-29 17:18:51 -06:00
return ;
2009-10-17 15:51:44 -07:00
2014-11-17 20:38:56 +01:00
// Effects for 58418 and 58420 are all DIFFICULTY_NONE so always valid
2021-09-04 15:13:15 +02:00
uint32 spellID = m_spellInfo -> GetEffect ( EFFECT_0 ). CalcValue ();
uint32 questID = m_spellInfo -> GetEffect ( EFFECT_1 ). CalcValue ();
2009-10-17 15:51:44 -07:00
2011-01-13 23:06:59 +01:00
if ( unitTarget -> ToPlayer () -> GetQuestStatus ( questID ) == QUEST_STATUS_COMPLETE )
2021-10-03 16:36:39 +02:00
unitTarget -> CastSpell ( unitTarget , spellID , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2009-10-17 15:51:44 -07:00
2009-03-29 17:18:51 -06:00
return ;
}
2009-05-05 14:46:32 -05:00
case 59317 : // Teleporting
2012-09-06 11:00:37 -04:00
{
2009-05-05 14:46:32 -05:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
2009-10-17 15:51:44 -07:00
2009-05-05 14:46:32 -05:00
// return from top
2010-03-07 15:20:19 +01:00
if ( unitTarget -> ToPlayer () -> GetAreaId () == 4637 )
2021-10-03 16:36:39 +02:00
unitTarget -> CastSpell ( unitTarget , 59316 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2009-05-05 14:46:32 -05:00
// teleport atop
else
2021-10-03 16:36:39 +02:00
unitTarget -> CastSpell ( unitTarget , 59314 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2009-10-17 15:51:44 -07:00
2009-05-05 14:46:32 -05:00
return ;
2009-01-20 19:59:43 -06:00
}
2009-08-28 11:26:20 -05:00
case 62482 : // Grab Crate
2009-12-17 13:07:38 +01:00
{
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
2010-04-07 19:14:10 +02:00
if ( unitTarget )
2009-08-28 11:26:20 -05:00
{
2018-02-10 16:43:01 -03:00
if ( Unit * seat = unitCaster -> GetVehicleBase ())
2009-08-28 11:26:20 -05:00
{
2011-08-18 20:24:46 +02:00
if ( Unit * parent = seat -> GetVehicleBase ())
{
2013-03-08 21:41:30 +01:00
/// @todo a hack, range = 11, should after some time cast, otherwise too far
2021-10-03 16:36:39 +02:00
unitCaster -> CastSpell ( parent , 62496 , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
unitTarget -> CastSpell ( parent , damage , CastSpellExtraArgs ()
. SetOriginalCastId ( m_castId )); // DIFFICULTY_NONE, so effect always valid
2011-08-18 20:24:46 +02:00
}
2009-08-28 11:26:20 -05:00
}
}
return ;
2009-12-17 12:23:01 +01:00
}
2009-08-17 02:53:39 +02:00
case 60123 : // Lightwell
2009-08-10 15:52:11 -05:00
{
2018-02-10 16:43:01 -03:00
if ( m_caster -> GetTypeId () != TYPEID_UNIT || ! m_caster -> ToCreature () -> IsSummon ())
2009-08-17 02:53:39 +02:00
return ;
2009-10-17 15:51:44 -07:00
2009-08-17 02:53:39 +02:00
uint32 spell_heal ;
2009-10-17 15:51:44 -07:00
2011-09-29 12:43:05 +02:00
switch ( m_caster -> GetEntry ())
2009-08-17 02:53:39 +02:00
{
case 31897 : spell_heal = 7001 ; break ;
case 31896 : spell_heal = 27873 ; break ;
case 31895 : spell_heal = 27874 ; break ;
case 31894 : spell_heal = 28276 ; break ;
case 31893 : spell_heal = 48084 ; break ;
case 31883 : spell_heal = 48085 ; break ;
default :
2016-02-20 13:23:35 +01:00
TC_LOG_ERROR ( "spells" , "Unknown Lightwell spell caster %u." , m_caster -> GetEntry ());
2009-08-17 02:53:39 +02:00
return ;
2009-08-10 15:52:11 -05:00
}
2009-10-17 15:51:44 -07:00
2011-06-07 17:25:34 +02:00
// proc a spellcast
2018-02-10 16:43:01 -03:00
if ( Aura * chargesAura = m_caster -> ToCreature () -> GetAura ( 59907 ))
2009-08-17 02:53:39 +02:00
{
2021-10-03 14:58:35 +02:00
m_caster -> CastSpell ( unitTarget , spell_heal , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
2021-10-03 16:36:39 +02:00
. SetOriginalCaster ( m_caster -> ToCreature () -> ToTempSummon () -> GetSummonerGUID ())
. SetOriginalCastId ( m_castId ));
2011-06-07 17:25:34 +02:00
if ( chargesAura -> ModCharges ( - 1 ))
2018-02-10 16:43:01 -03:00
m_caster -> ToCreature () -> ToTempSummon () -> UnSummon ();
2009-08-17 02:53:39 +02:00
}
2011-06-15 20:46:49 +02:00
2009-08-23 01:08:09 -05:00
return ;
2009-08-10 15:52:11 -05:00
}
2009-09-14 13:34:23 -07:00
// Stoneclaw Totem
case 55328 : // Rank 1
case 55329 : // Rank 2
case 55330 : // Rank 3
case 55332 : // Rank 4
case 55333 : // Rank 5
case 55335 : // Rank 6
case 55278 : // Rank 7
case 58589 : // Rank 8
case 58590 : // Rank 9
case 58591 : // Rank 10
{
// Cast Absorb on totems
2009-10-17 16:20:24 -07:00
for ( uint8 slot = SUMMON_SLOT_TOTEM ; slot < MAX_TOTEM_SLOT ; ++ slot )
2009-09-14 13:34:23 -07:00
{
2010-04-07 19:14:10 +02:00
if ( ! unitTarget -> m_SummonSlot [ slot ])
2009-09-14 13:34:23 -07:00
continue ;
2009-10-17 15:51:44 -07:00
2009-09-14 13:34:23 -07:00
Creature * totem = unitTarget -> GetMap () -> GetCreature ( unitTarget -> m_SummonSlot [ slot ]);
2013-06-11 19:54:27 -02:30
if ( totem && totem -> IsTotem ())
2009-09-14 13:34:23 -07:00
{
2017-12-30 20:28:41 +01:00
CastSpellExtraArgs args ( TRIGGERED_FULL_MASK );
2021-10-03 16:36:39 +02:00
args . SetOriginalCastId ( m_castId );
2018-01-13 20:38:32 -03:00
args . AddSpellMod ( SPELLVALUE_BASE_POINT0 , damage );
2017-12-30 20:28:41 +01:00
m_caster -> CastSpell ( totem , 55277 , args );
2009-09-14 13:34:23 -07:00
}
}
break ;
}
2010-02-23 23:48:07 +01:00
case 45668 : // Ultra-Advanced Proto-Typical Shortening Blaster
{
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_UNIT )
return ;
2010-04-07 18:09:10 +02:00
2010-02-23 23:48:07 +01:00
if ( roll_chance_i ( 50 )) // chance unknown, using 50
return ;
2010-04-07 18:09:10 +02:00
2010-02-23 23:48:07 +01:00
static uint32 const spellPlayer [ 5 ] =
{
45674 , // Bigger!
45675 , // Shrunk
45678 , // Yellow
45682 , // Ghost
45684 // Polymorph
};
2010-04-07 18:09:10 +02:00
2012-05-30 08:01:02 +02:00
static uint32 const spellTarget [ 5 ] =
{
2010-02-23 23:48:07 +01:00
45673 , // Bigger!
45672 , // Shrunk
45677 , // Yellow
45681 , // Ghost
45683 // Polymorph
};
2010-04-07 18:09:10 +02:00
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( m_caster , spellPlayer [ urand ( 0 , 4 )], CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
unitTarget -> CastSpell ( unitTarget , spellTarget [ urand ( 0 , 4 )], CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2010-02-23 23:48:07 +01:00
break ;
}
2008-10-11 14:16:25 -05:00
}
break ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// normal DB scripted effect
2021-08-28 19:51:29 +02:00
TC_LOG_DEBUG ( "spells" , "Spell ScriptStart spellid %u in EffectScriptEffect(%u)" , m_spellInfo -> Id , effectInfo -> EffectIndex );
m_caster -> GetMap () -> ScriptsStart ( sSpellScripts , uint32 ( m_spellInfo -> Id | ( effectInfo -> EffectIndex << 24 )), m_caster , unitTarget );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectSanctuary ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-07 19:14:10 +02:00
if ( ! unitTarget )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2018-01-03 20:04:19 +01:00
if ( unitTarget -> GetTypeId () == TYPEID_PLAYER && ! unitTarget -> GetMap () -> IsDungeon ())
2010-11-13 20:23:05 +01:00
{
2018-01-03 20:04:19 +01:00
// stop all pve combat for players outside dungeons, suppress pvp combat
unitTarget -> CombatStop ( false , false );
}
else
{
// in dungeons (or for nonplayers), reset this unit on all enemies' threat lists
for ( auto const & pair : unitTarget -> GetThreatManager (). GetThreatenedByMeList ())
2018-08-27 19:08:17 +02:00
pair . second -> ScaleThreat ( 0.0f );
2010-11-13 20:23:05 +01:00
}
2018-01-03 20:04:19 +01:00
// makes spells cast before this time fizzle
2017-03-02 02:19:25 +01:00
unitTarget -> m_lastSanctuaryTime = GameTime :: GetGameTimeMS ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectDuel ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-12-22 20:18:34 +02:00
if ( ! unitTarget || m_caster -> GetTypeId () != TYPEID_PLAYER || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-06-20 04:04:20 +07:00
Player * caster = m_caster -> ToPlayer ();
Player * target = unitTarget -> ToPlayer ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// caster or target already have requested duel
2014-10-22 12:52:12 +02:00
if ( caster -> duel || target -> duel || ! target -> GetSocial () || target -> GetSocial () -> HasIgnore ( caster -> GetGUID ()))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-05-29 02:40:37 +07:00
// Players can only fight a duel in zones with this flag
2016-02-02 19:13:04 +01:00
AreaTableEntry const * casterAreaEntry = sAreaTableStore . LookupEntry ( caster -> GetAreaId ());
2014-11-13 02:30:19 +02:00
if ( casterAreaEntry && ! ( casterAreaEntry -> Flags [ 0 ] & AREA_FLAG_ALLOW_DUELS ))
2008-10-11 14:16:25 -05:00
{
SendCastResult ( SPELL_FAILED_NO_DUELING ); // Dueling isn't allowed here
return ;
}
2009-10-17 15:51:44 -07:00
2016-02-02 19:13:04 +01:00
AreaTableEntry const * targetAreaEntry = sAreaTableStore . LookupEntry ( target -> GetAreaId ());
2014-11-13 02:30:19 +02:00
if ( targetAreaEntry && ! ( targetAreaEntry -> Flags [ 0 ] & AREA_FLAG_ALLOW_DUELS ))
2008-10-11 14:16:25 -05:00
{
SendCastResult ( SPELL_FAILED_NO_DUELING ); // Dueling isn't allowed here
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//CREATE DUEL FLAG OBJECT
2018-02-10 16:43:01 -03:00
Map * map = caster -> GetMap ();
2016-07-30 18:50:44 -03:00
Position const pos =
{
2018-02-10 16:43:01 -03:00
caster -> GetPositionX () + ( unitTarget -> GetPositionX () - caster -> GetPositionX ()) / 2 ,
caster -> GetPositionY () + ( unitTarget -> GetPositionY () - caster -> GetPositionY ()) / 2 ,
caster -> GetPositionZ (),
caster -> GetOrientation ()
2016-07-30 18:50:44 -03:00
};
2018-01-27 21:47:37 +01:00
QuaternionData rot = QuaternionData :: fromEulerAnglesZYX ( pos . GetOrientation (), 0.f , 0.f );
2016-07-30 18:50:44 -03:00
2018-01-27 21:47:37 +01:00
GameObject * go = GameObject :: CreateGameObject ( effectInfo -> MiscValue , map , pos , rot , 0 , GO_STATE_READY );
if ( ! go )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
PhasingHandler :: InheritPhaseShift ( go , caster );
2014-06-01 22:27:29 -05:00
2018-02-10 16:43:01 -03:00
go -> SetFaction ( caster -> GetFaction ());
go -> SetLevel ( caster -> getLevel () + 1 );
int32 duration = m_spellInfo -> CalcDuration ( caster );
2018-01-27 21:47:37 +01:00
go -> SetRespawnTime ( duration > 0 ? duration / IN_MILLISECONDS : 0 );
go -> SetSpellId ( m_spellInfo -> Id );
2009-10-17 15:51:44 -07:00
2021-08-28 18:30:45 +02:00
ExecuteLogEffectSummonObject ( SpellEffectName ( effectInfo -> Effect ), go );
2010-08-27 17:49:32 +02:00
2018-02-10 16:43:01 -03:00
caster -> AddGameObject ( go );
2018-01-27 21:47:37 +01:00
map -> AddToMap ( go );
2008-10-11 14:16:25 -05:00
//END
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Send request
2015-04-02 18:43:33 +02:00
WorldPackets :: Duel :: DuelRequested packet ;
2018-01-27 21:47:37 +01:00
packet . ArbiterGUID = go -> GetGUID ();
2015-04-02 18:43:33 +02:00
packet . RequestedByGUID = caster -> GetGUID ();
packet . RequestedByWowAccount = caster -> GetSession () -> GetAccountGUID ();
2015-04-02 18:58:35 +01:00
WorldPacket const * worldPacket = packet . Write ();
2017-06-04 01:00:45 +02:00
caster -> SendDirectMessage ( worldPacket );
target -> SendDirectMessage ( worldPacket );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// create duel-info
2011-09-15 14:08:17 +02:00
DuelInfo * duel = new DuelInfo ;
2008-10-11 14:16:25 -05:00
duel -> initiator = caster ;
duel -> opponent = target ;
duel -> startTime = 0 ;
duel -> startTimer = 0 ;
2012-01-30 00:21:42 +01:00
duel -> isMounted = ( GetSpellInfo () -> Id == 62875 ); // Mounted Duel
2008-10-11 14:16:25 -05:00
caster -> duel = duel ;
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
DuelInfo * duel2 = new DuelInfo ;
2008-10-11 14:16:25 -05:00
duel2 -> initiator = caster ;
duel2 -> opponent = caster ;
duel2 -> startTime = 0 ;
duel2 -> startTimer = 0 ;
2012-01-30 00:21:42 +01:00
duel2 -> isMounted = ( GetSpellInfo () -> Id == 62875 ); // Mounted Duel
2008-10-11 14:16:25 -05:00
target -> duel = duel2 ;
2009-10-17 15:51:44 -07:00
2019-06-03 20:40:34 +02:00
caster -> SetDuelArbiter ( go -> GetGUID ());
target -> SetDuelArbiter ( go -> GetGUID ());
2010-09-13 01:42:14 +03:00
2010-12-22 21:25:23 +01:00
sScriptMgr -> OnPlayerDuelRequest ( target , caster );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectStuck ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2010-12-23 23:25:44 +01:00
if ( ! sWorld -> getBoolConfig ( CONFIG_CAST_UNSTUCK ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2013-07-20 21:52:05 +02:00
Player * player = m_caster -> ToPlayer ();
if ( ! player )
return ;
2009-10-17 15:51:44 -07:00
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "spells" , "Spell Effect: Stuck" );
2016-02-20 13:23:35 +01:00
TC_LOG_DEBUG ( "spells" , "Player %s (%s) used the auto-unstuck feature at map %u (%f, %f, %f)." , player -> GetName (). c_str (), player -> GetGUID (). ToString (). c_str (), player -> GetMapId (), player -> GetPositionX (), player -> GetPositionY (), player -> GetPositionZ ());
2009-10-17 15:51:44 -07:00
2013-07-20 21:52:05 +02:00
if ( player -> IsInFlight ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2015-01-26 20:25:37 +00:00
// if player is dead without death timer is teleported to graveyard, otherwise not apply the effect
if ( player -> isDead ())
{
if ( ! player -> GetDeathTimer ())
player -> RepopAtGraveyard ();
2015-01-30 23:58:16 +01:00
2015-01-26 20:25:37 +00:00
return ;
}
2015-01-27 14:08:13 -06:00
// the player dies if hearthstone is in cooldown, else the player is teleported to home
2015-02-17 01:01:44 +01:00
if ( player -> GetSpellHistory () -> HasCooldown ( 8690 ))
2015-01-27 14:08:13 -06:00
{
2018-01-13 06:45:21 -03:00
player -> KillSelf ();
2015-01-27 14:08:13 -06:00
return ;
}
2015-01-30 23:58:16 +01:00
2021-10-16 01:17:47 +02:00
player -> TeleportTo ( player -> m_homebind , TELE_TO_SPELL );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Stuck spell trigger Hearthstone cooldown
2020-06-12 01:29:18 +02:00
SpellInfo const * spellInfo = sSpellMgr -> GetSpellInfo ( 8690 , GetCastDifficulty ());
2010-04-07 19:14:10 +02:00
if ( ! spellInfo )
2008-10-11 14:16:25 -05:00
return ;
2013-07-20 21:52:05 +02:00
Spell spell ( player , spellInfo , TRIGGERED_FULL_MASK );
2008-10-11 14:16:25 -05:00
spell . SendSpellCooldown ();
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectSummonPlayer ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
// workaround - this effect should not use target map
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
2010-04-07 19:14:10 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
unitTarget -> ToPlayer () -> SendSummonRequestFrom ( unitCaster );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectActivateObject ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-07 19:14:10 +02:00
if ( ! gameObjTarget )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-07-05 02:58:14 +01:00
ScriptInfo activateCommand ;
activateCommand . command = SCRIPT_COMMAND_ACTIVATE_OBJECT ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
// int32 unk = effectInfo->MiscValue; // This is set for EffectActivateObject spells; needs research
2009-10-17 15:51:44 -07:00
2011-07-05 02:58:14 +01:00
gameObjTarget -> GetMap () -> ScriptCommandStart ( activateCommand , 0 , m_caster , gameObjTarget );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectApplyGlyph ()
2008-12-24 09:58:26 -06:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2013-07-20 21:52:05 +02:00
Player * player = m_caster -> ToPlayer ();
if ( ! player )
return ;
2016-08-25 19:12:00 +02:00
std :: vector < uint32 >& glyphs = player -> GetGlyphs ( player -> GetActiveTalentGroup ());
std :: size_t replacedGlyph = glyphs . size ();
for ( std :: size_t i = 0 ; i < glyphs . size (); ++ i )
{
if ( std :: vector < uint32 > const * activeGlyphBindableSpells = sDB2Manager . GetGlyphBindableSpells ( glyphs [ i ]))
{
if ( std :: find ( activeGlyphBindableSpells -> begin (), activeGlyphBindableSpells -> end (), m_misc . SpellId ) != activeGlyphBindableSpells -> end ())
{
replacedGlyph = i ;
player -> RemoveAurasDueToSpell ( sGlyphPropertiesStore . AssertEntry ( glyphs [ i ]) -> SpellID );
break ;
}
}
}
uint32 glyphId = effectInfo -> MiscValue ;
if ( replacedGlyph < glyphs . size ())
{
if ( glyphId )
glyphs [ replacedGlyph ] = glyphId ;
else
glyphs . erase ( glyphs . begin () + replacedGlyph );
}
else if ( glyphId )
glyphs . push_back ( glyphId );
if ( GlyphPropertiesEntry const * glyphProperties = sGlyphPropertiesStore . LookupEntry ( glyphId ))
2021-10-03 16:36:39 +02:00
player -> CastSpell ( player , glyphProperties -> SpellID , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2016-08-25 19:12:00 +02:00
WorldPackets :: Talent :: ActiveGlyphs activeGlyphs ;
activeGlyphs . Glyphs . emplace_back ( m_misc . SpellId , uint16 ( glyphId ));
activeGlyphs . IsFullUpdate = false ;
player -> SendDirectMessage ( activeGlyphs . Write ());
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectEnchantHeldItem ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2008-10-11 14:16:25 -05:00
// this is only item spell effect applied to main-hand weapon of target player (players in area)
2010-04-07 19:14:10 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2013-05-25 11:09:21 +02:00
Player * item_owner = unitTarget -> ToPlayer ();
2008-10-11 14:16:25 -05:00
Item * item = item_owner -> GetItemByPos ( INVENTORY_SLOT_BAG_0 , EQUIPMENT_SLOT_MAINHAND );
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
if ( ! item )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// must be equipped
2012-05-30 08:01:02 +02:00
if ( ! item -> IsEquipped ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
if ( effectInfo -> MiscValue )
2008-10-11 14:16:25 -05:00
{
2014-12-19 23:52:29 +01:00
uint32 enchant_id = effectInfo -> MiscValue ;
2015-10-20 17:31:21 +02:00
int32 duration = m_spellInfo -> GetDuration (); //Try duration index first ..
2010-04-07 19:14:10 +02:00
if ( ! duration )
2015-10-20 17:31:21 +02:00
duration = damage ; //+1; //Base points after ..
2010-04-07 19:14:10 +02:00
if ( ! duration )
2015-10-20 17:31:21 +02:00
duration = 10 * IN_MILLISECONDS ; //10 seconds for enchants which don't have listed duration
if ( m_spellInfo -> Id == 14792 ) // Venomhide Poison
duration = 5 * MINUTE * IN_MILLISECONDS ;
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
SpellItemEnchantmentEntry const * pEnchant = sSpellItemEnchantmentStore . LookupEntry ( enchant_id );
2010-04-07 19:14:10 +02:00
if ( ! pEnchant )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Always go to temp enchantment slot
EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Enchantment will not be applied if a different one already exists
2010-04-07 19:14:10 +02:00
if ( item -> GetEnchantmentId ( slot ) && item -> GetEnchantmentId ( slot ) != enchant_id )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Apply the temporary enchantment
2015-10-20 17:31:21 +02:00
item -> SetEnchantment ( slot , enchant_id , duration , 0 , m_caster -> GetGUID ());
2009-05-31 15:56:51 -05:00
item_owner -> ApplyEnchantment ( item , slot , true );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectDisEnchant ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2012-06-03 02:35:00 +02:00
if ( Player * caster = m_caster -> ToPlayer ())
{
caster -> UpdateCraftSkill ( m_spellInfo -> Id );
caster -> SendLoot ( itemTarget -> GetGUID (), LOOT_DISENCHANTING );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// item will be removed at disenchanting end
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectInebriate ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-07 19:14:10 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2012-08-07 17:45:10 +02:00
Player * player = unitTarget -> ToPlayer ();
uint8 currentDrunk = player -> GetDrunkValue ();
uint8 drunkMod = damage ;
if ( currentDrunk + drunkMod > 100 )
2012-01-03 13:15:33 +01:00
{
2012-08-07 17:45:10 +02:00
currentDrunk = 100 ;
if ( rand_chance () < 25.0f )
2021-10-03 16:36:39 +02:00
player -> CastSpell ( player , 67468 , CastSpellExtraArgs ()
. SetOriginalCastId ( m_castId )); // Drunken Vomit
2012-01-03 13:15:33 +01:00
}
2008-10-11 14:16:25 -05:00
else
currentDrunk += drunkMod ;
2012-08-07 17:45:10 +02:00
2009-05-31 15:56:51 -05:00
player -> SetDrunkValue ( currentDrunk , m_CastItem ? m_CastItem -> GetEntry () : 0 );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectFeedPet ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2011-12-10 15:40:55 +01:00
Player * player = m_caster -> ToPlayer ();
if ( ! player )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-09-25 13:29:17 +02:00
Item * foodItem = itemTarget ;
2010-04-07 19:14:10 +02:00
if ( ! foodItem )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-12-10 15:40:55 +01:00
Pet * pet = player -> GetPet ();
2010-04-07 19:14:10 +02:00
if ( ! pet )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2013-06-11 19:54:27 -02:30
if ( ! pet -> IsAlive ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2021-08-28 18:30:45 +02:00
ExecuteLogEffectDestroyItem ( SpellEffectName ( effectInfo -> Effect ), foodItem -> GetEntry ());
2010-09-02 22:04:08 +02:00
2021-04-22 23:02:19 +03:00
int32 pct ;
int32 levelDiff = int32 ( pet -> getLevel ()) - int32 ( foodItem -> GetTemplate () -> GetBaseItemLevel ());
if ( levelDiff >= 30 )
return ;
else if ( levelDiff >= 20 )
pct = int32 ( 12.5 ); // we can't pass double so keeping the cast here for future references
else if ( levelDiff >= 10 )
pct = 25 ;
else
pct = 50 ;
2008-10-11 14:16:25 -05:00
uint32 count = 1 ;
2011-12-10 15:40:55 +01:00
player -> DestroyItemCount ( foodItem , count , true );
2013-03-08 21:41:30 +01:00
/// @todo fix crash when a spell has two effects, both pointed at the same item target
2009-10-17 15:51:44 -07:00
2018-01-13 20:38:32 -03:00
CastSpellExtraArgs args ( TRIGGERED_FULL_MASK );
2021-10-03 16:36:39 +02:00
args . SetOriginalCastId ( m_castId );
2018-01-13 20:38:32 -03:00
args . AddSpellMod ( SPELLVALUE_BASE_POINT0 , pct );
m_caster -> CastSpell ( pet , effectInfo -> TriggerSpell , args );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectDismissPet ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2013-06-11 18:39:51 -02:30
if ( ! unitTarget || ! unitTarget -> IsPet ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-09-25 13:29:17 +02:00
Pet * pet = unitTarget -> ToPet ();
2021-08-28 18:30:45 +02:00
ExecuteLogEffectUnsummonObject ( SpellEffectName ( effectInfo -> Effect ), pet );
2011-09-25 13:29:17 +02:00
pet -> GetOwner () -> RemovePet ( pet , PET_SAVE_NOT_IN_SLOT );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectSummonObject ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
2014-12-19 23:52:29 +01:00
uint8 slot = effectInfo -> Effect - SPELL_EFFECT_SUMMON_OBJECT_SLOT1 ;
2018-02-10 16:43:01 -03:00
ObjectGuid guid = unitCaster -> m_ObjectSlot [ slot ];
2014-10-21 20:27:00 +02:00
if ( ! guid . IsEmpty ())
2008-10-11 14:16:25 -05:00
{
2018-02-10 16:43:01 -03:00
if ( GameObject * obj = unitCaster -> GetMap () -> GetGameObject ( guid ))
2009-07-30 11:45:51 +02:00
{
// Recast case - null spell id to make auras not be removed on object remove from world
if ( m_spellInfo -> Id == obj -> GetSpellId ())
obj -> SetSpellId ( 0 );
2018-02-10 16:43:01 -03:00
unitCaster -> RemoveGameObject ( obj , true );
2009-07-30 11:45:51 +02:00
}
2018-02-10 16:43:01 -03:00
unitCaster -> m_ObjectSlot [ slot ]. Clear ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-31 15:56:51 -05:00
float x , y , z ;
2008-10-11 14:16:25 -05:00
// If dest location if present
2009-08-29 23:20:16 -05:00
if ( m_targets . HasDst ())
2012-05-30 08:01:02 +02:00
destTarget -> GetPosition ( x , y , z );
2008-10-11 14:16:25 -05:00
// Summon in random point all other units if location present
else
2018-02-10 16:43:01 -03:00
unitCaster -> GetClosePoint ( x , y , z , DEFAULT_PLAYER_BOUNDING_RADIUS );
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
Map * map = m_caster -> GetMap ();
2018-01-27 21:47:37 +01:00
Position pos = Position ( x , y , z , m_caster -> GetOrientation ());
QuaternionData rot = QuaternionData :: fromEulerAnglesZYX ( m_caster -> GetOrientation (), 0.f , 0.f );
GameObject * go = GameObject :: CreateGameObject ( effectInfo -> MiscValue , map , pos , rot , 255 , GO_STATE_READY );
if ( ! go )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2018-01-28 11:37:20 +01:00
PhasingHandler :: InheritPhaseShift ( go , m_caster );
2014-06-01 22:27:29 -05:00
2018-02-10 16:43:01 -03:00
go -> SetFaction ( unitCaster -> GetFaction ());
go -> SetLevel ( unitCaster -> getLevel ());
2017-01-29 00:00:43 +01:00
int32 duration = m_spellInfo -> CalcDuration ( m_caster );
2018-02-10 16:43:01 -03:00
go -> SetRespawnTime ( duration > 0 ? duration / IN_MILLISECONDS : 0 );
2013-08-01 21:31:11 +02:00
go -> SetSpellId ( m_spellInfo -> Id );
2018-02-10 16:43:01 -03:00
unitCaster -> AddGameObject ( go );
2009-10-17 15:51:44 -07:00
2021-08-28 18:30:45 +02:00
ExecuteLogEffectSummonObject ( SpellEffectName ( effectInfo -> Effect ), go );
2010-08-27 17:49:32 +02:00
2013-08-01 21:31:11 +02:00
map -> AddToMap ( go );
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
unitCaster -> m_ObjectSlot [ slot ] = go -> GetGUID ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectResurrect ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2013-01-20 04:30:17 +01:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2013-06-11 19:54:27 -02:30
if ( unitTarget -> IsAlive () || ! unitTarget -> IsInWorld ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-10-07 19:45:43 -05:00
Player * target = unitTarget -> ToPlayer ();
2009-10-17 15:51:44 -07:00
2014-05-25 21:52:27 +02:00
if ( target -> IsResurrectRequested ()) // already have one active request
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-10-07 19:45:43 -05:00
uint32 health = target -> CountPctFromMaxHealth ( damage );
2012-10-02 12:17:42 +02:00
uint32 mana = CalculatePct ( target -> GetMaxPower ( POWER_MANA ), damage );
2009-10-17 15:51:44 -07:00
2021-08-28 18:30:45 +02:00
ExecuteLogEffectResurrect ( SpellEffectName ( effectInfo -> Effect ), target );
2010-08-27 17:49:32 +02:00
2013-01-01 21:57:31 +01:00
target -> SetResurrectRequestData ( m_caster , health , mana , 0 );
2011-10-07 19:45:43 -05:00
SendResurrectRequest ( target );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectAddExtraAttacks ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2014-10-18 20:51:00 +01:00
if ( ! unitTarget || ! unitTarget -> IsAlive ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
if ( unitTarget -> m_extraAttacks )
2009-06-27 16:37:29 +02:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
unitTarget -> m_extraAttacks = damage ;
2009-10-17 15:51:44 -07:00
2021-08-28 18:30:45 +02:00
ExecuteLogEffectExtraAttacks ( SpellEffectName ( effectInfo -> Effect ), unitTarget , damage );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectParry ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
if ( m_caster -> GetTypeId () == TYPEID_PLAYER )
m_caster -> ToPlayer () -> SetCanParry ( true );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectBlock ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
if ( m_caster -> GetTypeId () == TYPEID_PLAYER )
m_caster -> ToPlayer () -> SetCanBlock ( true );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectLeap ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2013-06-11 19:54:27 -02:30
if ( ! unitTarget || unitTarget -> IsInFlight ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! m_targets . HasDst ())
2008-11-01 18:52:59 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-04-25 21:19:30 +02:00
Position pos = destTarget -> GetPosition ();
2012-02-11 19:23:18 -05:00
unitTarget -> NearTeleportTo ( pos . GetPositionX (), pos . GetPositionY (), pos . GetPositionZ (), pos . GetOrientation (), unitTarget == m_caster );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectReputation ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-08-09 11:33:31 -06:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-12-10 15:40:55 +01:00
Player * player = unitTarget -> ToPlayer ();
2009-10-17 15:51:44 -07:00
2012-12-02 16:32:44 +01:00
int32 repChange = damage ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
uint32 factionId = effectInfo -> MiscValue ;
2009-10-17 15:51:44 -07:00
2012-12-02 16:32:44 +01:00
FactionEntry const * factionEntry = sFactionStore . LookupEntry ( factionId );
2010-08-09 11:33:31 -06:00
if ( ! factionEntry )
return ;
2012-12-02 16:32:44 +01:00
repChange = player -> CalculateReputationGain ( REPUTATION_SOURCE_SPELL , 0 , repChange , factionId );
2010-08-09 11:33:31 -06:00
2012-12-02 16:32:44 +01:00
player -> GetReputationMgr (). ModifyReputation ( factionEntry , repChange );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectQuestComplete ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2010-01-25 20:45:02 +01:00
return ;
2011-09-25 13:29:17 +02:00
Player * player = unitTarget -> ToPlayer ();
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
uint32 questId = effectInfo -> MiscValue ;
2011-06-15 20:46:49 +02:00
if ( questId )
2010-07-04 19:16:40 +02:00
{
2011-06-15 20:46:49 +02:00
Quest const * quest = sObjectMgr -> GetQuestTemplate ( questId );
if ( ! quest )
2011-06-15 20:24:47 +03:00
return ;
2011-06-15 20:46:49 +02:00
uint16 logSlot = player -> FindQuestSlot ( questId );
if ( logSlot < MAX_QUEST_LOG_SIZE )
player -> AreaExploredOrEventHappens ( questId );
2016-10-16 22:39:36 +02:00
else if ( quest -> HasFlag ( QUEST_FLAGS_TRACKING )) // Check if the quest is used as a serverside flag.
player -> SetRewardedQuest ( questId ); // If so, set status to rewarded without broadcasting it to client.
2010-07-04 19:16:40 +02:00
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectForceDeselect ()
2010-01-13 10:27:44 +01:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
float dist = unitCaster -> GetVisibilityRange ();
2017-02-04 20:21:12 +01:00
// clear focus
2021-05-01 20:16:10 +02:00
Trinity :: PacketSenderOwning < WorldPackets :: Combat :: BreakTarget > breakTarget ;
breakTarget . Data . UnitGUID = m_caster -> GetGUID ();
breakTarget . Data . Write ();
2018-02-10 16:43:01 -03:00
Trinity :: MessageDistDelivererToHostile < Trinity :: PacketSenderOwning < WorldPackets :: Combat :: BreakTarget >> notifierBreak ( unitCaster , breakTarget , dist );
2017-02-04 20:21:12 +01:00
Cell :: VisitWorldObjects ( m_caster , notifierBreak , dist );
// and selection
2021-05-01 20:16:10 +02:00
Trinity :: PacketSenderOwning < WorldPackets :: Spells :: ClearTarget > clearTarget ;
clearTarget . Data . Guid = m_caster -> GetGUID ();
clearTarget . Data . Write ();
2018-02-10 16:43:01 -03:00
Trinity :: MessageDistDelivererToHostile < Trinity :: PacketSenderOwning < WorldPackets :: Spells :: ClearTarget >> notifierClear ( unitCaster , clearTarget , dist );
2017-02-04 20:21:12 +01:00
Cell :: VisitWorldObjects ( m_caster , notifierClear , dist );
// we should also force pets to remove us from current target
Unit :: AttackerSet attackerSet ;
2018-02-10 16:43:01 -03:00
for ( Unit :: AttackerSet :: const_iterator itr = unitCaster -> getAttackers (). begin (); itr != unitCaster -> getAttackers (). end (); ++ itr )
2017-02-04 20:21:12 +01:00
if (( * itr ) -> GetTypeId () == TYPEID_UNIT && ! ( * itr ) -> CanHaveThreatList ())
attackerSet . insert ( * itr );
for ( Unit :: AttackerSet :: const_iterator itr = attackerSet . begin (); itr != attackerSet . end (); ++ itr )
( * itr ) -> AttackStop ();
2010-01-13 10:27:44 +01:00
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectSelfResurrect ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
2008-10-11 14:16:25 -05:00
return ;
2011-09-25 13:29:17 +02:00
2018-02-10 16:43:01 -03:00
Player * player = m_caster -> ToPlayer ();
if ( ! player || ! player -> IsInWorld () || player -> IsAlive ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 health = 0 ;
uint32 mana = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// flat case
2010-04-07 19:14:10 +02:00
if ( damage < 0 )
2008-10-11 14:16:25 -05:00
{
health = uint32 ( - damage );
2014-12-19 23:52:29 +01:00
mana = effectInfo -> MiscValue ;
2008-10-11 14:16:25 -05:00
}
// percent case
else
{
2018-02-10 16:43:01 -03:00
health = player -> CountPctFromMaxHealth ( damage );
if ( player -> GetMaxPower ( POWER_MANA ) > 0 )
mana = CalculatePct ( player -> GetMaxPower ( POWER_MANA ), damage );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
player -> ResurrectPlayer ( 0.0f );
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
player -> SetHealth ( health );
player -> SetPower ( POWER_MANA , mana );
player -> SetPower ( POWER_RAGE , 0 );
2018-01-03 16:39:00 +01:00
player -> SetFullPower ( POWER_ENERGY );
2011-11-25 15:28:36 +01:00
player -> SetPower ( POWER_FOCUS , 0 );
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
player -> SpawnCorpseBones ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectSkinning ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-07 22:59:46 +02:00
if ( unitTarget -> GetTypeId () != TYPEID_UNIT )
2008-10-11 14:16:25 -05:00
return ;
2018-02-10 16:43:01 -03:00
Player * player = m_caster -> ToPlayer ();
if ( ! player )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-03-07 18:30:53 +01:00
Creature * creature = unitTarget -> ToCreature ();
2017-07-29 21:40:28 +02:00
int32 targetLevel = creature -> GetLevelForTarget ( m_caster );
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
uint32 skill = creature -> GetCreatureTemplate () -> GetRequiredLootSkill ();
2009-10-17 15:51:44 -07:00
2019-06-03 20:40:34 +02:00
creature -> RemoveUnitFlag ( UNIT_FLAG_SKINNABLE );
creature -> AddDynamicFlag ( UNIT_DYNFLAG_LOOTABLE );
2018-02-10 16:43:01 -03:00
player -> SendLoot ( creature -> GetGUID (), LOOT_SKINNING );
2009-10-17 15:51:44 -07:00
2018-12-07 19:09:10 +01:00
if ( skill == SKILL_SKINNING )
{
int32 reqValue ;
if ( targetLevel <= 10 )
reqValue = 1 ;
else if ( targetLevel < 20 )
reqValue = ( targetLevel - 10 ) * 10 ;
else if ( targetLevel <= 73 )
reqValue = targetLevel * 5 ;
else if ( targetLevel < 80 )
reqValue = targetLevel * 10 - 365 ;
else if ( targetLevel <= 84 )
reqValue = targetLevel * 5 + 35 ;
else if ( targetLevel <= 87 )
reqValue = targetLevel * 15 - 805 ;
else if ( targetLevel <= 92 )
reqValue = ( targetLevel - 62 ) * 20 ;
else if ( targetLevel <= 104 )
reqValue = targetLevel * 5 + 175 ;
else if ( targetLevel <= 107 )
reqValue = targetLevel * 15 - 905 ;
else if ( targetLevel <= 112 )
reqValue = ( targetLevel - 72 ) * 20 ;
else if ( targetLevel <= 122 )
reqValue = ( targetLevel - 32 ) * 10 ;
else
reqValue = 900 ;
2009-10-17 15:51:44 -07:00
2018-12-07 19:09:10 +01:00
// TODO: Specialize skillid for each expansion
// new db field?
// tied to one of existing expansion fields in creature_template?
2009-10-17 15:51:44 -07:00
2018-12-07 19:09:10 +01:00
// Double chances for elites
m_caster -> ToPlayer () -> UpdateGatherSkill ( skill , damage , reqValue , creature -> isElite () ? 2 : 1 );
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectCharge ()
2008-10-11 14:16:25 -05:00
{
2012-09-03 20:30:30 +02:00
if ( ! unitTarget )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
2011-09-25 13:29:17 +02:00
if ( effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET )
{
2017-02-13 21:05:32 +01:00
// charge changes fall time
2018-02-10 16:43:01 -03:00
if ( unitCaster -> GetTypeId () == TYPEID_PLAYER )
unitCaster -> ToPlayer () -> SetFallInformation ( 0 , unitCaster -> GetPositionZ ());
2017-02-13 21:05:32 +01:00
2014-09-17 23:24:31 +02:00
float speed = G3D :: fuzzyGt ( m_spellInfo -> Speed , 0.0f ) ? m_spellInfo -> Speed : SPEED_CHARGE ;
2018-08-29 23:50:22 +02:00
2017-03-12 00:40:52 +01:00
Optional < Movement :: SpellEffectExtraData > spellEffectExtraData ;
if ( effectInfo -> MiscValueB )
{
spellEffectExtraData = boost :: in_place ();
spellEffectExtraData -> Target = unitTarget -> GetGUID ();
spellEffectExtraData -> SpellVisualId = effectInfo -> MiscValueB ;
}
2013-02-13 20:21:26 +01:00
// Spell is not using explicit target - no generated path
2017-06-20 18:31:36 +02:00
if ( ! m_preGeneratedPath )
2012-09-03 20:30:30 +02:00
{
2014-04-25 21:19:30 +02:00
//unitTarget->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ);
2017-03-23 00:43:04 +01:00
Position pos = unitTarget -> GetFirstCollisionPosition ( unitTarget -> GetCombatReach (), unitTarget -> GetRelativeAngle ( m_caster ));
2019-08-31 01:29:54 +02:00
if ( G3D :: fuzzyGt ( m_spellInfo -> Speed , 0.0f ) && m_spellInfo -> HasAttribute ( SPELL_ATTR9_SPECIAL_DELAY_CALCULATION ))
2018-08-29 23:50:22 +02:00
speed = pos . GetExactDist ( m_caster ) / speed ;
2018-02-10 16:43:01 -03:00
unitCaster -> GetMotionMaster () -> MoveCharge ( pos . m_positionX , pos . m_positionY , pos . m_positionZ , speed , EVENT_CHARGE , false , unitTarget , spellEffectExtraData . get_ptr ());
2012-09-03 20:30:30 +02:00
}
else
2018-08-29 23:50:22 +02:00
{
2019-08-31 01:29:54 +02:00
if ( G3D :: fuzzyGt ( m_spellInfo -> Speed , 0.0f ) && m_spellInfo -> HasAttribute ( SPELL_ATTR9_SPECIAL_DELAY_CALCULATION ))
2018-08-29 23:50:22 +02:00
{
G3D :: Vector3 pos = m_preGeneratedPath -> GetActualEndPosition ();
speed = Position ( pos . x , pos . y , pos . z ). GetExactDist ( m_caster ) / speed ;
}
2018-02-10 16:43:01 -03:00
unitCaster -> GetMotionMaster () -> MoveCharge ( * m_preGeneratedPath , speed , unitTarget , spellEffectExtraData . get_ptr ());
2018-08-29 23:50:22 +02:00
}
2011-09-25 13:29:17 +02:00
}
if ( effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET )
{
// not all charge effects used in negative spells
if ( ! m_spellInfo -> IsPositive () && m_caster -> GetTypeId () == TYPEID_PLAYER )
2018-02-10 16:43:01 -03:00
unitCaster -> Attack ( unitTarget , true );
2016-01-25 19:35:41 +01:00
if ( effectInfo -> TriggerSpell )
2021-10-03 14:58:35 +02:00
m_caster -> CastSpell ( unitTarget , effectInfo -> TriggerSpell , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
2021-10-03 16:36:39 +02:00
. SetOriginalCaster ( m_originalCasterGUID )
. SetOriginalCastId ( m_castId ));
2011-09-25 13:29:17 +02:00
}
2009-07-01 17:36:34 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectChargeDest ()
2009-07-01 17:36:34 -05:00
{
2017-03-12 00:40:52 +01:00
if ( ! destTarget )
2011-09-25 13:29:17 +02:00
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
2017-03-12 00:40:52 +01:00
if ( effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH )
2009-07-01 17:47:31 -05:00
{
2014-04-25 21:19:30 +02:00
Position pos = destTarget -> GetPosition ();
2017-08-17 12:03:56 -03:00
2018-02-10 16:43:01 -03:00
if ( ! unitCaster -> IsWithinLOS ( pos . GetPositionX (), pos . GetPositionY (), pos . GetPositionZ ()))
2017-08-17 12:03:56 -03:00
{
2018-02-10 16:43:01 -03:00
float angle = unitCaster -> GetRelativeAngle ( pos . GetPositionX (), pos . GetPositionY ());
float dist = unitCaster -> GetDistance ( pos );
pos = unitCaster -> GetFirstCollisionPosition ( dist , angle );
2017-08-17 12:03:56 -03:00
}
2011-12-10 01:43:04 +01:00
2018-02-10 16:43:01 -03:00
unitCaster -> GetMotionMaster () -> MoveCharge ( pos . m_positionX , pos . m_positionY , pos . m_positionZ );
2009-07-01 17:47:31 -05:00
}
2017-03-12 00:40:52 +01:00
else if ( effectHandleMode == SPELL_EFFECT_HANDLE_HIT )
{
if ( effectInfo -> TriggerSpell )
2021-10-03 14:58:35 +02:00
m_caster -> CastSpell ( * destTarget , effectInfo -> TriggerSpell , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
2021-10-03 16:36:39 +02:00
. SetOriginalCaster ( m_originalCasterGUID )
. SetOriginalCastId ( m_castId ));
2017-03-12 00:40:52 +01:00
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectKnockBack ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-07 19:14:10 +02:00
if ( ! unitTarget )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
if ( m_caster -> GetAffectingPlayer ())
2017-06-14 14:16:12 +02:00
if ( Creature * creatureTarget = unitTarget -> ToCreature ())
if ( creatureTarget -> isWorldBoss () || creatureTarget -> IsDungeonBoss ())
return ;
2011-05-07 22:16:30 +02:00
2013-01-20 04:30:17 +01:00
// Spells with SPELL_EFFECT_KNOCK_BACK (like Thunderstorm) can't knockback target if target has ROOT/STUN
2012-07-28 23:19:45 +02:00
if ( unitTarget -> HasUnitState ( UNIT_STATE_ROOT | UNIT_STATE_STUNNED ))
2012-07-28 15:37:24 +02:00
return ;
2013-12-25 14:16:55 -03:30
// Instantly interrupt non melee spells being cast
if ( unitTarget -> IsNonMeleeSpellCast ( true ))
2011-05-05 18:08:01 -03:00
unitTarget -> InterruptNonMeleeSpells ( true );
2011-09-30 18:24:12 +02:00
float ratio = 0.1f ;
2014-12-19 23:52:29 +01:00
float speedxy = float ( effectInfo -> MiscValue ) * ratio ;
2009-08-25 16:34:17 -05:00
float speedz = float ( damage ) * ratio ;
2017-02-28 15:18:09 -03:00
if ( speedxy < 0.01f && speedz < 0.01f )
2009-08-25 16:34:17 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-02-06 21:48:47 -06:00
float x , y ;
2014-12-19 23:52:29 +01:00
if ( effectInfo -> Effect == SPELL_EFFECT_KNOCK_BACK_DEST )
2010-07-20 04:29:17 +02:00
{
if ( m_targets . HasDst ())
2012-05-30 08:01:02 +02:00
destTarget -> GetPosition ( x , y );
2010-07-20 04:29:17 +02:00
else
return ;
}
2011-07-26 23:09:28 +02:00
else //if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_KNOCK_BACK)
2009-08-29 23:20:16 -05:00
m_caster -> GetPosition ( x , y );
2009-10-17 15:51:44 -07:00
2009-04-11 22:41:15 -05:00
unitTarget -> KnockbackFrom ( x , y , speedxy , speedz );
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectLeapBack ()
2009-04-11 22:41:15 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET )
return ;
if ( ! unitTarget )
return ;
2015-02-15 15:01:36 +00:00
float speedxy = effectInfo -> MiscValue / 10.f ;
float speedz = damage / 10.f ;
2017-04-06 23:39:34 +02:00
// Disengage
unitTarget -> JumpTo ( speedxy , speedz , m_spellInfo -> IconFileDataId != 132572 );
2017-02-13 21:05:32 +01:00
// changes fall time
if ( m_caster -> GetTypeId () == TYPEID_PLAYER )
m_caster -> ToPlayer () -> SetFallInformation ( 0 , m_caster -> GetPositionZ ());
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectQuestClear ()
2010-07-04 19:16:40 +02:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-08-08 19:45:53 +02:00
2011-09-25 13:29:17 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2010-07-04 19:16:40 +02:00
return ;
2011-10-07 11:08:09 -05:00
Player * player = unitTarget -> ToPlayer ();
2010-07-04 19:16:40 +02:00
2014-12-19 23:52:29 +01:00
uint32 quest_id = effectInfo -> MiscValue ;
2010-07-04 19:16:40 +02:00
2011-10-07 19:45:43 -05:00
Quest const * quest = sObjectMgr -> GetQuestTemplate ( quest_id );
2010-07-04 19:16:40 +02:00
2011-10-07 19:45:43 -05:00
if ( ! quest )
2010-07-04 19:16:40 +02:00
return ;
2017-12-04 17:35:37 +01:00
QuestStatus oldStatus = player -> GetQuestStatus ( quest_id );
2010-07-04 19:16:40 +02:00
// Player has never done this quest
2017-12-04 17:35:37 +01:00
if ( oldStatus == QUEST_STATUS_NONE )
2010-07-04 19:16:40 +02:00
return ;
// remove all quest entries for 'entry' from quest log
for ( uint8 slot = 0 ; slot < MAX_QUEST_LOG_SIZE ; ++ slot )
{
2011-11-23 19:17:33 +01:00
uint32 logQuest = player -> GetQuestSlotQuestId ( slot );
if ( logQuest == quest_id )
2010-07-04 19:16:40 +02:00
{
2011-10-07 11:08:09 -05:00
player -> SetQuestSlot ( slot , 0 );
2010-07-04 19:16:40 +02:00
2011-11-23 19:17:33 +01:00
// we ignore unequippable quest items in this case, it's still be equipped
player -> TakeQuestSourceItem ( logQuest , false );
2013-02-26 17:14:13 +01:00
if ( quest -> HasFlag ( QUEST_FLAGS_FLAGS_PVP ))
{
player -> pvpInfo . IsHostile = player -> pvpInfo . IsInHostileArea || player -> HasPvPForcingQuest ();
player -> UpdatePvPState ();
}
2010-07-04 19:16:40 +02:00
}
}
2014-02-06 21:23:18 +01:00
player -> RemoveActiveQuest ( quest_id , false );
2011-10-07 11:08:09 -05:00
player -> RemoveRewardedQuest ( quest_id );
2016-09-09 22:11:36 +03:00
sScriptMgr -> OnQuestStatusChange ( player , quest_id );
2017-12-04 17:35:37 +01:00
sScriptMgr -> OnQuestStatusChange ( player , quest , oldStatus , QUEST_STATUS_NONE );
2010-07-04 19:16:40 +02:00
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectSendTaxi ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-07 19:14:10 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
unitTarget -> ToPlayer () -> ActivateTaxiPathTo ( effectInfo -> MiscValue , m_spellInfo -> Id );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectPullTowards ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-07 19:14:10 +02:00
if ( ! unitTarget )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-08-09 02:31:42 +02:00
Position pos ;
2014-12-19 23:52:29 +01:00
if ( effectInfo -> Effect == SPELL_EFFECT_PULL_TOWARDS_DEST )
2010-08-09 02:31:42 +02:00
{
if ( m_targets . HasDst ())
2012-05-30 08:01:02 +02:00
pos . Relocate ( * destTarget );
2010-08-09 02:31:42 +02:00
else
return ;
}
2011-07-26 23:09:28 +02:00
else //if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_PULL_TOWARDS)
2010-08-09 02:31:42 +02:00
{
pos . Relocate ( m_caster );
}
2014-12-19 23:52:29 +01:00
float speedXY = float ( effectInfo -> MiscValue ) * 0.1f ;
2013-12-31 13:08:45 +01:00
float speedZ = unitTarget -> GetDistance ( pos ) / speedXY * 0.5f * Movement :: gravity ;
2016-02-10 17:41:19 +01:00
unitTarget -> GetMotionMaster () -> MoveJump ( pos , speedXY , speedZ );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectChangeRaidMarker ()
2015-05-19 02:55:53 +01:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
Player * player = m_caster -> ToPlayer ();
if ( ! player || ! m_targets . HasDst ())
return ;
Group * group = player -> GetGroup ();
if ( ! group || ( group -> isRaidGroup () && ! group -> IsLeader ( player -> GetGUID ()) && ! group -> IsAssistant ( player -> GetGUID ())))
return ;
float x , y , z ;
destTarget -> GetPosition ( x , y , z );
group -> AddRaidMarker ( damage , player -> GetMapId (), x , y , z );
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectDispelMechanic ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-07 19:14:10 +02:00
if ( ! unitTarget )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
uint32 mechanic = effectInfo -> MiscValue ;
2014-09-14 16:14:12 +02:00
DispelList dispel_list ;
2010-01-10 20:09:44 +01:00
Unit :: AuraMap const & auras = unitTarget -> GetOwnedAuras ();
for ( Unit :: AuraMap :: const_iterator itr = auras . begin (); itr != auras . end (); ++ itr )
2009-04-13 18:56:29 +02:00
{
2011-09-15 14:08:17 +02:00
Aura * aura = itr -> second ;
2010-01-10 20:09:44 +01:00
if ( ! aura -> GetApplicationOfTarget ( unitTarget -> GetGUID ()))
continue ;
2011-07-26 23:09:28 +02:00
if ( roll_chance_i ( aura -> CalcDispelChance ( unitTarget , ! unitTarget -> IsFriendlyTo ( m_caster ))))
if (( aura -> GetSpellInfo () -> GetAllEffectsMechanicMask () & ( 1 << mechanic )))
2016-12-11 15:04:25 -03:00
dispel_list . emplace_back ( aura -> GetId (), aura -> GetCasterGUID ());
2009-04-13 18:56:29 +02:00
}
2009-10-17 15:51:44 -07:00
2016-12-11 15:04:25 -03:00
for ( auto itr = dispel_list . begin (); itr != dispel_list . end (); ++ itr )
unitTarget -> RemoveAura ( itr -> first , itr -> second , 0 , AURA_REMOVE_BY_ENEMY_SPELL );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectResurrectPet ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2013-11-11 13:22:41 +01:00
if ( damage < 0 )
2008-10-11 14:16:25 -05:00
return ;
2011-12-10 13:48:41 +01:00
2013-11-11 13:22:41 +01:00
Player * player = m_caster -> ToPlayer ();
if ( ! player )
2008-10-11 14:16:25 -05:00
return ;
2011-12-10 13:48:41 +01:00
2013-11-11 13:22:41 +01:00
// Maybe player dismissed dead pet or pet despawned?
bool hadPet = true ;
2014-01-17 17:54:52 +01:00
2013-11-11 13:22:41 +01:00
if ( ! player -> GetPet ())
2012-05-30 08:01:02 +02:00
{
2013-11-11 13:22:41 +01:00
// Position passed to SummonPet is irrelevant with current implementation,
// pet will be relocated without using these coords in Pet::LoadPetFromDB
player -> SummonPet ( 0 , 0.0f , 0.0f , 0.0f , 0.0f , SUMMON_PET , 0 );
hadPet = false ;
2012-05-30 08:01:02 +02:00
}
2013-11-11 13:22:41 +01:00
2014-01-18 01:05:03 +01:00
// TODO: Better to fail Hunter's "Revive Pet" at cast instead of here when casting ends
2013-11-11 13:22:41 +01:00
Pet * pet = player -> GetPet (); // Attempt to get current pet
2014-01-17 17:54:52 +01:00
if ( ! pet || pet -> IsAlive ())
2013-11-11 13:22:41 +01:00
return ;
// If player did have a pet before reviving, teleport it
if ( hadPet )
{
// Reposition the pet's corpse before reviving so as not to grab aggro
// We can use a different, more accurate version of GetClosePoint() since we have a pet
float x , y , z ; // Will be used later to reposition the pet if we have one
2017-03-23 00:43:04 +01:00
player -> GetClosePoint ( x , y , z , pet -> GetCombatReach (), PET_FOLLOW_DIST , pet -> GetFollowAngle ());
2013-11-11 13:22:41 +01:00
pet -> NearTeleportTo ( x , y , z , player -> GetOrientation ());
pet -> Relocate ( x , y , z , player -> GetOrientation ()); // This is needed so SaveStayPosition() will get the proper coords.
}
2010-01-16 19:11:32 +03:00
2019-06-03 20:40:34 +02:00
pet -> SetDynamicFlags ( UNIT_DYNFLAG_NONE );
pet -> RemoveUnitFlag ( UNIT_FLAG_SKINNABLE );
2010-04-07 22:59:46 +02:00
pet -> setDeathState ( ALIVE );
2017-03-25 12:16:13 +01:00
pet -> ClearUnitState ( UNIT_STATE_ALL_ERASABLE );
2010-08-26 01:20:57 +06:00
pet -> SetHealth ( pet -> CountPctFromMaxHealth ( damage ));
2009-10-17 15:51:44 -07:00
2013-11-11 13:22:41 +01:00
// Reset things for when the AI to takes over
CharmInfo * ci = pet -> GetCharmInfo ();
if ( ci )
{
// In case the pet was at stay, we don't want it running back
ci -> SaveStayPosition ();
ci -> SetIsAtStay ( ci -> HasCommandState ( COMMAND_STAY ));
ci -> SetIsFollowing ( false );
ci -> SetIsCommandAttack ( false );
ci -> SetIsCommandFollow ( false );
ci -> SetIsReturning ( false );
}
2008-10-11 14:16:25 -05:00
pet -> SavePetToDB ( PET_SAVE_AS_CURRENT );
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectDestroyAllTotems ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
2009-05-06 17:00:11 -05:00
int32 mana = 0 ;
2009-10-17 16:20:24 -07:00
for ( uint8 slot = SUMMON_SLOT_TOTEM ; slot < MAX_TOTEM_SLOT ; ++ slot )
2008-10-11 14:16:25 -05:00
{
2018-02-10 16:43:01 -03:00
if ( ! unitCaster -> m_SummonSlot [ slot ])
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
Creature * totem = unitCaster -> GetMap () -> GetCreature ( unitCaster -> m_SummonSlot [ slot ]);
2013-06-11 19:54:27 -02:30
if ( totem && totem -> IsTotem ())
2008-10-11 14:16:25 -05:00
{
2019-06-03 20:40:34 +02:00
uint32 spell_id = totem -> m_unitData -> CreatedBySpell ;
2020-06-12 01:29:18 +02:00
SpellInfo const * spellInfo = sSpellMgr -> GetSpellInfo ( spell_id , GetCastDifficulty ());
2010-04-07 19:14:10 +02:00
if ( spellInfo )
2009-04-12 01:29:56 +02:00
{
2018-02-10 16:43:01 -03:00
std :: vector < SpellPowerCost > costs = spellInfo -> CalcPowerCost ( unitCaster , spellInfo -> GetSchoolMask ());
2017-05-21 23:18:43 +02:00
auto m = std :: find_if ( costs . begin (), costs . end (), []( SpellPowerCost const & cost ) { return cost . Power == POWER_MANA ; });
2015-03-08 13:31:57 +01:00
if ( m != costs . end ())
mana += m -> Amount ;
2009-04-12 01:29:56 +02:00
}
2015-03-08 13:31:57 +01:00
2010-03-10 07:58:11 +01:00
totem -> ToTotem () -> UnSummon ();
2008-10-11 14:16:25 -05:00
}
}
2015-03-08 13:31:57 +01:00
2012-10-02 12:17:42 +02:00
ApplyPct ( mana , damage );
2015-03-08 13:31:57 +01:00
2009-05-06 17:00:11 -05:00
if ( mana )
2017-12-30 20:28:41 +01:00
{
CastSpellExtraArgs args ( TRIGGERED_FULL_MASK );
2021-10-03 16:36:39 +02:00
args . SetOriginalCastId ( m_castId );
2018-01-13 20:38:32 -03:00
args . AddSpellMod ( SPELLVALUE_BASE_POINT0 , mana );
2018-02-10 16:43:01 -03:00
unitCaster -> CastSpell ( unitCaster , 39104 , args );
2017-12-30 20:28:41 +01:00
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectDurabilityDamage ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-07 19:14:10 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
int32 slot = effectInfo -> MiscValue ;
2009-10-17 15:51:44 -07:00
2012-11-25 11:13:39 +01:00
// -1 means all player equipped items and -2 all items
2010-04-07 19:14:10 +02:00
if ( slot < 0 )
2008-10-11 14:16:25 -05:00
{
2010-03-07 15:20:19 +01:00
unitTarget -> ToPlayer () -> DurabilityPointsLossAll ( damage , ( slot < - 1 ));
2021-08-28 18:30:45 +02:00
ExecuteLogEffectDurabilityDamage ( SpellEffectName ( effectInfo -> Effect ), unitTarget , - 1 , - 1 );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// invalid slot value
2010-04-07 19:14:10 +02:00
if ( slot >= INVENTORY_SLOT_BAG_END )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( Item * item = unitTarget -> ToPlayer () -> GetItemByPos ( INVENTORY_SLOT_BAG_0 , slot ))
2012-10-20 00:02:32 +02:00
{
2010-03-07 15:20:19 +01:00
unitTarget -> ToPlayer () -> DurabilityPointsLoss ( item , damage );
2021-08-28 18:30:45 +02:00
ExecuteLogEffectDurabilityDamage ( SpellEffectName ( effectInfo -> Effect ), unitTarget , item -> GetEntry (), slot );
2012-10-20 00:02:32 +02:00
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectDurabilityDamagePCT ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-07 19:14:10 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
int32 slot = effectInfo -> MiscValue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// FIXME: some spells effects have value -1/-2
// Possibly its mean -1 all player equipped items and -2 all items
2010-04-07 19:14:10 +02:00
if ( slot < 0 )
2008-10-11 14:16:25 -05:00
{
2010-12-11 20:37:38 +06:00
unitTarget -> ToPlayer () -> DurabilityLossAll ( float ( damage ) / 100.0f , ( slot < - 1 ));
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// invalid slot value
2010-04-07 19:14:10 +02:00
if ( slot >= INVENTORY_SLOT_BAG_END )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( damage <= 0 )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( Item * item = unitTarget -> ToPlayer () -> GetItemByPos ( INVENTORY_SLOT_BAG_0 , slot ))
2010-12-11 20:37:38 +06:00
unitTarget -> ToPlayer () -> DurabilityLoss ( item , float ( damage ) / 100.0f );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectModifyThreatPercent ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster || ! unitTarget )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
unitTarget -> GetThreatManager (). ModifyThreatByPercent ( unitCaster , damage );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectTransmitted ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
uint32 name_id = effectInfo -> MiscValue ;
Unit :: AuraEffectList const & overrideSummonedGameObjects = unitCaster -> GetAuraEffectsByType ( SPELL_AURA_OVERRIDE_SUMMONED_OBJECT );
2017-02-11 13:04:12 +01:00
for ( AuraEffect const * aurEff : overrideSummonedGameObjects )
{
if ( uint32 ( aurEff -> GetMiscValue ()) == name_id )
{
name_id = uint32 ( aurEff -> GetMiscValueB ());
break ;
}
}
2011-04-28 22:54:30 +02:00
GameObjectTemplate const * goinfo = sObjectMgr -> GetGameObjectTemplate ( name_id );
2008-10-11 14:16:25 -05:00
if ( ! goinfo )
{
2016-02-20 13:23:35 +01:00
TC_LOG_ERROR ( "sql.sql" , "Gameobject (Entry: %u) does not exist and is not created by spell (ID: %u) cast." , name_id , m_spellInfo -> Id );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-05-31 15:56:51 -05:00
float fx , fy , fz ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_targets . HasDst ())
2012-05-30 08:01:02 +02:00
destTarget -> GetPosition ( fx , fy , fz );
2008-10-11 14:16:25 -05:00
//FIXME: this can be better check for most objects but still hack
2014-12-19 23:52:29 +01:00
else if ( effectInfo -> HasRadius () && m_spellInfo -> Speed == 0 )
2008-10-11 14:16:25 -05:00
{
2018-02-10 16:43:01 -03:00
float dis = effectInfo -> CalcRadius ( unitCaster );
unitCaster -> GetClosePoint ( fx , fy , fz , DEFAULT_PLAYER_BOUNDING_RADIUS , dis );
2008-10-11 14:16:25 -05:00
}
else
{
2009-02-14 15:56:04 +01:00
//GO is always friendly to it's creator, get range for friends
2011-07-26 23:09:28 +02:00
float min_dis = m_spellInfo -> GetMinRange ( true );
float max_dis = m_spellInfo -> GetMaxRange ( true );
2010-08-22 12:39:39 -07:00
float dis = ( float ) rand_norm () * ( max_dis - min_dis ) + min_dis ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
unitCaster -> GetClosePoint ( fx , fy , fz , DEFAULT_PLAYER_BOUNDING_RADIUS , dis );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
Map * cMap = unitCaster -> GetMap ();
2008-10-11 14:16:25 -05:00
// if gameobject is summoning object, it should be spawned right on caster's position
2014-10-06 18:37:38 -04:00
if ( goinfo -> type == GAMEOBJECT_TYPE_RITUAL )
2018-02-10 16:43:01 -03:00
unitCaster -> GetPosition ( fx , fy , fz );
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
Position pos = { fx , fy , fz , unitCaster -> GetOrientation () };
QuaternionData rot = QuaternionData :: fromEulerAnglesZYX ( unitCaster -> GetOrientation (), 0.f , 0.f );
2018-01-27 21:47:37 +01:00
GameObject * go = GameObject :: CreateGameObject ( name_id , cMap , pos , rot , 255 , GO_STATE_READY );
if ( ! go )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2018-01-28 11:37:20 +01:00
PhasingHandler :: InheritPhaseShift ( go , m_caster );
2017-01-29 00:00:43 +01:00
int32 duration = m_spellInfo -> CalcDuration ( m_caster );
2009-10-17 15:51:44 -07:00
2011-09-29 12:43:05 +02:00
switch ( goinfo -> type )
2008-10-11 14:16:25 -05:00
{
case GAMEOBJECT_TYPE_FISHINGNODE :
{
2018-02-10 16:43:01 -03:00
go -> SetFaction ( unitCaster -> GetFaction ());
2018-01-27 21:47:37 +01:00
ObjectGuid bobberGuid = go -> GetGUID ();
2017-07-04 20:30:16 +02:00
// client requires fishing bobber guid in channel object slot 0 to be usable
2018-02-10 16:43:01 -03:00
unitCaster -> SetChannelObject ( 0 , bobberGuid );
unitCaster -> AddGameObject ( go ); // will removed at spell cancel
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
// start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
2009-04-27 18:42:35 -05:00
int32 lastSec = 0 ;
2011-09-29 12:43:05 +02:00
switch ( urand ( 0 , 3 ))
2008-10-11 14:16:25 -05:00
{
case 0 : lastSec = 3 ; break ;
case 1 : lastSec = 7 ; break ;
case 2 : lastSec = 13 ; break ;
case 3 : lastSec = 17 ; break ;
}
2009-10-17 15:51:44 -07:00
2010-07-12 00:30:17 +02:00
duration = duration - lastSec * IN_MILLISECONDS + FISHING_BOBBER_READY_TIME * IN_MILLISECONDS ;
2008-10-11 14:16:25 -05:00
break ;
}
2014-10-06 18:37:38 -04:00
case GAMEOBJECT_TYPE_RITUAL :
2008-10-11 14:16:25 -05:00
{
2018-02-10 16:43:01 -03:00
if ( unitCaster -> GetTypeId () == TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
{
2018-02-10 16:43:01 -03:00
go -> AddUniqueUse ( unitCaster -> ToPlayer ());
unitCaster -> AddGameObject ( go ); // will be removed at spell cancel
2008-10-11 14:16:25 -05:00
}
break ;
}
2009-08-13 00:21:10 -05:00
case GAMEOBJECT_TYPE_DUEL_ARBITER : // 52991
2018-02-10 16:43:01 -03:00
unitCaster -> AddGameObject ( go );
2009-08-13 00:21:10 -05:00
break ;
2008-10-11 14:16:25 -05:00
case GAMEOBJECT_TYPE_FISHINGHOLE :
case GAMEOBJECT_TYPE_CHEST :
default :
break ;
}
2009-10-17 15:51:44 -07:00
2018-01-27 21:47:37 +01:00
go -> SetRespawnTime ( duration > 0 ? duration / IN_MILLISECONDS : 0 );
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
go -> SetOwnerGUID ( unitCaster -> GetGUID ());
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
//go->SetLevel(unitCaster->getLevel());
2018-01-27 21:47:37 +01:00
go -> SetSpellId ( m_spellInfo -> Id );
2009-10-17 15:51:44 -07:00
2021-08-28 18:30:45 +02:00
ExecuteLogEffectSummonObject ( SpellEffectName ( effectInfo -> Effect ), go );
2010-08-27 17:49:32 +02:00
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "spells" , "AddObject at SpellEfects.cpp EffectTransmitted" );
2018-02-10 16:43:01 -03:00
//unitCaster->AddGameObject(go);
2018-01-27 21:47:37 +01:00
//m_ObjToDel.push_back(go);
2009-10-17 15:51:44 -07:00
2018-01-27 21:47:37 +01:00
cMap -> AddToMap ( go );
2009-10-17 15:51:44 -07:00
2018-01-27 21:47:37 +01:00
if ( GameObject * linkedTrap = go -> GetLinkedTrap ())
2008-10-11 14:16:25 -05:00
{
2018-01-28 11:37:20 +01:00
PhasingHandler :: InheritPhaseShift ( linkedTrap , m_caster );
2014-06-01 22:27:29 -05:00
2016-11-01 22:24:03 +01:00
linkedTrap -> SetRespawnTime ( duration > 0 ? duration / IN_MILLISECONDS : 0 );
2018-02-10 16:43:01 -03:00
//linkedTrap->SetLevel(unitCaster->getLevel());
2016-11-01 22:24:03 +01:00
linkedTrap -> SetSpellId ( m_spellInfo -> Id );
2018-02-10 16:43:01 -03:00
linkedTrap -> SetOwnerGUID ( unitCaster -> GetGUID ());
2009-10-17 15:51:44 -07:00
2021-08-28 18:30:45 +02:00
ExecuteLogEffectSummonObject ( SpellEffectName ( effectInfo -> Effect ), linkedTrap );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectProspecting ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2013-07-20 21:52:05 +02:00
Player * player = m_caster -> ToPlayer ();
if ( ! player )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2016-09-09 10:22:57 +02:00
if ( ! itemTarget || ! ( itemTarget -> GetTemplate () -> GetFlags () & ITEM_FLAG_IS_PROSPECTABLE ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( itemTarget -> GetCount () < 5 )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-12-23 23:25:44 +01:00
if ( sWorld -> getBoolConfig ( CONFIG_SKILL_PROSPECTING ))
2008-10-11 14:16:25 -05:00
{
2013-07-20 21:52:05 +02:00
uint32 SkillValue = player -> GetPureSkillValue ( SKILL_JEWELCRAFTING );
2014-12-21 13:35:43 +01:00
uint32 reqSkillValue = itemTarget -> GetTemplate () -> GetRequiredSkillRank ();
2013-07-20 21:52:05 +02:00
player -> UpdateGatherSkill ( SKILL_JEWELCRAFTING , SkillValue , reqSkillValue );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2013-07-20 21:52:05 +02:00
player -> SendLoot ( itemTarget -> GetGUID (), LOOT_PROSPECTING );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectMilling ()
2008-12-24 09:58:26 -06:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2013-07-20 21:52:05 +02:00
Player * player = m_caster -> ToPlayer ();
if ( ! player )
2008-12-24 09:58:26 -06:00
return ;
2009-10-17 15:51:44 -07:00
2016-09-09 10:22:57 +02:00
if ( ! itemTarget || ! ( itemTarget -> GetTemplate () -> GetFlags () & ITEM_FLAG_IS_MILLABLE ))
2008-12-24 09:58:26 -06:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( itemTarget -> GetCount () < 5 )
2008-12-24 09:58:26 -06:00
return ;
2009-10-17 15:51:44 -07:00
2010-12-23 23:25:44 +01:00
if ( sWorld -> getBoolConfig ( CONFIG_SKILL_MILLING ))
2008-12-24 09:58:26 -06:00
{
2013-07-20 21:52:05 +02:00
uint32 SkillValue = player -> GetPureSkillValue ( SKILL_INSCRIPTION );
2014-12-21 13:35:43 +01:00
uint32 reqSkillValue = itemTarget -> GetTemplate () -> GetRequiredSkillRank ();
2013-07-20 21:52:05 +02:00
player -> UpdateGatherSkill ( SKILL_INSCRIPTION , SkillValue , reqSkillValue );
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2013-07-20 21:52:05 +02:00
player -> SendLoot ( itemTarget -> GetGUID (), LOOT_MILLING );
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectSkill ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "spells" , "WORLD: SkillEFFECT" );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
/* There is currently no need for this effect. We handle it in Battleground.cpp
2008-10-11 14:16:25 -05:00
If we would handle the resurrection here, the spiritguide would instantly disappear as the
player revives, and so we wouldn't see the spirit heal visual effect on the npc.
This is why we use a half sec delay between the visual effect and the resurrection itself */
2021-08-28 19:51:29 +02:00
void Spell :: EffectSpiritHeal ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
2008-10-11 14:16:25 -05:00
return ;
2011-09-25 13:29:17 +02:00
/*
2010-04-07 19:14:10 +02:00
if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2008-10-11 14:16:25 -05:00
return;
2010-04-07 19:14:10 +02:00
if (!unitTarget->IsInWorld())
2008-10-11 14:16:25 -05:00
return;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
//m_spellInfo->Effects[i].BasePoints; == 99 (percent?)
2010-03-07 15:20:19 +01:00
//unitTarget->ToPlayer()->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
unitTarget->ToPlayer()->ResurrectPlayer(1.0f);
unitTarget->ToPlayer()->SpawnCorpseBones();
2008-10-11 14:16:25 -05:00
*/
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// remove insignia spell effect
2021-08-28 19:51:29 +02:00
void Spell :: EffectSkinPlayerCorpse ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "spells" , "Effect: SkinPlayerCorpse" );
2013-07-20 21:52:05 +02:00
Player * player = m_caster -> ToPlayer ();
Player * target = unitTarget -> ToPlayer ();
if ( ! player || ! target || target -> IsAlive ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2013-07-20 21:52:05 +02:00
target -> RemovedInsignia ( player );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectStealBeneficialBuff ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "spells" , "Effect: StealBeneficialBuff" );
2009-10-17 15:51:44 -07:00
2010-04-07 23:25:02 +02:00
if ( ! unitTarget || unitTarget == m_caster ) // can't steal from self
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2016-12-11 15:04:25 -03:00
DispelChargesList stealList ;
2010-05-25 10:36:33 +02:00
2008-10-11 14:16:25 -05:00
// Create dispel mask by dispel type
2014-12-19 23:52:29 +01:00
uint32 dispelMask = SpellInfo :: GetDispelMask ( DispelType ( effectInfo -> MiscValue ));
2010-01-10 01:23:15 +01:00
Unit :: AuraMap const & auras = unitTarget -> GetOwnedAuras ();
2009-10-17 16:20:24 -07:00
for ( Unit :: AuraMap :: const_iterator itr = auras . begin (); itr != auras . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
2011-09-15 14:08:17 +02:00
Aura * aura = itr -> second ;
2016-12-11 15:04:25 -03:00
AuraApplication const * aurApp = aura -> GetApplicationOfTarget ( unitTarget -> GetGUID ());
2010-01-10 20:09:44 +01:00
if ( ! aurApp )
continue ;
2011-07-26 23:09:28 +02:00
if (( aura -> GetSpellInfo () -> GetDispelMask ()) & dispelMask )
2008-10-11 14:16:25 -05:00
{
// Need check for passive? this
2016-10-01 17:51:05 +02:00
if ( ! aurApp -> IsPositive () || aura -> IsPassive () || aura -> GetSpellInfo () -> HasAttribute ( SPELL_ATTR4_NOT_STEALABLE ))
2010-01-10 12:08:58 +01:00
continue ;
2016-12-11 15:04:25 -03:00
// 2.4.3 Patch Notes: "Dispel effects will no longer attempt to remove effects that have 100% dispel resistance."
int32 chance = aura -> CalcDispelChance ( unitTarget , ! unitTarget -> IsFriendlyTo ( m_caster ));
if ( ! chance )
continue ;
2010-05-25 10:36:33 +02:00
// The charges / stack amounts don't count towards the total number of auras that can be dispelled.
// Ie: A dispel on a target with 5 stacks of Winters Chill and a Polymorph has 1 / (1 + 1) -> 50% chance to dispell
// Polymorph instead of 1 / (5 + 1) -> 16%.
2016-10-01 17:51:05 +02:00
bool dispelCharges = aura -> GetSpellInfo () -> HasAttribute ( SPELL_ATTR7_DISPEL_CHARGES );
uint8 charges = dispelCharges ? aura -> GetCharges () : aura -> GetStackAmount ();
2010-05-25 10:36:33 +02:00
if ( charges > 0 )
2016-12-11 15:04:25 -03:00
stealList . emplace_back ( aura , chance , charges );
2008-10-11 14:16:25 -05:00
}
}
2010-05-25 10:36:33 +02:00
2016-12-11 15:04:25 -03:00
if ( stealList . empty ())
2010-05-25 10:36:33 +02:00
return ;
2016-12-11 15:04:25 -03:00
size_t remaining = stealList . size ();
2008-10-11 14:16:25 -05:00
// Ok if exist some buffs for dispel try dispel it
2016-12-11 15:04:25 -03:00
uint32 failCount = 0 ;
DispelList successList ;
successList . reserve ( damage );
2016-03-18 23:53:29 +01:00
WorldPackets :: Spells :: DispelFailed dispelFailed ;
dispelFailed . CasterGUID = m_caster -> GetGUID ();
dispelFailed . VictimGUID = unitTarget -> GetGUID ();
dispelFailed . SpellID = m_spellInfo -> Id ;
2010-05-25 10:36:33 +02:00
// dispel N = damage buffs (or while exist buffs for dispel)
2016-12-11 15:04:25 -03:00
for ( int32 count = 0 ; count < damage && remaining > 0 ;)
2008-10-11 14:16:25 -05:00
{
2010-05-25 10:36:33 +02:00
// Random select buff for dispel
2016-12-11 15:04:25 -03:00
DispelChargesList :: iterator itr = stealList . begin ();
std :: advance ( itr , urand ( 0 , remaining - 1 ));
2009-10-17 15:51:44 -07:00
2016-12-11 15:04:25 -03:00
if ( itr -> RollDispel ())
2008-10-11 14:16:25 -05:00
{
2016-12-11 15:04:25 -03:00
successList . emplace_back ( itr -> GetAura () -> GetId (), itr -> GetAura () -> GetCasterGUID ());
if ( ! itr -> DecrementCharge ())
{
-- remaining ;
std :: swap ( * itr , stealList [ remaining ]);
}
2008-10-11 14:16:25 -05:00
}
2010-05-25 10:36:33 +02:00
else
2008-10-11 14:16:25 -05:00
{
2016-12-11 15:04:25 -03:00
++ failCount ;
dispelFailed . FailedSpells . push_back ( int32 ( itr -> GetAura () -> GetId ()));
2008-10-11 14:16:25 -05:00
}
2016-12-11 15:04:25 -03:00
++ count ;
2008-10-11 14:16:25 -05:00
}
2010-05-25 10:36:33 +02:00
2016-03-18 23:53:29 +01:00
if ( ! dispelFailed . FailedSpells . empty ())
m_caster -> SendMessageToSet ( dispelFailed . Write (), true );
2010-05-25 10:36:33 +02:00
2016-12-11 15:04:25 -03:00
if ( successList . empty ())
2010-05-25 10:36:33 +02:00
return ;
2016-02-29 01:54:18 +00:00
WorldPackets :: CombatLog :: SpellDispellLog spellDispellLog ;
spellDispellLog . IsBreak = false ; // TODO: use me
spellDispellLog . IsSteal = true ;
spellDispellLog . TargetGUID = unitTarget -> GetGUID ();
spellDispellLog . CasterGUID = m_caster -> GetGUID ();
spellDispellLog . DispelledBySpellID = m_spellInfo -> Id ;
2016-12-11 15:04:25 -03:00
for ( std :: pair < uint32 , ObjectGuid > const & dispell : successList )
2010-05-25 10:36:33 +02:00
{
2016-02-29 01:54:18 +00:00
WorldPackets :: CombatLog :: SpellDispellData dispellData ;
dispellData . SpellID = dispell . first ;
dispellData . Harmful = false ; // TODO: use me
dispellData . Rolled = boost :: none ; // TODO: use me
dispellData . Needed = boost :: none ; // TODO: use me
unitTarget -> RemoveAurasDueToSpellBySteal ( dispell . first , dispell . second , m_caster );
spellDispellLog . DispellData . emplace_back ( dispellData );
2010-05-25 10:36:33 +02:00
}
2016-02-29 01:54:18 +00:00
m_caster -> SendMessageToSet ( spellDispellLog . Write (), true );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectKillCreditPersonal ()
2009-09-11 15:38:31 -07:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-07 19:14:10 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2009-09-11 15:38:31 -07:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
unitTarget -> ToPlayer () -> KilledMonsterCredit ( effectInfo -> MiscValue );
2009-09-11 15:38:31 -07:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectKillCredit ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-07 19:14:10 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2017-08-27 14:59:18 +02:00
if ( int32 creatureEntry = effectInfo -> MiscValue )
2010-03-07 15:20:19 +01:00
unitTarget -> ToPlayer () -> RewardPlayerAndGroupAtEvent ( creatureEntry , unitTarget );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectQuestFail ()
2008-10-11 14:16:25 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-07 19:14:10 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
unitTarget -> ToPlayer () -> FailQuest ( effectInfo -> MiscValue );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectQuestStart ()
2010-07-20 16:11:49 +02:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2014-04-21 16:48:05 +02:00
if ( ! unitTarget )
2010-07-20 16:11:49 +02:00
return ;
2011-06-11 22:35:29 +02:00
Player * player = unitTarget -> ToPlayer ();
2014-04-21 16:48:05 +02:00
if ( ! player )
return ;
2014-12-19 23:52:29 +01:00
if ( Quest const * quest = sObjectMgr -> GetQuestTemplate ( effectInfo -> MiscValue ))
2014-04-21 16:48:05 +02:00
{
if ( ! player -> CanTakeQuest ( quest , false ))
return ;
if ( quest -> IsAutoAccept () && player -> CanAddQuest ( quest , false ))
2017-11-28 00:04:03 +01:00
{
2014-04-21 16:48:05 +02:00
player -> AddQuestAndCheckCompletion ( quest , player );
2017-11-28 00:04:03 +01:00
player -> PlayerTalkClass -> SendQuestGiverQuestDetails ( quest , player -> GetGUID (), true , true );
}
else
player -> PlayerTalkClass -> SendQuestGiverQuestDetails ( quest , player -> GetGUID (), true , false );
2014-04-21 16:48:05 +02:00
}
2010-07-20 16:11:49 +02:00
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectCreateTamedPet ()
2010-07-20 22:55:28 +02:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2014-10-21 19:23:32 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER || ! unitTarget -> GetPetGUID (). IsEmpty () || unitTarget -> getClass () != CLASS_HUNTER )
2010-07-20 22:55:28 +02:00
return ;
2014-12-19 23:52:29 +01:00
uint32 creatureEntry = effectInfo -> MiscValue ;
2011-06-20 04:04:20 +07:00
Pet * pet = unitTarget -> CreateTamedPetFrom ( creatureEntry , m_spellInfo -> Id );
2010-07-20 22:55:28 +02:00
if ( ! pet )
return ;
2013-05-10 20:39:15 +02:00
// relocate
float px , py , pz ;
2017-03-23 00:43:04 +01:00
unitTarget -> GetClosePoint ( px , py , pz , pet -> GetCombatReach (), PET_FOLLOW_DIST , pet -> GetFollowAngle ());
2013-05-10 20:39:15 +02:00
pet -> Relocate ( px , py , pz , unitTarget -> GetOrientation ());
2010-07-20 22:55:28 +02:00
// add to world
2011-10-10 17:39:34 -04:00
pet -> GetMap () -> AddToMap ( pet -> ToCreature ());
2010-07-20 22:55:28 +02:00
// unitTarget has pet now
unitTarget -> SetMinion ( pet , true );
if ( unitTarget -> GetTypeId () == TYPEID_PLAYER )
{
pet -> SavePetToDB ( PET_SAVE_AS_CURRENT );
unitTarget -> ToPlayer () -> PetSpellInitialize ();
}
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectDiscoverTaxi ()
2010-07-20 18:27:18 +02:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-07-20 18:27:18 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
2014-12-19 23:52:29 +01:00
uint32 nodeid = effectInfo -> MiscValue ;
2010-07-20 18:27:18 +02:00
if ( sTaxiNodesStore . LookupEntry ( nodeid ))
unitTarget -> ToPlayer () -> GetSession () -> SendDiscoverNewTaxiNode ( nodeid );
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectTitanGrip ()
2008-12-24 09:58:26 -06:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
if ( m_caster -> GetTypeId () == TYPEID_PLAYER )
2016-10-02 07:34:23 +02:00
m_caster -> ToPlayer () -> SetCanTitanGrip ( true , uint32 ( effectInfo -> MiscValue ));
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectRedirectThreat ()
2008-12-17 20:07:25 -06:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
2010-04-07 19:14:10 +02:00
if ( unitTarget )
2018-02-10 16:43:01 -03:00
unitCaster -> GetThreatManager (). RegisterRedirectThreat ( m_spellInfo -> Id , unitTarget -> GetGUID (), uint32 ( damage ));
2009-01-06 15:48:42 -06:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectGameObjectDamage ()
2009-05-21 10:01:03 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2011-07-22 21:22:05 +02:00
if ( ! gameObjTarget )
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
FactionTemplateEntry const * casterFaction = m_caster -> GetFactionTemplateEntry ();
2019-06-03 20:40:34 +02:00
FactionTemplateEntry const * targetFaction = sFactionTemplateStore . LookupEntry ( gameObjTarget -> GetFaction ());
2011-07-22 21:22:05 +02:00
// Do not allow to damage GO's of friendly factions (ie: Wintergrasp Walls/Ulduar Storm Beacons)
2017-12-08 17:33:10 +01:00
if ( ! targetFaction || ( casterFaction && ! casterFaction -> IsFriendlyTo ( targetFaction )))
2018-02-10 16:43:01 -03:00
gameObjTarget -> ModifyHealth ( - damage , m_caster , GetSpellInfo () -> Id );
2009-05-21 10:01:03 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectGameObjectRepair ()
2009-05-21 10:01:03 -05:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2011-07-22 21:22:05 +02:00
if ( ! gameObjTarget )
return ;
gameObjTarget -> ModifyHealth ( damage , m_caster );
2009-05-21 10:01:03 -05:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectGameObjectSetDestructionState ()
2010-12-01 20:59:05 +02:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2018-02-10 16:43:01 -03:00
if ( ! gameObjTarget )
2011-07-22 21:22:05 +02:00
return ;
2010-12-01 20:59:05 +02:00
2018-02-10 16:43:01 -03:00
gameObjTarget -> SetDestructibleState ( GameObjectDestructibleState ( effectInfo -> MiscValue ), m_caster , true );
2010-12-01 20:59:05 +02:00
}
2021-08-28 18:30:45 +02:00
void Spell :: SummonGuardian ( SpellEffectInfo const * effect , uint32 entry , SummonPropertiesEntry const * properties , uint32 numGuardians , ObjectGuid privateObjectOwner )
2009-03-20 14:01:46 -06:00
{
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
2009-03-18 21:16:24 -06:00
return ;
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
if ( unitCaster -> IsTotem ())
unitCaster = unitCaster -> ToTotem () -> GetOwner ();
2009-10-17 15:51:44 -07:00
2009-03-20 14:01:46 -06:00
// in another case summon new
2018-02-10 16:43:01 -03:00
uint8 level = unitCaster -> getLevel ();
2009-10-17 15:51:44 -07:00
2009-03-20 14:01:46 -06:00
// level of pet summoned using engineering item based at engineering skill level
2018-02-10 16:43:01 -03:00
if ( m_CastItem && unitCaster -> GetTypeId () == TYPEID_PLAYER )
2011-09-15 14:08:17 +02:00
if ( ItemTemplate const * proto = m_CastItem -> GetTemplate ())
2014-12-21 13:35:43 +01:00
if ( proto -> GetRequiredSkill () == SKILL_ENGINEERING )
2018-02-10 16:43:01 -03:00
if ( uint16 skill202 = unitCaster -> ToPlayer () -> GetSkillValue ( SKILL_ENGINEERING ))
2011-11-02 19:13:51 +07:00
level = skill202 / 5 ;
2009-10-17 15:51:44 -07:00
2009-03-20 14:01:46 -06:00
float radius = 5.0f ;
2017-01-29 00:00:43 +01:00
int32 duration = m_spellInfo -> CalcDuration ( m_originalCaster );
2009-10-17 15:51:44 -07:00
2010-04-19 09:26:37 +02:00
//TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
2018-02-10 16:43:01 -03:00
Map * map = unitCaster -> GetMap ();
2012-02-09 20:26:30 +01:00
for ( uint32 count = 0 ; count < numGuardians ; ++ count )
2009-03-20 14:01:46 -06:00
{
2009-08-29 14:58:45 -05:00
Position pos ;
2012-05-30 08:01:02 +02:00
if ( count == 0 )
pos = * destTarget ;
else
// randomize position for multiple summons
2018-02-10 16:43:01 -03:00
pos = unitCaster -> GetRandomPoint ( * destTarget , radius );
2009-10-17 15:51:44 -07:00
2018-02-10 16:43:01 -03:00
TempSummon * summon = map -> SummonCreature ( entry , pos , properties , duration , unitCaster , m_spellInfo -> Id , 0 , privateObjectOwner );
2009-11-01 17:53:07 -08:00
if ( ! summon )
2009-03-20 14:01:46 -06:00
return ;
2014-01-26 23:56:53 +01:00
2009-11-01 17:53:07 -08:00
if ( summon -> HasUnitTypeMask ( UNIT_MASK_GUARDIAN ))
2009-03-20 14:01:46 -06:00
(( Guardian * ) summon ) -> InitStatsForLevel ( level );
2009-10-17 15:51:44 -07:00
2018-03-12 18:20:26 +01:00
if ( properties && properties -> Control == SUMMON_CATEGORY_ALLY )
2018-02-10 16:43:01 -03:00
summon -> SetFaction ( unitCaster -> GetFaction ());
2011-04-27 16:22:42 +06:00
2010-03-19 00:21:57 +01:00
if ( summon -> HasUnitTypeMask ( UNIT_MASK_MINION ) && m_targets . HasDst ())
2018-04-01 13:52:36 +02:00
(( Minion * ) summon ) -> SetFollowAngle ( unitCaster -> GetAbsoluteAngle ( summon ));
2009-10-17 15:51:44 -07:00
2009-12-14 01:51:12 +01:00
if ( summon -> GetEntry () == 27893 )
2010-08-30 15:25:15 +02:00
{
2019-06-03 20:40:34 +02:00
UF :: VisibleItem const & weapon = m_caster -> ToPlayer () -> m_playerData -> VisibleItems [ EQUIPMENT_SLOT_MAINHAND ];
if ( weapon . ItemID )
2009-12-14 01:51:12 +01:00
{
2014-01-04 18:22:06 +01:00
summon -> SetDisplayId ( 11686 ); // modelid2
2019-06-03 20:40:34 +02:00
summon -> SetVirtualItem ( 0 , weapon . ItemID , weapon . ItemAppearanceModID , weapon . ItemVisual );
2009-12-14 01:51:12 +01:00
}
else
2014-01-04 18:22:06 +01:00
summon -> SetDisplayId ( 1126 ); // modelid1
2010-08-30 15:25:15 +02:00
}
2009-12-17 12:23:01 +01:00
2009-05-12 10:11:54 -05:00
summon -> AI () -> EnterEvadeMode ();
2010-08-27 17:49:32 +02:00
2021-08-28 18:30:45 +02:00
ExecuteLogEffectSummonObject ( SpellEffectName ( effect -> Effect ), summon );
2009-03-20 14:01:46 -06:00
}
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectRenamePet ()
2009-01-22 22:44:27 -06:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2009-01-22 22:44:27 -06:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_UNIT ||
2015-08-12 12:48:33 +02:00
! unitTarget -> IsPet () || (( Pet * ) unitTarget ) -> getPetType () != HUNTER_PET )
2009-01-22 22:44:27 -06:00
return ;
2009-10-17 15:51:44 -07:00
2019-06-03 20:40:34 +02:00
unitTarget -> AddPetFlag ( UNIT_PET_FLAG_CAN_BE_RENAMED );
2009-07-30 10:18:05 +08:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectPlayMusic ()
2009-07-30 10:18:05 +08:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2009-11-01 17:53:07 -08:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2009-07-30 10:18:05 +08:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-19 23:52:29 +01:00
uint32 soundid = effectInfo -> MiscValue ;
2009-10-17 15:51:44 -07:00
2016-01-24 15:56:10 +01:00
if ( ! sSoundKitStore . LookupEntry ( soundid ))
2009-07-30 10:18:05 +08:00
{
2016-02-20 13:23:35 +01:00
TC_LOG_ERROR ( "spells" , "EffectPlayMusic: Sound (Id: %u) does not exist in spell %u." , soundid , m_spellInfo -> Id );
2009-07-30 10:18:05 +08:00
return ;
}
2009-10-17 15:51:44 -07:00
2017-06-04 01:00:45 +02:00
unitTarget -> ToPlayer () -> SendDirectMessage ( WorldPackets :: Misc :: PlayMusic ( soundid ). Write ());
2009-07-30 10:18:05 +08:00
}
2009-10-17 15:51:44 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectActivateSpec ()
2009-08-14 17:24:52 -07:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2009-11-01 17:53:07 -08:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2009-08-14 17:24:52 -07:00
return ;
2009-10-17 15:51:44 -07:00
2017-03-21 17:36:44 +01:00
Player * player = unitTarget -> ToPlayer ();
uint32 specID = m_misc . SpecializationId ;
ChrSpecializationEntry const * spec = sChrSpecializationStore . AssertEntry ( specID );
// Safety checks done in Spell::CheckCast
if ( ! spec -> IsPetSpecialization ())
player -> ActivateTalentGroup ( spec );
else
player -> GetPet () -> SetSpecialization ( specID );
2009-08-14 17:24:52 -07:00
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectPlaySound ()
2010-01-10 01:23:15 +01:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2014-09-13 20:41:31 +02:00
if ( ! unitTarget )
return ;
Player * player = unitTarget -> ToPlayer ();
if ( ! player )
2010-01-10 01:23:15 +01:00
return ;
2011-09-29 12:43:05 +02:00
switch ( m_spellInfo -> Id )
2010-01-10 01:23:15 +01:00
{
2013-01-03 17:37:39 +01:00
case 91604 : // Restricted Flight Area
2014-09-13 20:41:31 +02:00
player -> GetSession () -> SendNotification ( LANG_ZONE_NOFLYZONE );
2013-01-03 17:37:39 +01:00
break ;
default :
2010-01-10 01:23:15 +01:00
break ;
}
2011-03-07 21:13:18 +01:00
2014-12-19 23:52:29 +01:00
uint32 soundId = effectInfo -> MiscValue ;
2011-03-07 21:13:18 +01:00
2016-01-24 15:56:10 +01:00
if ( ! sSoundKitStore . LookupEntry ( soundId ))
2011-03-07 21:13:18 +01:00
{
2016-02-20 13:23:35 +01:00
TC_LOG_ERROR ( "spells" , "EffectPlaySound: Sound (Id: %u) does not exist in spell %u." , soundId , m_spellInfo -> Id );
2011-03-07 21:13:18 +01:00
return ;
}
2014-09-13 20:41:31 +02:00
player -> PlayDirectSound ( soundId , player );
2010-01-10 01:23:15 +01:00
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectRemoveAura ()
2010-07-20 04:29:17 +02:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-07-20 04:29:17 +02:00
if ( ! unitTarget )
return ;
// there may be need of specifying casterguid of removed auras
2014-12-19 23:52:29 +01:00
unitTarget -> RemoveAurasDueToSpell ( effectInfo -> TriggerSpell );
2010-07-20 04:29:17 +02:00
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectDamageFromMaxHealthPCT ()
2012-12-31 02:10:04 +01:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget )
return ;
m_damage += unitTarget -> CountPctFromMaxHealth ( damage );
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectGiveCurrency ()
2013-01-01 17:48:09 +01:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
2017-02-25 00:05:21 +01:00
if ( ! sCurrencyTypesStore . LookupEntry ( effectInfo -> MiscValue ))
return ;
2014-12-19 23:52:29 +01:00
unitTarget -> ToPlayer () -> ModifyCurrency ( effectInfo -> MiscValue , damage );
2013-01-01 17:48:09 +01:00
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectCastButtons ()
2009-12-17 12:23:01 +01:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2018-02-10 16:43:01 -03:00
Player * player = m_caster -> ToPlayer ();
if ( ! player )
2009-12-17 12:23:01 +01:00
return ;
2014-12-19 23:52:29 +01:00
uint32 button_id = effectInfo -> MiscValue + 132 ;
uint32 n_buttons = effectInfo -> MiscValueB ;
2009-12-17 12:23:01 +01:00
2011-08-03 08:18:24 +02:00
for (; n_buttons ; -- n_buttons , ++ button_id )
2009-12-17 12:23:01 +01:00
{
2018-02-10 16:43:01 -03:00
ActionButton const * ab = player -> GetActionButton ( button_id );
2010-04-29 11:35:31 +02:00
if ( ! ab || ab -> GetType () != ACTION_BUTTON_SPELL )
continue ;
2009-12-17 12:23:01 +01:00
2011-09-05 15:21:37 +02:00
//! Action button data is unverified when it's set so it can be "hacked"
2011-07-31 14:10:47 +02:00
//! to contain invalid spells, so filter here.
2010-04-28 16:08:31 +02:00
uint32 spell_id = ab -> GetAction ();
if ( ! spell_id )
continue ;
2020-06-12 01:29:18 +02:00
SpellInfo const * spellInfo = sSpellMgr -> GetSpellInfo ( spell_id , GetCastDifficulty ());
2011-07-31 14:10:47 +02:00
if ( ! spellInfo )
2010-04-28 16:08:31 +02:00
continue ;
2009-12-17 12:23:01 +01:00
2018-02-10 16:43:01 -03:00
if ( ! player -> HasSpell ( spell_id ) || player -> GetSpellHistory () -> HasCooldown ( spell_id ))
2011-07-31 14:10:47 +02:00
continue ;
2015-01-05 23:49:43 +02:00
if ( ! spellInfo -> HasAttribute ( SPELL_ATTR9_SUMMON_PLAYER_TOTEM ))
2011-07-31 14:10:47 +02:00
continue ;
2011-09-05 14:01:50 +02:00
2017-12-30 20:28:41 +01:00
CastSpellExtraArgs args ;
args . TriggerFlags = TriggerCastFlags ( TRIGGERED_IGNORE_GCD | TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_CAST_DIRECTLY | TRIGGERED_DONT_REPORT_CAST_ERROR );
2021-10-03 16:36:39 +02:00
args . OriginalCastId = m_castId ;
2017-12-30 20:28:41 +01:00
args . CastDifficulty = GetCastDifficulty ();
m_caster -> CastSpell ( m_caster , spellInfo -> Id , args );
2009-12-17 12:23:01 +01:00
}
}
2009-12-26 18:25:49 +01:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectRechargeItem ()
2009-12-26 18:25:49 +01:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2017-07-29 18:01:12 +02:00
if ( ! unitTarget )
2009-12-26 18:25:49 +01:00
return ;
2017-07-29 18:01:12 +02:00
Player * player = unitTarget -> ToPlayer ();
2009-12-26 18:25:49 +01:00
if ( ! player )
return ;
2014-11-17 20:38:56 +01:00
2017-07-29 18:01:12 +02:00
if ( Item * item = player -> GetItemByEntry ( effectInfo -> ItemType ))
{
2020-06-05 00:27:40 +02:00
for ( ItemEffectEntry const * itemEffect : item -> GetEffects ())
if ( itemEffect -> LegacySlotIndex <= item -> m_itemData -> SpellCharges . size ())
item -> SetSpellCharges ( itemEffect -> LegacySlotIndex , itemEffect -> Charges );
2017-07-29 18:01:12 +02:00
item -> SetState ( ITEM_CHANGED , player );
2009-12-26 18:25:49 +01:00
}
}
2010-04-18 23:20:07 +02:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectBind ()
2010-04-18 23:20:07 +02:00
{
2011-09-25 13:29:17 +02:00
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2010-04-18 23:20:07 +02:00
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
2010-12-03 13:54:00 +01:00
Player * player = unitTarget -> ToPlayer ();
2010-04-18 23:20:07 +02:00
2012-12-08 23:46:16 +01:00
WorldLocation homeLoc ;
uint32 areaId = player -> GetAreaId ();
2010-04-18 23:20:07 +02:00
2014-12-19 23:52:29 +01:00
if ( effectInfo -> MiscValue )
areaId = effectInfo -> MiscValue ;
2012-12-08 23:46:16 +01:00
if ( m_targets . HasDst ())
homeLoc . WorldRelocate ( * destTarget );
2010-04-18 23:20:07 +02:00
else
2014-04-25 21:19:30 +02:00
homeLoc = player -> GetWorldLocation ();
2010-04-18 23:20:07 +02:00
2012-12-08 23:46:16 +01:00
player -> SetHomebind ( homeLoc , areaId );
2014-11-19 02:12:47 +01:00
player -> SendBindPointUpdate ();
2010-04-18 23:20:07 +02:00
2021-10-16 01:17:47 +02:00
TC_LOG_DEBUG ( "spells" , "EffectBind: New homebind X: %f, Y: %f, Z: %f O: %f, MapId: %u, AreaId: %u" ,
homeLoc . GetPositionX (), homeLoc . GetPositionY (), homeLoc . GetPositionZ (), homeLoc . GetOrientation (), homeLoc . GetMapId (), areaId );
2010-04-18 23:20:07 +02:00
// zone update
2021-10-13 18:08:50 +02:00
player -> SendPlayerBound ( m_caster -> GetGUID (), areaId );
2010-04-18 23:20:07 +02:00
}
2011-08-03 09:28:12 -07:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectTeleportToReturnPoint ()
2021-03-28 02:22:34 +03:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( Player * player = unitTarget -> ToPlayer ())
if ( WorldLocation const * dest = player -> GetStoredAuraTeleportLocation ( effectInfo -> MiscValue ))
player -> TeleportTo ( * dest , unitTarget == m_caster ? TELE_TO_SPELL | TELE_TO_NOT_LEAVE_COMBAT : 0 );
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectSummonRaFFriend ()
2011-09-25 13:29:17 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
2011-08-03 09:28:12 -07:00
2011-08-04 13:16:09 +02:00
if ( m_caster -> GetTypeId () != TYPEID_PLAYER || ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2011-08-03 09:28:12 -07:00
return ;
2021-10-03 16:36:39 +02:00
m_caster -> CastSpell ( unitTarget , effectInfo -> TriggerSpell , CastSpellExtraArgs ( TRIGGERED_FULL_MASK )
. SetOriginalCastId ( m_castId ));
2011-08-03 09:28:12 -07:00
}
2013-01-01 21:57:31 +01:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectUnlockGuildVaultTab ()
2013-07-06 15:03:23 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
// Safety checks done in Spell::CheckCast
Player * caster = m_caster -> ToPlayer ();
if ( Guild * guild = caster -> GetGuild ())
2018-08-11 15:08:57 +02:00
guild -> HandleBuyBankTab ( caster -> GetSession (), damage - 1 ); // Bank tabs start at zero internally
2013-07-06 15:03:23 +02:00
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectSummonPersonalGameObject ()
2021-01-23 17:44:47 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
uint32 goId = effectInfo -> MiscValue ;
if ( ! goId )
return ;
float x , y , z ;
if ( m_targets . HasDst ())
destTarget -> GetPosition ( x , y , z );
else
m_caster -> GetClosePoint ( x , y , z , DEFAULT_PLAYER_BOUNDING_RADIUS );
Map * map = m_caster -> GetMap ();
Position pos = Position ( x , y , z , m_caster -> GetOrientation ());
QuaternionData rot = QuaternionData :: fromEulerAnglesZYX ( m_caster -> GetOrientation (), 0.f , 0.f );
GameObject * go = GameObject :: CreateGameObject ( goId , map , pos , rot , 255 , GO_STATE_READY );
if ( ! go )
{
2021-08-28 19:51:29 +02:00
TC_LOG_WARN ( "spells" , "SpellEffect Failed to summon personal gameobject. SpellId %u, effect %u" , m_spellInfo -> Id , effectInfo -> EffectIndex );
2021-01-23 17:44:47 +02:00
return ;
}
PhasingHandler :: InheritPhaseShift ( go , m_caster );
int32 duration = m_spellInfo -> CalcDuration ( m_caster );
go -> SetRespawnTime ( duration > 0 ? duration / IN_MILLISECONDS : 0 );
go -> SetSpellId ( m_spellInfo -> Id );
2021-03-14 21:23:07 +02:00
go -> SetPrivateObjectOwner ( m_caster -> GetGUID ());
2021-01-23 17:44:47 +02:00
2021-08-28 18:30:45 +02:00
ExecuteLogEffectSummonObject ( SpellEffectName ( effectInfo -> Effect ), go );
2021-01-23 17:44:47 +02:00
map -> AddToMap ( go );
if ( GameObject * linkedTrap = go -> GetLinkedTrap ())
{
PhasingHandler :: InheritPhaseShift ( linkedTrap , m_caster );
linkedTrap -> SetRespawnTime ( duration > 0 ? duration / IN_MILLISECONDS : 0 );
linkedTrap -> SetSpellId ( m_spellInfo -> Id );
2021-08-28 18:30:45 +02:00
ExecuteLogEffectSummonObject ( SpellEffectName ( effectInfo -> Effect ), linkedTrap );
2021-01-23 17:44:47 +02:00
}
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectResurrectWithAura ()
2013-01-01 21:57:31 +01:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget || ! unitTarget -> IsInWorld ())
return ;
Player * target = unitTarget -> ToPlayer ();
if ( ! target )
return ;
2013-06-13 19:35:01 +02:00
if ( unitTarget -> IsAlive ())
2013-01-01 21:57:31 +01:00
return ;
2014-05-25 21:52:27 +02:00
if ( target -> IsResurrectRequested ()) // already have one active request
2013-01-01 21:57:31 +01:00
return ;
uint32 health = target -> CountPctFromMaxHealth ( damage );
uint32 mana = CalculatePct ( target -> GetMaxPower ( POWER_MANA ), damage );
uint32 resurrectAura = 0 ;
2020-06-12 01:29:18 +02:00
if ( sSpellMgr -> GetSpellInfo ( effectInfo -> TriggerSpell , DIFFICULTY_NONE ))
2014-12-19 23:52:29 +01:00
resurrectAura = effectInfo -> TriggerSpell ;
2013-01-01 21:57:31 +01:00
if ( resurrectAura && target -> HasAura ( resurrectAura ))
return ;
2021-08-28 18:30:45 +02:00
ExecuteLogEffectResurrect ( SpellEffectName ( effectInfo -> Effect ), target );
2013-01-01 21:57:31 +01:00
target -> SetResurrectRequestData ( m_caster , health , mana , resurrectAura );
SendResurrectRequest ( target );
}
2013-05-26 04:47:10 +03:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectCreateAreaTrigger ()
2013-05-26 04:47:10 +03:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster || ! m_targets . HasDst ())
2017-01-29 00:00:43 +01:00
return ;
2013-05-26 04:47:10 +03:00
2017-01-29 00:00:43 +01:00
int32 duration = GetSpellInfo () -> CalcDuration ( GetCaster ());
2018-01-27 21:47:37 +01:00
2018-02-10 16:43:01 -03:00
AreaTrigger :: CreateAreaTrigger ( effectInfo -> MiscValue , unitCaster , nullptr , GetSpellInfo (), destTarget -> GetPosition (), duration , m_SpellVisual , m_castId );
2013-05-26 04:47:10 +03:00
}
2015-01-30 23:58:16 +01:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectRemoveTalent ()
2015-01-30 23:58:16 +01:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
TalentEntry const * talent = sTalentStore . LookupEntry ( m_misc . TalentId );
if ( ! talent )
return ;
Player * player = unitTarget ? unitTarget -> ToPlayer () : nullptr ;
if ( ! player )
return ;
player -> RemoveTalent ( talent );
player -> SendTalentsInfoData ();
}
2015-04-06 14:01:39 +02:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectDestroyItem ()
2015-04-06 14:01:39 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
Player * player = unitTarget -> ToPlayer ();
2018-08-11 15:08:57 +02:00
if ( Item * item = player -> GetItemByEntry ( effectInfo -> ItemType ))
2015-04-06 19:50:21 +02:00
player -> DestroyItem ( item -> GetBagSlot (), item -> GetSlot (), true );
2015-04-06 14:01:39 +02:00
}
2015-05-08 00:03:15 +02:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectLearnGarrisonBuilding ()
2015-05-08 00:03:15 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
if ( Garrison * garrison = unitTarget -> ToPlayer () -> GetGarrison ())
2018-08-11 15:08:57 +02:00
garrison -> LearnBlueprint ( effectInfo -> MiscValue );
2015-05-08 00:03:15 +02:00
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectCreateGarrison ()
2015-05-08 00:03:15 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
2018-08-11 15:08:57 +02:00
unitTarget -> ToPlayer () -> CreateGarrison ( effectInfo -> MiscValue );
2015-05-08 00:03:15 +02:00
}
2015-05-17 18:06:28 +02:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectCreateConversation ()
2017-05-14 11:40:55 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster || ! m_targets . HasDst ())
2017-05-14 11:40:55 +02:00
return ;
2021-10-09 13:30:47 +02:00
Conversation :: CreateConversation ( effectInfo -> MiscValue , unitCaster , destTarget -> GetPosition (), ObjectGuid :: Empty , GetSpellInfo ());
2017-05-14 11:40:55 +02:00
}
2021-10-11 14:50:04 +02:00
void Spell :: EffectCancelConversation ()
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget )
return ;
std :: vector < WorldObject *> objs ;
Trinity :: ObjectEntryAndPrivateOwnerIfExistsCheck check ( unitTarget -> GetGUID (), effectInfo -> MiscValue );
Trinity :: WorldObjectListSearcher < Trinity :: ObjectEntryAndPrivateOwnerIfExistsCheck > checker ( unitTarget , objs , check , GRID_MAP_TYPE_MASK_CONVERSATION );
Cell :: VisitGridObjects ( unitTarget , checker , 100.0f );
for ( WorldObject * obj : objs )
{
if ( Conversation * convo = obj -> ToConversation ())
convo -> Remove ();
}
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectAddGarrisonFollower ()
2015-05-17 18:06:28 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
if ( Garrison * garrison = unitTarget -> ToPlayer () -> GetGarrison ())
2018-08-11 15:08:57 +02:00
garrison -> AddFollower ( effectInfo -> MiscValue );
2015-05-17 18:06:28 +02:00
}
2015-06-22 00:02:02 +02:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectCreateHeirloomItem ()
2015-10-16 22:54:46 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
Player * player = m_caster -> ToPlayer ();
if ( ! player )
return ;
CollectionMgr * collectionMgr = player -> GetSession () -> GetCollectionMgr ();
if ( ! collectionMgr )
return ;
std :: vector < int32 > bonusList ;
bonusList . push_back ( collectionMgr -> GetHeirloomBonus ( m_misc . Raw . Data [ 0 ]));
2021-08-28 19:51:29 +02:00
DoCreateItem ( m_misc . Raw . Data [ 0 ], ItemContext :: NONE , bonusList );
2021-08-28 18:30:45 +02:00
ExecuteLogEffectCreateItem ( SpellEffectName ( effectInfo -> Effect ), m_misc . Raw . Data [ 0 ]);
2015-10-16 22:54:46 +02:00
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectActivateGarrisonBuilding ()
2015-06-22 00:02:02 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
if ( Garrison * garrison = unitTarget -> ToPlayer () -> GetGarrison ())
2018-08-11 15:08:57 +02:00
garrison -> ActivateBuilding ( effectInfo -> MiscValue );
2015-06-22 00:02:02 +02:00
}
2015-09-09 14:52:32 +02:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectHealBattlePetPct ()
2015-09-09 14:52:32 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
if ( BattlePetMgr * battlePetMgr = unitTarget -> ToPlayer () -> GetSession () -> GetBattlePetMgr ())
2018-08-11 15:08:57 +02:00
battlePetMgr -> HealBattlePetsPct ( damage );
2015-09-09 14:52:32 +02:00
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectEnableBattlePets ()
2015-09-09 14:52:32 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
Player * plr = unitTarget -> ToPlayer ();
2019-06-03 20:40:34 +02:00
plr -> AddPlayerFlag ( PLAYER_FLAGS_PET_BATTLES_UNLOCKED );
2015-09-09 14:52:32 +02:00
plr -> GetSession () -> GetBattlePetMgr () -> UnlockSlot ( 0 );
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectLaunchQuestChoice ()
2017-12-17 14:40:04 +01:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget || ! unitTarget -> IsPlayer ())
return ;
2017-12-31 18:37:09 +01:00
unitTarget -> ToPlayer () -> SendPlayerChoice ( GetCaster () -> GetGUID (), effectInfo -> MiscValue );
2017-12-17 14:40:04 +01:00
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectUncageBattlePet ()
2015-09-09 14:52:32 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
if ( ! m_CastItem || ! m_caster || m_caster -> GetTypeId () != TYPEID_PLAYER )
return ;
uint32 speciesId = m_CastItem -> GetModifier ( ITEM_MODIFIER_BATTLE_PET_SPECIES_ID );
uint16 breed = m_CastItem -> GetModifier ( ITEM_MODIFIER_BATTLE_PET_BREED_DATA ) & 0xFFFFFF ;
uint8 quality = ( m_CastItem -> GetModifier ( ITEM_MODIFIER_BATTLE_PET_BREED_DATA ) >> 24 ) & 0xFF ;
uint16 level = m_CastItem -> GetModifier ( ITEM_MODIFIER_BATTLE_PET_LEVEL );
2021-10-16 12:15:03 +02:00
uint32 displayId = m_CastItem -> GetModifier ( ITEM_MODIFIER_BATTLE_PET_DISPLAY_ID );
2015-09-09 14:52:32 +02:00
BattlePetSpeciesEntry const * speciesEntry = sBattlePetSpeciesStore . LookupEntry ( speciesId );
if ( ! speciesEntry )
return ;
2021-10-16 12:15:03 +02:00
Player * plr = m_caster -> ToPlayer ();
2015-09-09 14:52:32 +02:00
BattlePetMgr * battlePetMgr = plr -> GetSession () -> GetBattlePetMgr ();
if ( ! battlePetMgr )
return ;
2018-01-02 14:04:09 +01:00
if ( battlePetMgr -> GetMaxPetLevel () < level )
2015-09-09 14:52:32 +02:00
{
2021-10-16 12:15:03 +02:00
battlePetMgr -> SendError ( BATTLEPETRESULT_TOO_HIGH_LEVEL_TO_UNCAGE , speciesEntry -> CreatureID );
2015-09-09 14:52:32 +02:00
SendCastResult ( SPELL_FAILED_CANT_ADD_BATTLE_PET );
return ;
}
2021-09-29 22:26:25 +02:00
if ( battlePetMgr -> HasMaxPetCount ( speciesEntry ))
2015-09-09 14:52:32 +02:00
{
2021-10-16 12:15:03 +02:00
battlePetMgr -> SendError ( BATTLEPETRESULT_CANT_HAVE_MORE_PETS_OF_THAT_TYPE , speciesEntry -> CreatureID );
2015-09-09 14:52:32 +02:00
SendCastResult ( SPELL_FAILED_CANT_ADD_BATTLE_PET );
return ;
}
2021-10-16 12:15:03 +02:00
battlePetMgr -> AddPet ( speciesId , displayId , breed , BattlePetBreedQuality ( quality ), level );
2018-01-02 14:04:09 +01:00
2021-10-17 00:11:48 +02:00
if ( speciesEntry -> SummonSpellID )
if ( ! plr -> HasSpell ( speciesEntry -> SummonSpellID ))
plr -> LearnSpell ( speciesEntry -> SummonSpellID , false );
2015-09-09 14:52:32 +02:00
2021-10-16 12:15:03 +02:00
plr -> SendPlaySpellVisual ( plr , SPELL_VISUAL_UNCAGE_PET , 0 , 0 , 0.f , false );
2015-09-09 14:52:32 +02:00
plr -> DestroyItem ( m_CastItem -> GetBagSlot (), m_CastItem -> GetSlot (), true );
m_CastItem = nullptr ;
}
2015-10-16 22:54:46 +02:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectUpgradeHeirloom ()
2015-10-16 22:54:46 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
if ( Player * player = m_caster -> ToPlayer ())
if ( CollectionMgr * collectionMgr = player -> GetSession () -> GetCollectionMgr ())
2018-03-12 18:20:26 +01:00
collectionMgr -> UpgradeHeirloom ( m_misc . Raw . Data [ 0 ], int32 ( m_castItemEntry ));
2015-10-16 22:54:46 +02:00
}
2016-04-07 21:36:36 +02:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectApplyEnchantIllusion ()
2016-04-07 21:36:36 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! itemTarget )
return ;
Player * player = m_caster -> ToPlayer ();
if ( ! player || player -> GetGUID () != itemTarget -> GetOwnerGUID ())
return ;
itemTarget -> SetState ( ITEM_CHANGED , player );
2016-07-05 22:07:35 +02:00
itemTarget -> SetModifier ( ITEM_MODIFIER_ENCHANT_ILLUSION_ALL_SPECS , effectInfo -> MiscValue );
2016-04-07 21:36:36 +02:00
if ( itemTarget -> IsEquipped ())
2019-06-03 20:40:34 +02:00
player -> SetVisibleItemSlot ( itemTarget -> GetSlot (), itemTarget );
2016-04-07 21:36:36 +02:00
player -> RemoveTradeableItem ( itemTarget );
itemTarget -> ClearSoulboundTradeable ( player );
}
2016-04-13 20:24:51 +02:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectUpdatePlayerPhase ()
2016-04-13 20:24:51 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
2018-01-28 11:37:20 +01:00
PhasingHandler :: OnConditionChange ( unitTarget );
2016-04-13 20:24:51 +02:00
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectUpdateZoneAurasAndPhases ()
2016-04-13 20:24:51 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
unitTarget -> ToPlayer () -> UpdateAreaDependentAuras ( unitTarget -> GetAreaId ());
}
2016-08-15 00:03:38 +02:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectGiveArtifactPower ()
2016-08-15 00:03:38 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET )
return ;
2018-02-10 16:43:01 -03:00
Player * playerCaster = m_caster -> ToPlayer ();
if ( ! playerCaster )
2016-08-15 00:03:38 +02:00
return ;
2018-02-10 16:43:01 -03:00
if ( Aura * artifactAura = playerCaster -> GetAura ( ARTIFACTS_ALL_WEAPONS_GENERAL_WEAPON_EQUIPPED_PASSIVE ))
if ( Item * artifact = playerCaster -> GetItemByGuid ( artifactAura -> GetCastItemGUID ()))
2016-08-15 00:03:38 +02:00
artifact -> GiveArtifactXp ( damage , m_CastItem , uint32 ( effectInfo -> MiscValue ));
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectGiveArtifactPowerNoBonus ()
2016-08-15 00:03:38 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET )
return ;
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
if ( Aura * artifactAura = unitTarget -> GetAura ( ARTIFACTS_ALL_WEAPONS_GENERAL_WEAPON_EQUIPPED_PASSIVE ))
if ( Item * artifact = unitTarget -> ToPlayer () -> GetItemByGuid ( artifactAura -> GetCastItemGUID ()))
artifact -> GiveArtifactXp ( damage , m_CastItem , 0 );
}
2017-06-04 15:07:34 +02:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectPlaySceneScriptPackage ()
2021-03-04 20:31:08 +01:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
if ( m_caster -> GetTypeId () != TYPEID_PLAYER )
return ;
2021-10-05 22:36:22 +02:00
m_caster -> ToPlayer () -> GetSceneMgr (). PlaySceneByPackageId ( effectInfo -> MiscValue , SceneFlag :: PlayerNonInteractablePhased , destTarget );
2021-03-04 20:31:08 +01:00
}
2021-10-11 12:59:19 +02:00
template < typename TargetInfo >
bool IsUnitTargetSceneObjectAura ( Spell const * spell , TargetInfo const & target )
{
if ( target . TargetGUID != spell -> GetCaster () -> GetGUID ())
return false ;
for ( SpellEffectInfo const & spellEffectInfo : spell -> GetSpellInfo () -> GetEffects ())
if ( target . EffectMask & ( 1 << spellEffectInfo . EffectIndex ) && spellEffectInfo . IsUnitOwnedAuraEffect ())
return true ;
return false ;
}
void Spell :: EffectCreateSceneObject ()
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
if ( ! unitCaster || ! m_targets . HasDst ())
return ;
if ( SceneObject * sceneObject = SceneObject :: CreateSceneObject ( effectInfo -> MiscValue , unitCaster , destTarget -> GetPosition (), ObjectGuid :: Empty ))
{
bool hasAuraTargetingCaster = std :: find_if ( m_UniqueTargetInfo . begin (), m_UniqueTargetInfo . end (), [ this ]( TargetInfo const & target )
{
return IsUnitTargetSceneObjectAura ( this , target );
}) != m_UniqueTargetInfo . end ();
if ( hasAuraTargetingCaster )
sceneObject -> SetCreatedBySpellCast ( m_castId );
}
}
void Spell :: EffectCreatePrivateSceneObject ()
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
if ( ! unitCaster || ! m_targets . HasDst ())
return ;
if ( SceneObject * sceneObject = SceneObject :: CreateSceneObject ( effectInfo -> MiscValue , unitCaster , destTarget -> GetPosition (), unitCaster -> GetGUID ()))
{
bool hasAuraTargetingCaster = std :: find_if ( m_UniqueTargetInfo . begin (), m_UniqueTargetInfo . end (), [ this ]( TargetInfo const & target )
{
return IsUnitTargetSceneObjectAura ( this , target );
}) != m_UniqueTargetInfo . end ();
if ( hasAuraTargetingCaster )
sceneObject -> SetCreatedBySpellCast ( m_castId );
}
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectPlayScene ()
2017-06-04 15:07:34 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
if ( m_caster -> GetTypeId () != TYPEID_PLAYER )
return ;
m_caster -> ToPlayer () -> GetSceneMgr (). PlayScene ( effectInfo -> MiscValue , destTarget );
}
2017-06-04 16:51:47 +02:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectGiveHonor ()
2017-06-04 16:51:47 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
WorldPackets :: Combat :: PvPCredit packet ;
packet . Honor = damage ;
packet . OriginalHonor = damage ;
Player * playerTarget = unitTarget -> ToPlayer ();
playerTarget -> AddHonorXP ( damage );
playerTarget -> SendDirectMessage ( packet . Write ());
}
2017-08-24 20:39:22 +02:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectLearnTransmogSet ()
2017-08-24 20:39:22 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
return ;
unitTarget -> ToPlayer () -> GetSession () -> GetCollectionMgr () -> AddTransmogSet ( effectInfo -> MiscValue );
}
2019-11-22 11:02:04 +01:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectRespecAzeriteEmpoweredItem ()
2019-12-05 00:12:35 +01:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
if ( ! itemTarget || ! itemTarget -> IsAzeriteEmpoweredItem ())
return ;
Player * owner = m_caster -> ToPlayer ();
if ( ! owner )
return ;
AzeriteEmpoweredItem * azeriteEmpoweredItem = itemTarget -> ToAzeriteEmpoweredItem ();
owner -> ModifyMoney ( - azeriteEmpoweredItem -> GetRespecCost ());
// reapply all item mods - item level change affects stats and auras
if ( azeriteEmpoweredItem -> IsEquipped ())
owner -> _ApplyItemMods ( azeriteEmpoweredItem , azeriteEmpoweredItem -> GetSlot (), false );
azeriteEmpoweredItem -> ClearSelectedAzeritePowers ();
if ( azeriteEmpoweredItem -> IsEquipped ())
owner -> _ApplyItemMods ( azeriteEmpoweredItem , azeriteEmpoweredItem -> GetSlot (), true );
azeriteEmpoweredItem -> SetState ( ITEM_CHANGED , owner );
owner -> SetNumRespecs ( owner -> GetNumRespecs () + 1 );
}
2021-08-28 19:51:29 +02:00
void Spell :: EffectLearnAzeriteEssencePower ()
2019-11-22 11:02:04 +01:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET )
return ;
Player * playerTarget = unitTarget ? unitTarget -> ToPlayer () : nullptr ;
if ( ! playerTarget )
return ;
2021-04-21 11:02:42 +03:00
Item * heartOfAzeroth = playerTarget -> GetItemByEntry ( ITEM_ID_HEART_OF_AZEROTH , ItemSearchLocation :: Everywhere );
2019-11-22 11:02:04 +01:00
if ( ! heartOfAzeroth )
return ;
AzeriteItem * azeriteItem = heartOfAzeroth -> ToAzeriteItem ();
if ( ! azeriteItem )
return ;
// remove old rank and apply new one
if ( azeriteItem -> IsEquipped ())
{
if ( UF :: SelectedAzeriteEssences const * selectedEssences = azeriteItem -> GetSelectedAzeriteEssences ())
{
for ( int32 slot = 0 ; slot < MAX_AZERITE_ESSENCE_SLOT ; ++ slot )
{
if ( selectedEssences -> AzeriteEssenceID [ slot ] == uint32 ( effectInfo -> MiscValue ))
{
bool major = AzeriteItemMilestoneType ( sDB2Manager . GetAzeriteItemMilestonePower ( slot ) -> Type ) == AzeriteItemMilestoneType :: MajorEssence ;
playerTarget -> ApplyAzeriteEssence ( azeriteItem , effectInfo -> MiscValue , MAX_AZERITE_ESSENCE_RANK , major , false );
playerTarget -> ApplyAzeriteEssence ( azeriteItem , effectInfo -> MiscValue , effectInfo -> MiscValueB , major , false );
break ;
}
}
}
}
azeriteItem -> SetEssenceRank ( effectInfo -> MiscValue , effectInfo -> MiscValueB );
azeriteItem -> SetState ( ITEM_CHANGED , playerTarget );
}
2021-03-04 20:31:08 +01:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectCreatePrivateConversation ()
2021-03-04 20:31:08 +01:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster || ! unitTarget || unitTarget -> GetTypeId () != TYPEID_PLAYER )
2021-03-04 20:31:08 +01:00
return ;
2021-10-09 13:30:47 +02:00
Conversation :: CreateConversation ( effectInfo -> MiscValue , unitCaster , unitTarget -> GetPosition (), unitTarget -> GetGUID (), GetSpellInfo ());
2021-03-04 20:31:08 +01:00
}
2021-08-07 19:40:34 +02:00
2021-08-28 19:51:29 +02:00
void Spell :: EffectSendChatMessage ()
2021-08-07 19:40:34 +02:00
{
if ( effectHandleMode != SPELL_EFFECT_HANDLE_HIT )
return ;
2018-02-10 16:43:01 -03:00
if ( ! unitCaster )
return ;
2021-08-07 19:40:34 +02:00
uint32 broadcastTextId = effectInfo -> MiscValue ;
if ( ! sBroadcastTextStore . LookupEntry ( broadcastTextId ))
return ;
ChatMsg chatType = ChatMsg ( effectInfo -> MiscValueB );
2018-02-10 16:43:01 -03:00
unitCaster -> Talk ( broadcastTextId , chatType , CreatureTextMgr :: GetRangeForChatType ( chatType ), unitTarget );
2021-08-07 19:40:34 +02:00
}