Skip to content

Commit

Permalink
Add Scholomance entrance room reset on Rattlegore's death
Browse files Browse the repository at this point in the history
The entrance room of Scholomance (below the bridge) is now reset when
Rattlegore is killed by players. Many of the mobs there are removed,
some are replaced and a new patrol is added.
Data come from retail. Many thanks to @evil-at-wow for these.
See classicdb/database#832 for more details
  • Loading branch information
cala committed May 20, 2016
1 parent dae9312 commit 3e6fed7
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 6 deletions.
79 changes: 73 additions & 6 deletions src/scriptdev2/scripts/eastern_kingdoms/scholomance/instance_scholomance.cpp 100644 → 100755
Expand Up @@ -25,7 +25,8 @@ EndScriptData */
#include "scholomance.h"

instance_scholomance::instance_scholomance(Map* pMap) : ScriptedInstance(pMap),
m_uiGandlingEvent(0)
m_uiGandlingEvent(0),
m_bIsRoomReset(false)
{
Initialize();
}
Expand All @@ -42,12 +43,24 @@ void instance_scholomance::OnPlayerEnter(Player* /*pPlayer*/)
{
// Summon Gandling if can
DoSpawnGandlingIfCan(true);

if (GetData(TYPE_RATTLEGORE) == DONE)
DoRespawnEntranceRoom();
}

