Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2024-11-16 13:15:00 +08:00
768 changed files with 5628 additions and 5394 deletions
@@ -194,6 +194,7 @@ ScriptedAI::ScriptedAI(Creature* creature) : CreatureAI(creature),
{
_isHeroic = me->GetMap()->IsHeroic();
_difficulty = Difficulty(me->GetMap()->GetSpawnMode());
_invincible = false;
}
void ScriptedAI::AttackStartNoMove(Unit* who)
@@ -222,6 +223,12 @@ void ScriptedAI::UpdateAI(uint32 /*diff*/)
DoMeleeAttackIfReady();
}
void ScriptedAI::DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/)
{
if (IsInvincible() && damage >= me->GetHealth())
damage = me->GetHealth() - 1;
}
void ScriptedAI::DoStartMovement(Unit* victim, float distance, float angle)
{
if (victim)
@@ -732,8 +739,10 @@ void BossAI::UpdateAI(uint32 diff)
DoMeleeAttackIfReady();
}
void BossAI::DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/)
void BossAI::DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask)
{
ScriptedAI::DamageTaken(attacker, damage, damagetype, damageSchoolMask);
if (_nextHealthCheck._valid)
if (me->HealthBelowPctDamaged(_nextHealthCheck._healthPct, damage))
{
@@ -198,7 +198,7 @@ struct ScriptedAI : public CreatureAI
void AttackStartNoMove(Unit* target);
// Called at any Damage from any attacker (before damage apply)
void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override {}
void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override;
//Called at World update tick
void UpdateAI(uint32 diff) override;
@@ -438,9 +438,14 @@ struct ScriptedAI : public CreatureAI
Player* SelectTargetFromPlayerList(float maxdist, uint32 excludeAura = 0, bool mustBeInLOS = false) const;
// Allows dropping to 1 HP but prevents creature from dying.
void SetInvincibility(bool apply) { _invincible = apply; };
[[nodiscard]] bool IsInvincible() const { return _invincible; };
private:
Difficulty _difficulty;
bool _isHeroic;
bool _invincible;
std::unordered_set<uint32> _uniqueTimedEvents;
};
@@ -35,6 +35,7 @@
#include "SmartAI.h"
#include "SpellMgr.h"
#include "Vehicle.h"
#include "WorldState.h"
/// @todo: this import is not necessary for compilation and marked as unused by the IDE
// however, for some reasons removing it would cause a damn linking issue
@@ -696,6 +697,10 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (isWithinLOSInMap && isWithinMeleeRange && isRangedAttack && isTargetRooted && canCastSpell && !me->IsVehicle())
{
failedSpellCast = true; // Mark spellcast as failed so we can retry it later
if (me->IsRooted()) // Rooted inhabit type, never move/reposition
continue;
float minDistance = std::max(meleeRange, spellMinRange) - distanceToTarget + NOMINAL_MELEE_RANGE;
CAST_AI(SmartAI, me->AI())->MoveAway(std::min(minDistance, spellMaxRange));
continue;
@@ -705,12 +710,20 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (distanceToTarget > spellMaxRange && isWithinLOSInMap)
{
failedSpellCast = true;
if (me->IsRooted()) // Rooted inhabit type, never move/reposition
continue;
CAST_AI(SmartAI, me->AI())->SetCombatMove(true, std::max(spellMaxRange - NOMINAL_MELEE_RANGE, 0.0f));
continue;
}
else if (distanceToTarget < spellMinRange || !(isWithinLOSInMap || isSpellIgnoreLOS))
{
failedSpellCast = true;
if (me->IsRooted()) // Rooted inhabit type, never move/reposition
continue;
CAST_AI(SmartAI, me->AI())->SetCombatMove(true);
continue;
}
@@ -3257,6 +3270,11 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
break;
}
case SMART_ACTION_WORLD_SCRIPT:
{
sWorldState->HandleExternalEvent(static_cast<WorldStateEvent>(e.action.worldStateScript.eventId), e.action.worldStateScript.param);
break;
}
default:
LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Unhandled Action type {}", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
break;
@@ -5061,7 +5079,7 @@ void SmartScript::GetScript()
if (CreatureTemplate const* cInfo = me->GetCreatureTemplate())
{
if (cInfo->HasFlagsExtra(CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI))
if (cInfo->HasFlagsExtra(CREATURE_FLAG_EXTRA_DONT_OVERRIDE_ENTRY_SAI))
{
e = sSmartScriptMgr->GetScript((int32)me->GetEntry(), mScriptType);
FillScript(e, me, nullptr);
@@ -18,9 +18,7 @@
#ifndef ACORE_SMARTSCRIPT_H
#define ACORE_SMARTSCRIPT_H
#include "Common.h"
#include "Creature.h"
#include "CreatureAI.h"
#include "GridNotifiers.h"
#include "SmartScriptMgr.h"
#include "Spell.h"
@@ -777,6 +777,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
case SMART_ACTION_MOVEMENT_STOP: return NO_PARAMS;
case SMART_ACTION_MOVEMENT_PAUSE: return sizeof(SmartAction::move);
case SMART_ACTION_MOVEMENT_RESUME: return sizeof(SmartAction::move);
case SMART_ACTION_WORLD_SCRIPT: return sizeof(SmartAction::worldStateScript);
default:
LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.",
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
@@ -1960,6 +1961,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_MOVEMENT_STOP:
case SMART_ACTION_MOVEMENT_PAUSE:
case SMART_ACTION_MOVEMENT_RESUME:
case SMART_ACTION_WORLD_SCRIPT:
break;
default:
LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type({}), event_type({}), Entry {} SourceType {} Event {}, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);
@@ -20,12 +20,11 @@
#include "Common.h"
#include "Creature.h"
#include "CreatureAI.h"
#include "DBCStores.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Optional.h"
#include "Spell.h"
#include "SpellMgr.h"
#include "Unit.h"
#include <limits>
typedef uint32 SAIBool;
@@ -727,8 +726,9 @@ enum SMART_ACTION
SMART_ACTION_MOVEMENT_STOP = 234, //
SMART_ACTION_MOVEMENT_PAUSE = 235, // timer
SMART_ACTION_MOVEMENT_RESUME = 236, // timerOverride
SMART_ACTION_WORLD_SCRIPT = 237, // eventId, param
SMART_ACTION_AC_END = 237, // placeholder
SMART_ACTION_AC_END = 238, // placeholder
};
enum class SmartActionSummonCreatureFlags
@@ -1472,6 +1472,12 @@ struct SmartAction
{
uint32 timer;
} move;
struct
{
uint32 eventId;
uint32 param;
} worldStateScript;
//! Note for any new future actions
//! All parameters must have type uint32
@@ -20,7 +20,6 @@
#include "Battlefield.h"
#include "Log.h"
#include "ObjectAccessor.h"
#include "World.h"
class Group;
@@ -19,9 +19,10 @@
#define __BATTLEGROUNDQUEUE_H
#include "Battleground.h"
#include "Common.h"
#include "DBCEnums.h"
#include "EventProcessor.h"
#include "ObjectGuid.h"
#include "SharedDefines.h"
#include <array>
constexpr auto COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME = 10;
-1
View File
@@ -18,7 +18,6 @@
#ifndef _CHANNEL_H
#define _CHANNEL_H
#include "Common.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include <string>
@@ -506,6 +506,9 @@ bool Acore::Impl::ChatCommands::ChatCommandNode::IsInvokerVisible(ChatHandler co
if (!_invoker)
return false;
if (!sScriptMgr->OnBeforeIsInvokerVisible(_name, _permission, who))
return true;
if (who.IsConsole() && (_permission.AllowConsole == Acore::ChatCommands::Console::No))
return false;
+1
View File
@@ -23,6 +23,7 @@
#include "SharedDefines.h"
#include "SpellInfo.h"
#include "SpellMgr.h"
#include "World.h"
using namespace Acore::Hyperlinks;
@@ -28,6 +28,7 @@
#include "Spell.h"
#include "SpellAuras.h"
#include "SpellMgr.h"
#include "WorldState.h"
// Checks if object meets the condition
// Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: eventAI)
@@ -570,6 +571,11 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
condMeets = unit->IsCharmed();
break;
}
case CONDITION_WORLD_SCRIPT:
{
condMeets = sWorldState->IsConditionFulfilled(static_cast<WorldStateCondition>(ConditionValue1), static_cast<WorldStateConditionState>(ConditionValue2));
break;
}
default:
condMeets = false;
break;
@@ -770,6 +776,9 @@ uint32 Condition::GetSearcherTypeMaskForCondition()
case CONDITION_CHARMED:
mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
break;
case CONDITION_WORLD_SCRIPT:
mask |= GRID_MAP_TYPE_MASK_ALL;
break;
default:
ASSERT(false && "Condition::GetSearcherTypeMaskForCondition - missing condition handling!");
break;
+3 -1
View File
@@ -86,7 +86,9 @@ enum ConditionTypes
CONDITION_AC_START = 100,
CONDITION_QUEST_SATISFY_EXCLUSIVE = 101, // quest_id 0 0 true if satisfied exclusive group
CONDITION_HAS_AURA_TYPE = 102, // aura_type 0 0 true if has aura type
CONDITION_AC_END = 103 // placeholder
CONDITION_WORLD_SCRIPT = 103, // conditionId state 0 true if WorldState::IsConditionFulfilled returns true
CONDITION_AC_END = 104 // placeholder
};
/*! Documentation on implementing a new ConditionSourceType:
@@ -18,8 +18,6 @@
#ifndef _LFGQUEUE_H
#define _LFGQUEUE_H
#include <utility>
#include "LFG.h"
namespace lfg
@@ -22,10 +22,8 @@
#include "CharmInfo.h"
#include "Common.h"
#include "CreatureData.h"
#include "DatabaseEnv.h"
#include "LootMgr.h"
#include "Unit.h"
#include "World.h"
#include <list>
class SpellInfo;
@@ -69,7 +69,7 @@ enum CreatureFlagsExtra : uint32
CREATURE_FLAG_EXTRA_MODULE = 0x01000000,
CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE = 0x02000000, // Prevent creatures from calling for assistance on initial aggro
CREATURE_FLAG_EXTRA_IGNORE_ALL_ASSISTANCE_CALLS = 0x04000000, // Prevents creature from responding to assistance calls
CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI = 0x08000000, // Load both ENTRY and GUID specific SAI
CREATURE_FLAG_EXTRA_DONT_OVERRIDE_ENTRY_SAI = 0x08000000, // Load both ENTRY and GUID specific SAI
CREATURE_FLAG_EXTRA_DUNGEON_BOSS = 0x10000000, // creature is a dungeon boss (SET DYNAMICALLY, DO NOT ADD IN DB)
CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING = 0x20000000, // creature ignore pathfinding
CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK = 0x40000000, // creature is immune to knockback effects
@@ -21,6 +21,7 @@
#include "Log.h"
#include "MoveSplineInit.h"
#include "ObjectMgr.h"
#include "QueryResult.h"
#include "WaypointMgr.h"
FormationMgr::~FormationMgr()
@@ -19,6 +19,7 @@
#define _FORMATIONS_H
#include "Define.h"
#include "ObjectGuid.h"
#include "Unit.h"
#include <map>
#include <unordered_map>
@@ -20,8 +20,9 @@
#include "Common.h"
#include "NPCHandler.h"
#include "Object.h"
#include "ObjectGuid.h"
#include "QuestDef.h"
#include <map>
class WorldSession;
class ObjectGuid;
@@ -58,7 +58,7 @@ AC_API_EXPORT EnumText EnumUtils<CreatureFlagsExtra>::ToString(CreatureFlagsExtr
case CREATURE_FLAG_EXTRA_MODULE: return { "CREATURE_FLAG_EXTRA_MODULE", "CREATURE_FLAG_EXTRA_MODULE", "" };
case CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE: return { "CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE", "CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE", "Prevent creatures from calling for assistance on initial aggro" };
case CREATURE_FLAG_EXTRA_IGNORE_ALL_ASSISTANCE_CALLS: return { "CREATURE_FLAG_EXTRA_IGNORE_ALL_ASSISTANCE_CALLS", "CREATURE_FLAG_EXTRA_IGNORE_ALL_ASSISTANCE_CALLS", "Prevents creature from responding to assistance calls" };
case CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI: return { "CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI", "CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI", "Load both ENTRY and GUID specific SAI" };
case CREATURE_FLAG_EXTRA_DONT_OVERRIDE_ENTRY_SAI: return { "CREATURE_FLAG_EXTRA_DONT_OVERRIDE_ENTRY_SAI", "CREATURE_FLAG_EXTRA_DONT_OVERRIDE_ENTRY_SAI", "Load both ENTRY and GUID specific SAI" };
case CREATURE_FLAG_EXTRA_DUNGEON_BOSS: return { "CREATURE_FLAG_EXTRA_DUNGEON_BOSS", "CREATURE_FLAG_EXTRA_DUNGEON_BOSS", "creature is a dungeon boss (SET DYNAMICALLY, DO NOT ADD IN DB)" };
case CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING: return { "CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING", "CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING", "creature ignore pathfinding" };
case CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK: return { "CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK", "CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK", "creature is immune to knockback effects" };
@@ -102,7 +102,7 @@ AC_API_EXPORT CreatureFlagsExtra EnumUtils<CreatureFlagsExtra>::FromIndex(std::s
case 24: return CREATURE_FLAG_EXTRA_MODULE;
case 25: return CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE;
case 26: return CREATURE_FLAG_EXTRA_IGNORE_ALL_ASSISTANCE_CALLS;
case 27: return CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI;
case 27: return CREATURE_FLAG_EXTRA_DONT_OVERRIDE_ENTRY_SAI;
case 28: return CREATURE_FLAG_EXTRA_DUNGEON_BOSS;
case 29: return CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING;
case 30: return CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK;
@@ -143,7 +143,7 @@ AC_API_EXPORT std::size_t EnumUtils<CreatureFlagsExtra>::ToIndex(CreatureFlagsEx
case CREATURE_FLAG_EXTRA_MODULE: return 24;
case CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE: return 25;
case CREATURE_FLAG_EXTRA_IGNORE_ALL_ASSISTANCE_CALLS: return 26;
case CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI: return 27;
case CREATURE_FLAG_EXTRA_DONT_OVERRIDE_ENTRY_SAI: return 27;
case CREATURE_FLAG_EXTRA_DUNGEON_BOSS: return 28;
case CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING: return 29;
case CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK: return 30;
@@ -19,7 +19,6 @@
#define AZEROTHCORE_GAMEOBJECT_H
#include "Common.h"
#include "DatabaseEnv.h"
#include "G3D/Quat.h"
#include "GameObjectData.h"
#include "LootMgr.h"
@@ -19,9 +19,9 @@
#define GAMEOBJECTDATA_H
#include "SharedDefines.h"
#include "WorldPacket.h"
#include <string>
#include <array>
#include <vector>
#include <string>
#define MAX_GAMEOBJECT_QUEST_ITEMS 6
#define MAX_GO_STATE 3
@@ -20,6 +20,7 @@
#include "DatabaseEnv.h"
#include "Log.h"
#include "ObjectMgr.h"
#include "QueryResult.h"
#include "Util.h"
#include <cmath>
#include <functional>
@@ -19,6 +19,7 @@
#include "ByteBuffer.h"
#include "Geometry.h"
#include "GridDefines.h"
#include "Random.h"
#include <G3D/g3dmath.h>
#include <sstream>
@@ -19,7 +19,9 @@
#define CinematicMgr_h__
#include "Define.h"
#include "Object.h"
#include "Position.h"
#include "TemporarySummon.h"
#include <vector>
constexpr auto CINEMATIC_UPDATEDIFF = 500;
constexpr auto CINEMATIC_LOOKAHEAD = 2000;
+5 -1
View File
@@ -83,6 +83,7 @@
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "WorldState.h"
#include <cmath>
/// @todo: this import is not necessary for compilation and marked as unused by the IDE
@@ -1722,6 +1723,7 @@ void Player::RemoveFromWorld()
m_session->DoLootRelease(lguid);
sOutdoorPvPMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId);
sBattlefieldMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId);
sWorldState->HandlePlayerLeaveZone(this, static_cast<WorldStateZoneId>(m_zoneUpdateId));
}
// Remove items from world before self - player must be found in Item::RemoveFromObjectUpdate
@@ -6930,7 +6932,7 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
float maxDamage = proto->Damage[i].DamageMax;
// If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage
if (ssv)
if (ssv && i == 0) // scaling stats only for first damage
{
int32 extraDPS = ssv->getDPSMod(ScalingStatValue);
if (extraDPS)
@@ -6945,6 +6947,8 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
if (apply)
{
sScriptMgr->OnApplyWeaponDamage(this, slot, proto, minDamage, maxDamage, i);
if (minDamage > 0.f)
{
SetBaseWeaponDamage(WeaponAttackType(attType), MINDAMAGE, minDamage, i);
+1
View File
@@ -1423,6 +1423,7 @@ public:
void CompleteQuest(uint32 quest_id);
void IncompleteQuest(uint32 quest_id);
void RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, bool announce = true, bool isLFGReward = false);
void SetRewardedQuest(uint32 quest_id);
void FailQuest(uint32 quest_id);
bool SatisfyQuestSkill(Quest const* qInfo, bool msg) const;
bool SatisfyQuestLevel(Quest const* qInfo, bool msg) const;
@@ -819,8 +819,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
SetSeasonalQuestStatus(quest_id);
RemoveActiveQuest(quest_id, false);
m_RewardedQuests.insert(quest_id);
m_RewardedQuestsSave[quest_id] = true;
SetRewardedQuest(quest_id);
if (announce)
SendQuestReward(quest, XP);
@@ -877,6 +876,12 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
sScriptMgr->OnPlayerCompleteQuest(this, quest);
}
void Player::SetRewardedQuest(uint32 quest_id)
{
m_RewardedQuests.insert(quest_id);
m_RewardedQuestsSave[quest_id] = true;
}
void Player::FailQuest(uint32 questId)
{
if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
@@ -38,6 +38,7 @@
#include "Vehicle.h"
#include "Weather.h"
#include "WeatherMgr.h"
#include "WorldState.h"
#include "WorldStatePackets.h"
/// @todo: this import is not necessary for compilation and marked as unused by the IDE
@@ -1216,6 +1217,8 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
{
sOutdoorPvPMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId);
sOutdoorPvPMgr->HandlePlayerEnterZone(this, newZone);
sWorldState->HandlePlayerLeaveZone(this, static_cast<WorldStateZoneId>(m_zoneUpdateId));
sWorldState->HandlePlayerEnterZone(this, static_cast<WorldStateZoneId>(newZone));
sBattlefieldMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId);
sBattlefieldMgr->HandlePlayerEnterZone(this, newZone);
SendInitWorldStates(newZone,
+2 -1
View File
@@ -18,7 +18,8 @@
#ifndef _CHARMINFO_H
#define _CHARMINFO_H
#include "Object.h"
#include "Define.h"
#include "ObjectGuid.h"
#define MAX_SPELL_CHARM 4
#define MAX_SPELL_VEHICLE 6
+2
View File
@@ -180,6 +180,7 @@ enum eScriptFlags
// Playsound flags
SF_PLAYSOUND_TARGET_PLAYER = 0x1,
SF_PLAYSOUND_DISTANCE_SOUND = 0x2,
SF_PLAYSOUND_DISTANCE_RADIUS = 0x4,
// Orientation flags
SF_ORIENTATION_FACE_TARGET = 0x1,
@@ -307,6 +308,7 @@ struct ScriptInfo
{
uint32 SoundID; // datalong
uint32 Flags; // datalong2
int32 Radius; // dataint
} Playsound;
struct // SCRIPT_COMMAND_CREATE_ITEM (17)
-1
View File
@@ -24,7 +24,6 @@
#include "Grid.h"
#include "GridReference.h"
#include "Timer.h"
#include "Util.h"
template
<
-1
View File
@@ -22,7 +22,6 @@
#include "ObjectMgr.h"
#include "Optional.h"
#include "Player.h"
#include "WorldPacket.h"
#include <set>
#include <unordered_map>
+27 -1
View File
@@ -59,6 +59,9 @@ void InstanceScript::OnCreatureCreate(Creature* creature)
{
AddObject(creature);
AddMinion(creature);
if (creature->IsSummon())
SetSummoner(creature);
}
void InstanceScript::OnCreatureRemove(Creature* creature)
@@ -194,6 +197,15 @@ void InstanceScript::LoadObjectData(ObjectData const* data, ObjectInfoMap& objec
}
}
void InstanceScript::LoadSummonData(ObjectData const* data)
{
while (data->entry)
{
_summonInfo[data->entry] = data->type;
++data;
}
}
void InstanceScript::UpdateMinionState(Creature* minion, EncounterState state)
{
switch (state)
@@ -348,6 +360,16 @@ void InstanceScript::RemoveMinion(Creature* minion)
AddMinion(minion, false);
}
void InstanceScript::SetSummoner(Creature* creature)
{
auto const& summonData = _summonInfo.find(creature->GetEntry());
if (summonData != _summonInfo.end())
if (Creature* summoner = GetCreature(summonData->second))
if (summoner->IsAIEnabled)
summoner->AI()->JustSummoned(creature);
}
bool InstanceScript::SetBossState(uint32 id, EncounterState state)
{
if (id < bosses.size())
@@ -393,7 +415,11 @@ void InstanceScript::StorePersistentData(uint32 index, uint32 data)
return;
}
persistentData[index] = data;
if (persistentData[index] != data)
{
persistentData[index] = data;
SaveToDB();
}
}
void InstanceScript::DoForAllMinions(uint32 id, std::function<void(Creature*)> exec)
@@ -288,6 +288,11 @@ protected:
void LoadDoorData(DoorData const* data);
void LoadMinionData(MinionData const* data);
void LoadObjectData(ObjectData const* creatureData, ObjectData const* gameObjectData);
// Allows setting another creature as summoner for a creature.
// This is used to handle summons that are not directly controlled by the summoner.
// Summoner creature must be loaded in the instance data (LoadObjectData).
void LoadSummonData(ObjectData const* data);
void SetSummoner(Creature* creature);
void AddObject(Creature* obj, bool add = true);
void RemoveObject(Creature* obj);
@@ -324,6 +329,7 @@ private:
MinionInfoMap minions;
ObjectInfoMap _creatureInfo;
ObjectInfoMap _gameObjectInfo;
ObjectInfoMap _summonInfo;
ObjectGuidMap _objectGuids;
ObjectStateMap _objectStateMap;
uint32 completedEncounters; // completed encounter mask, bit indexes are DungeonEncounter.dbc boss numbers, used for packets
+1
View File
@@ -19,6 +19,7 @@
#include "DatabaseEnv.h"
#include "ObjectMgr.h"
#include "PreparedStatement.h"
#include "QueryResult.h"
LootItemStorage::LootItemStorage()
{
+1
View File
@@ -31,6 +31,7 @@
#include "MapInstanced.h"
#include "Metric.h"
#include "MiscPackets.h"
#include "MMapFactory.h"
#include "Object.h"
#include "ObjectAccessor.h"
#include "ObjectGridLoader.h"
+1
View File
@@ -19,6 +19,7 @@
#include "InstanceScript.h"
#include "MapMgr.h"
#include "MoveSpline.h"
#include "QueryResult.h"
#include "Transport.h"
TransportTemplate::~TransportTemplate()
+1 -1
View File
@@ -18,7 +18,7 @@
#ifndef __DYNAMICVISIBILITY_H
#define __DYNAMICVISIBILITY_H
#include "Common.h"
#include "Define.h"
struct VisibilitySettingData
{
+3 -1
View File
@@ -19,7 +19,9 @@
#define ACORE_MOTIONMASTER_H
#include "Common.h"
#include "Object.h"
#include "ObjectGuid.h"
#include "PathGenerator.h"
#include "Position.h"
#include "SharedDefines.h"
#include "Spline/MoveSpline.h"
#include <optional>
@@ -18,7 +18,9 @@
#ifndef ACORE_FLEEINGMOVEMENTGENERATOR_H
#define ACORE_FLEEINGMOVEMENTGENERATOR_H
#include "Creature.h"
#include "MovementGenerator.h"
#include "Timer.h"
template<class T>
class FleeingMovementGenerator : public MovementGeneratorMedium< T, FleeingMovementGenerator<T> >
@@ -20,7 +20,6 @@
#include "DetourNavMesh.h"
#include "DetourNavMeshQuery.h"
#include "MMapFactory.h"
#include "MMapMgr.h"
#include "MapDefines.h"
#include "MoveSplineInitArgs.h"
@@ -18,7 +18,7 @@
#ifndef ACORE_POINTMOVEMENTGENERATOR_H
#define ACORE_POINTMOVEMENTGENERATOR_H
#include "FollowerReference.h"
#include "Creature.h"
#include "MovementGenerator.h"
template<class T>
@@ -25,6 +25,7 @@
#include "ObjectAccessor.h"
#include "Spell.h"
#include "Util.h"
#include "World.h"
template<class T>
RandomMovementGenerator<T>::~RandomMovementGenerator() { }
@@ -20,6 +20,7 @@
#include "MovementGenerator.h"
#include "PathGenerator.h"
#include "Timer.h"
#define RANDOM_POINTS_NUMBER 12
#define RANDOM_LINKS_COUNT 7
@@ -18,7 +18,7 @@
#ifndef ACORE_WAYPOINTMANAGER_H
#define ACORE_WAYPOINTMANAGER_H
#include "Common.h"
#include "Define.h"
#include <optional>
#include <unordered_map>
#include <vector>
+1
View File
@@ -20,6 +20,7 @@
#include "Log.h"
#include "MapMgr.h"
#include "ObjectMgr.h"
#include "QueryResult.h"
#include "Transport.h"
////////////////////////////////////////////////////////////
+1 -2
View File
@@ -18,10 +18,9 @@
#ifndef __ACORE_REPUTATION_MGR_H
#define __ACORE_REPUTATION_MGR_H
#include "Common.h"
#include "DatabaseEnvFwd.h"
#include "DBCStructure.h"
#include "Language.h"
#include "QueryResult.h"
#include "SharedDefines.h"
#include <map>
+4 -4
View File
@@ -20,14 +20,12 @@
#include "GridNotifiers.h"
#include "Map.h"
#include "MapMgr.h"
#include "MapRefMgr.h"
#include "ObjectMgr.h"
#include "Pet.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "Transport.h"
#include "WaypointMgr.h"
#include "World.h"
/// Put scripts in the execution queue
void Map::ScriptsStart(ScriptMapMap const& scripts, uint32 id, Object* source, Object* target)
@@ -730,8 +728,10 @@ void Map::ScriptsProcess()
break;
}
// Playsound.Flags bitmask: 0/2=without/with distance dependent
if (step.script->Playsound.Flags & SF_PLAYSOUND_DISTANCE_SOUND)
// Playsound.Flags bitmask: 0/2/4=without/with distance dependent/radius
if (step.script->Playsound.Flags & SF_PLAYSOUND_DISTANCE_RADIUS)
object->PlayRadiusSound(step.script->Playsound.SoundID, step.script->Playsound.Radius);
else if (step.script->Playsound.Flags & SF_PLAYSOUND_DISTANCE_SOUND)
object->PlayDistanceSound(step.script->Playsound.SoundID, player);
else
object->PlayDirectSound(step.script->Playsound.SoundID, player);
@@ -16,6 +16,7 @@
*/
#include "AllCommandScript.h"
#include "ChatCommand.h"
#include "ScriptMgr.h"
#include "ScriptMgrMacros.h"
@@ -29,6 +30,11 @@ bool ScriptMgr::OnTryExecuteCommand(ChatHandler& handler, std::string_view cmdSt
CALL_ENABLED_BOOLEAN_HOOKS(AllCommandScript, ALLCOMMANDHOOK_ON_TRY_EXECUTE_COMMAND, !script->OnTryExecuteCommand(handler, cmdStr));
}
bool ScriptMgr::OnBeforeIsInvokerVisible(std::string name, Acore::Impl::ChatCommands::CommandPermissions permissions, ChatHandler const& who)
{
CALL_ENABLED_BOOLEAN_HOOKS(AllCommandScript, ALLCOMMANDHOOK_ON_BEFORE_IS_INVOKER_VISIBLE, !script->OnBeforeIsInvokerVisible(name, permissions, who));
}
AllCommandScript::AllCommandScript(const char* name, std::vector<uint16> enabledHooks)
: ScriptObject(name, ALLCOMMANDHOOK_END)
{
@@ -19,12 +19,14 @@
#define SCRIPT_OBJECT_ALL_COMMAND_SCRIPT_H_
#include "ScriptObject.h"
#include "ChatCommand.h"
#include <vector>
enum AllCommandHook
{
ALLCOMMANDHOOK_ON_HANDLE_DEV_COMMAND,
ALLCOMMANDHOOK_ON_TRY_EXECUTE_COMMAND,
ALLCOMMANDHOOK_ON_BEFORE_IS_INVOKER_VISIBLE,
ALLCOMMANDHOOK_END
};
@@ -45,6 +47,8 @@ public:
* @param cmdStr Contains information about the command name
*/
[[nodiscard]] virtual bool OnTryExecuteCommand(ChatHandler& /*handler*/, std::string_view /*cmdStr*/) { return true; }
[[nodiscard]] virtual bool OnBeforeIsInvokerVisible(std::string /*name*/, Acore::Impl::ChatCommands::CommandPermissions /*permissions*/, ChatHandler const& /*who*/) { return true; }
};
// Compatibility for old scripts
@@ -18,6 +18,7 @@
#ifndef SCRIPT_OBJECT_GLOBAL_SCRIPT_H_
#define SCRIPT_OBJECT_GLOBAL_SCRIPT_H_
#include "DatabaseEnvFwd.h"
#include "DBCEnums.h"
#include "ObjectGuid.h"
#include "ScriptObject.h"
@@ -652,6 +652,11 @@ void ScriptMgr::OnApplyEnchantmentItemModsBefore(Player* player, Item* item, Enc
CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_APPLY_ENCHANTMENT_ITEM_MODS_BEFORE, script->OnApplyEnchantmentItemModsBefore(player, item, slot, apply, enchant_spell_id, enchant_amount));
}
void ScriptMgr::OnApplyWeaponDamage(Player* player, uint8 slot, ItemTemplate const* proto, float& minDamage, float& maxDamage, uint8 damageIndex)
{
CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_APPLY_WEAPON_DAMAGE, script->OnApplyWeaponDamage(player, slot, proto, minDamage, maxDamage, damageIndex));
}
bool ScriptMgr::CanArmorDamageModifier(Player* player)
{
CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_ARMOR_DAMAGE_MODIFIER, !script->CanArmorDamageModifier(player));
@@ -150,6 +150,7 @@ enum PlayerHook
PLAYERHOOK_ON_CUSTOM_SCALING_STAT_VALUE,
PLAYERHOOK_ON_APPLY_ITEM_MODS_BEFORE,
PLAYERHOOK_ON_APPLY_ENCHANTMENT_ITEM_MODS_BEFORE,
PLAYERHOOK_ON_APPLY_WEAPON_DAMAGE,
PLAYERHOOK_CAN_ARMOR_DAMAGE_MODIFIER,
PLAYERHOOK_ON_GET_FERAL_AP_BONUS,
PLAYERHOOK_CAN_APPLY_WEAPON_DEPENDENT_AURA_DAMAGE_MOD,
@@ -548,6 +549,8 @@ public:
virtual void OnApplyEnchantmentItemModsBefore(Player* /*player*/, Item* /*item*/, EnchantmentSlot /*slot*/, bool /*apply*/, uint32 /*enchant_spell_id*/, uint32& /*enchant_amount*/) { }
virtual void OnApplyWeaponDamage(Player* /*player*/, uint8 /*slot*/, ItemTemplate const* /*proto*/, float& /*minDamage*/, float& /*maxDamage*/, uint8 /*damageIndex*/) { }
[[nodiscard]] virtual bool CanArmorDamageModifier(Player* /*player*/) { return true; }
virtual void OnGetFeralApBonus(Player* /*player*/, int32& /*feral_bonus*/, int32 /*dpsMod*/, ItemTemplate const* /*proto*/, ScalingStatValuesEntry const* /*ssv*/) { }
@@ -20,6 +20,7 @@
#include "ScriptObject.h"
#include <vector>
#include <memory> // NOTE: this import is NEEDED (even though some IDEs report it as unused)
enum ServerHook
{
+3
View File
@@ -22,6 +22,7 @@
#include "ArenaTeam.h"
#include "AuctionHouseMgr.h"
#include "Battleground.h"
#include "ChatCommand.h"
#include "Common.h"
#include "DBCStores.h"
#include "DynamicObject.h"
@@ -444,6 +445,7 @@ public: /* PlayerScript */
void OnCustomScalingStatValue(Player* player, ItemTemplate const* proto, uint32& statType, int32& val, uint8 itemProtoStatNumber, uint32 ScalingStatValue, ScalingStatValuesEntry const* ssv);
void OnApplyItemModsBefore(Player* player, uint8 slot, bool apply, uint8 itemProtoStatNumber, uint32 statType, int32& val);
void OnApplyEnchantmentItemModsBefore(Player* player, Item* item, EnchantmentSlot slot, bool apply, uint32 enchant_spell_id, uint32& enchant_amount);
void OnApplyWeaponDamage(Player* player, uint8 slot, ItemTemplate const* proto, float& minDamage, float& maxDamage, uint8 damageIndex);
bool CanArmorDamageModifier(Player* player);
void OnGetFeralApBonus(Player* player, int32& feral_bonus, int32 dpsMod, ItemTemplate const* proto, ScalingStatValuesEntry const* ssv);
bool CanApplyWeaponDependentAuraDamageMod(Player* player, Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply);
@@ -704,6 +706,7 @@ public: /* CommandSC */
void OnHandleDevCommand(Player* player, bool& enable);
bool OnTryExecuteCommand(ChatHandler& handler, std::string_view cmdStr);
bool OnBeforeIsInvokerVisible(std::string name, Acore::Impl::ChatCommands::CommandPermissions permissions, ChatHandler const& who);
public: /* DatabaseScript */
+1 -1
View File
@@ -18,8 +18,8 @@
#ifndef _SCRIPT_OBJECT_H_
#define _SCRIPT_OBJECT_H_
#include "DatabaseEnvFwd.h"
#include "ScriptObjectFwd.h"
#include <string>
//#include "Duration.h"
//#include "LFG.h"
+2
View File
@@ -49,6 +49,7 @@
#include "World.h"
#include "WorldPacket.h"
#include "WorldSocket.h"
#include "WorldState.h"
#include <zlib.h>
#include "BanMgr.h"
@@ -641,6 +642,7 @@ void WorldSession::LogoutPlayer(bool save)
_player->RepopAtGraveyard();
sOutdoorPvPMgr->HandlePlayerLeaveZone(_player, _player->GetZoneId());
sWorldState->HandlePlayerLeaveZone(_player, static_cast<WorldStateZoneId>(_player->GetZoneId()));
// pussywizard: remove from battleground queues on logout
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
+3 -1
View File
@@ -18,11 +18,13 @@
#ifndef __SPELL_H
#define __SPELL_H
#include "ConditionMgr.h"
#include "GridDefines.h"
#include "ObjectMgr.h"
#include "LootMgr.h"
#include "PathGenerator.h"
#include "SharedDefines.h"
#include "SpellInfo.h"
#include "Unit.h"
class Unit;
class Player;
+36 -8
View File
@@ -1152,13 +1152,29 @@ void Spell::EffectJumpDest(SpellEffIndex effIndex)
void Spell::CalculateJumpSpeeds(uint8 i, float dist, float& speedXY, float& speedZ)
{
if (m_spellInfo->Effects[i].MiscValue)
speedZ = float(m_spellInfo->Effects[i].MiscValue) / 10;
else if (m_spellInfo->Effects[i].MiscValueB)
speedZ = float(m_spellInfo->Effects[i].MiscValueB) / 10;
float runSpeed = m_caster->IsControlledByPlayer() ? playerBaseMoveSpeed[MOVE_RUN] : baseMoveSpeed[MOVE_RUN];
if (Creature* creature = m_caster->ToCreature())
runSpeed *= creature->GetCreatureTemplate()->speed_run;
float multiplier = m_spellInfo->Effects[i].ValueMultiplier;
if (multiplier <= 0.0f)
multiplier = 1.0f;
speedXY = std::min(runSpeed * 3.0f * multiplier, std::max(28.0f, m_caster->GetSpeed(MOVE_RUN) * 4.0f));
float duration = dist / speedXY;
float durationSqr = duration * duration;
float minHeight = m_spellInfo->Effects[i].MiscValue ? m_spellInfo->Effects[i].MiscValue / 10.0f : 0.5f; // Lower bound is blizzlike
float maxHeight = m_spellInfo->Effects[i].MiscValueB ? m_spellInfo->Effects[i].MiscValueB / 10.0f : 1000.0f; // Upper bound is unknown
float height;
if (durationSqr < minHeight * 8 / Movement::gravity)
height = minHeight;
else if (durationSqr > maxHeight * 8 / Movement::gravity)
height = maxHeight;
else
speedZ = 10.0f;
speedXY = dist * 10.0f / speedZ;
height = Movement::gravity * durationSqr / 8;
speedZ = std::sqrt(2 * Movement::gravity * height);
}
void Spell::EffectTeleportUnits(SpellEffIndex /*effIndex*/)
@@ -1869,6 +1885,12 @@ void Spell::EffectEnergize(SpellEffIndex effIndex)
if (!unitTarget->IsAlive())
return;
if (unitTarget->HasUnitState(UNIT_STATE_ISOLATED))
{
m_caster->SendSpellDamageImmune(unitTarget, GetSpellInfo()->Id);
return;
}
if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS))
return;
@@ -3663,6 +3685,12 @@ void Spell::EffectHealMaxHealth(SpellEffIndex /*effIndex*/)
if (!unitTarget || !unitTarget->IsAlive())
return;
if (unitTarget->HasUnitState(UNIT_STATE_ISOLATED))
{
m_caster->SendSpellDamageImmune(unitTarget, GetSpellInfo()->Id);
return;
}
int32 addhealth = 0;
// damage == 0 - heal for caster max health
@@ -4743,8 +4771,8 @@ void Spell::EffectQuestComplete(SpellEffIndex effIndex)
uint16 logSlot = player->FindQuestSlot(questId);
if (logSlot < MAX_QUEST_LOG_SIZE)
player->AreaExploredOrEventHappens(questId);
else if (player->CanTakeQuest(quest, false)) // never rewarded before
player->CompleteQuest(questId); // quest not in log - for internal use
else if (player->CanTakeQuest(quest, false)) // Check if the quest has already been turned in.
player->SetRewardedQuest(questId); // If not, set status to rewarded without broadcasting it to client.
}
}
@@ -1389,18 +1389,6 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(13); // 50000yd
});
// A'dal's Song of Battle
ApplySpellFix({ 39953 }, [](SpellInfo* spellInfo)
{
spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_SRC_CASTER);
spellInfo->Effects[EFFECT_1].TargetA = SpellImplicitTargetInfo(TARGET_SRC_CASTER);
spellInfo->Effects[EFFECT_2].TargetA = SpellImplicitTargetInfo(TARGET_SRC_CASTER);
spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ALLY);
spellInfo->Effects[EFFECT_1].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ALLY);
spellInfo->Effects[EFFECT_2].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ALLY);
spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(367); // 2 Hours
});
ApplySpellFix({
57607, // WintergraspCatapult - Spell Plague Barrel - EffectRadiusIndex
57619, // WintergraspDemolisher - Spell Hourl Boulder - EffectRadiusIndex
@@ -4856,6 +4844,12 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->AttributesEx3 |= SPELL_ATTR3_SUPPRESS_CASTER_PROCS;
});
// Claw Rage
ApplySpellFix({ 43149 }, [](SpellInfo* spellInfo)
{
spellInfo->Effects[EFFECT_0].TriggerSpell = 0;
});
// Black Qiraji Battle Tank
ApplySpellFix({ 26655, 26656 }, [](SpellInfo* spellInfo)
{
-1
View File
@@ -21,7 +21,6 @@
#include "Define.h"
#include "Duration.h"
#include <array>
#include <string>
constexpr auto AVG_DIFF_COUNT = 500;
@@ -19,6 +19,7 @@
#include "DBCStores.h"
#include "Database/DatabaseEnv.h"
#include "Log.h"
#include "QueryResult.h"
#include "SpellMgr.h"
#include "World.h"
-1
View File
@@ -19,7 +19,6 @@
#define _PLAYER_DUMP_H
#include "ObjectGuid.h"
#include <map>
#include <set>
enum DumpTableType
@@ -18,6 +18,7 @@
#include "WardenCheckMgr.h"
#include "Database/DatabaseEnv.h"
#include "Log.h"
#include "QueryResult.h"
#include "Util.h"
#include "Warden.h"
#include "WorldSession.h"
-1
View File
@@ -26,7 +26,6 @@
#include "Player.h"
#include "Weather.h"
#include "WorldSession.h"
#include <memory>
namespace WeatherMgr
{
+6
View File
@@ -93,6 +93,7 @@
#include "WhoListCacheMgr.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "WorldState.h"
#include <boost/asio/ip/address.hpp>
#include <cmath>
@@ -2414,6 +2415,11 @@ void World::Update(uint32 diff)
sOutdoorPvPMgr->Update(diff);
}
{
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update worldstate"));
sWorldState->Update(diff);
}
{
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update battlefields"));
sBattlefieldMgr->Update(diff);
+1 -1
View File
@@ -22,10 +22,10 @@
#ifndef __WORLD_H
#define __WORLD_H
#include "DatabaseEnvFwd.h"
#include "IWorld.h"
#include "LockedQueue.h"
#include "ObjectGuid.h"
#include "QueryResult.h"
#include "SharedDefines.h"
#include "Timer.h"
#include <atomic>
+293
View File
@@ -0,0 +1,293 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero 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/>.
*/
#include "MapMgr.h"
#include "Player.h"
#include "SharedDefines.h"
#include "WorldState.h"
WorldState* WorldState::instance()
{
static WorldState instance;
return &instance;
}
WorldState::WorldState() : _isMagtheridonHeadSpawnedHorde(false), _isMagtheridonHeadSpawnedAlliance(false)
{
_transportStates[WORLD_STATE_CONDITION_THE_IRON_EAGLE] = WORLD_STATE_CONDITION_STATE_NONE;
_transportStates[WORLD_STATE_CONDITION_THE_PURPLE_PRINCESS] = WORLD_STATE_CONDITION_STATE_NONE;
_transportStates[WORLD_STATE_CONDITION_THE_THUNDERCALLER] = WORLD_STATE_CONDITION_STATE_NONE;
}
WorldState::~WorldState()
{
}
bool WorldState::IsConditionFulfilled(WorldStateCondition conditionId, WorldStateConditionState state) const
{
switch (conditionId)
{
case WORLD_STATE_CONDITION_TROLLBANES_COMMAND:
return _isMagtheridonHeadSpawnedAlliance;
case WORLD_STATE_CONDITION_NAZGRELS_FAVOR:
return _isMagtheridonHeadSpawnedHorde;
case WORLD_STATE_CONDITION_THE_IRON_EAGLE:
case WORLD_STATE_CONDITION_THE_PURPLE_PRINCESS:
case WORLD_STATE_CONDITION_THE_THUNDERCALLER:
return _transportStates.at(conditionId) == state;
default:
LOG_ERROR("scripts", "WorldState::IsConditionFulfilled: Unhandled WorldStateCondition {}", conditionId);
return false;
}
}
void WorldState::HandleConditionStateChange(WorldStateCondition conditionId, WorldStateConditionState state)
{
_transportStates[conditionId] = state;
}
void WorldState::HandleExternalEvent(WorldStateEvent eventId, uint32 param)
{
std::lock_guard<std::mutex> guard(_mutex);
switch (eventId)
{
case WORLD_STATE_CUSTOM_EVENT_ON_ADALS_SONG_OF_BATTLE:
if (!_adalSongOfBattleTimer)
{
_adalSongOfBattleTimer = 120 * MINUTE * IN_MILLISECONDS;
BuffAdalsSongOfBattle();
}
break;
case WORLD_STATE_CUSTOM_EVENT_ON_MAGTHERIDON_HEAD_SPAWN:
if (param == TEAM_ALLIANCE)
{
_isMagtheridonHeadSpawnedAlliance = true;
BuffMagtheridonTeam(TEAM_ALLIANCE);
}
else
{
_isMagtheridonHeadSpawnedHorde = true;
BuffMagtheridonTeam(TEAM_HORDE);
}
break;
case WORLD_STATE_CUSTOM_EVENT_ON_MAGTHERIDON_HEAD_DESPAWN:
if (param == TEAM_ALLIANCE)
{
_isMagtheridonHeadSpawnedAlliance = false;
DispelMagtheridonTeam(TEAM_ALLIANCE);
}
else
{
_isMagtheridonHeadSpawnedHorde = false;
DispelMagtheridonTeam(TEAM_HORDE);
}
break;
default:
break;
}
}
void WorldState::Update(uint32 diff)
{
if (_adalSongOfBattleTimer)
{
if (_adalSongOfBattleTimer <= diff)
{
_adalSongOfBattleTimer = 0;
DispelAdalsSongOfBattle();
}
else
{
_adalSongOfBattleTimer -= diff;
}
}
}
void WorldState::HandlePlayerEnterZone(Player* player, WorldStateZoneId zoneId)
{
std::lock_guard<std::mutex> guard(_mutex);
switch (zoneId)
{
case ZONEID_SHATTRATH:
case ZONEID_BOTANICA:
case ZONEID_MECHANAR:
case ZONEID_ARCATRAZ:
if (_adalSongOfBattleTimer)
player->CastSpell(player, SPELL_ADAL_SONG_OF_BATTLE, true);
break;
case ZONEID_HELLFIRE_PENINSULA:
case ZONEID_HELLFIRE_RAMPARTS:
case ZONEID_HELLFIRE_CITADEL:
case ZONEID_BLOOD_FURNACE:
case ZONEID_SHATTERED_HALLS:
case ZONEID_MAGTHERIDON_LAIR:
if (_isMagtheridonHeadSpawnedAlliance && player->GetTeamId() == TEAM_ALLIANCE)
player->CastSpell(player, SPELL_TROLLBANES_COMMAND, true);
else if (_isMagtheridonHeadSpawnedHorde && player->GetTeamId() == TEAM_HORDE)
player->CastSpell(player, SPELL_NAZGRELS_FAVOR, true);
break;
default:
break;
}
};
void WorldState::HandlePlayerLeaveZone(Player* player, WorldStateZoneId zoneId)
{
std::lock_guard<std::mutex> guard(_mutex);
switch (zoneId)
{
case ZONEID_SHATTRATH:
case ZONEID_BOTANICA:
case ZONEID_MECHANAR:
case ZONEID_ARCATRAZ:
if (!_adalSongOfBattleTimer)
player->RemoveAurasDueToSpell(SPELL_ADAL_SONG_OF_BATTLE);
break;
case ZONEID_HELLFIRE_PENINSULA:
case ZONEID_HELLFIRE_RAMPARTS:
case ZONEID_HELLFIRE_CITADEL:
case ZONEID_BLOOD_FURNACE:
case ZONEID_SHATTERED_HALLS:
case ZONEID_MAGTHERIDON_LAIR:
if (player->GetTeamId() == TEAM_ALLIANCE)
player->RemoveAurasDueToSpell(SPELL_TROLLBANES_COMMAND);
else if (player->GetTeamId() == TEAM_HORDE)
player->RemoveAurasDueToSpell(SPELL_NAZGRELS_FAVOR);
break;
default:
break;
}
};
void WorldState::BuffMagtheridonTeam(TeamId team)
{
sMapMgr->DoForAllMaps([&](Map* map) -> void
{
switch (map->GetId())
{
case 530: // Outland
map->DoForAllPlayers([&](Player* player)
{
if (player->GetZoneId() == ZONEID_HELLFIRE_PENINSULA && player->GetTeamId() == TEAM_ALLIANCE && team == TEAM_ALLIANCE)
player->CastSpell(player, SPELL_TROLLBANES_COMMAND, true);
else if (player->GetZoneId() == ZONEID_HELLFIRE_PENINSULA && player->GetTeamId() == TEAM_HORDE && team == TEAM_HORDE)
player->CastSpell(player, SPELL_NAZGRELS_FAVOR, true);
});
break;
case 540: // The Shattered Halls
case 542: // The Blood Furnace
case 543: // Ramparts
case 544: // Magtheridon's Lair
map->DoForAllPlayers([&](Player* player)
{
if (player->GetTeamId() == TEAM_ALLIANCE && team == TEAM_ALLIANCE)
player->CastSpell(player, SPELL_TROLLBANES_COMMAND, true);
else if (player->GetTeamId() == TEAM_HORDE && team == TEAM_HORDE)
player->CastSpell(player, SPELL_NAZGRELS_FAVOR, true);
});
break;
default:
break;
}
});
}
void WorldState::DispelMagtheridonTeam(TeamId team)
{
sMapMgr->DoForAllMaps([&](Map* map) -> void
{
switch (map->GetId())
{
case 530: // Outland
map->DoForAllPlayers([&](Player* player)
{
if (player->GetZoneId() == ZONEID_HELLFIRE_PENINSULA && player->GetTeamId() == TEAM_ALLIANCE && team == TEAM_ALLIANCE)
player->RemoveAurasDueToSpell(SPELL_TROLLBANES_COMMAND);
else if (player->GetZoneId() == ZONEID_HELLFIRE_PENINSULA && player->GetTeamId() == TEAM_HORDE && team == TEAM_HORDE)
player->RemoveAurasDueToSpell(SPELL_NAZGRELS_FAVOR);
});
break;
case 540: // The Shattered Halls
case 542: // The Blood Furnace
case 543: // Ramparts
case 544: // Magtheridon's Lair
map->DoForAllPlayers([&](Player* player)
{
if (player->GetTeamId() == TEAM_ALLIANCE && team == TEAM_ALLIANCE)
player->RemoveAurasDueToSpell(SPELL_TROLLBANES_COMMAND);
else if (player->GetTeamId() == TEAM_HORDE && team == TEAM_HORDE)
player->RemoveAurasDueToSpell(SPELL_NAZGRELS_FAVOR);
});
break;
default:
break;
}
});
}
void WorldState::BuffAdalsSongOfBattle()
{
sMapMgr->DoForAllMaps([&](Map* map) -> void
{
switch (map->GetId())
{
case 530: // Outland
map->DoForAllPlayers([&](Player* player)
{
if (player->GetZoneId() == ZONEID_SHATTRATH)
player->CastSpell(player, SPELL_ADAL_SONG_OF_BATTLE, true);
});
break;
case 552: // Arcatraz
case 553: // Botanica
case 554: // Mechanar
map->DoForAllPlayers([&](Player* player)
{
player->CastSpell(player, SPELL_ADAL_SONG_OF_BATTLE, true);
});
break;
default:
break;
}
});
}
void WorldState::DispelAdalsSongOfBattle()
{
sMapMgr->DoForAllMaps([&](Map* map) -> void
{
switch (map->GetId())
{
case 530: // Outland
map->DoForAllPlayers([&](Player* player)
{
if (player->GetZoneId() == ZONEID_SHATTRATH)
player->RemoveAurasDueToSpell(SPELL_ADAL_SONG_OF_BATTLE);
});
break;
case 552: // Arcatraz
case 553: // Botanica
case 554: // Mechanar
map->DoForAllPlayers([&](Player* player)
{
player->RemoveAurasDueToSpell(SPELL_ADAL_SONG_OF_BATTLE);
});
break;
default:
break;
}
});
}
+95
View File
@@ -0,0 +1,95 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero 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/>.
*/
#ifndef WORLD_STATE_H
#define WORLD_STATE_H
#include "Player.h"
#include <atomic>
enum WorldStateCondition
{
WORLD_STATE_CONDITION_TROLLBANES_COMMAND = 39911,
WORLD_STATE_CONDITION_NAZGRELS_FAVOR = 39913,
// Zeppelins
WORLD_STATE_CONDITION_THE_THUNDERCALLER = 164871,
WORLD_STATE_CONDITION_THE_IRON_EAGLE = 175080,
WORLD_STATE_CONDITION_THE_PURPLE_PRINCESS = 176495,
};
enum WorldStateConditionState
{
WORLD_STATE_CONDITION_STATE_NONE = 0,
};
enum WorldStateEvent
{
WORLD_STATE_CUSTOM_EVENT_ON_ADALS_SONG_OF_BATTLE = 39953,
WORLD_STATE_CUSTOM_EVENT_ON_MAGTHERIDON_HEAD_SPAWN = 184640,
WORLD_STATE_CUSTOM_EVENT_ON_MAGTHERIDON_HEAD_DESPAWN = 184641,
};
enum WorldStateZoneId
{
ZONEID_SHATTRATH = 3703,
ZONEID_BOTANICA = 3847,
ZONEID_ARCATRAZ = 3848,
ZONEID_MECHANAR = 3849,
ZONEID_HELLFIRE_PENINSULA = 3483,
ZONEID_HELLFIRE_RAMPARTS = 3562,
ZONEID_HELLFIRE_CITADEL = 3563,
ZONEID_BLOOD_FURNACE = 3713,
ZONEID_SHATTERED_HALLS = 3714,
ZONEID_MAGTHERIDON_LAIR = 3836,
};
enum WorldStateSpells
{
SPELL_ADAL_SONG_OF_BATTLE = 39953,
SPELL_TROLLBANES_COMMAND = 39911,
SPELL_NAZGRELS_FAVOR = 39913,
};
// Intended for implementing server wide scripts, note: all behaviour must be safeguarded towards multithreading
class WorldState
{
public:
WorldState();
virtual ~WorldState();
static WorldState* instance();
void HandlePlayerEnterZone(Player* player, WorldStateZoneId zoneId);
void HandlePlayerLeaveZone(Player* player, WorldStateZoneId zoneId);
bool IsConditionFulfilled(WorldStateCondition conditionId, WorldStateConditionState state = WORLD_STATE_CONDITION_STATE_NONE) const;
void HandleConditionStateChange(WorldStateCondition conditionId, WorldStateConditionState state);
void HandleExternalEvent(WorldStateEvent eventId, uint32 param);
void Update(uint32 diff);
private:
void BuffAdalsSongOfBattle();
void DispelAdalsSongOfBattle();
uint32 _adalSongOfBattleTimer;
void BuffMagtheridonTeam(TeamId team);
void DispelMagtheridonTeam(TeamId team);
bool _isMagtheridonHeadSpawnedHorde;
bool _isMagtheridonHeadSpawnedAlliance;
std::map<WorldStateCondition, std::atomic<WorldStateConditionState>> _transportStates; // atomic to avoid having to lock
std::mutex _mutex; // all World State operations are threat unsafe
};
#define sWorldState WorldState::instance()
#endif