/* * zonehandler.cpp Keith Fulton * * Copyright (C) 2003 Atomic Blue (info@planeshift.it, http://www.atomicblue.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 the Free Software Foundation (version 2 of the License) * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "physicallayer/propclas.h" #include "globals.h" #include "psbehave/psworld.h" #include "zonehandler.h" #include "pscamera.h" #include "globals.h" #include "iclient/isoundmngr.h" #include "net/messages.h" #include "net/msghandler.h" #include "pscelclient.h" #include "modehandler.h" #include "util/psscf.h" #include "util/log.h" #include "paws/pawsmanager.h" #include "paws/pawsprogressbar.h" #include "gui/pawsloading.h" #include "pscharcontrol.h" ZoneHandler::ZoneHandler(MsgHandler* mh,iObjectRegistry* obj_reg, psCelClient *cc) { msghandler = mh; object_reg = obj_reg; world = NULL; celclient = cc; haveNewPos = false; msghandler->Subscribe(this,MSGTYPE_NEWSECTOR); valid = LoadZoneInfo(); needsToLoadMaps = false; loadWindow = NULL; loadProgressBar = NULL; } ZoneHandler::~ZoneHandler() { if (msghandler) { msghandler->Unsubscribe(this,MSGTYPE_NEWSECTOR); } } bool ZoneHandler::FindLoadWindow() { if (loadProgressBar != NULL) return true; // Already found loadWindow = static_cast (PawsManager::GetSingleton().FindWidget("LoadWindow")); if (loadWindow == NULL) return false; loadProgressBar = static_cast (loadWindow->FindWidget("Progress")); if (loadProgressBar == NULL) return false; return true; } ZoneLoadInfo * ZoneHandler::FindZone(const char* sector) { ZoneLoadInfo key(sector, NULL); ZoneLoadInfo* zone = zonelist.Find(&key); if (zone == NULL) Error2("Fatal error: Could not find zone info for sector %s!\n",sector); return zone; } bool ZoneHandler::LoadZoneInfo() { iVFS* vfs = psengine->GetVFS (); if (!vfs) return false; iDocumentSystem* xml = psengine->GetXMLParser (); csRef doc = xml->CreateDocument(); csRef file = vfs->Open("/planeshift/data/zoneinfo.xml", VFS_FILE_READ); if (!file) return false; const char* error = doc->Parse(file); if (error) { Error2("Error Loading Zone Data: %s\n", error); return false; } csRef zoneIter = doc->GetRoot()->GetNode("zonelist")->GetNodes("zone"); while (zoneIter->HasNext()) { csRef zoneNode = zoneIter->Next(); csRef regionIter = zoneNode->GetNodes("region"); while (regionIter->HasNext()) { // Parse attributes from tag csRef regionNode = regionIter->Next(); csString mapname = regionNode->GetAttributeValue("map"); bool found = false; for(size_t i =0;iFatalError("The sector you have entered couldn't be loaded.\nPlease check your logs for details."); return; } FlagRegions(zone); if (world->NeedsLoading(zone->transitional)) { needsToLoadMaps = true; sectorToLoad = msg.newSector; haveNewPos = true; newPos = msg.pos; psengine->GetCharControl()->GetMovementManager()->StopAllMovement(); if (FindLoadWindow()) { loadWindow->SetAlwaysOnTop(true); loadWindow->Clear(); // If the area has its own loading image, use it if (zone->loadImage) { Debug2(LOG_LOAD, 0, "Setting background %s", zone->loadImage.GetData()); loadWindow->SetBackground(zone->loadImage.GetData()); } loadWindow->AddText("Loading region"); loadWindow->Show(); psengine->ForceRefresh(); } } else // If we don't need to load map, set player's position immediately MovePlayerTo(msg.pos, msg.newSector); if(!needsToLoadMaps) psengine->GetModeHandler()->DoneLoading(msg.newSector); } void ZoneHandler::MovePlayerTo(const csVector3 & newPos, const csString & newSector) { csVector3 pos; float yrot; iSector* sector; csRef pcmove; pcmove = celclient->GetMainPlayer()->linmove; pcmove->GetLastPosition (pos, yrot, sector); // retrieve last yrot sector = psengine->GetEngine()->FindSector(newSector); if (sector != NULL) { Notify5(LOG_LOAD, "Setting position of player %f %f %f in sector '%s'", newPos.x, newPos.y, newPos.z, newSector.GetData()); pcmove->SetPosition(newPos, yrot, sector); // set new position } else { Error2("Couldn't find sector '%s'", newSector.GetData()); } if (FindLoadWindow()) loadProgressBar->Completed(); } void ZoneHandler::OnDrawingFinished() { if (needsToLoadMaps) { //Error1("Going to load and unload maps"); if (ExecuteFlaggedRegions(sectorToLoad)) { needsToLoadMaps = false; psengine->SetLoadedMap(true); psengine->GetModeHandler()->ClearLightFadeSettings(); // make sure new map gets relit for time of day if (haveNewPos) { MovePlayerTo(newPos, sectorToLoad); psengine->GetPSCamera()->ResetCameraPositioning(); } } if (FindLoadWindow()) { loadProgressBar->SetCurrentValue(loadProgressBar->GetCurrentValue() + 1); psengine->ForceRefresh(); } } } void ZoneHandler::FlagRegions(ZoneLoadInfo* zone) { if (!zone) return; if(!keepMapsLoaded) world->FlagAllRegionsAsNotNeeded(); csArray loading; for (size_t i=0; i < zone->regions.Length(); i++) { csString *map = zone->regions[i]; world->FlagRegionAsNeeded(*map); loading.Push(*map); } if(loadAllMaps) { Debug1(LOG_LOAD,0, "Flagging all maps to be loaded"); for (size_t i=0; iFlagRegionAsNeeded(alllist[i]); } } if (FindLoadWindow()) { if (loadAllMaps) { loadProgressBar->SetTotalValue(alllist.Length()); } else { csArray deletedRegions; world->GetNotNeededRegions(deletedRegions); loadProgressBar->SetTotalValue(zone->regions.Length() + deletedRegions.Length()); } loadProgressBar->SetCurrentValue(0); psengine->ForceRefresh(); } } void ZoneHandler::LoadZone(const char* sector) { sectorToLoad = sector; needsToLoadMaps = true; FlagRegions( FindZone(sectorToLoad) ); } inline bool ZoneHandler::ExecuteFlaggedRegions(const csString & sector) { ZoneLoadInfo* found = FindZone(sector); if (found) { // If the sector has a loading screen, display it if (found->loadImage && FindLoadWindow()) { Debug2(LOG_LOAD, 0, "Setting background %s", found->loadImage.GetData()); loadWindow->SetBackground(found->loadImage.GetData()); psengine->ForceRefresh(); } if(!found->transitional) { csArray deletedRegions; world->GetNotNeededRegions(deletedRegions); celclient->OnRegionsDeleted(deletedRegions); } if (!world->ExecuteFlaggedRegions(found->transitional, true)) return false; celclient->OnMapsLoaded(); // If this is the first time, don't hide the loading (we still got NPCs to load) if (psengine->IsGameLoaded()) { if (FindLoadWindow()) loadWindow->Hide(); } else { // Else we need to call this since it's not a "new" sector psengine->GetModeHandler()->DoneLoading(sector); } } return true; } ZoneLoadInfo::ZoneLoadInfo(const char *sector, const char *image) { inSector = sector; loadImage = image; } ZoneLoadInfo::ZoneLoadInfo(iDocumentNode *node) { csString trans; inSector = node->GetAttributeValue("sector"); loadImage = node->GetAttributeValue("loadimage"); trans = node->GetAttributeValue("transitional"); transitional = (trans=="yes"); csRef regionIter = node->GetNodes("region"); while (regionIter->HasNext()) { // Parse attributes from tag csRef regionNode = regionIter->Next(); csString *mapname = new csString(regionNode->GetAttributeValue("map")); regions.Push(mapname); } }