void instance_scholomance::OnCreatureCreate(Creature* pCreature)
{
switch (pCreature->GetEntry())
{
// Store the Guids of the NPCs in the entrance room to remove them
// and spawn their replacement or Rattlegore's death
// (only store those located in the room volume)
case NPC_REANIMATED_CORPSE:
case NPC_DISEASED_GHOUL:
case NPC_RISEN_ABERRATION:
if (GetData(TYPE_RATTLEGORE) != DONE && (pCreature->GetPositionZ() > aEntranceRoom->m_fCenterZ) && (pCreature->GetPositionX() - aEntranceRoom->m_fCornerX < aEntranceRoom->m_uiLength) && (pCreature->GetPositionY() - aEntranceRoom->m_fCornerY < aEntranceRoom->m_uiWidth))
m_sEntranceRoomGuids.insert(pCreature->GetObjectGuid());
break;
case NPC_DARKMASTER_GANDLING:
m_mNpcEntryGuidStore[NPC_DARKMASTER_GANDLING] = pCreature->GetObjectGuid();
break;
Expand All @@ -63,6 +76,10 @@ void instance_scholomance::OnObjectCreate(GameObject* pGo)
{
switch (pGo->GetEntry())
{
case GO_VIEWING_ROOM_DOOR:
// In normal flow of the instance, this door is opened by a dropped key
if (m_auiEncounter[TYPE_RATTLEGORE] == DONE)
pGo->SetGoState(GO_STATE_ACTIVE);
case GO_GATE_KIRTONOS:
case GO_GATE_RAS:
case GO_GATE_GANDLING:
Expand All @@ -75,13 +92,61 @@ void instance_scholomance::OnObjectCreate(GameObject* pGo)
case GO_GATE_RAVENIAN: m_mGandlingData[EVENT_ID_RAVENIAN].m_doorGuid = pGo->GetObjectGuid(); break;
case GO_GATE_BAROV: m_mGandlingData[EVENT_ID_BAROV].m_doorGuid = pGo->GetObjectGuid(); break;
case GO_GATE_ILLUCIA: m_mGandlingData[EVENT_ID_ILLUCIA].m_doorGuid = pGo->GetObjectGuid(); break;
}
}

case GO_VIEWING_ROOM_DOOR:
// In normal flow of the instance, this door is opened by a dropped key
if (m_auiEncounter[TYPE_RATTLEGORE] == DONE)
pGo->SetGoState(GO_STATE_ACTIVE);
break;
void instance_scholomance::DoRespawnEntranceRoom()
{
// safety check to avoid the room being reset for each OnPlayerEnter() call if Rattlegore is dead
if (m_bIsRoomReset)
return;

// Despawn the mobs already in the room with the exception of the necrofiend (not stored, so not despawned)
for (GuidSet::const_iterator itr = m_sEntranceRoomGuids.begin(); itr != m_sEntranceRoomGuids.end(); ++itr)
{
if (Creature* pMob = instance->GetCreature(*itr))
pMob->ForcedDespawn();
}
// Spawn the new and less numerous groups instead
// Four groups, one in each corner
// The creatures in each point are random
// but follow the generic rule for each group of 4 NPCs:
// 2 risen aberrations, 1 diseased ghoul, 1 diseased ghoul/reanimated corpse
for (uint8 i = 0; i < MAX_GROUPS; ++i)
{
std::vector<uint32> uiMobList; // Vector holding the 4 creatures entries for each spawned group
uiMobList.push_back(NPC_RISEN_ABERRATION); // 3 static NPC entries
uiMobList.push_back(NPC_RISEN_ABERRATION);
uiMobList.push_back(NPC_DISEASED_GHOUL);

uint32 uiMobEntry; // will hold the last random creature entry

// Pick the fourth NPC in the group and randomize the four possible spawns
switch (urand(0, 1))
{
case 0: uiMobEntry = NPC_REANIMATED_CORPSE; break;
case 1: uiMobEntry = NPC_DISEASED_GHOUL; break;
}

uiMobList.push_back(uiMobEntry);
std::random_shuffle(uiMobList.begin(), uiMobList.end());

for (uint8 j = 0; j < MAX_NPC_PER_GROUP; ++j)
// We use the Viewing Room door as the summoning object because we are sure it is here
if (GameObject* pGo = GetSingleGameObjectFromStorage(GO_VIEWING_ROOM_DOOR))
pGo->SummonCreature(uiMobList[j], aEntranceRoomSpawnLocs[4*i+j].m_fX, aEntranceRoomSpawnLocs[4*i+j].m_fY, aEntranceRoomSpawnLocs[4*i+j].m_fZ, aEntranceRoomSpawnLocs[4*i+j].m_fO, TEMPSUMMON_DEAD_DESPAWN, 0);
}
// spawn also a patrolling necrofiend
// the waypoints are handled in DB creature_movement_template table (shared with the other necrofiend in the room)
// the two other necrofiends in the instance are using DB creature_movement table
if (GameObject* pGo = GetSingleGameObjectFromStorage(GO_VIEWING_ROOM_DOOR))
if (Creature* pNecrofiend = pGo->SummonCreature(NPC_NECROFIEND, aEntranceRoomSpawnLocs[16].m_fX, aEntranceRoomSpawnLocs[16].m_fY, aEntranceRoomSpawnLocs[16].m_fZ, aEntranceRoomSpawnLocs[16].m_fO, TEMPSUMMON_DEAD_DESPAWN, 0))
pNecrofiend->GetMotionMaster()->MoveWaypoint();

m_bIsRoomReset = true;

debug_log("SD2: Entrance room in Scholomance reset after Rattlegore's death");
return;
}

void instance_scholomance::SetData(uint32 uiType, uint32 uiData)
Expand All @@ -97,6 +162,8 @@ void instance_scholomance::SetData(uint32 uiType, uint32 uiData)
break;
case TYPE_RATTLEGORE:
m_auiEncounter[uiType] = uiData;
if (uiData == DONE)
DoRespawnEntranceRoom();
break;
case TYPE_RAS_FROSTWHISPER:
m_auiEncounter[uiType] = uiData;
Expand Down
45 changes: 45 additions & 0 deletions src/scriptdev2/scripts/eastern_kingdoms/scholomance/scholomance.h 100644 → 100755
Expand Up @@ -9,6 +9,8 @@ enum
{
MAX_ENCOUNTER = 10,
MAX_EVENTS = 6,
MAX_GROUPS = 4,
MAX_NPC_PER_GROUP = 4,

TYPE_KIRTONOS = 0,
TYPE_RATTLEGORE = 1,
Expand All @@ -21,6 +23,11 @@ enum
TYPE_ILLUCIA_BAROV = 8,
TYPE_GANDLING = 9,

NPC_NECROFIEND = 11551,
NPC_RISEN_ABERRATION = 10485,
NPC_DISEASED_GHOUL = 10495,
NPC_REANIMATED_CORPSE = 10481,

NPC_KIRTONOS = 10506,
NPC_RATTLEGORE = 11622,
NPC_RAS_FROSTWHISPER = 10508,
Expand Down Expand Up @@ -66,6 +73,29 @@ static const SpawnLocation aGandlingSpawnLocs[1] =
{180.771f, -5.4286f, 75.5702f, 1.29154f}
};

// Coordinates used to respawn the NPCs in the entrance room
// (right before the Viewing Room) on Rattlegore's death
static const SpawnLocation aEntranceRoomSpawnLocs[17] =
{
{186.036f, 94.5f, 104.72f, 1.29154f}, // First corner
{179.117f, 95.5166f, 104.81f, 1.29154f},
{180.612f, 100.176f, 104.80f, 1.29154f},
{185.926f, 100.079f, 104.80f, 1.29154f},
{178.999f, 75.2952f, 104.72f, 1.29154f}, // Second corner
{185.558f, 77.276f, 104.72f, 1.29154f},
{187.556f, 70.4334f, 104.72f, 1.29154f},
{180.51f, 82.3917f, 104.72f, 1.29154f},
{212.915f, 70.6005f, 104.80f, 1.29154f}, // Third corner
{221.199f, 77.0037f, 104.72f, 1.29154f},
{214.381f, 76.233f, 104.80f, 1.29154f},
{218.64f, 71.5957f, 104.72f, 1.29154f},
{221.249f, 94.9361f, 104.72f, 1.29154f}, // Fourth corner
{214.406f, 101.903f, 104.72f, 1.29154f},
{217.521f, 95.4237f, 104.72f, 1.29154f},
{223.296f, 105.101f, 104.72f, 1.29154f},
{209.233f, 73.2819f, 104.80f, 1.29154f} // patrolling necrofiend
};

struct GandlingEventData
{
GandlingEventData() : m_bIsActive(false) {}
Expand All @@ -74,6 +104,17 @@ struct GandlingEventData
std::set<uint32> m_sAddGuids;
};

struct BoxVolume
{
float m_fCornerX;
float m_fCornerY;
float m_fCenterZ;
uint32 m_uiLength;
uint32 m_uiWidth;
};

static const BoxVolume aEntranceRoom[] = {174.13f, 63.84f, 104.0f, 54, 44};

static const uint32 aGandlingEvents[MAX_EVENTS] = {EVENT_ID_POLKELT, EVENT_ID_THEOLEN, EVENT_ID_MALICIA, EVENT_ID_ILLUCIA, EVENT_ID_BAROV, EVENT_ID_RAVENIAN};

typedef std::map<uint32, GandlingEventData> GandlingEventMap;
Expand Down Expand Up @@ -104,12 +145,16 @@ class instance_scholomance : public ScriptedInstance

private:
void DoSpawnGandlingIfCan(bool bByPlayerEnter);
void DoRespawnEntranceRoom();

uint32 m_auiEncounter[MAX_ENCOUNTER];
std::string m_strInstData;

uint32 m_uiGandlingEvent;
GandlingEventMap m_mGandlingData;

bool m_bIsRoomReset;
GuidSet m_sEntranceRoomGuids;
};

#endif

0 comments on commit 3e6fed7

Please sign in to comment.