diff --git a/src/game/Entities/Item/Item.cpp b/src/game/Entities/Item/Item.cpp index 8fa60a7ff..e4148240e 100644 --- a/src/game/Entities/Item/Item.cpp +++ b/src/game/Entities/Item/Item.cpp @@ -642,8 +642,11 @@ void Item::SetState(ItemUpdateState state, Player* forplayer) if (uState == ITEM_NEW && state == ITEM_REMOVED) { // pretend the item never existed - RemoveFromUpdateQueueOf(forplayer); - forplayer->DeleteRefundReference(GetGUIDLow()); + if (forplayer) + { + RemoveFromUpdateQueueOf(forplayer); + forplayer->DeleteRefundReference(GetGUIDLow()); + } delete this; return; } @@ -652,8 +655,8 @@ void Item::SetState(ItemUpdateState state, Player* forplayer) // new items must stay in new state until saved if (uState != ITEM_NEW) uState = state; - - AddToUpdateQueueOf(forplayer); + if (forplayer) + AddToUpdateQueueOf(forplayer); } else { diff --git a/src/game/Entities/Player/Player.cpp b/src/game/Entities/Player/Player.cpp index 623f5f60c..f1477c68a 100644 --- a/src/game/Entities/Player/Player.cpp +++ b/src/game/Entities/Player/Player.cpp @@ -15501,6 +15501,8 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, { Item* item = StoreNewItem(dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId)); SendNewItem(item, quest->RewardChoiceItemCount[reward], true, false); + + sScriptMgr->OnQuestRewardItem(this, item, quest->RewardChoiceItemCount[reward]); } else problematicItems.push_back(std::pair(itemId, quest->RewardChoiceItemCount[reward])); @@ -15518,6 +15520,8 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, { Item* item = StoreNewItem(dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId)); SendNewItem(item, quest->RewardItemIdCount[i], true, false); + + sScriptMgr->OnQuestRewardItem(this, item, quest->RewardItemIdCount[i]); } else problematicItems.push_back(std::pair(itemId, quest->RewardItemIdCount[i])); @@ -24743,6 +24747,8 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot) // LootItem is being removed (looted) from the container, delete it from the DB. if (loot->containerId > 0) sLootItemStorage->RemoveStoredLootItem(loot->containerId, item->itemid, item->count); + + sScriptMgr->OnLootItem(this, newitem, item->count, this->GetLootGUID()); } else SendEquipError(msg, NULL, NULL, item->itemid); diff --git a/src/game/Entities/Unit/Unit.cpp b/src/game/Entities/Unit/Unit.cpp index c35ac57c2..a4062b3f1 100644 --- a/src/game/Entities/Unit/Unit.cpp +++ b/src/game/Entities/Unit/Unit.cpp @@ -680,7 +680,10 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage if (attacker && attacker->IsAIEnabled) attacker->GetAI()->DamageDealt(victim, damage, damagetype); } - + + // Hook for OnDamage Event + sScriptMgr->OnDamage(attacker, victim, damage); + if (victim->GetTypeId() == TYPEID_PLAYER && attacker != victim) { // Signal to pets that their owner was attacked @@ -1181,7 +1184,10 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama default: break; } - + + // Script Hook For CalculateSpellDamageTaken -- Allow scripts to change the Damage post class mitigation calculations + sScriptMgr->ModifySpellDamageTaken(damageInfo->target, damageInfo->attacker, damage); + // Calculate absorb resist if (damage > 0) { @@ -1277,7 +1283,10 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam // Add melee damage bonus damage = MeleeDamageBonusDone(damageInfo->target, damage, damageInfo->attackType); damage = damageInfo->target->MeleeDamageBonusTaken(this, damage, damageInfo->attackType); - + + // Script Hook For CalculateMeleeDamage -- Allow scripts to change the Damage pre class mitigation calculations + sScriptMgr->ModifyMeleeDamage(damageInfo->target, damageInfo->attacker, damage); + // Calculate armor reduction if (IsDamageReducedByArmor((SpellSchoolMask)(damageInfo->damageSchoolMask))) { @@ -9943,7 +9952,10 @@ int32 Unit::DealHeal(Unit* healer, Unit* victim, uint32 addhealth) if (addhealth) gain = victim->ModifyHealth(int32(addhealth)); - + + // Hook for OnHeal Event + sScriptMgr->OnHeal(healer, victim, (uint32&)gain); + Unit* unit = healer; if (healer && healer->GetTypeId() == TYPEID_UNIT && healer->ToCreature()->IsTotem()) @@ -10209,7 +10221,9 @@ int32 Unit::HealBySpell(Unit* victim, SpellInfo const* spellInfo, uint32 addHeal uint32 absorb = 0; // calculate heal absorb and reduce healing CalcHealAbsorb(victim, spellInfo, addHealth, absorb); - + + sScriptMgr->ModifyHealRecieved(this, victim, addHealth); + int32 gain = Unit::DealHeal(this, victim, addHealth); SendHealSpellLog(victim, spellInfo->Id, addHealth, uint32(addHealth - gain), absorb, critical); return gain; diff --git a/src/game/Handlers/MovementHandler.cpp b/src/game/Handlers/MovementHandler.cpp index bf6fbdefa..8707e7685 100644 --- a/src/game/Handlers/MovementHandler.cpp +++ b/src/game/Handlers/MovementHandler.cpp @@ -23,6 +23,7 @@ #include "ArenaSpectator.h" #include "Chat.h" #include "BattlegroundMgr.h" +#include "ScriptMgr.h" #define MOVEMENT_PACKET_TIME_DELAY 0 @@ -392,6 +393,8 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recvData) // now client not include swimming flag in case jumping under water plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ())); } + if (plrMover)//Hook for OnPlayerMove + sScriptMgr->OnPlayerMove(plrMover, movementInfo, opcode); // Dont allow to turn on walking if charming other player if (mover->GetGUID() != _player->GetGUID()) movementInfo.flags &= ~MOVEMENTFLAG_WALKING; diff --git a/src/game/Scripting/ScriptMgr.cpp b/src/game/Scripting/ScriptMgr.cpp index 6ca910a33..ec5e6c825 100644 --- a/src/game/Scripting/ScriptMgr.cpp +++ b/src/game/Scripting/ScriptMgr.cpp @@ -602,6 +602,8 @@ void ScriptMgr::OnPlayerEnterMap(Map* map, Player* player) ASSERT(map); ASSERT(player); + FOREACH_SCRIPT(AllMapScript)->OnPlayerEnterAll(map, player); + FOREACH_SCRIPT(PlayerScript)->OnMapChanged(player); SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap); @@ -621,7 +623,9 @@ void ScriptMgr::OnPlayerLeaveMap(Map* map, Player* player) { ASSERT(map); ASSERT(player); - + + FOREACH_SCRIPT(AllMapScript)->OnPlayerLeaveAll(map, player); + SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap); itr->second->OnPlayerLeave(map, player); SCR_MAP_END; @@ -815,6 +819,8 @@ void ScriptMgr::OnCreatureUpdate(Creature* creature, uint32 diff) { ASSERT(creature); + FOREACH_SCRIPT(AllCreatureScript)->OnAllCreatureUpdate(creature, diff); + GET_SCRIPT(CreatureScript, creature->GetScriptId(), tmpscript); tmpscript->OnUpdate(creature, diff); } @@ -1335,19 +1341,33 @@ void ScriptMgr::OnAfterPlayerMoveItemFromInventory(Player* player, Item* it, uin void ScriptMgr::OnEquip(Player* player, Item* it, uint8 bag, uint8 slot, bool update) { - FOREACH_SCRIPT(PlayerScript)->OnEquip(player, it, bag, slot, update); + FOREACH_SCRIPT(PlayerScript)->OnEquip(player, it, bag, slot, update); } void ScriptMgr::OnPlayerJoinBG(Player* player, Battleground* bg) { - FOREACH_SCRIPT(PlayerScript)->OnPlayerJoinBG(player, bg); + FOREACH_SCRIPT(PlayerScript)->OnPlayerJoinBG(player, bg); } void ScriptMgr::OnPlayerJoinArena(Player* player, Battleground* bg) { - FOREACH_SCRIPT(PlayerScript)->OnPlayerJoinArena(player, bg); + FOREACH_SCRIPT(PlayerScript)->OnPlayerJoinArena(player, bg); } +void ScriptMgr::OnLootItem(Player* player, Item* item, uint32 count, uint64 lootguid) +{ + FOREACH_SCRIPT(PlayerScript)->OnLootItem(player, item, count, lootguid); +} + +void ScriptMgr::OnCreateItem(Player* player, Item* item, uint32 count) +{ + FOREACH_SCRIPT(PlayerScript)->OnCreateItem(player, item, count); +} + +void ScriptMgr::OnQuestRewardItem(Player* player, Item* item, uint32 count) +{ + FOREACH_SCRIPT(PlayerScript)->OnQuestRewardItem(player, item, count); +} // Guild void ScriptMgr::OnGuildAddMember(Guild* guild, Player* player, uint8& plRank) @@ -1455,6 +1475,76 @@ void ScriptMgr::OnBeforeUpdateArenaPoints(ArenaTeam* at, std::mapOnBeforeUpdateArenaPoints(at,ap); } +uint32 ScriptMgr::DealDamage(Unit* AttackerUnit, Unit *pVictim, uint32 damage, DamageEffectType damagetype) +{ + FOR_SCRIPTS_RET(UnitScript, itr, end, damage) + damage = itr->second->DealDamage(AttackerUnit, pVictim, damage, damagetype); + return damage; +} +void ScriptMgr::Creature_SelectLevel(const CreatureTemplate *cinfo, Creature* creature) +{ + FOREACH_SCRIPT(AllCreatureScript)->Creature_SelectLevel(cinfo, creature); +} +void ScriptMgr::OnHeal(Unit* healer, Unit* reciever, uint32& gain) +{ + FOREACH_SCRIPT(UnitScript)->OnHeal(healer, reciever, gain); +} + +void ScriptMgr::OnDamage(Unit* attacker, Unit* victim, uint32& damage) +{ + FOREACH_SCRIPT(UnitScript)->OnDamage(attacker, victim, damage); +} + +void ScriptMgr::ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage) +{ + FOREACH_SCRIPT(UnitScript)->ModifyPeriodicDamageAurasTick(target, attacker, damage); +} + +void ScriptMgr::ModifyMeleeDamage(Unit* target, Unit* attacker, uint32& damage) +{ + FOREACH_SCRIPT(UnitScript)->ModifyMeleeDamage(target, attacker, damage); +} + +void ScriptMgr::ModifySpellDamageTaken(Unit* target, Unit* attacker, int32& damage) +{ + FOREACH_SCRIPT(UnitScript)->ModifySpellDamageTaken(target, attacker, damage); +} + +void ScriptMgr::ModifyHealRecieved(Unit* target, Unit* attacker, uint32& damage) +{ + FOREACH_SCRIPT(UnitScript)->ModifyHealRecieved(target, attacker, damage); +} + +void ScriptMgr::OnPlayerMove(Player* player, MovementInfo movementInfo, uint32 opcode) +{ + FOREACH_SCRIPT(MovementHandlerScript)->OnPlayerMove(player, movementInfo, opcode); +} + +AllMapScript::AllMapScript(const char* name) + : ScriptObject(name) +{ + ScriptRegistry::AddScript(this); +} + +AllCreatureScript::AllCreatureScript(const char* name) + : ScriptObject(name) +{ + ScriptRegistry::AddScript(this); +} + +UnitScript::UnitScript(const char* name, bool addToScripts) + : ScriptObject(name) +{ + if (addToScripts) + ScriptRegistry::AddScript(this); +} + +MovementHandlerScript::MovementHandlerScript(const char* name) + : ScriptObject(name) +{ + ScriptRegistry::AddScript(this); +} + SpellScriptLoader::SpellScriptLoader(const char* name) : ScriptObject(name) { @@ -1636,6 +1726,10 @@ template class ScriptRegistry; template class ScriptRegistry; template class ScriptRegistry; template class ScriptRegistry; +template class ScriptRegistry; +template class ScriptRegistry; +template class ScriptRegistry; +template class ScriptRegistry; // Undefine utility macros. #undef GET_SCRIPT_RET diff --git a/src/game/Scripting/ScriptMgr.h b/src/game/Scripting/ScriptMgr.h index 38edd234b..b7fa6efe7 100644 --- a/src/game/Scripting/ScriptMgr.h +++ b/src/game/Scripting/ScriptMgr.h @@ -417,6 +417,77 @@ class ItemScript : public ScriptObject virtual void OnGossipSelectCode(Player* /*player*/, Item* /*item*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/) { } }; +class UnitScript : public ScriptObject +{ +protected: + + UnitScript(const char* name, bool addToScripts = true); + +public: + // Called when a unit deals healing to another unit + virtual void OnHeal(Unit* /*healer*/, Unit* /*reciever*/, uint32& /*gain*/) { } + + // Called when a unit deals damage to another unit + virtual void OnDamage(Unit* /*attacker*/, Unit* /*victim*/, uint32& /*damage*/) { } + + // Called when DoT's Tick Damage is being Dealt + virtual void ModifyPeriodicDamageAurasTick(Unit* /*target*/, Unit* /*attacker*/, uint32& /*damage*/) { } + + // Called when Melee Damage is being Dealt + virtual void ModifyMeleeDamage(Unit* /*target*/, Unit* /*attacker*/, uint32& /*damage*/) { } + + // Called when Spell Damage is being Dealt + virtual void ModifySpellDamageTaken(Unit* /*target*/, Unit* /*attacker*/, int32& /*damage*/) { } + + // Called when Heal is Recieved + virtual void ModifyHealRecieved(Unit* /*target*/, Unit* /*attacker*/, uint32& /*damage*/) { } + + //Called when Damage is Dealt + virtual uint32 DealDamage(Unit* AttackerUnit, Unit *pVictim, uint32 damage, DamageEffectType damagetype) { return damage; } +}; + +class MovementHandlerScript : public ScriptObject +{ +protected: + + MovementHandlerScript(const char* name); + +public: + + //Called whenever a player moves + virtual void OnPlayerMove(Player* /*player*/, MovementInfo /*movementInfo*/, uint32 /*opcode*/) { } +}; + +class AllMapScript : public ScriptObject +{ +protected: + + AllMapScript(const char* name); + +public: + + // Called when a player enters any Map + virtual void OnPlayerEnterAll(Map* /*map*/, Player* /*player*/) { } + + // Called when a player leave any Map + virtual void OnPlayerLeaveAll(Map* /*map*/, Player* /*player*/) { } +}; + +class AllCreatureScript : public ScriptObject +{ +protected: + + AllCreatureScript(const char* name); + +public: + + // Called from End of Creature Update. + virtual void OnAllCreatureUpdate(Creature* /*creature*/, uint32 /*diff*/) { } + + // Called from End of Creature SelectLevel. + virtual void Creature_SelectLevel(const CreatureTemplate* /*cinfo*/, Creature* /*creature*/) { } +}; + class CreatureScript : public ScriptObject, public UpdatableScript { protected: @@ -801,6 +872,16 @@ class PlayerScript : public ScriptObject // After player enters queue for Arena virtual void OnPlayerJoinArena(Player* player, Battleground* bg) { } + + //After looting item + virtual void OnLootItem(Player* player, Item* item, uint32 count, uint64 lootguid) { } + + //After creating item (eg profession item creation) + virtual void OnCreateItem(Player* player, Item* item, uint32 count) { } + + //After receiving item as a quest reward + virtual void OnQuestRewardItem(Player* player, Item* item, uint32 count) { } + }; class GuildScript : public ScriptObject @@ -1105,6 +1186,9 @@ class ScriptMgr void OnEquip(Player* player, Item* it, uint8 bag, uint8 slot, bool update); void OnPlayerJoinBG(Player* player, Battleground* bg); void OnPlayerJoinArena(Player* player, Battleground* bg); + void OnLootItem(Player* player, Item* item, uint32 count, uint64 lootguid); + void OnCreateItem(Player* player, Item* item, uint32 count); + void OnQuestRewardItem(Player* player, Item* item, uint32 count); public: /* GuildScript */ @@ -1141,6 +1225,30 @@ class ScriptMgr uint32 DecreaseScheduledScriptCount(size_t count) { return _scheduledScripts -= count; } bool IsScriptScheduled() const { return _scheduledScripts > 0; } + public: /* UnitScript */ + + void OnHeal(Unit* healer, Unit* reciever, uint32& gain); + void OnDamage(Unit* attacker, Unit* victim, uint32& damage); + void ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage); + void ModifyMeleeDamage(Unit* target, Unit* attacker, uint32& damage); + void ModifySpellDamageTaken(Unit* target, Unit* attacker, int32& damage); + void ModifyHealRecieved(Unit* target, Unit* attacker, uint32& addHealth); + uint32 DealDamage(Unit* AttackerUnit, Unit *pVictim, uint32 damage, DamageEffectType damagetype); + + public: /* MovementHandlerScript */ + + void OnPlayerMove(Player* player, MovementInfo movementInfo, uint32 opcode); + + public: /* AllCreatureScript */ + + void OnAllCreatureUpdate(Creature* creature, uint32 diff); + void Creature_SelectLevel(const CreatureTemplate *cinfo, Creature* creature); + + public: /* AllMapScript */ + + void OnPlayerEnterMapAll(Map* map, Player* player); + void OnPlayerLeaveMapAll(Map* map, Player* player); + private: uint32 _scriptCount; diff --git a/src/game/Spells/Auras/SpellAuraEffects.cpp b/src/game/Spells/Auras/SpellAuraEffects.cpp index 238a3f0a1..34923f1b2 100644 --- a/src/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/game/Spells/Auras/SpellAuraEffects.cpp @@ -6070,7 +6070,10 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const // ignore non positive values (can be result apply spellmods to aura damage uint32 damage = std::max(GetAmount(), 0); - + + // Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations + sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); + if (GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE) { // xinef: leave only target depending bonuses, rest is handled in calculate amount @@ -6183,6 +6186,10 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL); uint32 damage = std::max(GetAmount(), 0); + + // Script Hook For HandlePeriodicHealthLeechAurasTick -- Allow scripts to change the Damage pre class mitigation calculations + sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); + if (GetBase()->GetType() == DYNOBJ_AURA_TYPE) damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, 0.0f, GetBase()->GetStackAmount()); damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()); @@ -6370,6 +6377,10 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const uint32 absorb = 0; uint32 heal = uint32(damage); + + // Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations + sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, heal); + Unit::CalcHealAbsorb(target, GetSpellInfo(), heal, absorb); int32 gain = Unit::DealHeal(caster, target, heal); diff --git a/src/game/Spells/SpellEffects.cpp b/src/game/Spells/SpellEffects.cpp index 31f47f75e..085245d63 100644 --- a/src/game/Spells/SpellEffects.cpp +++ b/src/game/Spells/SpellEffects.cpp @@ -1727,6 +1727,8 @@ void Spell::DoCreateItem(uint8 /*effIndex*/, uint32 itemId) // send info to the client player->SendNewItem(pItem, addNumber, true, SelfCast); + + sScriptMgr->OnCreateItem(player, pItem, addNumber); // we succeeded in creating at least one item, so a levelup is possible if (SelfCast)