diff options
Diffstat (limited to 'src/game/InstanceData.cpp')
-rw-r--r-- | src/game/InstanceData.cpp | 235 |
1 files changed, 176 insertions, 59 deletions
diff --git a/src/game/InstanceData.cpp b/src/game/InstanceData.cpp index 0f62e9e27af..bb4bfe5e8fc 100644 --- a/src/game/InstanceData.cpp +++ b/src/game/InstanceData.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,21 +21,25 @@ #include "InstanceData.h" #include "Database/DatabaseEnv.h" #include "Map.h" +#include "GameObject.h" +#include "Creature.h" +#include "CreatureAI.h" void InstanceData::SaveToDB() { - if(!Save()) return; - std::string data = Save(); + std::string data = GetSaveData(); + if(data.empty()) + return; CharacterDatabase.escape_string(data); CharacterDatabase.PExecute("UPDATE instance SET data = '%s' WHERE id = '%d'", data.c_str(), instance->GetInstanceId()); } -void InstanceData::HandleGameObject(uint64 GUID, bool open, GameObject *go) -{ +void InstanceData::HandleGameObject(uint64 GUID, bool open, GameObject *go) +{ if(!go) - go = instance->GetGameObjectInMap(GUID); + go = instance->GetGameObject(GUID); if(go) - go->SetGoState(open ? 0 : 1); + go->SetGoState(open ? GO_STATE_ACTIVE : GO_STATE_READY); else debug_log("TSCR: InstanceData: HandleGameObject failed"); } @@ -49,83 +53,196 @@ bool InstanceData::IsEncounterInProgress() const return false; } -void InstanceData::AddBossRoomDoor(uint32 id, GameObject *door) +//This will be removed in the future, just compitiable with Mangos +void InstanceData::OnCreatureCreate(Creature *creature, bool add) { - if(id < bosses.size()) + OnCreatureCreate(creature, creature->GetEntry()); +} + +void InstanceData::LoadMinionData(const MinionData *data) +{ + while(data->entry) { - BossInfo *bossInfo = &bosses[id]; - bossInfo->roomDoor.insert(door); - // Room door is only closed when encounter is in progress - if(bossInfo->state == IN_PROGRESS) - door->SetGoState(1); - else - door->SetGoState(0); + if(data->bossId < bosses.size()) + minions.insert(std::make_pair(data->entry, MinionInfo(&bosses[data->bossId]))); + + ++data; } + sLog.outDebug("InstanceData::LoadMinionData: %u minions loaded.", doors.size()); } -void InstanceData::AddBossPassageDoor(uint32 id, GameObject *door) +void InstanceData::LoadDoorData(const DoorData *data) { - if(id < bosses.size()) + while(data->entry) { - BossInfo *bossInfo = &bosses[id]; - bossInfo->passageDoor.insert(door); - // Passage door is only opened when boss is defeated - if(bossInfo->state == DONE) - door->SetGoState(0); - else - door->SetGoState(1); + if(data->bossId < bosses.size()) + doors.insert(std::make_pair(data->entry, DoorInfo(&bosses[data->bossId], data->type, BoundaryType(data->boundary)))); + + ++data; } + sLog.outDebug("InstanceData::LoadDoorData: %u doors loaded.", doors.size()); } -void InstanceData::RemoveBossRoomDoor(uint32 id, GameObject *door) +void InstanceData::UpdateMinionState(Creature *minion, EncounterState state) { - if(id < bosses.size()) + switch(state) + { + case NOT_STARTED: + if(!minion->isAlive()) + minion->Respawn(); + else if(minion->isInCombat()) + minion->AI()->EnterEvadeMode(); + break; + case IN_PROGRESS: + if(!minion->isAlive()) + minion->Respawn(); + else if(!minion->getVictim()) + minion->AI()->DoZoneInCombat(); + break; + } +} + +void InstanceData::UpdateDoorState(GameObject *door) +{ + DoorInfoMap::iterator lower = doors.lower_bound(door->GetEntry()); + DoorInfoMap::iterator upper = doors.upper_bound(door->GetEntry()); + if(lower == upper) + return; + + bool open = true; + for(DoorInfoMap::iterator itr = lower; itr != upper; ++itr) { - bosses[id].roomDoor.erase(door); + if(itr->second.type == DOOR_TYPE_ROOM) + { + if(itr->second.bossInfo->state == IN_PROGRESS) + { + open = false; + break; + } + } + else if(itr->second.type == DOOR_TYPE_PASSAGE) + { + if(itr->second.bossInfo->state != DONE) + { + open = false; + break; + } + } } + + door->SetGoState(open ? GO_STATE_ACTIVE : GO_STATE_READY); } -void InstanceData::RemoveBossPassageDoor(uint32 id, GameObject *door) +void InstanceData::AddDoor(GameObject *door, bool add) { - if(id < bosses.size()) + DoorInfoMap::iterator lower = doors.lower_bound(door->GetEntry()); + DoorInfoMap::iterator upper = doors.upper_bound(door->GetEntry()); + if(lower == upper) + return; + + for(DoorInfoMap::iterator itr = lower; itr != upper; ++itr) { - bosses[id].passageDoor.erase(door); + if(add) + { + itr->second.bossInfo->door[itr->second.type].insert(door); + switch(itr->second.boundary) + { + default: + case BOUNDARY_NONE: + break; + case BOUNDARY_N: + case BOUNDARY_S: + itr->second.bossInfo->boundary[itr->second.boundary] = door->GetPositionX(); + break; + case BOUNDARY_E: + case BOUNDARY_W: + itr->second.bossInfo->boundary[itr->second.boundary] = door->GetPositionY(); + break; + case BOUNDARY_NW: + case BOUNDARY_SE: + itr->second.bossInfo->boundary[itr->second.boundary] = door->GetPositionX() + door->GetPositionY(); + break; + case BOUNDARY_NE: + case BOUNDARY_SW: + itr->second.bossInfo->boundary[itr->second.boundary] = door->GetPositionX() - door->GetPositionY(); + break; + } + } + else + itr->second.bossInfo->door[itr->second.type].erase(door); } + + if(add) + UpdateDoorState(door); } -void InstanceData::SetBossState(uint32 id, EncounterState state) +void InstanceData::AddMinion(Creature *minion, bool add) +{ + MinionInfoMap::iterator itr = minions.find(minion->GetEntry()); + if(itr == minions.end()) + return; + + if(add) + itr->second.bossInfo->minion.insert(minion); + else + itr->second.bossInfo->minion.erase(minion); +} + +bool InstanceData::SetBossState(uint32 id, EncounterState state) { if(id < bosses.size()) { BossInfo *bossInfo = &bosses[id]; - - bossInfo->state = state; - switch(state) + if(bossInfo->state == TO_BE_DECIDED) // loading { - case NOT_STARTED: - // Open all room doors, close all passage doors - for(DoorSet::iterator i = bossInfo->roomDoor.begin(); i != bossInfo->roomDoor.end(); ++i) - (*i)->SetGoState(0); - for(DoorSet::iterator i = bossInfo->passageDoor.begin(); i != bossInfo->passageDoor.end(); ++i) - (*i)->SetGoState(1); - break; - case IN_PROGRESS: - // Close all doors - for(DoorSet::iterator i = bossInfo->roomDoor.begin(); i != bossInfo->roomDoor.end(); ++i) - (*i)->SetGoState(1); - for(DoorSet::iterator i = bossInfo->passageDoor.begin(); i != bossInfo->passageDoor.end(); ++i) - (*i)->SetGoState(1); - break; - case DONE: - // Open all doors - for(DoorSet::iterator i = bossInfo->roomDoor.begin(); i != bossInfo->roomDoor.end(); ++i) - (*i)->SetGoState(0); - for(DoorSet::iterator i = bossInfo->passageDoor.begin(); i != bossInfo->passageDoor.end(); ++i) - (*i)->SetGoState(0); - break; - default: - break; + bossInfo->state = state; + return false; + } + else + { + if(bossInfo->state == state) + return false; + + if(state == DONE) + for(MinionSet::iterator i = bossInfo->minion.begin(); i != bossInfo->minion.end(); ++i) + if((*i)->isWorldBoss() && (*i)->isAlive()) + return false; + + bossInfo->state = state; + SaveToDB(); } + + for(uint32 type = 0; type < MAX_DOOR_TYPES; ++type) + for(DoorSet::iterator i = bossInfo->door[type].begin(); i != bossInfo->door[type].end(); ++i) + UpdateDoorState(*i); + + for(MinionSet::iterator i = bossInfo->minion.begin(); i != bossInfo->minion.end(); ++i) + UpdateMinionState(*i, state); + + return true; } + return false; } +std::string InstanceData::LoadBossState(const char * data) +{ + if(!data) return NULL; + std::istringstream loadStream(data); + uint32 buff; + uint32 bossId = 0; + for(std::vector<BossInfo>::iterator i = bosses.begin(); i != bosses.end(); ++i, ++bossId) + { + loadStream >> buff; + if(buff < TO_BE_DECIDED) + SetBossState(bossId, (EncounterState)buff); + } + return loadStream.str(); +} + +std::string InstanceData::GetBossSaveData() +{ + std::ostringstream saveStream; + for(std::vector<BossInfo>::iterator i = bosses.begin(); i != bosses.end(); ++i) + saveStream << (uint32)i->state << " "; + return saveStream.str(); +} |