diff --git a/src/scriptdev2/scripts/eastern_kingdoms/scholomance/instance_scholomance.cpp b/src/scriptdev2/scripts/eastern_kingdoms/scholomance/instance_scholomance.cpp old mode 100644 new mode 100755 index 8478b56496..ad49a034a1 --- a/src/scriptdev2/scripts/eastern_kingdoms/scholomance/instance_scholomance.cpp +++ b/src/scriptdev2/scripts/eastern_kingdoms/scholomance/instance_scholomance.cpp @@ -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(); } @@ -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; @@ -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: @@ -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 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) @@ -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; diff --git a/src/scriptdev2/scripts/eastern_kingdoms/scholomance/scholomance.h b/src/scriptdev2/scripts/eastern_kingdoms/scholomance/scholomance.h old mode 100644 new mode 100755 index 4637dd02b1..225cc81d0d --- a/src/scriptdev2/scripts/eastern_kingdoms/scholomance/scholomance.h +++ b/src/scriptdev2/scripts/eastern_kingdoms/scholomance/scholomance.h @@ -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, @@ -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, @@ -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) {} @@ -74,6 +104,17 @@ struct GandlingEventData std::set 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 GandlingEventMap; @@ -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