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

(based on cmangos/mangos-classic@3e6fed7)

Signed-off-by: Cala <calaftp@free.fr>

(based on cmangos/mangos-tbc@69bf156)

Signed-off-by: Cala <calaftp@free.fr>
  • Loading branch information
cala committed May 20, 2016
1 parent f8370a4 commit 389b331
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 6 deletions.
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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

2 comments on commit 389b331

@cala
Copy link
Contributor Author

@cala cala commented on 389b331 May 20, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested DB update:

-- Updated default movement of NPC 11551 (Necrofiend) in Scholomance
-- Moved to creature_movement_template the path followed by the two necrofiends
-- located in the entrance room of Scholomance (before the Viewing Room)
-- The other patrolling necrofiends in the instance still use their path from creature_movement
-- This change is required because one of the necrofiend is spawned dynamically
DELETE FROM creature_movement_template WHERE entry = 11551;
INSERT INTO `creature_movement_template` VALUES 
(11551, 1, 206.346, 80.7189, 104.244, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0),
(11551, 2, 221.189, 86.5182, 104.715, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0),
(11551, 3, 207.384, 91.5904, 104.244, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0),
(11551, 4, 199.815, 104.765, 104.715, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0),
(11551, 5, 192.953, 90.7216, 104.244, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0),
(11551, 6, 178.803, 86.621, 104.716, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0),
(11551, 7, 192.998, 81.0231, 104.244, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0),
(11551, 8, 199.444, 69.7478, 104.716, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0);

UPDATE creature_template SET MovementType = 2 WHERE Entry = 11551;

@Rog360
Copy link

@Rog360 Rog360 commented on 389b331 May 20, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice Work to all involved... :)

Please sign in to comment.