diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 86e380e3d..245c3a696 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -1083,6 +1083,9 @@ void BattleGround::Reset() m_Events = 0; + // door-event2 is always 0 + m_ActiveEvents[BG_EVENT_DOOR] = 0; + if (m_InvitedAlliance > 0 || m_InvitedHorde > 0) sLog.outError("BattleGround system: bad counter, m_InvitedAlliance: %d, m_InvitedHorde: %d", m_InvitedAlliance, m_InvitedHorde); @@ -1447,6 +1450,90 @@ void BattleGround::DoorOpen(uint64 const& guid) } } +void BattleGround::OnObjectDBLoad(Creature* creature) +{ + BattleGroundEventIdx eventId = sBattleGroundMgr.GetCreatureEventIndex(creature->GetDBTableGUIDLow()); + if (eventId.event1 == BG_EVENT_NONE) + return; + m_EventObjects[MAKE_PAIR32(eventId.event1, eventId.event2)].creatures.push_back(creature->GetGUID()); + if (!IsActiveEvent(eventId.event1, eventId.event2)) + SpawnBGCreature(creature->GetGUID(), RESPAWN_ONE_DAY); +} + + +void BattleGround::OnObjectDBLoad(GameObject* obj) +{ + BattleGroundEventIdx eventId = sBattleGroundMgr.GetGameObjectEventIndex(obj->GetDBTableGUIDLow()); + if (eventId.event1 == BG_EVENT_NONE) + return; + m_EventObjects[MAKE_PAIR32(eventId.event1, eventId.event2)].gameobjects.push_back(obj->GetGUID()); + if (!IsActiveEvent(eventId.event1, eventId.event2)) + { + SpawnBGObject(obj->GetGUID(), RESPAWN_ONE_DAY); + } + else + { + // it's possible, that doors aren't spawned anymore (wsg) + if (GetStatus() >= STATUS_IN_PROGRESS && IsDoor(eventId.event1, eventId.event2)) + DoorOpen(obj->GetGUID()); + } +} + +bool BattleGround::IsDoor(uint8 event1, uint8 event2) +{ + if (event1 == BG_EVENT_DOOR) + { + if (event2 > 0) + { + sLog.outError("BattleGround too high event2 for event1:%i", event1); + return false; + } + return true; + } + return false; +} + +void BattleGround::OpenDoorEvent(uint8 event1, uint8 event2 /*=0*/) +{ + if (!IsDoor(event1, event2)) + { + sLog.outError("BattleGround:OpenDoorEvent this is no door event1:%u event2:%u", event1, event2); + return; + } + if (!IsActiveEvent(event1, event2)) // maybe already despawned (eye) + { + sLog.outError("BattleGround:OpenDoorEvent this event isn't active event1:%u event2:%u", event1, event2); + return; + } + BGObjects::const_iterator itr = m_EventObjects[MAKE_PAIR32(event1, event2)].gameobjects.begin(); + for(; itr != m_EventObjects[MAKE_PAIR32(event1, event2)].gameobjects.end(); ++itr) + DoorOpen(*itr); +} + +void BattleGround::SpawnEvent(uint8 event1, uint8 event2, bool spawn) +{ + // stop if we want to spawn something which was already spawned + // or despawn something which was already despawned + if (event2 == BG_EVENT_NONE || (spawn && m_ActiveEvents[event1] == event2) + || (!spawn && m_ActiveEvents[event1] != event2)) + return; + + if (spawn) + { + // if event gets spawned, the current active event mus get despawned + SpawnEvent(event1, m_ActiveEvents[event1], false); + m_ActiveEvents[event1] = event2; // set this event to active + } + else + m_ActiveEvents[event1] = BG_EVENT_NONE; // no event active if event2 gets despawned + + BGCreatures::const_iterator itr = m_EventObjects[MAKE_PAIR32(event1, event2)].creatures.begin(); + for(; itr != m_EventObjects[MAKE_PAIR32(event1, event2)].creatures.end(); ++itr) + SpawnBGCreature(*itr, (spawn) ? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); + BGObjects::const_iterator itr2 = m_EventObjects[MAKE_PAIR32(event1, event2)].gameobjects.begin(); + for(; itr2 != m_EventObjects[MAKE_PAIR32(event1, event2)].gameobjects.end(); ++itr2) + SpawnBGObject(*itr2, (spawn) ? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); +} void BattleGround::SpawnBGObject(uint64 const& guid, uint32 respawntime) { diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 688c8fbc6..a16d4243e 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -22,7 +22,12 @@ #include "Common.h" #include "SharedDefines.h" +// magic event-numbers #define BG_EVENT_NONE 255 +// those generic events should get a high event id +#define BG_EVENT_DOOR 254 + + class Creature; class GameObject; class Group; @@ -484,14 +489,30 @@ class BattleGround virtual void RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket); // can be extended in in BG subclass + /* event related */ + // generic implementation in BattleGround-class + // called when a creature gets added to map (NOTE: only triggered if + // a player activates the cell of the creature) virtual void OnObjectDBLoad(Creature* /*creature*/); virtual void OnObjectDBLoad(GameObject* /*obj*/); + // (de-)spawns creatures and gameobjects from an event + void SpawnEvent(uint8 event1, uint8 event2, bool spawn); + bool IsActiveEvent(uint8 event1, uint8 event2) + { + if (m_ActiveEvents.find(event1) == m_ActiveEvents.end()) + return false; + return m_ActiveEvents[event1] == event2; + } + void OpenDoorEvent(uint8 event1, uint8 event2 = 0); + bool IsDoor(uint8 event1, uint8 event2); + /* other things */ void HandleTriggerBuff(uint64 const& go_guid); // TODO: make this protected: typedef std::vector BGObjects; typedef std::vector BGCreatures; + // TODO drop m_BGObjects BGObjects m_BgObjects; BGCreatures m_BgCreatures; void SpawnBGObject(uint64 const& guid, uint32 respawntime); @@ -517,13 +538,31 @@ class BattleGround /* virtual score-array - get's used in bg-subclasses */ int32 m_TeamScores[BG_TEAMS_COUNT]; + struct EventObjects + { + BGObjects gameobjects; + BGCreatures creatures; + }; + + //typedef std::map> BGObjectMap; + //typedef std::map> BGEventMap; + // cause we create it dynamicly i use a map - to avoid resizing when + // using vector - also it contains 2*events concatenated with PAIR32 + // this is needed to avoid overhead of a 2dimensional std::map + std::map m_EventObjects; + // this must be filled first in BattleGroundXY::Reset().. else + // creatures will get added wrong + // door-events are automaticly added - but _ALL_ other must be in this vector + std::map m_ActiveEvents; + + protected: //this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends BattleGround void EndNow(); void PlayerAddedToBGCheckIfBGIsRunning(Player* plr); /* Scorekeeping */ - + BattleGroundScoreMap m_PlayerScores; // Player scores // must be implemented in BG subclass virtual void RemovePlayer(Player * /*player*/, uint64 /*guid*/) {}