// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // 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 Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "stdpch.h" #include "nel/misc/command.h" #include "nel/misc/variable.h" #include "nel/misc/config_file.h" #include "nel/net/service.h" #include "nel/ligo/primitive_utils.h" #include "game_share/time_weather_season/time_and_season.h" #include "zone_manager.h" #include "mission_manager/mission_manager.h" #include "primitives_parser.h" #include "player_manager/player_manager.h" #include "player_manager/player.h" #include "player_manager/character.h" #include "creature_manager/creature_manager.h" #include "deposit.h" #include "egs_globals.h" #include "phrase_manager/phrase_utilities_functions.h" #include "player_manager/character_respawn_points.h" #include "stables/stable.h" #include "chat_groups_ids.h" #include "pvp_manager/pvp_manager.h" #include "pvp_manager/pvp_manager_2.h" #include "pvp_manager/pvp_safe_zone.h" //#include "backward_compatibility/spawn_zones_back_compat.h" #include "backward_compatibility/places_back_compat.h" #include "pvp_manager/pvp.h" #include "pvp_manager/pvp_faction_reward_manager/pvp_faction_reward_manager.h" #include "outpost_manager/outpost_manager.h" #include "modules/shard_unifier_client.h" using namespace std; using namespace NLMISC; using namespace NLLIGO; using namespace NLNET; // The ecotype zones CEcotypeZones CZoneManager::_EcotypeZones; /* const std::string CContinent::ContNames [] = { "fyros", "tryker" "zorai", "matis", }; */ /* arg0: is the zone name id arg1: if zone is not pvp arg1 is interpreted as a boolean (0 - inactive, 1 - active) if zone is a pvp zone arg1 is interpreted as 0 - inactive 1 - active with faction point rewards 2 - active without faction point rewards */ void cbSetZoneState( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId ) { string sZoneName; uint32 nState; msgin.serial(sZoneName); msgin.serial(nState); CZoneManager *pZM = &CZoneManager::getInstance(); // get the places CPlace *place = pZM->getPlaceFromName(sZoneName); if (place != NULL) if (place->isGooPath()) place->setGooActive(nState != 0); // get the deposit zone (linear search) const vector &rDeps = pZM->getDeposits(); for (uint32 i = 0; i < rDeps.size(); ++i) { CDeposit *pd = rDeps[i]; if (pd->getName() == sZoneName) { pd->enable(nState!=0); return; } } // get the pvp zone CPVPManager *pPVPM = CPVPManager::getInstance(); IPVPZone *pPVPZ = pPVPM->getPVPZone(sZoneName); if (pPVPZ != NULL) { pPVPZ->setActive(nState!=0); CPVPVersusZone *pPVPVZ = dynamic_cast(pPVPZ); if (pPVPVZ != NULL) pPVPVZ->giveFactionPoints(nState == 1); return; } // TODO : treat other zones ! } //----------------------------------------------- // CGooPath build //----------------------------------------------- /*bool CGooPath::build(const NLLIGO::CPrimPath * path,uint16 id ) { _Id = id; *( (NLLIGO::CPrimPath*)this ) = *path; if ( !zone->getPropertyByName("name",_Name) ) { nlwarning(" : no name in goo place %u", id); return false; } if ( VPoints.empty() ) { nlwarning(" :no points in goo place %u/%s", id, _Name.c_str()); return false; } // get the bounding box float minX = VPoints[0].x; float minY = VPoints[0].y; float maxX = VPoints[0].x; float maxY = VPoints[0].y; for ( uint i = 1; i < VPoints.size(); i++) { if ( VPoints[i].x < minX )minX = VPoints[i].x; if ( VPoints[i].y < minY )minY = VPoints[i].y; if ( VPoints[i].x > maxX )maxX = VPoints[i].x; if ( VPoints[i].y > maxY )maxY = VPoints[i].y; } // get the center of the Box _CenterX = sint32 ( ( minX + maxX ) *1000.0f / 2.0f ); _CenterY = sint32 ( ( minY + maxY ) *1000.0f / 2.0f ); return true; }// CGooPath build */ //----------------------------------------------- // Tp Dest zone build //----------------------------------------------- bool CTpSpawnZone::build(const NLLIGO::CPrimPoint * point) { *( (NLLIGO::CPrimPoint*)this ) = *point; _Continent = CONTINENT::UNKNOWN; string value; if ( !point->getPropertyByName("name",_Name) ) { nlwarning(" : no name in CTpSpawnZone" ); return false; } if ( !point->getPropertyByName("radius",value) ) { nlwarning(" : no radius in CTpSpawnZone '%s'",_Name.c_str() ); return false; } // get radius in mm _Radius = uint16( atof( value.c_str() ) * 1000.0f ); // get the z value if necessary if ( !point->getPropertyByName("use_z", value) ) { nlwarning(" : no use_z in CTpSpawnZone '%s'",_Name.c_str() ); return false; } if ( value == "true" ) { if ( !point->getPropertyByName("z", value) ) { nlwarning(" : no z in CTpSpawnZone '%s'",_Name.c_str() ); return false; } NLMISC::fromString(value, Point.z); Point.z = float( sint32 (1000.0f* Point.z) ); } else Point.z = 0.0f; // convert coords in mm Point.x = float( sint32 (1000.0f* Point.x) ); Point.y = float( sint32 (1000.0f* Point.y) ); if ( !point->getPropertyByName("type", value) ) { nlwarning(" : no type in CTpSpawnZone '%s'",_Name.c_str() ); return false; } _Type = RESPAWN_POINT::toRespawnPointType( value ); if ( _Type == RESPAWN_POINT::UNKNOWN ) { nlwarning(" : invalid type '%s' in CTpSpawnZone '%s'",value.c_str(), _Name.c_str() ); return false; } return true; } //----------------------------------------------- // CPlace build //----------------------------------------------- bool CPlace::build(const NLLIGO::CPrimPath * path, uint16 id) { _Id = id; if (!path->VPoints.empty()) *( (NLLIGO::CPrimZone*)this ) = *(NLLIGO::CPrimZone*) path; if ( !path->getPropertyByName("name",_Name) ) { nlwarning(" : no name for GooPath %u", id); return false; } if ( VPoints.empty() ) { nlwarning(" :no points in GooPath %u/%s", id, _Name.c_str()); return false; } string val; if (path->getPropertyByName("main place", val)) _MainPlace = val == "true"; else _MainPlace = false; nlverify (CPrimitivesParser::getAlias(path, _Alias)); // _Alias = NLMISC::fromString( val.c_str() ); nlassert( _Alias != CAIAliasTranslator::Invalid ); // get the bounding box float minX = VPoints[0].x; float minY = VPoints[0].y; float maxX = VPoints[0].x; float maxY = VPoints[0].y; for ( uint i = 1; i < VPoints.size(); i++) { if ( VPoints[i].x < minX )minX = VPoints[i].x; if ( VPoints[i].y < minY )minY = VPoints[i].y; if ( VPoints[i].x > maxX )maxX = VPoints[i].x; if ( VPoints[i].y > maxY )maxY = VPoints[i].y; } // get the center of the Box _CenterX = sint32 ( ( minX + maxX ) *1000.0f / 2.0f ); _CenterY = sint32 ( ( minY + maxY ) *1000.0f / 2.0f ); _GooPath = true; _GooActive = true; _Reported = false; return true; } //----------------------------------------------- // CPlace build //----------------------------------------------- bool CPlace::build(const NLLIGO::CPrimZone * zone,uint16 id, bool reportAutorised ) { _Id = id; if (!zone->VPoints.empty()) *( (NLLIGO::CPrimZone*)this ) = *zone; if ( !zone->getPropertyByName("name",_Name) ) { nlwarning(" : no name in place %u", id); return false; } string val; if (zone->getPropertyByName("reported", val)) _Reported = val == "true"; else _Reported = true & reportAutorised; if (zone->getPropertyByName("main place", val)) _MainPlace = val == "true"; else _MainPlace = true; if (!CPrimitivesParser::getAlias(zone, _Alias)) { nlwarning("Fatal Error, no alias in primitive '%s'", buildPrimPath(zone).c_str()); nlstop; } // _Alias = NLMISC::fromString( val.c_str() ); nlassert( _Alias != CAIAliasTranslator::Invalid ); if ( VPoints.empty() ) { nlwarning(" :no points in place %u/%s", id, _Name.c_str()); return false; } // get the bounding box float minX = VPoints[0].x; float minY = VPoints[0].y; float maxX = VPoints[0].x; float maxY = VPoints[0].y; for ( uint i = 1; i < VPoints.size(); i++) { if ( VPoints[i].x < minX )minX = VPoints[i].x; if ( VPoints[i].y < minY )minY = VPoints[i].y; if ( VPoints[i].x > maxX )maxX = VPoints[i].x; if ( VPoints[i].y > maxY )maxY = VPoints[i].y; } // get the center of the Box _CenterX = sint32 ( ( minX + maxX ) *1000.0f / 2.0f ); _CenterY = sint32 ( ( minY + maxY ) *1000.0f / 2.0f ); _GooPath = false; _GooActive = false; if( zone->getPropertyByName("place_type", val) ) { _PlaceType = PLACE_TYPE::fromString(val); if( _PlaceType == PLACE_TYPE::Undefined ) _PlaceType = PLACE_TYPE::Place; } else _PlaceType = PLACE_TYPE::Place; // get children respawn points bool ret = true; for (uint i=0; i< getNumChildren();++i) { const IPrimitive *child; if ( getChild(child,i) && child ) { child->getPropertyByName("name",val); uint16 idx = CZoneManager::getInstance().getTpSpawnZoneIdByName(val); if ( idx != InvalidSpawnZoneId ) { const CTpSpawnZone * spawn = CZoneManager::getInstance().getTpSpawnZone( idx ); if ( spawn == NULL ) { nlwarning( "Invalid spawn zone '%s' in place '%s' : bad index %u",val.c_str(), _Name.c_str(), idx ); ret = false; } // if the respawn point is validated when user enters the place, add it to the place. // we dont add special respawn points ( outposts,... ) because they are validated separatly from the place where they are else if ( spawn->getType() == RESPAWN_POINT::KAMI || spawn->getType() == RESPAWN_POINT::KARAVAN || spawn->getType() == RESPAWN_POINT::NEWBIELAND || spawn->getType() == RESPAWN_POINT::RESPAWNABLE ) { (const_cast(spawn))->setPlaceType(_PlaceType); _RespawnPoints.push_back( idx ); } } } } return ret; }// CPlace build //----------------------------------------------- // CRegion build //----------------------------------------------- bool CRegion::build(const NLLIGO::CPrimZone * zone,uint16 id) { if ( CPlace::build(zone,id) ) { string value; if ( !zone->getPropertyByName("newbie_region",value) ) { nlwarning(" : failed : no newbie_region property in primitive"); _NewbieRegion = false; } else { _NewbieRegion = (!nlstricmp( value,"true"))?true:false; } return true; } else { nlwarning(" : failed in place build"); return false; } }// CRegion build //----------------------------------------------- // CRegion dtor //----------------------------------------------- CRegion::~CRegion() { }// CRegion dtor //----------------------------------------------- // CRegion registerChatGroup //----------------------------------------------- void CRegion::registerChatGroup() { TGroupId idGroup = CHAT_GROUPS_IDS::getRegionChatGroupId(_Id); CMessage msgout("ADD_GROUP"); msgout.serial( idGroup ); CChatGroup::TGroupType type = CChatGroup::region; msgout.serialEnum( type ); sendMessageViaMirror( "IOS", msgout ); // add online members ( if IOS crashed... ) set< CEntityId >::iterator it = _Players.begin(); for (; it != _Players.end(); ++it ) { TDataSetRow row = TheDataset.getDataSetRow( (*it) ); // if we can get the user from this row, the user is ingame CCharacter* user = PlayerManager.getChar( row ); if ( user ) { CMessage msgout("ADD_TO_GROUP"); msgout.serial( idGroup ); msgout.serial( const_cast(user->getId()) ); sendMessageViaMirror( "IOS", msgout ); } } } //----------------------------------------------- // CRegion addPlayer //----------------------------------------------- void CRegion::addPlayer( const NLMISC::CEntityId & id ) { _Players.insert(id); TGroupId idGroup = CHAT_GROUPS_IDS::getRegionChatGroupId(_Id); CMessage msgout("ADD_TO_GROUP"); msgout.serial( idGroup ); msgout.serial( const_cast(id) ); sendMessageViaMirror( "IOS", msgout ); } //----------------------------------------------- // CRegion removePlayer //----------------------------------------------- void CRegion::removePlayer( const NLMISC::CEntityId & id ) { _Players.erase(id); TGroupId idGroup = CHAT_GROUPS_IDS::getRegionChatGroupId(_Id); CMessage msgout("REMOVE_FROM_GROUP"); msgout.serial( idGroup ); msgout.serial( const_cast(id) ); sendMessageViaMirror( "IOS", msgout ); } //----------------------------------------------- // CContinent build //----------------------------------------------- bool CContinent::build(const NLLIGO::CPrimZone * zone) { string value; if ( zone->getPropertyByName("id",value) ) { _Id = CONTINENT::toContinent( value ); if ( _Id != CONTINENT::UNKNOWN ) { return CPlace::build( zone,_Id ); } else nlwarning(" : invalid continent id '%s'",value.c_str()); } else nlwarning(" : no id in a continent"); return false; }// CContinent build //----------------------------------------------- // CContinent dtor //----------------------------------------------- CContinent::~CContinent() { }// CContinent dtor //----------------------------------------------- // CZoneManager init //----------------------------------------------- void CZoneManager::init() { RandomGenerator.srand( CTickEventHandler::getGameCycle() ); initInstance(); }// CZoneManager init //----------------------------------------------- // CZoneManager release //----------------------------------------------- void CZoneManager::release() { for (uint i = 0; i < _Deposits.size(); i++ ) delete _Deposits[i]; for ( uint i = 0; i < _Places.size(); i++ ) delete _Places[i]; clearEcotypes(); }// CZoneManager release //----------------------------------------------- // CZoneManager initInstance //----------------------------------------------- void CZoneManager::initInstance() { _NextDepositIndexUpdated = 0; _SpreadUpdateLoopBeginTick = CTickEventHandler::getGameCycle(); // get the loaded primitives const CPrimitivesParser::TPrimitivesList & primsList = CPrimitivesParser::getInstance().getPrimitives(); _PlacesByAlias.clear(); // parse the zones nlinfo("CZoneManager : parsing the zones"); CPrimitivesParser::TPrimitivesList::const_iterator first, last; for (first = primsList.begin(), last = primsList.end(); first != last; ++first) { if (! parseContinents(first->Primitive.RootNode ) ) { nlwarning(" Error while building the continents"); } } for (first = primsList.begin(), last = primsList.end(); first != last; ++first) { if (! parseRegions(first->Primitive.RootNode ) ) { nlwarning(" Error while building the regions"); } } for (first = primsList.begin(), last = primsList.end(); first != last; ++first) { if (! parseTpSpawnZones(first->Primitive.RootNode ) ) { nlwarning(" Error while building the tp spawn Zones"); } } for (first = primsList.begin(), last = primsList.end(); first != last; ++first) { if (! parseZones(first->Primitive.RootNode ) ) { nlwarning(" Error while building the zones"); } } // Parse ecotypes, that will be used when building deposits for (first = primsList.begin(), last = primsList.end(); first != last; ++first) { if (! parseEcotypes( first->Primitive.RootNode ) ) { nlwarning(" Error while building the ecotypes"); } } // Parse (and build) deposits for (first = primsList.begin(), last = primsList.end(); first != last; ++first) { if (! parseDeposits(first->Primitive.RootNode ) ) { nlwarning(" Error while building the zones"); } } // Don't keep ecotypes in memory, the information is already in the deposits CDeposit::clearEcotypes(); // Parse stables for (first = primsList.begin(), last = primsList.end(); first != last; ++first) { if (! parseStables(first->Primitive.RootNode ) ) { nlwarning(" Error while building the stables"); } } // Parse the goo border for (first = primsList.begin(), last = primsList.end(); first != last; ++first) { if (! parseGooBorder(first->Primitive.RootNode ) ) { nlwarning(" Error while building the Goo Border"); } } // preallocate 5 start points per newbieland _StartPoints.reserve( 20 ); // Parse the start points for (first = primsList.begin(), last = primsList.end(); first != last; ++first) { if (! parseStartPoints(first->Primitive.RootNode ) ) { nlwarning(" Error while building the start points"); } } // parse the PVP zones, must be before parsing the PVP safe zones! for (first = primsList.begin(), last = primsList.end(); first != last; ++first) { if ( !parsePVPZones(first->Primitive.RootNode) ) { nlwarning(" Error while building the PVP zones"); } } // parse the PVP safe zones (except for outpost zones) for (first = primsList.begin(), last = primsList.end(); first != last; ++first) { if ( !parsePVPSafeZones(first->Primitive.RootNode) ) { nlwarning(" Error while building the PVP safe zones"); } } // apply config to PVP zones (must be done after loading primitives), except outpost ones CPVPManager::getInstance()->applyConfigToPVPZones(); // for backward compatibility //BACK_COMPAT::initSpawnZonesCompat(); BACK_COMPAT::initPlacesCompat(); // Initialize messages from other services // array of callback items NLNET::TUnifiedCallbackItem _cbArray[] = { { "SET_ZONE_STATE", cbSetZoneState }, }; // register call back for zone manager CUnifiedNetwork::getInstance()->addCallbackArray( _cbArray, sizeof(_cbArray) / sizeof(_cbArray[0]) ); }// CZoneManager ctor //----------------------------------------------- // CZoneManager dtor //----------------------------------------------- CZoneManager::~CZoneManager() { // remove deposits for (uint i = 0; i < _Deposits.size(); i++ ) delete _Deposits[i]; // all must have unregistered from the set of autospawn update nlassert(_DepositNeedingAutoSpawnUpdate.empty()); // remove places for ( uint i = 0; i < _Places.size(); i++ ) delete _Places[i]; // clear ecotypes clearEcotypes(); }// CZoneManager dtor //----------------------------------------------- // CZoneManager iosConnection //----------------------------------------------- void CZoneManager::iosConnection() { for ( uint i = 0; i < _Continents.size(); i++ ) { for ( uint j = 0; j < _Continents[i].getRegions().size(); j++ ) { _Continents[i].getRegions()[j]->registerChatGroup(); } } }// CZoneManager iosConnection //----------------------------------------------- // CZoneManager getTpSpawnZoneIdByName //----------------------------------------------- uint16 CZoneManager::getTpSpawnZoneIdByName( const std::string & name ) { map::const_iterator it = _TpSpawnZoneIdByName.find( name ); if ( it == _TpSpawnZoneIdByName.end() ) { return InvalidSpawnZoneId; } const uint16 id = (*it).second; BOMB_IF( (id >= _TpSpawnZones.size()), " invalid spawn zone id", return InvalidSpawnZoneId ); BOMB_IF( (name != _TpSpawnZones[id].getName()), " spawn zone name does not match", return InvalidSpawnZoneId ); return id; }// CZoneManager getTpSpawnZoneIdByName //----------------------------------------------- // CZoneManager parseContinents //----------------------------------------------- bool CZoneManager::parseContinents( const NLLIGO::IPrimitive* prim ) { std::string value; const CPrimZone* zone = dynamic_cast( prim); // if the primitive is a continent, parse it, build it and add it to this manager if it is correct if ( zone && zone->getPropertyByName("class",value) && value == "continent" ) { CContinent continent; if ( continent.build( zone ) ) { uint i = 0; for (; i < _Continents.size(); i++ ) { if ( _Continents[i].getId() == continent.getId() ) break; } if ( i == _Continents.size() ) { _Continents.push_back( continent ); } } } // Lookup recursively in the children bool ok = true; for (uint i=0;igetNumChildren();++i) { const IPrimitive *child; if ( prim->getChild(child,i) ) ok = parseContinents(child) && ok; } return ok; }// CZoneManager parseContinents //----------------------------------------------- // CZoneManager parseRegions //----------------------------------------------- bool CZoneManager::parseRegions( const NLLIGO::IPrimitive* prim ) { std::string value; const CPrimZone* zone = dynamic_cast(prim); // if the primitive is a continent, parse it, build it and add it to this manager if it is correct if ( zone && prim->getPropertyByName("class",value) && value == "region" ) { CRegion * region = new CRegion(); if ( region->build( zone,(uint16)_Places.size() ) ) { bool found = false; for (uint i = 0; i < _Continents.size(); i++ ) { const std::vector & regionPoints = zone->VPoints; for (uint j = 0; j < regionPoints.size(); j++ ) { if ( _Continents[i].contains( regionPoints[j] ) ) { found = true; _Continents[i].addRegion( region ); region->setContinent( (CONTINENT::TContinent) _Continents[i].getId() ); break; } } } nlassertex(found, (toString("No continent found that includes the region %s", prim->getName().c_str()).c_str() ) ); _Places.push_back( region ); _PlacesByAlias.insert( make_pair(region->getAlias(), region) ); } else delete region; } // Lookup recursively in the children bool ok = true; for (uint i=0;igetNumChildren();++i) { const IPrimitive *child; if ( prim->getChild(child,i) ) ok = parseRegions(child) && ok; } return ok; }// CZoneManager parseRegions //----------------------------------------------- // CZoneManager parseZones //----------------------------------------------- bool CZoneManager::parseZones( const NLLIGO::IPrimitive* prim ) { std::string value; const CPrimZone* zone = dynamic_cast(prim); // if the primitive is a zone, parse it if ( zone ) { // build the zone and add it to this manager if it is correct if (prim->getPropertyByName("class",value) ) { if ( value == "place" ) { CPlace* place = new CPlace(); if ( place->build( zone,(uint16)_Places.size() ) ) { for (uint i = 0; i < _Continents.size(); i++ ) { for (uint j = 0; j < _Continents[i].getRegions().size(); j++ ) { for ( uint k = 0; k < place->VPoints.size(); k++ ) { if ( _Continents[i].getRegions()[j]->contains( place->VPoints[k] ) ) { _Continents[i].getRegions()[j]->addPlace( place ); break; } } } } _Places.push_back( place ); _PlacesByAlias.insert( make_pair(place->getAlias(), place) ); } else delete place; } } } // Lookup recursively in the children bool ok = true; for (uint i=0;igetNumChildren();++i) { const IPrimitive *child; if ( prim->getChild(child,i) ) ok = parseZones(child) && ok; } return ok; } // CZoneManager parseZones //----------------------------------------------- // CZoneManager parseEcotypes //----------------------------------------------- bool CZoneManager::parseEcotypes( const NLLIGO::IPrimitive* prim ) { std::string value; if (prim->getPropertyByName("class",value) ) { if ( value == "ecotypezone_list" ) { std::string ecotypeZoneListName; prim->getPropertyByName( "name", ecotypeZoneListName ); // Parse the children ecotypes for( uint i = 0; i < prim->getNumChildren(); ++i ) { const IPrimitive * childPrim; if ( prim->getChild( childPrim, i ) ) { // If the primitive is a zone, parse it const CPrimZone* zone = dynamic_cast(childPrim); if ( zone ) { string primType; childPrim->getPropertyByName( "class", primType ); if( primType == "ecotypezone" ) { CEcotypeZone *ecotype = new CEcotypeZone(); if ( ecotype->build( zone ) ) { CDeposit::addEcotype( ecotype ); CEcotypeZone *ecotype2 = new CEcotypeZone(); if( ecotype2->build( zone ) ) CZoneManager::addEcotype( ecotype2 ); else delete ecotype2; } else delete ecotype; } } } } } } // Lookup recursively in the children bool ok = true; for (uint i=0;igetNumChildren();++i) { const IPrimitive *child; if ( prim->getChild(child,i) ) ok = parseEcotypes(child) && ok; } return ok; } //----------------------------------------------- // CZoneManager parseDeposits // Assumes the ecotypes have been parsed before //----------------------------------------------- bool CZoneManager::parseDeposits( const NLLIGO::IPrimitive* prim ) { std::string value; if (prim->getPropertyByName("class",value) ) { if ( value == "depositzone_list" ) { std::string depositZoneListName; prim->getPropertyByName( "name", depositZoneListName ); // Parse the children deposits for( uint i = 0; i < prim->getNumChildren(); ++i ) { const IPrimitive * childPrim; if ( prim->getChild( childPrim, i ) ) { // If the primitive is a zone, parse it const CPrimZone* zone = dynamic_cast(childPrim); if ( zone ) { string primType; childPrim->getPropertyByName( "class", primType ); if( primType == "depositzone" ) { bool found = false; CDeposit * deposit = new CDeposit; if ( deposit->build( zone ) ) { for (uint j = 0; j < _Continents.size(); j++ ) { for (uint k = 0; k < _Continents[j].getRegions().size(); k++ ) { uint l = 0; for ( ; l < deposit->VPoints.size(); l++ ) { if ( _Continents[j].getRegions()[k]->contains( deposit->VPoints[l] ) ) { _Continents[j].getRegions()[k]->addDeposit( deposit ); found = true; break; } } } if ( !found ) { for ( uint k = 0; k < _Continents[j].getRegions().size(); k++ ) { for ( uint l = 0 ; l < _Continents[j].getRegions()[k]->VPoints.size(); l++ ) { if ( deposit->contains( _Continents[j].getRegions()[k]->VPoints[l] ) ) { _Continents[j].getRegions()[k]->addDeposit( deposit ); found = true; break; } } } } } if ( !found ) nlwarning(" a deposit of %s is not in a region", depositZoneListName.c_str()); _Deposits.push_back(deposit); } else delete deposit; } } } } } } // Lookup recursively in the children bool ok = true; for (uint i=0;igetNumChildren();++i) { const IPrimitive *child; if ( prim->getChild(child,i) ) ok = parseDeposits(child) && ok; } return ok; } // CZoneManager parseDeposits //----------------------------------------------- // CZoneManager parseStables //----------------------------------------------- bool CZoneManager::parseStables( const NLLIGO::IPrimitive* prim ) { // Primitives format: // // // // // // // > // // // // // // // // std::string value; if (prim->getPropertyByName("class",value) ) { if ( value == "stables" ) { string stableName, continent; prim->getPropertyByName( "name", stableName ); for( uint c = 0; c < prim->getNumChildren(); ++c ) { const NLLIGO::IPrimitive* child; prim->getChild(child,c); if (child->getPropertyByName("class",value) ) { if( value == "stable" ) { //geometry of stable point (normally one dot with directional information) const NLLIGO::CPrimZone* primZone = dynamic_cast(child); if( primZone ) { bool found = false; CPlace* place = new CPlace(); if ( place->build( primZone,(uint16)_Places.size(), true ) ) { for (uint i = 0; i < _Continents.size(); i++ ) { continent = CONTINENT::toString( (CONTINENT::TContinent)_Continents[i].getId() ); for (uint j = 0; j < _Continents[i].getRegions().size(); ++j ) { for ( uint k = 0; k < place->VPoints.size(); ++k ) { if ( _Continents[i].getRegions()[j]->contains( place->VPoints[k] ) ) { _Continents[i].getRegions()[j]->addPlace( place ); found = true; // Displaying the aliases of all the stables: //string branchPath = _Continents[i].getName() + "." + _Continents[i].getRegions()[j]->getName() + "." + place->getName(); //InfoLog->displayRawNL( "STBL:%s: %u", branchPath.c_str(), place->getAlias() ); break; } } } } } if( place->getId() == 0x35 ) { nlinfo("catch it!"); } if( found == false ) { nlwarning(" Stable %s is not in a region", stableName.c_str()); delete place; } else { _Places.push_back( place ); _PlacesByAlias.insert( make_pair(place->getAlias(), place) ); for( uint c2 = 0; c2 < child->getNumChildren(); ++c2 ) { const NLLIGO::IPrimitive* child2; child->getChild(child2,c2); if (child2->getPropertyByName("class",value) ) { if( value == "stable_entry" ) { const NLLIGO::CPrimPoint *stableEntryPoint = dynamic_cast< const CPrimPoint * >(child2); if( stableEntryPoint == 0 ) { nlwarning(" Stable %s not contained stable entry point", stableName.c_str()); return false; } CStable::getInstance()->addStable( stableName, place->getId(), continent, stableEntryPoint->Point.x, stableEntryPoint->Point.y, stableEntryPoint->Point.z, stableEntryPoint->Angle ); } } } } } } } } } } // Lookup recursively in the children bool ok = true; for (uint i=0;igetNumChildren();++i) { const IPrimitive *child; if ( prim->getChild(child,i) ) ok = parseStables(child) && ok; } return ok; } //----------------------------------------------- // CZoneManager parseTpSpawnZones //----------------------------------------------- bool CZoneManager::parseTpSpawnZones( const NLLIGO::IPrimitive* prim ) { std::string value; if (prim->getPropertyByName("class",value) ) { if ( value == "teleport_spawn_zone" ) { const NLLIGO::CPrimPoint* point = dynamic_cast(prim); if ( !point ) { nlwarning("CZoneManager::parseTpSpawnZones -> teleport_trigger should be prim points"); return false; } CTpSpawnZone zone; if( !zone.build( point ) ) return false; // if it is a respawn point get the continent where the zone is if ( zone.getType() == RESPAWN_POINT::KAMI || zone.getType() == RESPAWN_POINT::KARAVAN || zone.getType() == RESPAWN_POINT::NEWBIELAND || zone.getType() == RESPAWN_POINT::RESPAWNABLE ) { bool found = false; uint j; for ( j = 0; j < _Continents.size() && !found; ++j ) { if ( _Continents[j].contains( point->Point ) ) { zone.setContinent((CONTINENT::TContinent) _Continents[j].getId()); found = true; break; } } if( !found ) { nlwarning(" Re-spawn point '%s' is not in a continent", zone.getName().c_str()); return false; } found = false; for ( uint k = 0; k < _Continents[j].getRegions().size(); k++ ) { if( _Continents[j].getRegions()[k]->contains( point->Point ) ) { zone.setRegion( _Continents[j].getRegions()[k]->getId() ); found = true; break; } } if( ! found ) { nlwarning(" Re-spawn point '%s' is not in a region", zone.getName().c_str()); return false; } } nlassert( _TpSpawnZones.size() < 0xffff ); map::const_iterator it = _TpSpawnZoneIdByName.find( zone.getName() ); BOMB_IF( (it != _TpSpawnZoneIdByName.end()), toString( " spawn zone name '%s' is already used!!!", zone.getName().c_str() ), return false ); _TpSpawnZoneIdByName[zone.getName()] = (uint16)_TpSpawnZones.size(); _TpSpawnZones.push_back( zone ); return true; } } // Lookup recursively in the children bool ok = true; for (uint i=0;igetNumChildren();++i) { const IPrimitive *child; if ( prim->getChild(child,i) ) ok = parseTpSpawnZones(child) && ok; } return ok; } //----------------------------------------------- // CZoneManager parseGooBorder //----------------------------------------------- bool CZoneManager::parseGooBorder( const NLLIGO::IPrimitive* prim ) { std::string value; if (prim->getPropertyByName("class",value) ) { if ( value == "goo_border" ) { string gooBorderName, continent; prim->getPropertyByName( "name", gooBorderName ); const CPrimPath * path = dynamic_cast(prim); if( path ) { CPlace* place = new CPlace(); if ( place->build( path,(uint16)_Places.size() ) ) //assume CPrimPath and CPrimZone has the same members, method needed are only in CPrimZone { for (uint i = 0; i < _Continents.size(); i++ ) { for (uint j = 0; j < _Continents[i].getRegions().size(); j++ ) { for ( uint k = 0; k < place->VPoints.size(); k++ ) { if ( _Continents[i].getRegions()[j]->contains( place->VPoints[k] ) ) { _Continents[i].getRegions()[j]->addPlace( place ); break; } } } } _Places.push_back( place ); _PlacesByAlias.insert( make_pair(place->getAlias(), place) ); } else { delete place; } } } } // Lookup recursively in the children bool ok = true; for (uint i=0;igetNumChildren();++i) { const IPrimitive *child; if ( prim->getChild(child,i) ) ok = parseGooBorder(child) && ok; } return ok; } //----------------------------------------------- // CZoneManager parseStartPoints //----------------------------------------------- bool CZoneManager::parseStartPoints( const NLLIGO::IPrimitive* prim ) { std::string value; if (prim->getPropertyByName("class",value) ) { if ( value == "start_village" ) { string value; prim->getPropertyByName( "name", value ); RYZOM_STARTING_POINT::TStartPoint start = RYZOM_STARTING_POINT::toStartPoint( value ); if ( start == RYZOM_STARTING_POINT::NB_START_POINTS ) { nlwarning(" invalid start point %s",value.c_str() ); return false; } uint16 startIdx = (uint16) start; if ( startIdx >= _StartPoints.size() ) _StartPoints.resize( startIdx + 1); bool ok = true; for (uint i=0;igetNumChildren();++i) { const IPrimitive *child = NULL; if ( prim->getChild(child,i) && child && child->getPropertyByName("class",value) && value == "start_point") { CStartPoint point; child->getPropertyByName( "mission", value ); point.Mission = CAIAliasTranslator::getInstance()->getMissionUniqueIdFromName( value ); if ( point.Mission == CAIAliasTranslator::Invalid ) { nlwarning(" invalid mission %s",value.c_str() ); } child->getPropertyByName( "welcomer", value ); point.Welcomer = CAIAliasTranslator::Invalid; vector aliases; CAIAliasTranslator::getInstance()->getNPCAliasesFromName( value, aliases ); if ( aliases.empty() ) { nlwarning(" invalid welcomer %s",value.c_str() ); } else point.Welcomer = aliases[0]; if ( point.Welcomer == CAIAliasTranslator::Invalid ) { nlwarning(" invalid welcomer %s",value.c_str() ); } child->getPropertyByName( "spawn_zone", value ); point.SpawnZoneId = getTpSpawnZoneIdByName( value ); if ( point.SpawnZoneId == InvalidSpawnZoneId ) { nlwarning(" invalid spawn zone %s",value.c_str() ); ok = false; } if ( ok ) { _StartPoints[startIdx].push_back( point ); } } } return ok; } } // Lookup recursively in the children bool ok = true; for (uint i=0;igetNumChildren();++i) { const IPrimitive *child; if ( prim->getChild(child,i) ) ok = parseStartPoints(child) && ok; } return ok; } CVariable LoadPVPFreeZones("egs", "LoadPVPFreeZones", "If true PVP free zones will be loaded", false, 0, true ); CVariable LoadPVPVersusZones("egs", "LoadPVPVersusZones", "If true PVP versus zones will be loaded", false, 0, true ); CVariable LoadPVPGuildZones("egs", "LoadPVPGuildZones", "If true PVP guild zones will be loaded", false, 0, true ); //----------------------------------------------- // CZoneManager parsePVPZones //----------------------------------------------- bool CZoneManager::parsePVPZones( const NLLIGO::IPrimitive * prim ) { std::string value; prim->getPropertyByName("class",value); const CPrimZone * zone = dynamic_cast(prim); // if the primitive is a zone, parse it if ( zone && (value == "pvp_zone") ) { CSmartPtr pvpZone = IPVPZone::build( zone ); bool load = false; switch (pvpZone->getPVPZoneType()) { case PVP_ZONE_TYPE::FreeZone: load = LoadPVPFreeZones; break; case PVP_ZONE_TYPE::VersusZone: load = LoadPVPVersusZones; break; case PVP_ZONE_TYPE::GuildZone: load = LoadPVPGuildZones; break; default: nlwarning( "Invalid %s zone in pvp_zone primitive %s", PVP_ZONE_TYPE::toString( pvpZone->getPVPZoneType() ).c_str(), prim->getName().c_str() ); load = false; } if (load) CPVPManager::getInstance()->addPVPZone( pvpZone ); } // lookup recursively in the children bool result = true; for (uint i = 0; i < prim->getNumChildren(); i++) { const IPrimitive * child; if ( prim->getChild(child, i) ) result &= parsePVPZones(child); } return result; } // CZoneManager parsePVPZones //----------------------------------------------- // CZoneManager parsePVPSafeZones //----------------------------------------------- bool CZoneManager::parsePVPSafeZones( const NLLIGO::IPrimitive * prim ) { std::string value; const CPrimPoint * point = dynamic_cast(prim); // if the primitive is a point, parse it if ( point && prim->getPropertyByName("class",value) && value == "safe_zone" ) { value = "true"; prim->getPropertyByName("safe_from_pvp", value); if ( value == "true" ) { CSmartPtr safeZone = CPVPSafeZone::build( point ); if ( !safeZone.isNull() ) { CPVPManager::getInstance()->addPVPSafeZone( safeZone ); CPVPManager2::getInstance()->addPVPSafeZone( safeZone ); } } } // lookup recursively in the children bool result = true; for (uint i = 0; i < prim->getNumChildren(); i++) { const IPrimitive * child; if ( prim->getChild(child, i) ) result &= parsePVPSafeZones(child); } return result; } // CZoneManager parsePVPSafeZones //----------------------------------------------- // CZoneManager getContinent //----------------------------------------------- CContinent * CZoneManager::getContinent( sint32 x, sint32 y ) { CVector vect( x * 0.001f, y * 0.001f, 0.0f ); for ( uint i = 0; i < _Continents.size(); i++ ) { if ( _Continents[i].contains(vect) ) return &_Continents[i]; } return NULL; return getContinent(vect); }// CZoneManager getContinent* //----------------------------------------------- // Same with vector //----------------------------------------------- CContinent * CZoneManager::getContinent( const NLMISC::CVector& pos ) { for ( uint i = 0; i < _Continents.size(); i++ ) { if ( _Continents[i].contains(pos) ) return &_Continents[i]; } return NULL; }// CZoneManager getContinent //----------------------------------------------- // CZoneManager getRegion //----------------------------------------------- bool CZoneManager::getRegion( sint32 x, sint32 y, const CRegion ** region, const CContinent ** continent) { nlassert(region); CVector vect( x * 0.001f, y * 0.001f, 0.0f ); for ( uint i = 0; i < _Continents.size(); i++ ) { if ( _Continents[i].contains(vect) ) { for (uint j = 0; j < _Continents[i].getRegions().size(); j++ ) { if ( _Continents[i].getRegions()[j]->contains( vect ) ) { if ( continent ) *continent = &_Continents[i]; *region = _Continents[i].getRegions()[j]; return true; } } } } return false; }// CZoneManager getRegion #include //----------------------------------------------- // CZoneManager getPlace //----------------------------------------------- bool CZoneManager::getPlace( sint32 x, sint32 y, float& gooDistance, const CPlace ** stable, std::vector& places, const CRegion ** region , const CContinent ** continent ) { nlassert(stable); if( continent ) *continent = NULL; if( region ) *region = NULL; *stable = NULL; float nearGooDistance = numeric_limits::max(); CVector vect( x * 0.001f, y * 0.001f, 0.0f ); for ( uint i = 0; i < _Continents.size(); i++ ) { if ( _Continents[i].contains(vect) ) { if ( continent ) *continent = &_Continents[i]; for (uint j = 0; j < _Continents[i].getRegions().size(); j++ ) { if ( _Continents[i].getRegions()[j]->contains( vect ) ) { if ( region ) { *region = _Continents[i].getRegions()[j]; } for (uint k = 0; k < _Continents[i].getRegions()[j]->getPlaces().size(); k++ ) { if(!_Continents[i].getRegions()[j]->getPlaces()[k]->isGooActive()) { if ( _Continents[i].getRegions()[j]->getPlaces()[k]->contains( vect ) ) { const CPlace * p; p = _Continents[i].getRegions()[j]->getPlaces()[k]; CStable::TStableData stableData; if( CStable::getInstance()->getStableData( p->getId(), stableData ) ) { *stable = p; } places.push_back( p ); } } else { CVector p1, p2, nearPos; float distance; CPrimZone::contains (vect, _Continents[i].getRegions()[j]->getPlaces()[k]->VPoints, distance, nearPos, true); if( distance < nearGooDistance ) { nearGooDistance = distance; } } } gooDistance = nearGooDistance; return true; } } } } gooDistance = nearGooDistance; return false; }// CZoneManager getPlace //----------------------------------------------- // CZoneManager getRegion //----------------------------------------------- CRegion * CZoneManager::getRegion( const NLMISC::CVector& pos ) { const CRegion *cregion = 0; if ( (! getRegion( (sint32)(pos.x*1000.0f), (sint32)(pos.y*1000.0f), &cregion )) || (! cregion) ) { nlwarning( "Invalid region for pos %s", pos.asString().c_str() ); return NULL; } return (const_cast(cregion)); } //----------------------------------------------- // CZoneManager getDepositsUnderUser //----------------------------------------------- void CZoneManager::getDepositsUnderPos( const CVector& pos, std::vector& deposits, bool warnIfOutsideOfRegion ) { const CRegion *cregion = 0; CRegion *region; if ( (! getRegion( (sint32)(pos.x*1000.0f), (sint32)(pos.y*1000.0f), &cregion )) || (! cregion) ) { if ( warnIfOutsideOfRegion ) nlwarning( " invalid region for pos %s", pos.asString().c_str() ); return; } region = (const_cast(cregion)); deposits.clear(); for (uint i=0; i!=region->getDeposits().size(); ++i ) { if ( region->getDeposits()[i]->contains( pos ) ) deposits.push_back( region->getDeposits()[i] ); } }// CZoneManager getDepositsUnderPos // // get the first deposit found under the position (faster than getDepositsUnderPos()), or NULL if not found // CDeposit* CZoneManager::getFirstFoundDepositUnderPos( const NLMISC::CVector& pos ) { const CRegion *cregion = 0; CRegion *region; if ( (! getRegion( (sint32)(pos.x*1000.0f), (sint32)(pos.y*1000.0f), &cregion )) || (! cregion) ) { nlwarning( " invalid region for pos %s", pos.asString().c_str() ); return NULL; } region = (const_cast(cregion)); for (uint i=0; i!=region->getDeposits().size(); ++i ) { if ( region->getDeposits()[i]->contains( pos ) ) return region->getDeposits()[i]; } return NULL; } //----------------------------------------------- // CZoneManager getContinentFromId //----------------------------------------------- CPlace* CZoneManager::getPlaceFromAlias( TAIAlias alias ) { std::map< TAIAlias, CPlace* >::iterator it = _PlacesByAlias.find( alias ); if ( it != _PlacesByAlias.end() ) { return ( (*it).second ); } return NULL; } //----------------------------------------------- // CZoneManager getPlaceFromName //----------------------------------------------- CPlace* CZoneManager::getPlaceFromName( const std::string & name ) { for ( uint i = 0; i < _Places.size(); i++ ) { if ( _Places[i] && _Places[i]->getName() == name ) { return _Places[i]; } } return NULL; }// CZoneManager getPlaceFromName //----------------------------------------------- // CZoneManager getContinentFromId //----------------------------------------------- CContinent* CZoneManager::getContinentFromId( CONTINENT::TContinent id ) { if (id == CONTINENT::UNKNOWN ) return NULL; for ( uint i = 0; i< _Continents.size(); i++ ) { if ( _Continents[i].getId() == id ) return &_Continents[i]; } nlwarning(" continent id %u is out of bound",id); return NULL; }// CZoneManager getContinentFromId //----------------------------------------------- // CZoneManager updateCharacterPosition //----------------------------------------------- void CZoneManager::updateCharacterPosition( CCharacter * user ) { nlassert(user); // if user is in an instance, do not update the places where he is CMirrorPropValueRO mirrorCell( TheDataset, user->getEntityRowId(), DSPropertyCELL ); sint32 cell = mirrorCell; if ( cell <= - 2 ) return; if ( user->getState().X <= 0 || user->getState().Y >= 0 ) return; SM_STATIC_PARAMS_1(params, STRING_MANAGER::place); SM_STATIC_PARAMS_2(params2, STRING_MANAGER::place, STRING_MANAGER::faction); // get the current location of the character const CPlace * stable; std::vector places; const CRegion * region ; const CContinent * continent; float gooDistance; getPlace( user, gooDistance, &stable, places, ®ion, &continent); // SOURCE: user->getCurrentContinent() // DESTINATION: continent->getId() // { // update the continent if necessary if ( continent == NULL ) { CPlace * oldPlace = getContinentFromId( user->getCurrentContinent() ); // returns NULL for CONTINENT::UNKNOWN if (oldPlace) { params[0].Identifier = oldPlace->getName(); PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_LEAVE_CONTINENT",params); } user->setCurrentContinent( CONTINENT::UNKNOWN ); } else if ( (CONTINENT::TContinent)continent->getId() != user->getCurrentContinent() ) { // if current continent is NEWBIELAND, send an 'newbie' update to the SU bool updateSU = false; if (user->getCurrentContinent() == CONTINENT::NEWBIELAND) updateSU = true; const CONTINENT::TContinent oldContinent = user->getCurrentContinent(); CPlace * oldPlace = getContinentFromId( oldContinent ); // returns NULL for CONTINENT::UNKNOWN if (oldPlace) { params[0].Identifier = oldPlace->getName(); PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_LEAVE_CONTINENT",params); } params[0].Identifier = continent->getName(); PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_ENTER_CONTINENT",params); user->setCurrentContinent( (CONTINENT::TContinent)continent->getId() ); // notify player respawn points system that continent changed user->getRespawnPoints().cbContinentChanged(oldContinent); // update newbieland flag (defailt to 1 if there's aproblem determining the true value) bool newbie = user->isNewbie(); // user->_PropertyDatabase.setProp("USER:IS_NEWBIE", newbie); CBankAccessor_PLR::getUSER().setIS_NEWBIE(user->_PropertyDatabase, newbie); bool trialPlayer = false; CPlayer *player = PlayerManager.getPlayer( PlayerManager.getPlayerId(user->getId())); if (!player) { nlwarning("Error %s was not found in player manager.",user->getId().toString().c_str()); trialPlayer = player->isTrialPlayer(); } // user->_PropertyDatabase.setProp("USER:IS_TRIAL", trialPlayer); CBankAccessor_PLR::getUSER().setIS_TRIAL(user->_PropertyDatabase, trialPlayer); if (updateSU) { if (IShardUnifierEvent::getInstance() != NULL) IShardUnifierEvent::getInstance()->onUpdateCharNewbieFlag(user->getId(), newbie); } } // do the same for region // first send message for leaving previous region CRegion * oldRegion = dynamic_cast ( getPlaceFromId( user->getCurrentRegion() ) ); if( user->getCurrentRegion() != 0xFFFF ) { // previously in region if( region == 0 || ( region->getId() != user->getCurrentRegion()) ) { // and not the same than actual region if (oldRegion) { const CTotemBase* pTotem = CPVPFactionRewardManager::getInstance().getTotemBaseFromId( user->getCurrentRegion() ); if( pTotem ) { PVP_CLAN::TPVPClan regionFaction = pTotem->getOwnerFaction(); if( regionFaction == PVP_CLAN::Neutral ) { params[0].Identifier = oldRegion->getName(); PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_LEAVE_NEUTRAL_REGION",params); } else { params2[0].Identifier = oldRegion->getName(); params2[1].Enum = PVP_CLAN::getFactionIndex(regionFaction); PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_LEAVE_FACTION_REGION",params2); } } else { params[0].Identifier = oldRegion->getName(); PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_LEAVE_NEUTRAL_REGION",params); } oldRegion->removePlayer( user->getId() ); // check if user leaves newbieland if ( region != 0 && oldRegion->isNewbieRegion() && !region->isNewbieRegion() ) { user->getRespawnPoints().clearRespawnPoints(); } } if( region == 0 ) { user->setCurrentRegion( 0xFFFF ); // remove spire effects for Pvp-flagged players if ( user->getPVPFlag() ) CPVPFactionRewardManager::getInstance().removeTotemsEffects( user ); } } } if ( region != 0 && (user->getCurrentRegion() != region->getId()) ) { const CTotemBase* pTotem = CPVPFactionRewardManager::getInstance().getTotemBaseFromId( region->getId() ); if( pTotem ) { PVP_CLAN::TPVPClan regionFaction = pTotem->getOwnerFaction(); if( regionFaction == PVP_CLAN::Neutral ) { params[0].Identifier = region->getName(); PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_ENTER_NEUTRAL_REGION",params); } else { params2[0].Identifier = region->getName(); params2[1].Enum = PVP_CLAN::getFactionIndex(regionFaction); PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_ENTER_FACTION_REGION",params2); } } else { params[0].Identifier = region->getName(); PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_ENTER_NEUTRAL_REGION",params); } user->setCurrentRegion( region->getId() ); ((CRegion*)region)->addPlayer( user->getId() ); // check if user leaves newbieland if ( oldRegion != 0 && oldRegion->isNewbieRegion() && !region->isNewbieRegion() ) { user->getRespawnPoints().clearRespawnPoints(); } // add new spire effects for Pvp-flagged players if ( user->getPVPFlag() ) CPVPFactionRewardManager::getInstance().giveTotemsEffects( user ); // Now the VisitPlace missions are checked in CMissionManager::checkVisitPlaceMissions() //CMissionEventVisitPlace event(region->getId() ); //user->processMissionMultipleEvent(event); } // get new places const uint newPlacesSize = (uint)places.size(); //bool sendWarning = false; bool changed = false; for ( uint i = 0; i < newPlacesSize; i++ ) { if ( !user->isInPlace( places[i]->getId() ) ) { if( places[i]->getReported() ) { params[0].Identifier = places[i]->getName(); PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_ENTER_PLACE",params); } // Now the VisitPlace missions are checked in CMissionManager::checkVisitPlaceMissions() //CMissionEventVisitPlace event( places[i]->getId() ); //user->processMissionMultipleEvent(event); // validate respawn points for ( uint j = 0; j< places[i]->getRespawnPoints().size(); j++ ) { user->getRespawnPoints().addRespawnPoint( places[i]->getRespawnPoints()[j] ); } changed = true; /// tells mission system that user enters a place for ( map::iterator it = user->getMissionsBegin(); it != user->getMissionsEnd(); ++it ) { CMissionManager::getInstance()->enterPlace( (*it).second,places[i]->getAlias(), places[i]->getId() ); } } } // get left places const uint oldPlacesSize = (uint)user->getPlaces().size(); for ( uint i = 0; i < oldPlacesSize; i++ ) { uint j = 0; for (; j < newPlacesSize; j++ ) { if ( places[j]->getId() == user->getPlaces()[i] ) break; } if ( j == newPlacesSize ) { CPlace * place = getPlaceFromId( user->getPlaces()[i] ); if ( place ) { if( place->getReported() ) { params[0].Identifier = place->getName(); PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_LEAVE_PLACE",params); } /// tells mission system that user enters a place for ( map::iterator it = user->getMissionsBegin(); it != user->getMissionsEnd(); ++it ) { CMissionManager::getInstance()->leavePlace( (*it).second,place->getAlias(), place->getId() ); } } changed = true; } } // enter/leave PVP zones TAIAlias pvpZoneAlias = CPVPManager::getInstance()->getPVPZoneFromUserPosition( user ); if ( pvpZoneAlias != user->getCurrentPVPZone() && !user->isDead() ) { if ( user->getCurrentPVPZone() != CAIAliasTranslator::Invalid ) { CPVPManager::getInstance()->leavePVPZone( user ); } if ( pvpZoneAlias != CAIAliasTranslator::Invalid ) { CPVPManager::getInstance()->enterPVPZone( user, pvpZoneAlias ); } user->setCurrentPVPZone( pvpZoneAlias ); } // enter/leave outpost zones TAIAlias outpostAlias = COutpostManager::getInstance().getOutpostFromUserPosition( user ); if ( outpostAlias != user->getCurrentOutpostZone() && !user->isDead() ) { if ( user->getCurrentOutpostZone() != CAIAliasTranslator::Invalid ) { COutpostManager::getInstance().leaveOutpostZone( user ); } user->setCurrentOutpostZone( outpostAlias ); if ( outpostAlias != CAIAliasTranslator::Invalid ) { COutpostManager::getInstance().enterOutpostZone( user ); } } if ( changed ) user->setPlaces( places ); // and stable // if the player is now in an unknown stable if( stable == NULL ) { // disable this message because stables are already treated as places /*CPlace * oldStable = getPlaceFromId( user->getCurrentStable() ); if (oldStable) { if( oldStable->getReported() ) { params[0].Identifier = oldStable->getName(); PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_LEAVE_PLACE",params); } }*/ user->setCurrentStable( 0xFFFF,0xFFFF); } // check if player left old current stable for enter to another else if( user->getCurrentStable() != stable->getId() ) { // disable this message because stables are already treated as places /*CPlace * oldStable = getPlaceFromId( user->getCurrentStable() ); if (oldStable) { if( oldStable->getReported() ) { params[0].Identifier = oldStable->getName(); PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_LEAVE_PLACE",params); } } if( stable->getReported() ) { params[0].Identifier = stable->getName(); PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_ENTER_PLACE",params); }*/ for ( uint i = 0; i < newPlacesSize; i++ ) { if ( places[i]->isMainPlace() ) { user->setCurrentStable( stable->getId(), places[i]->getId() ); break; } } // Now the VisitPlace missions are checked in CMissionManager::checkVisitPlaceMissions() //CMissionEventVisitPlace event(stable->getId() ); //user->processMissionMultipleEvent(event); } // apply goo damage if needed user->applyGooDamage( gooDistance ); //} }// CZoneManager updateCharacterPosition //----------------------------------------------- // CZoneManager tickUpdate //----------------------------------------------- void CZoneManager::tickUpdate() { // *** Update deposits at low frequency (each deposit is updated once per DepositUpdateFrequency (which is a period in game cycles, actually)) // CPU is smoothed if there are more deposits than cycles in the period. uint32 nbDeposit = (uint32)_Deposits.size(); if( ( (_NextDepositIndexUpdated != 0) || (CTickEventHandler::getGameCycle() - _SpreadUpdateLoopBeginTick ) >= DepositUpdateFrequency.get()) ) { if ( _NextDepositIndexUpdated == 0 ) { _SpreadUpdateLoopBeginTick = CTickEventHandler::getGameCycle(); } uint32 i, nbDepositUpdatedByTick = (uint32 ) ( nbDeposit / DepositUpdateFrequency.get() ) + 1; for( i = _NextDepositIndexUpdated; i < _NextDepositIndexUpdated + nbDepositUpdatedByTick; ++i ) { if( i < nbDeposit ) { _Deposits[ i ]->lowFreqUpdate(); } } if( i >= nbDeposit ) _NextDepositIndexUpdated = 0; else _NextDepositIndexUpdated = i; } // *** Update the deposits that need an update for auto spawn std::set< CDeposit* >::iterator itDeposit= _DepositNeedingAutoSpawnUpdate.begin(); while(itDeposit!= _DepositNeedingAutoSpawnUpdate.end()) { CDeposit *deposit= *itDeposit; nlassert(deposit); deposit->autoSpawnUpdate(); // remove the deposit from the set, and go next to update std::set< CDeposit* >::iterator itNext= itDeposit; itNext++; _DepositNeedingAutoSpawnUpdate.erase(itDeposit); itDeposit= itNext; } }// CZoneManager tickUpdate //----------------------------------------------- // CZoneManager dumpWorld //----------------------------------------------- void CZoneManager::dumpWorld(CLog & log) { log.displayNL("%u continents", _Continents.size() ); for (uint i = 0; i < _Continents.size(); i++ ) { log.displayNL("CONTINENT %u : id=%u, name=%s", i, _Continents[i].getId(),_Continents[i].getName().c_str() ); const std::vector< CRegion* > & regions = _Continents[i].getRegions(); for (uint j = 0; j < regions.size();j++ ) { log.displayNL(" region %u : id=%u, name=%s",j, regions[j]->getId(),regions[j]->getName().c_str() ); const std::vector< CPlace* > & places = regions[j]->getPlaces(); for (uint k = 0; k < places.size();k++ ) { log.displayNL(" place %u : id=%u, name=%s", k, places[k]->getId(),places[k]->getName().c_str() ); } log.displayNL(""); const std::vector< CDeposit* > & deposits = regions[j]->getDeposits(); log.displayNL("%u deposits", deposits.size() ); //for (uint k = 0; k < deposits.size();k++ ) //{ // log.displayNL(" deposits %u : id=%u", k, /*deposits[k]->getId()*/0, /*deposits[k]->getName().c_str()*/ ); //} } } } //----------------------------------------------- // CZoneManager dumpTpSpawnZones //----------------------------------------------- void CZoneManager::dumpTpSpawnZones(CLog & log) { log.displayNL("%u tp spawn zones", _TpSpawnZones.size()); for (uint i = 0; i < _TpSpawnZones.size(); i++) { log.displayNL("TP SPAWN ZONE %u : name=%s", i, _TpSpawnZones[i].getName().c_str()); } } //----------------------------------------------- // CZoneManager answerWhere //----------------------------------------------- void CZoneManager::answerWhere(const NLMISC::CEntityId & eId) { ///\todo nico manage building CCharacter * c = PlayerManager.getChar( eId ); if (c ) { c->setAfkState(false); CContinent * cont = getContinentFromId(c->getCurrentContinent()); if ( !cont ) { nlwarning(" invalid continent %u for entity %s",c->getCurrentContinent(),eId.toString().c_str()); return; } CPlace * region = getPlaceFromId( c->getCurrentRegion() ); if ( !region ) { nlwarning(" invalid region %u for entity %s",c->getCurrentRegion(),eId.toString().c_str()); return; } uint size = (uint)c->getPlaces().size(); CPlace * place = NULL; for ( uint i = 0; i < size; i++ ) { CPlace * placeTest = getPlaceFromId( c->getPlaces()[i] ); nlassert( placeTest ); if ( placeTest->isMainPlace() ) { place = placeTest; break; } } STRING_MANAGER::TParam param; param.Type = STRING_MANAGER::place; if (place) { SM_STATIC_PARAMS_3(params, STRING_MANAGER::place, STRING_MANAGER::place, STRING_MANAGER::place); params[0].Identifier = cont->getName(); params[1].Identifier = region->getName(); params[2].Identifier = place->getName(); PHRASE_UTILITIES::sendDynamicSystemMessage(TheDataset.getDataSetRow(eId),"EGS_ANSWER_WHERE",params); } else { SM_STATIC_PARAMS_2(params, STRING_MANAGER::place, STRING_MANAGER::place); params[0].Identifier = cont->getName(); params[1].Identifier = region->getName(); PHRASE_UTILITIES::sendDynamicSystemMessage(TheDataset.getDataSetRow(eId),"EGS_ANSWER_WHERE_NO_PLACE",params); } /* std::vector< NLMISC::CEntityId > bots; for ( uint i = 0; i < c->getPickedMissions().size(); i++ ) { if ( c->getPickedMissions()[i] ) { CStaticMission * mission = c->getPickedMissions()[i]->getTemplate(); NLMISC::CEntityId bot; if ( CAIAliasTranslator::getInstance()->getEntityId(c->getPickedMissions()[i]->getRewardGiver(), bot ) ) { uint j = 0; for (; j < bots.size(); j++ ) { if ( bots[j] == bot ) break; } if ( j == bots.size() ) bots.push_back( bot ); } for (uint j = 0; j < mission->getSteps().size(); j++ ) { mission->getSteps()[j]->addImpliedBots( bots ); } } } if ( !bots.empty() ) { CCharacter::sendMessageToClient( eId,"EGS_MISSION_DIR_INTRO" ); double xUser = (double)c->getState().X; double yUser = (double)c->getState().Y; for ( uint i = 0; i < bots.size(); i++ ) { CCreature * botPtr = CreatureManager.getCreature( bots[i] ); if ( botPtr ) { string botName; if ( CAIAliasTranslator::getInstance()->getNPCNameFromAlias( botPtr->getAlias(), botName ) ) { double dx = (double)botPtr->getState().X/1000.0-(double)xUser/1000.0; double dy = (double)botPtr->getState().Y/1000.0-(double)yUser/1000.0; double dist = sqrt(dx*dx+dy*dy); uint32 distshort = (uint16)dist; double angle = atan2 (dy, dx) + NLMISC::Pi; sint direction =(sint) floor( 0.5 + 8.0 * angle /(NLMISC::Pi) ); direction = direction %16; static string txts[]= { "W", "WSW", "SW", "SSW", "S", "SSE", "SE", "ESE", "E", "ENE", "NE", "NNE", "N", "NNW", "NW", "WNW", }; static string msgBot = ("EGS_MISSION_DIR_BOT"); CMessage msgout("STATIC_STRING"); msgout.serial( const_cast(eId) ); std::set empty; msgout.serialCont( empty ); msgout.serial( msgBot ); msgout.serial( botName ); msgout.serial( distshort ); msgout.serial( txts[direction] ); sendMessageViaMirror( "IOS", msgout ); } } } } */ } else { nlwarning( "Invalid char %s",eId.toString().c_str() ); } } //----------------------------------------------- // CZoneManager harvestDeposit //----------------------------------------------- /*void CZoneManager::harvestDeposit(CCharacter * user) { nlassert(user); vector deposits; nlerror( "getDepositsUnderUser(user,deposits);" ); if ( deposits.size() ) { uint nbMps = 0; for (uint i = 0; i < deposits.size(); i++ ) nbMps+= deposits[i]->getContentSize(); uint result = RandomGenerator.rand( nbMps - 1 ); nbMps = 0; for (uint i = 0; i < deposits.size(); i++ ) { if ( result < nbMps + deposits[i]->getContentSize() ) { nlerror( "deposits[i]->harvestInfo(user->getId(),user->getHarvestInfos());" ); break; } nbMps += deposits[i]->getContentSize(); } } if (user->getHarvestInfos().Sheet == CSheetId::Unknown) { // no raw material found, return return; } user->getHarvestInfos().EndCherchingTime = CTickEventHandler::getGameCycle() + DepositSearchTime; user->setCurrentAction( CLIENT_ACTION_TYPE::Harvest, user->getHarvestInfos().EndCherchingTime ); }// CZoneManager harvestDeposit */ //----------------------------------------------- // CZoneManager displayAllDeposit //----------------------------------------------- void CZoneManager::dumpDeposits( NLMISC::CLog & log, const std::string& depName, bool extendedInfo ) { bool displayAll = (depName == "ALL"); for( uint i = 0; i < _Deposits.size(); i++ ) { if ( _Deposits[i] ) { if ( displayAll || (_Deposits[i]->name() == depName) ) _Deposits[i]->displayContent( &log, extendedInfo ); } else log.displayNL( "===== Deposit %d is NULL" ); } }// CZoneManager displayAllDeposit //----------------------------------------------- // CZoneManager getStartPointVector //----------------------------------------------- vector CZoneManager::getStartPointVector( uint16 startPointIdx ) const { if ( startPointIdx >= _StartPoints.size() ) { nlwarning("bad start point index %u ( count %u )",startPointIdx , _StartPoints.size() ); return vector(); } return _StartPoints[startPointIdx]; }// CZoneManager getStartPointVector //----------------------------------------------- // Get the ecotype zone under the position. // If not found, a NULL pointer is returned. //----------------------------------------------- ECOSYSTEM::EECosystem CZoneManager::getEcotype( const NLMISC::CVector& pos ) { // The ecotypes must not be overlapped: only the first one found is returned for ( CEcotypeZones::iterator it=_EcotypeZones.begin(); it!=_EcotypeZones.end(); ++it ) { CEcotypeZone *ecotypeZone = (*it); if ( ecotypeZone->contains( pos ) ) { return ecotypeZone->ecotype(); } } return ECOSYSTEM::unknown; } //----------------------------------------------- // Clear ecotype information //----------------------------------------------- void CZoneManager::clearEcotypes() { for ( CEcotypeZones::iterator iez=_EcotypeZones.begin(); iez!=_EcotypeZones.end(); ++iez ) { delete (*iez); } _EcotypeZones.clear(); } //----------------------------------------------- // deposit auto spawn //----------------------------------------------- void CZoneManager::registerDepositToAutoSpawnUpdate(CDeposit *deposit) { if(deposit) _DepositNeedingAutoSpawnUpdate.insert(deposit); } void CZoneManager::unregisterDepositToAutoSpawnUpdate(CDeposit *deposit) { if(deposit) _DepositNeedingAutoSpawnUpdate.erase(deposit); } // dump the world organisation NLMISC_COMMAND(dumpWorld," dump the world organisation","") { if (args.size() == 0) { CZoneManager::getInstance().dumpWorld(log); return true; } return false; } NLMISC_COMMAND(dumpTpSpawnZones, "dump the tp spawn zones", "") { if (args.size() == 0) { CZoneManager::getInstance().dumpTpSpawnZones(log); return true; } return false; }