See More

/* Copyright (C) 2006 - 2011 ScriptDev2 * This program is free software licensed under GPL version 2 * Please see the included DOCS/LICENSE.TXT for more information */ #include "precompiled.h" /** Function that uses a door or a button @param guid The ObjectGuid of the Door/ Button that will be used @param uiWithRestoreTime (in seconds) if == 0 autoCloseTime will be used (if not 0 by default in *_template) @param bUseAlternativeState Use to alternative state */ void ScriptedInstance::DoUseDoorOrButton(ObjectGuid guid, uint32 uiWithRestoreTime, bool bUseAlternativeState) { if (!guid) return; if (GameObject* pGo = instance->GetGameObject(guid)) { if (pGo->GetGoType() == GAMEOBJECT_TYPE_DOOR || pGo->GetGoType() == GAMEOBJECT_TYPE_BUTTON) { if (pGo->getLootState() == GO_READY) pGo->UseDoorOrButton(uiWithRestoreTime, bUseAlternativeState); else if (pGo->getLootState() == GO_ACTIVATED) pGo->ResetDoorOrButton(); } else error_log("SD2: Script call DoUseDoorOrButton, but gameobject entry %u is type %u.", pGo->GetEntry(), pGo->GetGoType()); } } /// Function that uses a door or button that is stored in m_mGoEntryGuidStore void ScriptedInstance::DoUseDoorOrButton(uint32 uiEntry, uint32 uiWithRestoreTime /*= 0*/, bool bUseAlternativeState /*= false*/) { EntryGuidMap::iterator find = m_mGoEntryGuidStore.find(uiEntry); if (find != m_mGoEntryGuidStore.end()) DoUseDoorOrButton(find->second, uiWithRestoreTime, bUseAlternativeState); else // Output log, possible reason is not added GO to storage, or not yet loaded debug_log("SD2: Script call DoUseDoorOrButton(by Entry), but no gameobject of entry %u was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId()); } /** Function that respawns a despawned GameObject with given time @param guid The ObjectGuid of the GO that will be respawned @param uiTimeToDespawn (in seconds) Despawn the GO after this time, default is a minute */ void ScriptedInstance::DoRespawnGameObject(ObjectGuid guid, uint32 uiTimeToDespawn) { if (!guid) return; if (GameObject* pGo = instance->GetGameObject(guid)) { //not expect any of these should ever be handled if (pGo->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE || pGo->GetGoType() == GAMEOBJECT_TYPE_DOOR || pGo->GetGoType() == GAMEOBJECT_TYPE_BUTTON || pGo->GetGoType() == GAMEOBJECT_TYPE_TRAP) return; if (pGo->isSpawned()) return; pGo->SetRespawnTime(uiTimeToDespawn); pGo->Refresh(); } } /// Function that respawns a despawned GO that is stored in m_mGoEntryGuidStore void ScriptedInstance::DoRespawnGameObject(uint32 uiEntry, uint32 uiTimeToDespawn) { EntryGuidMap::iterator find = m_mGoEntryGuidStore.find(uiEntry); if (find != m_mGoEntryGuidStore.end()) DoRespawnGameObject(find->second, uiTimeToDespawn); else // Output log, possible reason is not added GO to storage, or not yet loaded; debug_log("SD2: Script call DoRespawnGameObject(by Entry), but no gameobject of entry %u was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId()); } /** Helper function to update a world state for all players in the map @param uiStateId The WorldState that will be set for all players in the map @param uiStateData The Value to which the State will be set to */ void ScriptedInstance::DoUpdateWorldState(uint32 uiStateId, uint32 uiStateData) { Map::PlayerList const& lPlayers = instance->GetPlayers(); if (!lPlayers.isEmpty()) { for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) { if (Player* pPlayer = itr->getSource()) pPlayer->SendUpdateWorldState(uiStateId, uiStateData); } } else debug_log("SD2: DoUpdateWorldState attempt send data but no players in map."); } /// Get the first found Player* (with requested properties) in the map. Can return NULL. Player* ScriptedInstance::GetPlayerInMap(bool bOnlyAlive /*=false*/, bool bCanBeGamemaster /*=true*/) { Map::PlayerList const& lPlayers = instance->GetPlayers(); for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) { Player* pPlayer = itr->getSource(); if (pPlayer && (!bOnlyAlive || pPlayer->isAlive()) && (bCanBeGamemaster || !pPlayer->isGameMaster())) return pPlayer; } return NULL; } /// Returns a pointer to a loaded GameObject that was stored in m_mGoEntryGuidStore. Can return NULL GameObject* ScriptedInstance::GetSingleGameObjectFromStorage(uint32 uiEntry) { EntryGuidMap::iterator find = m_mGoEntryGuidStore.find(uiEntry); if (find != m_mGoEntryGuidStore.end()) return instance->GetGameObject(find->second); // Output log, possible reason is not added GO to map, or not yet loaded; debug_log("SD2: Script requested gameobject with entry %u, but no gameobject of this entry was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId()); return NULL; } /// Returns a pointer to a loaded Creature that was stored in m_mGoEntryGuidStore. Can return NULL Creature* ScriptedInstance::GetSingleCreatureFromStorage(uint32 uiEntry, bool bSkipDebugLog /*=false*/) { EntryGuidMap::iterator find = m_mNpcEntryGuidStore.find(uiEntry); if (find != m_mNpcEntryGuidStore.end()) return instance->GetCreature(find->second); // Output log, possible reason is not added GO to map, or not yet loaded; if (!bSkipDebugLog) debug_log("SD2: Script requested creature with entry %u, but no npc of this entry was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId()); return NULL; } /** Helper function to start a timed achievement criteria for players in the map @param criteriaType The Type that is required to complete the criteria, see enum AchievementCriteriaTypes in MaNGOS @param uiTimedCriteriaMiscId The ID that identifies how the criteria is started */ void ScriptedInstance::DoStartTimedAchievement(AchievementCriteriaTypes criteriaType, uint32 uiTimedCriteriaMiscId) { Map::PlayerList const& lPlayers = instance->GetPlayers(); if (!lPlayers.isEmpty()) { for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) { if (Player* pPlayer = itr->getSource()) pPlayer->StartTimedAchievementCriteria(criteriaType, uiTimedCriteriaMiscId); } } else debug_log("SD2: DoStartTimedAchievement attempt start achievements but no players in map."); } /** Constructor for DialogueHelper @param pDialogueArray The static const array of DialogueEntry holding the information about the dialogue. This array MUST be terminated by {0,0,0} */ DialogueHelper::DialogueHelper(DialogueEntry const* pDialogueArray) : m_pDialogueArray(pDialogueArray), m_pDialogueTwoSideArray(NULL), m_pInstance(NULL), m_pCurrentEntry(NULL), m_pCurrentEntryTwoSide(NULL), m_uiTimer(0), m_bCanSimulate(false), m_bIsFirstSide(true) {} /** Constructor for DialogueHelper (Two Sides) @param pDialogueTwoSideArray The static const array of DialogueEntryTwoSide holding the information about the dialogue. This array MUST be terminated by {0,0,0,0,0} */ DialogueHelper::DialogueHelper(DialogueEntryTwoSide const* pDialogueTwoSideArray) : m_pDialogueArray(NULL), m_pDialogueTwoSideArray(pDialogueTwoSideArray), m_pInstance(NULL), m_pCurrentEntry(NULL), m_pCurrentEntryTwoSide(NULL), m_uiTimer(0), m_bCanSimulate(false), m_bIsFirstSide(true) {} /** Function to start a (part of a) dialogue @param iTextEntry The TextEntry of the dialogue that will be started (must be always the entry of first side) */ void DialogueHelper::StartNextDialogueText(int32 iTextEntry) { // Find iTextEntry bool bFound = false; if (m_pDialogueArray) // One Side { for (DialogueEntry const* pEntry = m_pDialogueArray; pEntry->iTextEntry; ++pEntry) { if (pEntry->iTextEntry == iTextEntry) { m_pCurrentEntry = pEntry; bFound = true; break; } } } else // Two Sides { for (DialogueEntryTwoSide const* pEntry = m_pDialogueTwoSideArray; pEntry->iTextEntry; ++pEntry) { if (pEntry->iTextEntry == iTextEntry) { m_pCurrentEntryTwoSide = pEntry; bFound = true; break; } } } if (!bFound) { error_log("SD2: Script call DialogueHelper::StartNextDialogueText, but textEntry %i is not in provided dialogue (on map id %u)", iTextEntry, m_pInstance ? m_pInstance->instance->GetId() : 0); return; } DoNextDialogueStep(); } /// Internal helper function to do the actual say of a DialogueEntry void DialogueHelper::DoNextDialogueStep() { // Last Dialogue Entry done? if (m_pCurrentEntry && !m_pCurrentEntry->iTextEntry || m_pCurrentEntryTwoSide && !m_pCurrentEntryTwoSide->iTextEntry) { m_uiTimer = 0; return; } // Get Text, SpeakerEntry and Timer int32 iTextEntry = 0; uint32 uiSpeakerEntry = 0; if (m_pDialogueArray) // One Side { uiSpeakerEntry = m_pCurrentEntry->uiSayerEntry; iTextEntry = m_pCurrentEntry->iTextEntry; m_uiTimer = m_pCurrentEntry->uiTimer; } else // Two Sides { // Second Entries can be 0, if they are the entry from first side will be taken uiSpeakerEntry = !m_bIsFirstSide && m_pCurrentEntryTwoSide->uiSayerEntryAlt ? m_pCurrentEntryTwoSide->uiSayerEntryAlt : m_pCurrentEntryTwoSide->uiSayerEntry; iTextEntry = !m_bIsFirstSide && m_pCurrentEntryTwoSide->iTextEntryAlt ? m_pCurrentEntryTwoSide->iTextEntryAlt : m_pCurrentEntryTwoSide->iTextEntry; m_uiTimer = m_pCurrentEntryTwoSide->uiTimer; } // Simulate Case if (m_bCanSimulate && m_pInstance && uiSpeakerEntry && iTextEntry < 0) m_pInstance->DoOrSimulateScriptTextForThisInstance(iTextEntry, uiSpeakerEntry); else { // Get Speaker Creature* pSpeaker = NULL; if (m_pInstance && uiSpeakerEntry) pSpeaker = m_pInstance->GetSingleCreatureFromStorage(uiSpeakerEntry); if (pSpeaker && iTextEntry < 0) DoScriptText(iTextEntry, pSpeaker); } JustDidDialogueStep(m_pDialogueArray ? m_pCurrentEntry->iTextEntry : m_pCurrentEntryTwoSide->iTextEntry); // Increment position if (m_pDialogueArray) ++m_pCurrentEntry; else ++m_pCurrentEntryTwoSide; } /// Call this function within any DialogueUpdate method. This is required for saying next steps in a dialogue void DialogueHelper::DialogueUpdate(uint32 uiDiff) { if (m_uiTimer) { if (m_uiTimer <= uiDiff) DoNextDialogueStep(); else m_uiTimer -= uiDiff; } }