Add infos into target window
[ryzomcore.git] / ryzom / server / src / entities_game_service / zone_manager.cpp
blob8db6c439d3ff5e40768db12a0e1ec97108a85a0e
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "stdpch.h"
21 #include "nel/misc/command.h"
22 #include "nel/misc/variable.h"
23 #include "nel/misc/config_file.h"
24 #include "nel/net/service.h"
25 #include "nel/ligo/primitive_utils.h"
27 #include "game_share/time_weather_season/time_and_season.h"
29 #include "zone_manager.h"
30 #include "mission_manager/mission_manager.h"
31 #include "primitives_parser.h"
32 #include "player_manager/player_manager.h"
33 #include "player_manager/player.h"
34 #include "player_manager/character.h"
35 #include "creature_manager/creature_manager.h"
36 #include "deposit.h"
37 #include "egs_globals.h"
38 #include "phrase_manager/phrase_utilities_functions.h"
39 #include "player_manager/character_respawn_points.h"
40 #include "stables/stable.h"
41 #include "chat_groups_ids.h"
42 #include "pvp_manager/pvp_manager.h"
43 #include "pvp_manager/pvp_manager_2.h"
44 #include "pvp_manager/pvp_safe_zone.h"
46 #include "backward_compatibility/spawn_zones_back_compat.h"
47 #include "backward_compatibility/places_back_compat.h"
49 #include "pvp_manager/pvp.h"
50 #include "pvp_manager/pvp_faction_reward_manager/pvp_faction_reward_manager.h"
52 #include "outpost_manager/outpost_manager.h"
53 #include "modules/shard_unifier_client.h"
55 using namespace std;
56 using namespace NLMISC;
57 using namespace NLLIGO;
58 using namespace NLNET;
60 // The ecotype zones
61 CEcotypeZones CZoneManager::_EcotypeZones;
63 const std::string CContinent::ContNames [] =
65 "fyros",
66 "tryker"
67 "zorai",
68 "matis",
72 arg0: is the zone name id
74 arg1:
75 if zone is not pvp
76 arg1 is interpreted as a boolean (0 - inactive, 1 - active)
77 if zone is a pvp zone
78 arg1 is interpreted as
79 0 - inactive
80 1 - active with faction point rewards
81 2 - active without faction point rewards
83 void cbSetZoneState( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId )
85 string sZoneName;
86 uint32 nState;
88 msgin.serial(sZoneName);
89 msgin.serial(nState);
91 CZoneManager *pZM = &CZoneManager::getInstance();
93 // get the places
94 CPlace *place = pZM->getPlaceFromName(sZoneName);
95 if (place != NULL)
96 if (place->isGooPath())
97 place->setGooActive(nState != 0);
101 // get the deposit zone (linear search)
102 const vector<CDeposit*> &rDeps = pZM->getDeposits();
103 for (uint32 i = 0; i < rDeps.size(); ++i)
105 CDeposit *pd = rDeps[i];
106 if (pd->getName() == sZoneName)
108 pd->enable(nState!=0);
109 return;
113 // get the pvp zone
114 CPVPManager *pPVPM = CPVPManager::getInstance();
115 IPVPZone *pPVPZ = pPVPM->getPVPZone(sZoneName);
116 if (pPVPZ != NULL)
118 pPVPZ->setActive(nState!=0);
120 CPVPVersusZone *pPVPVZ = dynamic_cast<CPVPVersusZone*>(pPVPZ);
121 if (pPVPVZ != NULL)
122 pPVPVZ->giveFactionPoints(nState == 1);
124 return;
127 // TODO : treat other zones !
131 //-----------------------------------------------
132 // CGooPath build
133 //-----------------------------------------------
134 /*bool CGooPath::build(const NLLIGO::CPrimPath * path,uint16 id )
136 _Id = id;
137 *( (NLLIGO::CPrimPath*)this ) = *path;
139 if ( !zone->getPropertyByName("name",_Name) )
141 nlwarning("<CGooPath build> : no name in goo place %u", id);
142 return false;
145 if ( VPoints.empty() )
147 nlwarning("<CGooPath build> :no points in goo place %u/%s", id, _Name.c_str());
148 return false;
150 // get the bounding box
151 float minX = VPoints[0].x;
152 float minY = VPoints[0].y;
153 float maxX = VPoints[0].x;
154 float maxY = VPoints[0].y;
155 for ( uint i = 1; i < VPoints.size(); i++)
157 if ( VPoints[i].x < minX )minX = VPoints[i].x;
158 if ( VPoints[i].y < minY )minY = VPoints[i].y;
159 if ( VPoints[i].x > maxX )maxX = VPoints[i].x;
160 if ( VPoints[i].y > maxY )maxY = VPoints[i].y;
162 // get the center of the Box
163 _CenterX = sint32 ( ( minX + maxX ) *1000.0f / 2.0f );
164 _CenterY = sint32 ( ( minY + maxY ) *1000.0f / 2.0f );
165 return true;
166 }// CGooPath build
169 //-----------------------------------------------
170 // Tp Dest zone build
171 //-----------------------------------------------
172 bool CTpSpawnZone::build(const NLLIGO::CPrimPoint * point)
174 *( (NLLIGO::CPrimPoint*)this ) = *point;
175 _Continent = CONTINENT::UNKNOWN;
176 string value;
177 if ( !point->getPropertyByName("name",_Name) )
179 nlwarning("<CTpSpawnZone build> : no name in CTpSpawnZone" );
180 return false;
182 if ( !point->getPropertyByName("radius",value) )
184 nlwarning("<CTpSpawnZone build> : no radius in CTpSpawnZone '%s'",_Name.c_str() );
185 return false;
188 // get radius in mm
189 _Radius = uint16( atof( value.c_str() ) * 1000.0f );
190 // get the z value if necessary
191 if ( !point->getPropertyByName("use_z", value) )
193 nlwarning("<CTpSpawnZone build> : no use_z in CTpSpawnZone '%s'",_Name.c_str() );
194 return false;
197 if ( value == "true" )
199 if ( !point->getPropertyByName("z", value) )
201 nlwarning("<CTpSpawnZone build> : no z in CTpSpawnZone '%s'",_Name.c_str() );
202 return false;
204 NLMISC::fromString(value, Point.z);
205 Point.z = float( sint32 (1000.0f* Point.z) );
207 else
208 Point.z = 0.0f;
212 // convert coords in mm
213 Point.x = float( sint32 (1000.0f* Point.x) );
214 Point.y = float( sint32 (1000.0f* Point.y) );
217 if ( !point->getPropertyByName("type", value) )
219 nlwarning("<CTpSpawnZone build> : no type in CTpSpawnZone '%s'",_Name.c_str() );
220 return false;
222 _Type = RESPAWN_POINT::toRespawnPointType( value );
223 if ( _Type == RESPAWN_POINT::UNKNOWN )
225 nlwarning("<CTpSpawnZone build> : invalid type '%s' in CTpSpawnZone '%s'",value.c_str(), _Name.c_str() );
226 return false;
228 return true;
231 //-----------------------------------------------
232 // CPlace build
233 //-----------------------------------------------
234 bool CPlace::build(const NLLIGO::CPrimPath * path, uint16 id, bool isPrim)
236 _Id = id;
237 if (!path->VPoints.empty())
240 *( (NLLIGO::CPrimZone*)this ) = *(NLLIGO::CPrimZone*) path;
244 if ( isPrim && !path->getPropertyByName("name",_Name) )
246 nlwarning("<CPlace build> : no name for GooPath %u", id);
247 return false;
250 if ( VPoints.empty() )
252 nlwarning("<CPlace build> :no points in GooPath %u/%s", id, _Name.c_str());
253 return false;
256 string val;
257 if (path->getPropertyByName("main place", val))
258 _MainPlace = val == "true";
259 else
260 _MainPlace = false;
262 if (isPrim)
263 nlverify (CPrimitivesParser::getAlias(path, _Alias));
264 // _Alias = NLMISC::fromString( val.c_str() );
265 nlassert( _Alias != CAIAliasTranslator::Invalid );
267 updateCenter();
269 _GooPath = true;
270 _GooActive = true;
271 _Reported = false;
273 return true;
276 void CPlace::updateCenter()
278 // get the bounding box
279 float minX = VPoints[0].x;
280 float minY = VPoints[0].y;
281 float maxX = VPoints[0].x;
282 float maxY = VPoints[0].y;
283 for ( uint i = 1; i < VPoints.size(); i++)
285 if ( VPoints[i].x < minX )minX = VPoints[i].x;
286 if ( VPoints[i].y < minY )minY = VPoints[i].y;
287 if ( VPoints[i].x > maxX )maxX = VPoints[i].x;
288 if ( VPoints[i].y > maxY )maxY = VPoints[i].y;
290 // get the center of the Box
291 _CenterX = sint32 ( ( minX + maxX ) *1000.0f / 2.0f );
292 _CenterY = sint32 ( ( minY + maxY ) *1000.0f / 2.0f );
296 //-----------------------------------------------
297 // CPlace build
298 //-----------------------------------------------
299 bool CPlace::build(const NLLIGO::CPrimZone * zone,uint16 id, bool reportAutorised )
301 _Id = id;
302 if (!zone->VPoints.empty())
303 *( (NLLIGO::CPrimZone*)this ) = *zone;
305 if ( !zone->getPropertyByName("name",_Name) )
307 nlwarning("<CPlace build> : no name in place %u", id);
308 return false;
311 string val;
312 if (zone->getPropertyByName("reported", val))
313 _Reported = val == "true";
314 else
315 _Reported = true & reportAutorised;
317 if (zone->getPropertyByName("main place", val))
318 _MainPlace = val == "true";
319 else
320 _MainPlace = true;
322 if (!CPrimitivesParser::getAlias(zone, _Alias))
324 nlwarning("Fatal Error, no alias in primitive '%s'",
325 buildPrimPath(zone).c_str());
326 nlstop;
328 // _Alias = NLMISC::fromString( val.c_str() );
329 nlassert( _Alias != CAIAliasTranslator::Invalid );
333 if ( VPoints.empty() )
335 nlwarning("<CPlace build> :no points in place %u/%s", id, _Name.c_str());
336 return false;
339 updateCenter();
341 _GooPath = false;
342 _GooActive = false;
344 if( zone->getPropertyByName("place_type", val) )
346 _PlaceType = PLACE_TYPE::fromString(val);
347 if( _PlaceType == PLACE_TYPE::Undefined )
348 _PlaceType = PLACE_TYPE::Place;
350 else
351 _PlaceType = PLACE_TYPE::Place;
353 // get children respawn points
354 bool ret = true;
355 for (uint i=0; i< getNumChildren();++i)
357 const IPrimitive *child;
358 if ( getChild(child,i) && child )
360 child->getPropertyByName("name",val);
361 uint16 idx = CZoneManager::getInstance().getTpSpawnZoneIdByName(val);
362 if ( idx != InvalidSpawnZoneId )
364 const CTpSpawnZone * spawn = CZoneManager::getInstance().getTpSpawnZone( idx );
365 if ( spawn == NULL )
367 nlwarning( "Invalid spawn zone '%s' in place '%s' : bad index %u",val.c_str(), _Name.c_str(), idx );
368 ret = false;
370 // if the respawn point is validated when user enters the place, add it to the place.
371 // we dont add special respawn points ( outposts,... ) because they are validated separatly from the place where they are
372 else if ( spawn->getType() == RESPAWN_POINT::KAMI ||
373 spawn->getType() == RESPAWN_POINT::KARAVAN ||
374 spawn->getType() == RESPAWN_POINT::RANGER ||
375 spawn->getType() == RESPAWN_POINT::NEWBIELAND ||
376 spawn->getType() == RESPAWN_POINT::RESPAWNABLE )
378 (const_cast<CTpSpawnZone *>(spawn))->setPlaceType(_PlaceType);
379 _RespawnPoints.push_back( idx );
384 return ret;
385 }// CPlace build
387 //-----------------------------------------------
388 // CRegion build
389 //-----------------------------------------------
390 bool CRegion::build(const NLLIGO::CPrimZone * zone,uint16 id)
392 if ( CPlace::build(zone,id) )
394 string value;
395 if ( !zone->getPropertyByName("newbie_region",value) )
397 nlwarning("<CRegion build> : failed : no newbie_region property in primitive");
398 _NewbieRegion = false;
400 else
402 _NewbieRegion = (!nlstricmp( value,"true"))?true:false;
404 return true;
406 else
408 nlwarning("<CRegion build> : failed in place build");
409 return false;
411 }// CRegion build
413 //-----------------------------------------------
414 // CRegion dtor
415 //-----------------------------------------------
416 CRegion::~CRegion()
419 }// CRegion dtor
421 //-----------------------------------------------
422 // CRegion registerChatGroup
423 //-----------------------------------------------
424 void CRegion::registerChatGroup()
426 TGroupId idGroup = CHAT_GROUPS_IDS::getRegionChatGroupId(_Id);
427 CMessage msgout("ADD_GROUP");
428 msgout.serial( idGroup );
429 CChatGroup::TGroupType type = CChatGroup::region;
430 msgout.serialEnum( type );
431 sendMessageViaMirror( "IOS", msgout );
433 // add online members ( if IOS crashed... )
434 set< CEntityId >::iterator it = _Players.begin();
435 for (; it != _Players.end(); ++it )
437 TDataSetRow row = TheDataset.getDataSetRow( (*it) );
438 // if we can get the user from this row, the user is ingame
439 CCharacter* user = PlayerManager.getChar( row );
440 if ( user )
442 CMessage msgout("ADD_TO_GROUP");
443 msgout.serial( idGroup );
444 msgout.serial( const_cast<NLMISC::CEntityId &>(user->getId()) );
445 sendMessageViaMirror( "IOS", msgout );
450 //-----------------------------------------------
451 // CRegion addPlayer
452 //-----------------------------------------------
453 void CRegion::addPlayer( const NLMISC::CEntityId & id )
455 _Players.insert(id);
456 TGroupId idGroup = CHAT_GROUPS_IDS::getRegionChatGroupId(_Id);
457 CMessage msgout("ADD_TO_GROUP");
458 msgout.serial( idGroup );
459 msgout.serial( const_cast<NLMISC::CEntityId &>(id) );
460 sendMessageViaMirror( "IOS", msgout );
463 //-----------------------------------------------
464 // CRegion removePlayer
465 //-----------------------------------------------
466 void CRegion::removePlayer( const NLMISC::CEntityId & id )
468 _Players.erase(id);
469 TGroupId idGroup = CHAT_GROUPS_IDS::getRegionChatGroupId(_Id);
470 CMessage msgout("REMOVE_FROM_GROUP");
471 msgout.serial( idGroup );
472 msgout.serial( const_cast<NLMISC::CEntityId &>(id) );
473 sendMessageViaMirror( "IOS", msgout );
476 //-----------------------------------------------
477 // CContinent build
478 //-----------------------------------------------
479 bool CContinent::build(const NLLIGO::CPrimZone * zone)
481 string value;
482 if ( zone->getPropertyByName("id",value) )
484 _Id = CONTINENT::toContinent( value );
485 if ( _Id != CONTINENT::UNKNOWN )
487 return CPlace::build( zone,_Id );
489 else
490 nlwarning("<CContinent build> : invalid continent id '%s'",value.c_str());
492 else
493 nlwarning("<CContinent build> : no id in a continent");
494 return false;
495 }// CContinent build
497 //-----------------------------------------------
498 // CContinent dtor
499 //-----------------------------------------------
500 CContinent::~CContinent()
503 }// CContinent dtor
506 //-----------------------------------------------
507 // CZoneManager init
508 //-----------------------------------------------
509 void CZoneManager::init()
511 RandomGenerator.srand( CTickEventHandler::getGameCycle() );
512 initInstance();
513 }// CZoneManager init
515 //-----------------------------------------------
516 // CZoneManager release
517 //-----------------------------------------------
518 void CZoneManager::release()
520 for (uint i = 0; i < _Deposits.size(); i++ )
521 delete _Deposits[i];
522 for ( uint i = 0; i < _Places.size(); i++ )
523 delete _Places[i];
524 clearEcotypes();
525 }// CZoneManager release
527 //-----------------------------------------------
528 // CZoneManager initInstance
529 //-----------------------------------------------
530 void CZoneManager::initInstance()
532 _NextDepositIndexUpdated = 0;
533 _SpreadUpdateLoopBeginTick = CTickEventHandler::getGameCycle();
535 // get the loaded primitives
536 const CPrimitivesParser::TPrimitivesList & primsList = CPrimitivesParser::getInstance().getPrimitives();
538 _PlacesByAlias.clear();
539 // parse the zones
540 nlinfo("CZoneManager : parsing the zones");
541 CPrimitivesParser::TPrimitivesList::const_iterator first, last;
543 for (first = primsList.begin(), last = primsList.end(); first != last; ++first)
545 if (! parseContinents(first->Primitive.RootNode ) )
547 nlwarning("<CZoneManager constructor> Error while building the continents");
551 for (first = primsList.begin(), last = primsList.end(); first != last; ++first)
553 if (! parseRegions(first->Primitive.RootNode ) )
555 nlwarning("<CZoneManager constructor> Error while building the regions");
559 for (first = primsList.begin(), last = primsList.end(); first != last; ++first)
561 if (! parseTpSpawnZones(first->Primitive.RootNode ) )
563 nlwarning("<CZoneManager constructor> Error while building the tp spawn Zones");
567 for (first = primsList.begin(), last = primsList.end(); first != last; ++first)
569 if (! parseZones(first->Primitive.RootNode ) )
571 nlwarning("<CZoneManager constructor> Error while building the zones");
575 // Parse ecotypes, that will be used when building deposits
576 for (first = primsList.begin(), last = primsList.end(); first != last; ++first)
578 if (! parseEcotypes( first->Primitive.RootNode ) )
580 nlwarning("<CZoneManager constructor> Error while building the ecotypes");
584 // Parse (and build) deposits
585 for (first = primsList.begin(), last = primsList.end(); first != last; ++first)
587 if (! parseDeposits(first->Primitive.RootNode ) )
589 nlwarning("<CZoneManager constructor> Error while building the zones");
593 // Don't keep ecotypes in memory, the information is already in the deposits
594 CDeposit::clearEcotypes();
596 // Parse stables
597 for (first = primsList.begin(), last = primsList.end(); first != last; ++first)
599 if (! parseStables(first->Primitive.RootNode ) )
601 nlwarning("<CZoneManager constructor> Error while building the stables");
605 // Parse the goo border
606 for (first = primsList.begin(), last = primsList.end(); first != last; ++first)
608 if (! parseGooBorder(first->Primitive.RootNode ) )
610 nlwarning("<CZoneManager constructor> Error while building the Goo Border");
614 // preallocate 5 start points per newbieland
615 _StartPoints.reserve( 20 );
616 // Parse the start points
617 for (first = primsList.begin(), last = primsList.end(); first != last; ++first)
619 if (! parseStartPoints(first->Primitive.RootNode ) )
621 nlwarning("<CZoneManager constructor> Error while building the start points");
625 // parse the PVP zones, must be before parsing the PVP safe zones!
626 for (first = primsList.begin(), last = primsList.end(); first != last; ++first)
628 if ( !parsePVPZones(first->Primitive.RootNode) )
630 nlwarning("<CZoneManager constructor> Error while building the PVP zones");
634 // parse the PVP safe zones (except for outpost zones)
635 for (first = primsList.begin(), last = primsList.end(); first != last; ++first)
637 if ( !parsePVPSafeZones(first->Primitive.RootNode) )
639 nlwarning("<CZoneManager constructor> Error while building the PVP safe zones");
643 // apply config to PVP zones (must be done after loading primitives), except outpost ones
644 CPVPManager::getInstance()->applyConfigToPVPZones();
646 // for backward compatibility
647 //BACK_COMPAT::initSpawnZonesCompat();
648 BACK_COMPAT::initPlacesCompat();
651 // Initialize messages from other services
653 // array of callback items
654 NLNET::TUnifiedCallbackItem _cbArray[] =
656 { "SET_ZONE_STATE", cbSetZoneState },
658 // register call back for zone manager
659 CUnifiedNetwork::getInstance()->addCallbackArray( _cbArray, sizeof(_cbArray) / sizeof(_cbArray[0]) );
661 }// CZoneManager ctor
663 //-----------------------------------------------
664 // CZoneManager dtor
665 //-----------------------------------------------
666 CZoneManager::~CZoneManager()
668 // remove deposits
669 for (uint i = 0; i < _Deposits.size(); i++ )
670 delete _Deposits[i];
671 // all must have unregistered from the set of autospawn update
672 nlassert(_DepositNeedingAutoSpawnUpdate.empty());
674 // remove places
675 for ( uint i = 0; i < _Places.size(); i++ )
676 delete _Places[i];
678 // clear ecotypes
679 clearEcotypes();
680 }// CZoneManager dtor
682 //-----------------------------------------------
683 // CZoneManager iosConnection
684 //-----------------------------------------------
685 void CZoneManager::iosConnection()
687 for ( uint i = 0; i < _Continents.size(); i++ )
689 for ( uint j = 0; j < _Continents[i].getRegions().size(); j++ )
691 _Continents[i].getRegions()[j]->registerChatGroup();
694 }// CZoneManager iosConnection
696 //-----------------------------------------------
697 // CZoneManager getTpSpawnZoneIdByName
698 //-----------------------------------------------
699 uint16 CZoneManager::getTpSpawnZoneIdByName( const std::string & name )
701 map<string,uint16>::const_iterator it = _TpSpawnZoneIdByName.find( name );
702 if ( it == _TpSpawnZoneIdByName.end() )
704 return InvalidSpawnZoneId;
707 const uint16 id = (*it).second;
708 BOMB_IF( (id >= _TpSpawnZones.size()), "<SPAWN_ZONE> invalid spawn zone id", return InvalidSpawnZoneId );
709 BOMB_IF( (name != _TpSpawnZones[id].getName()), "<SPAWN_ZONE> spawn zone name does not match", return InvalidSpawnZoneId );
711 return id;
712 }// CZoneManager getTpSpawnZoneIdByName
715 //-----------------------------------------------
716 // CZoneManager parseContinents
717 //-----------------------------------------------
718 bool CZoneManager::parseContinents( const NLLIGO::IPrimitive* prim )
720 std::string value;
721 const CPrimZone* zone = dynamic_cast<const CPrimZone*>( prim);
722 // if the primitive is a continent, parse it, build it and add it to this manager if it is correct
723 if ( zone && zone->getPropertyByName("class",value) && value == "continent" )
725 CContinent continent;
726 if ( continent.build( zone ) )
728 uint i = 0;
729 for (; i < _Continents.size(); i++ )
731 if ( _Continents[i].getId() == continent.getId() )
732 break;
734 if ( i == _Continents.size() )
736 _Continents.push_back( continent );
740 // Lookup recursively in the children
741 bool ok = true;
742 for (uint i=0;i<prim->getNumChildren();++i)
744 const IPrimitive *child;
745 if ( prim->getChild(child,i) )
746 ok = parseContinents(child) && ok;
748 return ok;
749 }// CZoneManager parseContinents
751 //-----------------------------------------------
752 // CZoneManager parseRegions
753 //-----------------------------------------------
754 bool CZoneManager::parseRegions( const NLLIGO::IPrimitive* prim )
756 std::string value;
757 const CPrimZone* zone = dynamic_cast<const CPrimZone*>(prim);
758 // if the primitive is a continent, parse it, build it and add it to this manager if it is correct
759 if ( zone && prim->getPropertyByName("class",value) && value == "region" )
761 CRegion * region = new CRegion();
762 if ( region->build( zone,(uint16)_Places.size() ) )
764 bool found = false;
765 for (uint i = 0; i < _Continents.size(); i++ )
767 const std::vector<CPrimVector> & regionPoints = zone->VPoints;
768 for (uint j = 0; j < regionPoints.size(); j++ )
770 if ( _Continents[i].contains( regionPoints[j] ) )
772 found = true;
773 _Continents[i].addRegion( region );
774 region->setContinent( (CONTINENT::TContinent) _Continents[i].getId() );
775 break;
779 nlassertex(found, (toString("No continent found that includes the region %s", prim->getName().c_str()).c_str() ) );
780 _Places.push_back( region );
781 _PlacesByAlias.insert( make_pair(region->getAlias(), region) );
783 else
784 delete region;
786 // Lookup recursively in the children
787 bool ok = true;
788 for (uint i=0;i<prim->getNumChildren();++i)
790 const IPrimitive *child;
791 if ( prim->getChild(child,i) )
792 ok = parseRegions(child) && ok;
794 return ok;
795 }// CZoneManager parseRegions
797 //-----------------------------------------------
798 // CZoneManager parseZones
799 //-----------------------------------------------
800 bool CZoneManager::parseZones( const NLLIGO::IPrimitive* prim )
802 std::string value;
803 const CPrimZone* zone = dynamic_cast<const CPrimZone*>(prim);
804 // if the primitive is a zone, parse it
805 if ( zone )
807 // build the zone and add it to this manager if it is correct
808 if (prim->getPropertyByName("class",value) )
810 if ( value == "place" )
812 CPlace* place = new CPlace();
813 if ( place->build( zone,(uint16)_Places.size() ) )
815 for (uint i = 0; i < _Continents.size(); i++ )
817 for (uint j = 0; j < _Continents[i].getRegions().size(); j++ )
819 for ( uint k = 0; k < place->VPoints.size(); k++ )
821 if ( _Continents[i].getRegions()[j]->contains( place->VPoints[k] ) )
823 _Continents[i].getRegions()[j]->addPlace( place );
824 break;
829 _Places.push_back( place );
831 TAIAlias alias = place->getAlias();
832 if (alias > maxGooBorderAlias)
833 maxGooBorderAlias = alias;
835 _PlacesByAlias.insert( make_pair(place->getAlias(), place) );
837 else
838 delete place;
842 // Lookup recursively in the children
843 bool ok = true;
844 for (uint i=0;i<prim->getNumChildren();++i)
846 const IPrimitive *child;
847 if ( prim->getChild(child,i) )
848 ok = parseZones(child) && ok;
850 return ok;
851 } // CZoneManager parseZones
853 //-----------------------------------------------
854 // CZoneManager parseEcotypes
855 //-----------------------------------------------
856 bool CZoneManager::parseEcotypes( const NLLIGO::IPrimitive* prim )
858 std::string value;
859 if (prim->getPropertyByName("class",value) )
861 if ( value == "ecotypezone_list" )
863 std::string ecotypeZoneListName;
864 prim->getPropertyByName( "name", ecotypeZoneListName );
866 // Parse the children ecotypes
867 for( uint i = 0; i < prim->getNumChildren(); ++i )
869 const IPrimitive * childPrim;
870 if ( prim->getChild( childPrim, i ) )
872 // If the primitive is a zone, parse it
873 const CPrimZone* zone = dynamic_cast<const CPrimZone*>(childPrim);
874 if ( zone )
876 string primType;
877 childPrim->getPropertyByName( "class", primType );
878 if( primType == "ecotypezone" )
880 CEcotypeZone *ecotype = new CEcotypeZone();
881 if ( ecotype->build( zone ) )
883 CDeposit::addEcotype( ecotype );
884 CEcotypeZone *ecotype2 = new CEcotypeZone();
885 if( ecotype2->build( zone ) )
886 CZoneManager::addEcotype( ecotype2 );
887 else
888 delete ecotype2;
890 else
891 delete ecotype;
899 // Lookup recursively in the children
900 bool ok = true;
901 for (uint i=0;i<prim->getNumChildren();++i)
903 const IPrimitive *child;
904 if ( prim->getChild(child,i) )
905 ok = parseEcotypes(child) && ok;
907 return ok;
910 //-----------------------------------------------
911 // CZoneManager parseDeposits
912 // Assumes the ecotypes have been parsed before
913 //-----------------------------------------------
914 bool CZoneManager::parseDeposits( const NLLIGO::IPrimitive* prim )
916 std::string value;
917 if (prim->getPropertyByName("class",value) )
919 if ( value == "depositzone_list" )
921 std::string depositZoneListName;
922 prim->getPropertyByName( "name", depositZoneListName );
924 // Parse the children deposits
925 for( uint i = 0; i < prim->getNumChildren(); ++i )
927 const IPrimitive * childPrim;
928 if ( prim->getChild( childPrim, i ) )
930 // If the primitive is a zone, parse it
931 const CPrimZone* zone = dynamic_cast<const CPrimZone*>(childPrim);
932 if ( zone )
934 string primType;
935 childPrim->getPropertyByName( "class", primType );
936 if( primType == "depositzone" )
938 bool found = false;
939 CDeposit * deposit = new CDeposit;
940 if ( deposit->build( zone ) )
942 for (uint j = 0; j < _Continents.size(); j++ )
944 for (uint k = 0; k < _Continents[j].getRegions().size(); k++ )
946 uint l = 0;
947 for ( ; l < deposit->VPoints.size(); l++ )
949 if ( _Continents[j].getRegions()[k]->contains( deposit->VPoints[l] ) )
951 _Continents[j].getRegions()[k]->addDeposit( deposit );
952 found = true;
953 break;
957 if ( !found )
959 for ( uint k = 0; k < _Continents[j].getRegions().size(); k++ )
961 for ( uint l = 0 ; l < _Continents[j].getRegions()[k]->VPoints.size(); l++ )
963 if ( deposit->contains( _Continents[j].getRegions()[k]->VPoints[l] ) )
965 _Continents[j].getRegions()[k]->addDeposit( deposit );
966 found = true;
967 break;
973 if ( !found )
974 nlwarning("<CZoneManager parseDeposits> a deposit of %s is not in a region", depositZoneListName.c_str());
975 _Deposits.push_back(deposit);
977 else
978 delete deposit;
986 // Lookup recursively in the children
987 bool ok = true;
988 for (uint i=0;i<prim->getNumChildren();++i)
990 const IPrimitive *child;
991 if ( prim->getChild(child,i) )
992 ok = parseDeposits(child) && ok;
994 return ok;
995 } // CZoneManager parseDeposits
997 //-----------------------------------------------
998 // CZoneManager parseStables
999 //-----------------------------------------------
1000 bool CZoneManager::parseStables( const NLLIGO::IPrimitive* prim )
1002 // Primitives format:
1003 // <!-- stables -->
1004 // <PRIMITIVE CLASS_NAME="stables" TYPE="node" AUTO_INIT="true" DELETABLE="true">
1005 // <DYNAMIC_CHILD CLASS_NAME="stable"/>
1006 // </PRIMITIVE>
1008 // <!-- stable -->
1009 // <PRIMITIVE CLASS_NAME="stable" TYPE="zone" R="0" G="255" B="255" A="128" AUTO_INIT="false" DELETABLE="true">>
1010 // <PARAMETER NAME="name" TYPE="string" VISIBLE="true"/>
1012 // <STATIC_CHILD CLASS_NAME="stable_entry" NAME ="stable entry"/>
1013 // </PRIMITIVE>
1015 // <!-- stable entry point -->
1016 // <PRIMITIVE CLASS_NAME="stable_entry" TYPE="point" R="128" G="50" B="200" A="128" AUTO_INIT="true" DELETABLE="false">
1017 // </PRIMITIVE>
1019 std::string value;
1020 if (prim->getPropertyByName("class",value) )
1022 if ( value == "stables" )
1024 string stableName, continent;
1026 prim->getPropertyByName( "name", stableName );
1028 for( uint c = 0; c < prim->getNumChildren(); ++c )
1030 const NLLIGO::IPrimitive* child;
1031 prim->getChild(child,c);
1032 if (child->getPropertyByName("class",value) )
1034 if( value == "stable" )
1036 //geometry of stable point (normally one dot with directional information)
1037 const NLLIGO::CPrimZone* primZone = dynamic_cast<const CPrimZone*>(child);
1038 if( primZone )
1040 bool found = false;
1042 CPlace* place = new CPlace();
1043 if ( place->build( primZone,(uint16)_Places.size(), true ) )
1045 for (uint i = 0; i < _Continents.size(); i++ )
1047 continent = CONTINENT::toString( (CONTINENT::TContinent)_Continents[i].getId() );
1048 for (uint j = 0; j < _Continents[i].getRegions().size(); ++j )
1050 for ( uint k = 0; k < place->VPoints.size(); ++k )
1052 if ( _Continents[i].getRegions()[j]->contains( place->VPoints[k] ) )
1054 _Continents[i].getRegions()[j]->addPlace( place );
1055 found = true;
1056 // Displaying the aliases of all the stables:
1057 //string branchPath = _Continents[i].getName() + "." + _Continents[i].getRegions()[j]->getName() + "." + place->getName();
1058 //InfoLog->displayRawNL( "STBL:%s: %u", branchPath.c_str(), place->getAlias() );
1059 break;
1066 if( place->getId() == 0x35 )
1068 nlinfo("catch it!");
1071 if( found == false )
1073 nlwarning("<CZoneManager::parseStables> Stable %s is not in a region", stableName.c_str());
1074 delete place;
1076 else
1078 _Places.push_back( place );
1079 _PlacesByAlias.insert( make_pair(place->getAlias(), place) );
1081 for( uint c2 = 0; c2 < child->getNumChildren(); ++c2 )
1083 const NLLIGO::IPrimitive* child2;
1084 child->getChild(child2,c2);
1086 if (child2->getPropertyByName("class",value) )
1088 if( value == "stable_entry" )
1090 const NLLIGO::CPrimPoint *stableEntryPoint = dynamic_cast< const CPrimPoint * >(child2);
1091 if( stableEntryPoint == 0 )
1093 nlwarning("<CZoneManager::parseStables> Stable %s not contained stable entry point", stableName.c_str());
1094 return false;
1096 CStable::getInstance()->addStable( stableName, place->getId(), continent, stableEntryPoint->Point.x, stableEntryPoint->Point.y, stableEntryPoint->Point.z, stableEntryPoint->Angle );
1108 // Lookup recursively in the children
1109 bool ok = true;
1110 for (uint i=0;i<prim->getNumChildren();++i)
1112 const IPrimitive *child;
1113 if ( prim->getChild(child,i) )
1114 ok = parseStables(child) && ok;
1116 return ok;
1119 //-----------------------------------------------
1120 // CZoneManager parseTpSpawnZones
1121 //-----------------------------------------------
1122 bool CZoneManager::parseTpSpawnZones( const NLLIGO::IPrimitive* prim )
1124 std::string value;
1125 if (prim->getPropertyByName("class",value) )
1127 if ( value == "teleport_spawn_zone" )
1129 const NLLIGO::CPrimPoint* point = dynamic_cast<const CPrimPoint*>(prim);
1130 if ( !point )
1132 nlwarning("CZoneManager::parseTpSpawnZones -> teleport_trigger should be prim points");
1133 return false;
1135 CTpSpawnZone zone;
1136 if( !zone.build( point ) )
1137 return false;
1139 // if it is a respawn point get the continent where the zone is
1140 if ( zone.getType() == RESPAWN_POINT::KAMI ||
1141 zone.getType() == RESPAWN_POINT::KARAVAN ||
1142 zone.getType() == RESPAWN_POINT::NEWBIELAND ||
1143 zone.getType() == RESPAWN_POINT::RANGER ||
1144 zone.getType() == RESPAWN_POINT::RESPAWNABLE )
1146 bool found = false;
1147 uint j;
1148 for ( j = 0; j < _Continents.size() && !found; ++j )
1150 if ( _Continents[j].contains( point->Point ) )
1152 zone.setContinent((CONTINENT::TContinent) _Continents[j].getId());
1153 found = true;
1154 break;
1157 if( !found )
1159 nlwarning("<CZoneManager::parseTpSpawnZones> Re-spawn point '%s' is not in a continent", zone.getName().c_str());
1160 return false;
1163 found = false;
1164 for ( uint k = 0; k < _Continents[j].getRegions().size(); k++ )
1166 if( _Continents[j].getRegions()[k]->contains( point->Point ) )
1168 zone.setRegion( _Continents[j].getRegions()[k]->getId() );
1169 found = true;
1170 break;
1173 if( ! found )
1175 nlwarning("<CZoneManager::parseTpSpawnZones> Re-spawn point '%s' is not in a region", zone.getName().c_str());
1176 return false;
1180 nlassert( _TpSpawnZones.size() < 0xffff );
1182 map<string,uint16>::const_iterator it = _TpSpawnZoneIdByName.find( zone.getName() );
1183 BOMB_IF( (it != _TpSpawnZoneIdByName.end()),
1184 toString( "<SPAWN_ZONE> spawn zone name '%s' is already used!!!", zone.getName().c_str() ),
1185 return false
1188 _TpSpawnZoneIdByName[zone.getName()] = (uint16)_TpSpawnZones.size();
1189 _TpSpawnZones.push_back( zone );
1190 return true;
1194 // Lookup recursively in the children
1195 bool ok = true;
1196 for (uint i=0;i<prim->getNumChildren();++i)
1198 const IPrimitive *child;
1199 if ( prim->getChild(child,i) )
1200 ok = parseTpSpawnZones(child) && ok;
1202 return ok;
1205 //-----------------------------------------------
1206 // CZoneManager parseGooBorder
1207 //-----------------------------------------------
1208 bool CZoneManager::parseGooBorder( const NLLIGO::IPrimitive* prim )
1210 std::string value;
1211 if (prim->getPropertyByName("class",value) )
1213 if ( value == "goo_border" )
1215 string gooBorderName, continent;
1216 prim->getPropertyByName( "name", gooBorderName );
1218 const CPrimPath * path = dynamic_cast<const CPrimPath*>(prim);
1219 if( path )
1221 CPlace* place = new CPlace();
1222 if ( place->build( path, (uint16)_Places.size()) ) //assume CPrimPath and CPrimZone has the same members, method needed are only in CPrimZone
1224 for (uint i = 0; i < _Continents.size(); i++ )
1226 for (uint j = 0; j < _Continents[i].getRegions().size(); j++ )
1228 for ( uint k = 0; k < place->VPoints.size(); k++ )
1230 if ( _Continents[i].getRegions()[j]->contains( place->VPoints[k] ) )
1232 _Continents[i].getRegions()[j]->addPlace( place );
1233 break;
1238 _Places.push_back( place );
1240 TAIAlias alias = place->getAlias();
1241 if (alias > maxGooBorderAlias)
1242 maxGooBorderAlias = alias;
1244 _PlacesByAlias.insert( make_pair(place->getAlias(), place) );
1246 else
1248 delete place;
1254 // Lookup recursively in the children
1255 bool ok = true;
1256 for (uint i=0;i<prim->getNumChildren();++i)
1258 const IPrimitive *child;
1259 if ( prim->getChild(child,i) )
1260 ok = parseGooBorder(child) && ok;
1262 return ok;
1265 bool CZoneManager::parseGooBorder( const string &name, const string &params, const string &damages )
1267 CPlace* havePlace = getPlaceFromName(name);
1269 if (havePlace != NULL)
1271 if (params.empty())
1273 havePlace->setGooActive(false);
1275 else
1277 havePlace->setGooActive(true);
1278 havePlace->setDamageName(damages);
1280 return true;
1283 CPlace* place = new CPlace();
1285 place->setName(name);
1288 place->setDamageName(damages);
1289 place->setAlias(++maxGooBorderAlias);
1290 CPrimPath* path = new CPrimPath();
1291 if (parsePath(params, path)) {
1292 if ( place->build( path, (uint16)_Places.size(), false ) ) //assume CPrimPath and CPrimZone has the same members, method needed are only in CPrimZone
1294 for (uint i = 0; i < _Continents.size(); i++ )
1296 for (uint j = 0; j < _Continents[i].getRegions().size(); j++ )
1298 for ( uint k = 0; k < place->VPoints.size(); k++ )
1300 if ( _Continents[i].getRegions()[j]->contains( place->VPoints[k] ) )
1302 _Continents[i].getRegions()[j]->addPlace( place );
1303 break;
1308 _Places.push_back( place );
1309 _PlacesByAlias.insert( make_pair(place->getAlias(), place) );
1311 else
1313 delete place;
1318 bool CZoneManager::parsePath( const string &params, CPrimPath *path )
1320 vector< string > points;
1321 NLMISC::splitString(params, "|", points);
1322 for (uint i=0; i<points.size(); i++)
1324 float x, y;
1325 vector< string > point_params;
1326 NLMISC::splitString(points[i], ",", point_params);
1328 if (point_params.size() == 2)
1330 fromString(point_params[0], x);
1331 fromString(point_params[1], y);
1332 path->VPoints.push_back(CPrimVector(NLMISC::CVector(x, y, 0)));
1333 } else {
1334 return false;
1337 return true;
1340 //-----------------------------------------------
1341 // CZoneManager parseStartPoints
1342 //-----------------------------------------------
1343 bool CZoneManager::parseStartPoints( const NLLIGO::IPrimitive* prim )
1345 std::string value;
1346 if (prim->getPropertyByName("class",value) )
1348 if ( value == "start_village" )
1350 string value;
1351 prim->getPropertyByName( "name", value );
1352 RYZOM_STARTING_POINT::TStartPoint start = RYZOM_STARTING_POINT::toStartPoint( value );
1353 if ( start == RYZOM_STARTING_POINT::NB_START_POINTS )
1355 nlwarning("<parseStartPoints> invalid start point %s",value.c_str() );
1356 return false;
1358 uint16 startIdx = (uint16) start;
1359 if ( startIdx >= _StartPoints.size() )
1360 _StartPoints.resize( startIdx + 1);
1362 bool ok = true;
1363 for (uint i=0;i<prim->getNumChildren();++i)
1365 const IPrimitive *child = NULL;
1366 if ( prim->getChild(child,i) && child && child->getPropertyByName("class",value) && value == "start_point")
1368 CStartPoint point;
1369 child->getPropertyByName( "mission", value );
1370 point.Mission = CAIAliasTranslator::getInstance()->getMissionUniqueIdFromName( value );
1371 if ( point.Mission == CAIAliasTranslator::Invalid )
1373 nlwarning("<parseStartPoints> invalid mission %s",value.c_str() );
1375 child->getPropertyByName( "welcomer", value );
1376 point.Welcomer = CAIAliasTranslator::Invalid;
1377 vector<TAIAlias> aliases;
1378 CAIAliasTranslator::getInstance()->getNPCAliasesFromName( value, aliases );
1379 if ( aliases.empty() )
1381 nlwarning("<parseStartPoints> invalid welcomer %s",value.c_str() );
1383 else
1384 point.Welcomer = aliases[0];
1385 if ( point.Welcomer == CAIAliasTranslator::Invalid )
1387 nlwarning("<parseStartPoints> invalid welcomer %s",value.c_str() );
1389 child->getPropertyByName( "spawn_zone", value );
1390 point.SpawnZoneId = getTpSpawnZoneIdByName( value );
1391 if ( point.SpawnZoneId == InvalidSpawnZoneId )
1393 nlwarning("<parseStartPoints> invalid spawn zone %s",value.c_str() );
1394 ok = false;
1396 if ( ok )
1398 _StartPoints[startIdx].push_back( point );
1402 return ok;
1405 // Lookup recursively in the children
1406 bool ok = true;
1407 for (uint i=0;i<prim->getNumChildren();++i)
1409 const IPrimitive *child;
1410 if ( prim->getChild(child,i) )
1411 ok = parseStartPoints(child) && ok;
1413 return ok;
1416 CVariable<bool> LoadPVPFreeZones("egs", "LoadPVPFreeZones", "If true PVP free zones will be loaded", false, 0, true );
1417 CVariable<bool> LoadPVPVersusZones("egs", "LoadPVPVersusZones", "If true PVP versus zones will be loaded", false, 0, true );
1418 CVariable<bool> LoadPVPGuildZones("egs", "LoadPVPGuildZones", "If true PVP guild zones will be loaded", false, 0, true );
1420 //-----------------------------------------------
1421 // CZoneManager parsePVPZones
1422 //-----------------------------------------------
1423 bool CZoneManager::parsePVPZones( const NLLIGO::IPrimitive * prim )
1425 std::string value;
1426 prim->getPropertyByName("class",value);
1427 const CPrimZone * zone = dynamic_cast<const CPrimZone *>(prim);
1429 // if the primitive is a zone, parse it
1430 if ( zone && (value == "pvp_zone") )
1432 CSmartPtr<IPVPZone> pvpZone = IPVPZone::build( zone );
1433 bool load = false;
1435 switch (pvpZone->getPVPZoneType())
1437 case PVP_ZONE_TYPE::FreeZone:
1438 load = LoadPVPFreeZones;
1439 break;
1441 case PVP_ZONE_TYPE::VersusZone:
1442 load = LoadPVPVersusZones;
1443 break;
1445 case PVP_ZONE_TYPE::GuildZone:
1446 load = LoadPVPGuildZones;
1447 break;
1449 default:
1450 nlwarning( "Invalid %s zone in pvp_zone primitive %s", PVP_ZONE_TYPE::toString( pvpZone->getPVPZoneType() ).c_str(), prim->getName().c_str() );
1451 load = false;
1453 if (load)
1454 CPVPManager::getInstance()->addPVPZone( pvpZone );
1458 // lookup recursively in the children
1459 bool result = true;
1460 for (uint i = 0; i < prim->getNumChildren(); i++)
1462 const IPrimitive * child;
1463 if ( prim->getChild(child, i) )
1464 result &= parsePVPZones(child);
1467 return result;
1468 } // CZoneManager parsePVPZones
1470 //-----------------------------------------------
1471 // CZoneManager parsePVPSafeZones
1472 //-----------------------------------------------
1473 bool CZoneManager::parsePVPSafeZones( const NLLIGO::IPrimitive * prim )
1475 std::string value;
1476 const CPrimPoint * point = dynamic_cast<const CPrimPoint *>(prim);
1478 // if the primitive is a point, parse it
1479 if ( point && prim->getPropertyByName("class",value) && value == "safe_zone" )
1481 value = "true";
1482 prim->getPropertyByName("safe_from_pvp", value);
1483 if ( value == "true" )
1485 CSmartPtr<CPVPSafeZone> safeZone = CPVPSafeZone::build( point );
1486 if ( !safeZone.isNull() )
1488 CPVPManager::getInstance()->addPVPSafeZone( safeZone );
1489 CPVPManager2::getInstance()->addPVPSafeZone( safeZone );
1494 // lookup recursively in the children
1495 bool result = true;
1496 for (uint i = 0; i < prim->getNumChildren(); i++)
1498 const IPrimitive * child;
1499 if ( prim->getChild(child, i) )
1500 result &= parsePVPSafeZones(child);
1503 return result;
1504 } // CZoneManager parsePVPSafeZones
1506 //-----------------------------------------------
1507 // CZoneManager getContinent
1508 //-----------------------------------------------
1509 CContinent * CZoneManager::getContinent( sint32 x, sint32 y )
1511 CVector vect( x * 0.001f, y * 0.001f, 0.0f );
1512 return getContinent(vect);
1513 }// CZoneManager getContinent*
1516 //-----------------------------------------------
1517 // Same with vector
1518 //-----------------------------------------------
1519 CContinent * CZoneManager::getContinent( const NLMISC::CVector& pos )
1521 for ( uint i = 0; i < _Continents.size(); i++ )
1523 if ( _Continents[i].contains(pos) )
1524 return &_Continents[i];
1526 return NULL;
1527 }// CZoneManager getContinent
1530 //-----------------------------------------------
1531 // CZoneManager getRegion
1532 //-----------------------------------------------
1533 bool CZoneManager::getRegion( sint32 x, sint32 y, const CRegion ** region, const CContinent ** continent)
1535 nlassert(region);
1536 CVector vect( x * 0.001f, y * 0.001f, 0.0f );
1537 for ( uint i = 0; i < _Continents.size(); i++ )
1539 if ( _Continents[i].contains(vect) )
1541 for (uint j = 0; j < _Continents[i].getRegions().size(); j++ )
1543 if ( _Continents[i].getRegions()[j]->contains( vect ) )
1545 if ( continent )
1546 *continent = &_Continents[i];
1548 *region = _Continents[i].getRegions()[j];
1549 return true;
1554 return false;
1555 }// CZoneManager getRegion
1557 #include <limits>
1559 //-----------------------------------------------
1560 // CZoneManager getPlace
1561 //-----------------------------------------------
1562 bool CZoneManager::getPlace( sint32 x, sint32 y, float& gooDistance, const CPlace ** stable, std::vector<const CPlace *>& places, const CRegion ** region , const CContinent ** continent, bool withGooActive )
1564 nlassert(stable);
1566 if( continent ) *continent = NULL;
1567 if( region ) *region = NULL;
1568 *stable = NULL;
1570 float nearGooDistance = numeric_limits<float>::max();
1572 CVector vect( x * 0.001f, y * 0.001f, 0.0f );
1573 for ( uint i = 0; i < _Continents.size(); i++ )
1575 if ( _Continents[i].contains(vect) )
1577 if ( continent )
1578 *continent = &_Continents[i];
1579 for (uint j = 0; j < _Continents[i].getRegions().size(); j++ )
1581 if ( _Continents[i].getRegions()[j]->contains( vect ) )
1583 if ( region )
1585 *region = _Continents[i].getRegions()[j];
1587 for (uint k = 0; k < _Continents[i].getRegions()[j]->getPlaces().size(); k++ )
1589 const CPlace * p;
1590 p = _Continents[i].getRegions()[j]->getPlaces()[k];
1592 if (!p->isGooActive())
1594 if ( p->contains( vect ) )
1596 CStable::TStableData stableData;
1597 if( CStable::getInstance()->getStableData( p->getId(), stableData ) )
1599 *stable = p;
1601 places.push_back( p );
1604 else
1606 CVector p1, p2, nearPos;
1607 float distance;
1609 CPrimZone::contains (vect, _Continents[i].getRegions()[j]->getPlaces()[k]->VPoints, distance, nearPos, true);
1610 if( distance < nearGooDistance )
1612 nearGooDistance = distance;
1614 if (withGooActive)
1615 places.push_back( p );
1618 gooDistance = nearGooDistance;
1619 return true;
1624 gooDistance = nearGooDistance;
1625 return false;
1626 }// CZoneManager getPlace
1629 //-----------------------------------------------
1630 // CZoneManager getRegion
1631 //-----------------------------------------------
1632 CRegion * CZoneManager::getRegion( const NLMISC::CVector& pos )
1634 const CRegion *cregion = 0;
1635 if ( (! getRegion( (sint32)(pos.x*1000.0f), (sint32)(pos.y*1000.0f), &cregion )) || (! cregion) )
1637 nlwarning( "Invalid region for pos %s", pos.asString().c_str() );
1638 return NULL;
1640 return (const_cast<CRegion*>(cregion));
1644 //-----------------------------------------------
1645 // CZoneManager getDepositsUnderUser
1646 //-----------------------------------------------
1647 void CZoneManager::getDepositsUnderPos( const CVector& pos, std::vector<CDeposit*>& deposits, bool warnIfOutsideOfRegion )
1649 const CRegion *cregion = 0;
1650 CRegion *region;
1651 if ( (! getRegion( (sint32)(pos.x*1000.0f), (sint32)(pos.y*1000.0f), &cregion )) || (! cregion) )
1653 if ( warnIfOutsideOfRegion )
1654 nlwarning( "<CZoneManager getDepositsUnderPos> invalid region for pos %s", pos.asString().c_str() );
1655 return;
1657 region = (const_cast<CRegion*>(cregion));
1658 deposits.clear();
1659 for (uint i=0; i!=region->getDeposits().size(); ++i )
1661 if ( region->getDeposits()[i]->contains( pos ) )
1662 deposits.push_back( region->getDeposits()[i] );
1664 }// CZoneManager getDepositsUnderPos
1668 // get the first deposit found under the position (faster than getDepositsUnderPos()), or NULL if not found
1670 CDeposit* CZoneManager::getFirstFoundDepositUnderPos( const NLMISC::CVector& pos )
1672 const CRegion *cregion = 0;
1673 CRegion *region;
1674 if ( (! getRegion( (sint32)(pos.x*1000.0f), (sint32)(pos.y*1000.0f), &cregion )) || (! cregion) )
1676 nlwarning( "<CZoneManager getFirstFoundDepositUnderPos> invalid region for pos %s", pos.asString().c_str() );
1677 return NULL;
1679 region = (const_cast<CRegion*>(cregion));
1680 for (uint i=0; i!=region->getDeposits().size(); ++i )
1682 if ( region->getDeposits()[i]->contains( pos ) )
1683 return region->getDeposits()[i];
1685 return NULL;
1688 //-----------------------------------------------
1689 // CZoneManager getContinentFromId
1690 //-----------------------------------------------
1691 CPlace* CZoneManager::getPlaceFromAlias( TAIAlias alias )
1693 std::map< TAIAlias, CPlace* >::iterator it = _PlacesByAlias.find( alias );
1694 if ( it != _PlacesByAlias.end() )
1696 return ( (*it).second );
1698 return NULL;
1701 //-----------------------------------------------
1702 // CZoneManager getPlaceFromName
1703 //-----------------------------------------------
1704 CPlace* CZoneManager::getPlaceFromName( const std::string & name )
1706 for ( uint i = 0; i < _Places.size(); i++ )
1708 if ( _Places[i] && _Places[i]->getName() == name )
1710 return _Places[i];
1713 return NULL;
1714 }// CZoneManager getPlaceFromName
1716 //-----------------------------------------------
1717 // CZoneManager getContinentFromId
1718 //-----------------------------------------------
1719 CContinent* CZoneManager::getContinentFromId( CONTINENT::TContinent id )
1721 if (id == CONTINENT::UNKNOWN )
1722 return NULL;
1723 for ( uint i = 0; i< _Continents.size(); i++ )
1725 if ( _Continents[i].getId() == id )
1726 return &_Continents[i];
1728 nlwarning("<CZoneManager getContinentFromId> continent id %u is out of bound",id);
1729 return NULL;
1730 }// CZoneManager getContinentFromId
1732 //-----------------------------------------------
1733 // CZoneManager updateCharacterPosition
1734 //-----------------------------------------------
1735 void CZoneManager::updateCharacterPosition( CCharacter * user, uint32 elapsedTime )
1737 nlassert(user);
1739 // if user is in an instance, do not update the places where he is
1740 CMirrorPropValueRO<TYPE_CELL> mirrorCell( TheDataset, user->getEntityRowId(), DSPropertyCELL );
1741 sint32 cell = mirrorCell;
1742 if ( cell <= - 2 )
1743 return;
1744 if ( user->getState().X <= 0 || user->getState().Y >= 0 )
1745 return;
1747 SM_STATIC_PARAMS_1(params, STRING_MANAGER::place);
1748 SM_STATIC_PARAMS_2(params2, STRING_MANAGER::place, STRING_MANAGER::faction);
1750 // get the current location of the character
1751 const CPlace * stable;
1752 std::vector<const CPlace*> places;
1753 const CRegion * region ;
1754 const CContinent * continent;
1755 float gooDistance;
1756 getPlace( user, gooDistance, &stable, places, &region, &continent, true);
1758 // SOURCE: user->getCurrentContinent()
1759 // DESTINATION: continent->getId()
1760 // {
1761 // update the continent if necessary
1762 if ( continent == NULL )
1764 CPlace * oldPlace = getContinentFromId( user->getCurrentContinent() ); // returns NULL for CONTINENT::UNKNOWN
1765 if (oldPlace)
1767 params[0].Identifier = oldPlace->getName();
1768 PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_LEAVE_CONTINENT",params);
1770 user->setCurrentContinent( CONTINENT::UNKNOWN );
1772 else if ( (CONTINENT::TContinent)continent->getId() != user->getCurrentContinent() )
1774 // if current continent is NEWBIELAND, send an 'newbie' update to the SU
1775 bool updateSU = false;
1776 if (user->getCurrentContinent() == CONTINENT::NEWBIELAND)
1777 updateSU = true;
1779 const CONTINENT::TContinent oldContinent = user->getCurrentContinent();
1780 CPlace * oldPlace = getContinentFromId( oldContinent ); // returns NULL for CONTINENT::UNKNOWN
1781 if (oldPlace)
1783 params[0].Identifier = oldPlace->getName();
1784 PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_LEAVE_CONTINENT",params);
1786 params[0].Identifier = continent->getName();
1787 PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_ENTER_CONTINENT",params);
1788 user->setCurrentContinent( (CONTINENT::TContinent)continent->getId() );
1789 // notify player respawn points system that continent changed
1790 user->getRespawnPoints().cbContinentChanged(oldContinent);
1791 // update newbieland flag (defailt to 1 if there's aproblem determining the true value)
1792 bool newbie = user->isNewbie();
1793 // user->_PropertyDatabase.setProp("USER:IS_NEWBIE", newbie);
1794 CBankAccessor_PLR::getUSER().setIS_NEWBIE(user->_PropertyDatabase, newbie);
1796 bool trialPlayer = false;
1797 CPlayer *player = PlayerManager.getPlayer( PlayerManager.getPlayerId(user->getId()));
1798 if (!player)
1800 nlwarning("Error %s was not found in player manager.",user->getId().toString().c_str());
1801 trialPlayer = player->isTrialPlayer();
1803 // user->_PropertyDatabase.setProp("USER:IS_TRIAL", trialPlayer);
1804 CBankAccessor_PLR::getUSER().setIS_TRIAL(user->_PropertyDatabase, trialPlayer);
1806 if (updateSU)
1808 if (IShardUnifierEvent::getInstance() != NULL)
1809 IShardUnifierEvent::getInstance()->onUpdateCharNewbieFlag(user->getId(), newbie);
1813 // do the same for region
1814 // first send message for leaving previous region
1815 CRegion * oldRegion = dynamic_cast<CRegion *> ( getPlaceFromId( user->getCurrentRegion() ) );
1816 if( user->getCurrentRegion() != 0xFFFF )
1818 // previously in region
1819 if( region == 0 || ( region->getId() != user->getCurrentRegion()) )
1821 // and not the same than actual region
1822 if (oldRegion)
1824 const CTotemBase* pTotem = CPVPFactionRewardManager::getInstance().getTotemBaseFromId( user->getCurrentRegion() );
1825 if( pTotem )
1827 PVP_CLAN::TPVPClan regionFaction = pTotem->getOwnerFaction();
1828 if( regionFaction == PVP_CLAN::Neutral )
1830 params[0].Identifier = oldRegion->getName();
1831 PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_LEAVE_NEUTRAL_REGION",params);
1833 else
1835 params2[0].Identifier = oldRegion->getName();
1836 params2[1].Enum = PVP_CLAN::getFactionIndex(regionFaction);
1837 PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_LEAVE_FACTION_REGION",params2);
1840 else
1842 params[0].Identifier = oldRegion->getName();
1843 PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_LEAVE_NEUTRAL_REGION",params);
1846 oldRegion->removePlayer( user->getId() );
1849 if( region == 0 )
1851 user->setCurrentRegion( 0xFFFF );
1852 // remove spire effects for Pvp-flagged players
1853 if ( user->getPVPFlag() )
1854 CPVPFactionRewardManager::getInstance().removeTotemsEffects( user );
1859 if ( region != 0 && (user->getCurrentRegion() != region->getId()) )
1861 const CTotemBase* pTotem = CPVPFactionRewardManager::getInstance().getTotemBaseFromId( region->getId() );
1862 if( pTotem )
1864 PVP_CLAN::TPVPClan regionFaction = pTotem->getOwnerFaction();
1865 if( regionFaction == PVP_CLAN::Neutral )
1867 params[0].Identifier = region->getName();
1868 PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_ENTER_NEUTRAL_REGION",params);
1870 else
1872 params2[0].Identifier = region->getName();
1873 params2[1].Enum = PVP_CLAN::getFactionIndex(regionFaction);
1874 PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_ENTER_FACTION_REGION",params2);
1877 else
1879 params[0].Identifier = region->getName();
1880 PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_ENTER_NEUTRAL_REGION",params);
1883 // Check is region have a trigger to send an url
1884 string regionTrigger = getRegionTrigger(region->getName());
1885 if (!regionTrigger.empty())
1886 user->sendUrl(regionTrigger);
1888 user->setCurrentRegion( region->getId() );
1890 ((CRegion*)region)->addPlayer( user->getId() );
1892 // add new spire effects for Pvp-flagged players
1893 if ( user->getPVPFlag() )
1894 CPVPFactionRewardManager::getInstance().giveTotemsEffects( user );
1896 // Now the VisitPlace missions are checked in CMissionManager::checkVisitPlaceMissions()
1897 //CMissionEventVisitPlace event(region->getId() );
1898 //user->processMissionMultipleEvent(event);
1901 // Trigger entities
1902 std::map<TAIAlias, uint8>::const_iterator it;
1903 for (it = EntitiesDistanceTriggers.begin(); it != EntitiesDistanceTriggers.end(); it++)
1905 nlinfo("Entity trigger : %s", NLMISC::toString(it->first).c_str());
1906 if (it->second == 0)
1908 std::map<TAIAlias, std::string>::const_iterator it2 = EntitiesUrlTriggers.find(it->first);
1909 if ( it2 != EntitiesUrlTriggers.end() )
1910 user->sendRpPoints(it2->second);
1912 else
1914 nlinfo("Distance = %d", it->second);
1915 const CEntityId & botId = CAIAliasTranslator::getInstance()->getEntityId(it->first);
1916 if ( botId != CEntityId::Unknown )
1918 nlinfo("Botid found");
1919 CEntityBase *entityBase = CreatureManager.getCreature (botId);
1920 if (entityBase != NULL)
1922 sint32 x = entityBase->getState().X/1000.f;
1923 sint32 y = entityBase->getState().Y/1000.f;
1924 sint32 px = user->getState().X/1000.f;
1925 sint32 py = user->getState().Y/1000.f;
1926 nlinfo("entityBase found, check pos %i, %i, %i, %i", x, y, px, py);
1927 if ((px-x)*(px-x)+(py-y)*(py-y) < it->second * it->second)
1928 user->addRpPoints(elapsedTime);
1935 string zoneDamage;
1937 // get new places
1938 const uint newPlacesSize = (uint)places.size();
1939 //bool sendWarning = false;
1940 bool changed = false;
1941 for ( uint i = 0; i < newPlacesSize; i++ )
1943 // Setup the damage name of the zone (place)
1944 if (!places[i]->getDamageName().empty())
1946 zoneDamage = places[i]->getDamageName();
1949 if ( !user->isInPlace( places[i]->getId() ) )
1951 if( places[i]->getReported() )
1953 params[0].Identifier = places[i]->getName();
1954 PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_ENTER_PLACE",params);
1956 // Now the VisitPlace missions are checked in CMissionManager::checkVisitPlaceMissions()
1957 //CMissionEventVisitPlace event( places[i]->getId() );
1958 //user->processMissionMultipleEvent(event);
1960 // validate respawn points
1961 for ( uint j = 0; j< places[i]->getRespawnPoints().size(); j++ )
1963 user->getRespawnPoints().addRespawnPoint( places[i]->getRespawnPoints()[j] );
1966 changed = true;
1968 /// tells mission system that user enters a place
1969 for ( map<TAIAlias, CMission*>::iterator it = user->getMissionsBegin(); it != user->getMissionsEnd(); ++it )
1971 CMissionManager::getInstance()->enterPlace( (*it).second,places[i]->getAlias(), places[i]->getId() );
1976 // get left places
1977 const uint oldPlacesSize = (uint)user->getPlaces().size();
1978 for ( uint i = 0; i < oldPlacesSize; i++ )
1980 uint j = 0;
1981 for (; j < newPlacesSize; j++ )
1983 if ( places[j]->getId() == user->getPlaces()[i] )
1984 break;
1986 if ( j == newPlacesSize )
1988 CPlace * place = getPlaceFromId( user->getPlaces()[i] );
1989 if ( place )
1991 if( place->getReported() )
1993 params[0].Identifier = place->getName();
1994 PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_LEAVE_PLACE",params);
1997 /// tells mission system that user enters a place
1998 for ( map<TAIAlias, CMission*>::iterator it = user->getMissionsBegin(); it != user->getMissionsEnd(); ++it )
2000 CMissionManager::getInstance()->leavePlace( (*it).second,place->getAlias(), place->getId() );
2003 changed = true;
2008 // enter/leave PVP zones
2009 TAIAlias pvpZoneAlias = CPVPManager::getInstance()->getPVPZoneFromUserPosition( user );
2010 if ( pvpZoneAlias != user->getCurrentPVPZone() && !user->isDead() )
2012 if ( user->getCurrentPVPZone() != CAIAliasTranslator::Invalid )
2014 CPVPManager::getInstance()->leavePVPZone( user );
2017 if ( pvpZoneAlias != CAIAliasTranslator::Invalid )
2019 CPVPManager::getInstance()->enterPVPZone( user, pvpZoneAlias );
2022 user->setCurrentPVPZone( pvpZoneAlias );
2025 // enter/leave outpost zones
2026 TAIAlias outpostAlias = COutpostManager::getInstance().getOutpostFromUserPosition( user );
2027 if ( outpostAlias != user->getCurrentOutpostZone() && !user->isDead() )
2029 if ( user->getCurrentOutpostZone() != CAIAliasTranslator::Invalid )
2031 COutpostManager::getInstance().leaveOutpostZone( user );
2034 user->setCurrentOutpostZone( outpostAlias );
2036 if ( outpostAlias != CAIAliasTranslator::Invalid )
2038 COutpostManager::getInstance().enterOutpostZone( user );
2041 else // Check if outpost have changed from peace state, if yes => player re-enter the pvpzone to ask to choose a side
2043 CSmartPtr<COutpost> outpost = COutpostManager::getInstance().getOutpostFromAlias(outpostAlias);
2044 if (outpost)
2046 OUTPOSTENUMS::TOutpostState savedState = user->getCurrentOutpostState();
2047 user->setCurrentOutpostZone( outpostAlias );
2048 if (savedState != outpost->getState() && (savedState == OUTPOSTENUMS::Peace || savedState == OUTPOSTENUMS::WarDeclaration || savedState == OUTPOSTENUMS::AttackAfter))
2050 if ( pvpZoneAlias != CAIAliasTranslator::Invalid && !user->isDead() )
2051 CPVPManager::getInstance()->enterPVPZone( user, pvpZoneAlias );
2056 if ( changed )
2057 user->setPlaces( places );
2059 // and stable
2060 // if the player is now in an unknown stable
2061 if( stable == NULL )
2063 // disable this message because stables are already treated as places
2064 /*CPlace * oldStable = getPlaceFromId( user->getCurrentStable() );
2065 if (oldStable)
2067 if( oldStable->getReported() )
2069 params[0].Identifier = oldStable->getName();
2070 PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_LEAVE_PLACE",params);
2074 user->setCurrentStable( 0xFFFF,0xFFFF);
2076 // check if player left old current stable for enter to another
2077 else if( user->getCurrentStable() != stable->getId() )
2079 // disable this message because stables are already treated as places
2080 /*CPlace * oldStable = getPlaceFromId( user->getCurrentStable() );
2081 if (oldStable)
2083 if( oldStable->getReported() )
2085 params[0].Identifier = oldStable->getName();
2086 PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_LEAVE_PLACE",params);
2089 if( stable->getReported() )
2091 params[0].Identifier = stable->getName();
2092 PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"EGS_ENTER_PLACE",params);
2095 for ( uint i = 0; i < newPlacesSize; i++ )
2097 if ( places[i]->isMainPlace() )
2099 user->setCurrentStable( stable->getId(), places[i]->getId() );
2100 break;
2103 // Now the VisitPlace missions are checked in CMissionManager::checkVisitPlaceMissions()
2104 //CMissionEventVisitPlace event(stable->getId() );
2105 //user->processMissionMultipleEvent(event);
2108 // apply goo damage if needed
2109 user->applyGooDamage( gooDistance, zoneDamage);
2111 }// CZoneManager updateCharacterPosition
2113 //-----------------------------------------------
2114 // CZoneManager tickUpdate
2115 //-----------------------------------------------
2116 void CZoneManager::tickUpdate()
2118 // *** Update deposits at low frequency (each deposit is updated once per DepositUpdateFrequency (which is a period in game cycles, actually))
2119 // CPU is smoothed if there are more deposits than cycles in the period.
2120 uint32 nbDeposit = (uint32)_Deposits.size();
2121 if( ( (_NextDepositIndexUpdated != 0) || (CTickEventHandler::getGameCycle() - _SpreadUpdateLoopBeginTick ) >= DepositUpdateFrequency.get()) )
2123 if ( _NextDepositIndexUpdated == 0 )
2125 _SpreadUpdateLoopBeginTick = CTickEventHandler::getGameCycle();
2127 uint32 i, nbDepositUpdatedByTick = (uint32 ) ( nbDeposit / DepositUpdateFrequency.get() ) + 1;
2128 for( i = _NextDepositIndexUpdated; i < _NextDepositIndexUpdated + nbDepositUpdatedByTick; ++i )
2130 if( i < nbDeposit )
2132 _Deposits[ i ]->lowFreqUpdate();
2136 if( i >= nbDeposit )
2137 _NextDepositIndexUpdated = 0;
2138 else
2139 _NextDepositIndexUpdated = i;
2142 // *** Update the deposits that need an update for auto spawn
2143 std::set< CDeposit* >::iterator itDeposit= _DepositNeedingAutoSpawnUpdate.begin();
2144 while(itDeposit!= _DepositNeedingAutoSpawnUpdate.end())
2146 CDeposit *deposit= *itDeposit;
2147 nlassert(deposit);
2148 deposit->autoSpawnUpdate();
2150 // remove the deposit from the set, and go next to update
2151 std::set< CDeposit* >::iterator itNext= itDeposit;
2152 itNext++;
2153 _DepositNeedingAutoSpawnUpdate.erase(itDeposit);
2154 itDeposit= itNext;
2157 }// CZoneManager tickUpdate
2159 //-----------------------------------------------
2160 // CZoneManager dumpWorld
2161 //-----------------------------------------------
2162 void CZoneManager::dumpWorld(CLog & log)
2164 log.displayNL("%u continents", _Continents.size() );
2165 for (uint i = 0; i < _Continents.size(); i++ )
2167 log.displayNL("CONTINENT %u : id=%u, name=%s", i, _Continents[i].getId(),_Continents[i].getName().c_str() );
2168 const std::vector< CRegion* > & regions = _Continents[i].getRegions();
2169 for (uint j = 0; j < regions.size();j++ )
2171 log.displayNL(" region %u : id=%u, name=%s",j, regions[j]->getId(),regions[j]->getName().c_str() );
2172 const std::vector< CPlace* > & places = regions[j]->getPlaces();
2173 for (uint k = 0; k < places.size();k++ )
2175 log.displayNL(" place %u : id=%u, name=%s", k, places[k]->getId(),places[k]->getName().c_str() );
2177 log.displayNL("");
2178 const std::vector< CDeposit* > & deposits = regions[j]->getDeposits();
2179 log.displayNL("%u deposits", deposits.size() );
2180 //for (uint k = 0; k < deposits.size();k++ )
2182 // log.displayNL(" deposits %u : id=%u", k, /*deposits[k]->getId()*/0, /*deposits[k]->getName().c_str()*/ );
2189 //-----------------------------------------------
2190 // CZoneManager dumpTpSpawnZones
2191 //-----------------------------------------------
2192 void CZoneManager::dumpTpSpawnZones(CLog & log)
2194 log.displayNL("%u tp spawn zones", _TpSpawnZones.size());
2195 for (uint i = 0; i < _TpSpawnZones.size(); i++)
2197 log.displayNL("TP SPAWN ZONE %u : name=%s", i, _TpSpawnZones[i].getName().c_str());
2201 //-----------------------------------------------
2202 // CZoneManager answerWhere
2203 //-----------------------------------------------
2204 void CZoneManager::answerWhere(const NLMISC::CEntityId & eId)
2206 ///\todo nico manage building
2207 CCharacter * c = PlayerManager.getChar( eId );
2208 if (c )
2210 c->setAfkState(false);
2211 CContinent * cont = getContinentFromId(c->getCurrentContinent());
2212 if ( !cont )
2214 nlwarning("<CZoneManager answerWhere> invalid continent %u for entity %s",c->getCurrentContinent(),eId.toString().c_str());
2215 return;
2217 CPlace * region = getPlaceFromId( c->getCurrentRegion() );
2218 if ( !region )
2220 nlwarning("<CZoneManager answerWhere> invalid region %u for entity %s",c->getCurrentRegion(),eId.toString().c_str());
2221 return;
2224 uint size = (uint)c->getPlaces().size();
2225 CPlace * place = NULL;
2226 for ( uint i = 0; i < size; i++ )
2228 CPlace * placeTest = getPlaceFromId( c->getPlaces()[i] );
2229 nlassert( placeTest );
2230 if ( placeTest->isMainPlace() )
2232 place = placeTest;
2233 break;
2237 STRING_MANAGER::TParam param;
2238 param.Type = STRING_MANAGER::place;
2239 if (place)
2241 SM_STATIC_PARAMS_3(params, STRING_MANAGER::place, STRING_MANAGER::place, STRING_MANAGER::place);
2242 params[0].Identifier = cont->getName();
2243 params[1].Identifier = region->getName();
2244 params[2].Identifier = place->getName();
2245 PHRASE_UTILITIES::sendDynamicSystemMessage(TheDataset.getDataSetRow(eId),"EGS_ANSWER_WHERE",params);
2247 else
2249 SM_STATIC_PARAMS_2(params, STRING_MANAGER::place, STRING_MANAGER::place);
2250 params[0].Identifier = cont->getName();
2251 params[1].Identifier = region->getName();
2252 PHRASE_UTILITIES::sendDynamicSystemMessage(TheDataset.getDataSetRow(eId),"EGS_ANSWER_WHERE_NO_PLACE",params);
2256 std::vector< NLMISC::CEntityId > bots;
2257 for ( uint i = 0; i < c->getPickedMissions().size(); i++ )
2259 if ( c->getPickedMissions()[i] )
2261 CStaticMission * mission = c->getPickedMissions()[i]->getTemplate();
2262 NLMISC::CEntityId bot;
2263 if ( CAIAliasTranslator::getInstance()->getEntityId(c->getPickedMissions()[i]->getRewardGiver(), bot ) )
2265 uint j = 0;
2266 for (; j < bots.size(); j++ )
2268 if ( bots[j] == bot )
2269 break;
2271 if ( j == bots.size() )
2272 bots.push_back( bot );
2274 for (uint j = 0; j < mission->getSteps().size(); j++ )
2276 mission->getSteps()[j]->addImpliedBots( bots );
2280 if ( !bots.empty() )
2282 CCharacter::sendMessageToClient( eId,"EGS_MISSION_DIR_INTRO" );
2283 double xUser = (double)c->getState().X;
2284 double yUser = (double)c->getState().Y;
2285 for ( uint i = 0; i < bots.size(); i++ )
2287 CCreature * botPtr = CreatureManager.getCreature( bots[i] );
2288 if ( botPtr )
2290 string botName;
2291 if ( CAIAliasTranslator::getInstance()->getNPCNameFromAlias( botPtr->getAlias(), botName ) )
2293 double dx = (double)botPtr->getState().X/1000.0-(double)xUser/1000.0;
2294 double dy = (double)botPtr->getState().Y/1000.0-(double)yUser/1000.0;
2295 double dist = sqrt(dx*dx+dy*dy);
2296 uint32 distshort = (uint16)dist;
2298 double angle = atan2 (dy, dx) + NLMISC::Pi;
2299 sint direction =(sint) floor( 0.5 + 8.0 * angle /(NLMISC::Pi) );
2300 direction = direction %16;
2302 static string txts[]=
2304 "W",
2305 "WSW",
2306 "SW",
2307 "SSW",
2308 "S",
2309 "SSE",
2310 "SE",
2311 "ESE",
2312 "E",
2313 "ENE",
2314 "NE",
2315 "NNE",
2316 "N",
2317 "NNW",
2318 "NW",
2319 "WNW",
2321 static string msgBot = ("EGS_MISSION_DIR_BOT");
2323 CMessage msgout("STATIC_STRING");
2324 msgout.serial( const_cast<CEntityId&>(eId) );
2325 std::set<CEntityId> empty;
2326 msgout.serialCont( empty );
2327 msgout.serial( msgBot );
2328 msgout.serial( botName );
2329 msgout.serial( distshort );
2330 msgout.serial( txts[direction] );
2331 sendMessageViaMirror( "IOS", msgout );
2338 else
2340 nlwarning( "<CZoneManager answerWhere>Invalid char %s",eId.toString().c_str() );
2345 //-----------------------------------------------
2346 // CZoneManager harvestDeposit
2347 //-----------------------------------------------
2348 /*void CZoneManager::harvestDeposit(CCharacter * user)
2350 nlassert(user);
2351 vector<CDeposit*> deposits;
2352 nlerror( "getDepositsUnderUser(user,deposits);" );
2353 if ( deposits.size() )
2355 uint nbMps = 0;
2356 for (uint i = 0; i < deposits.size(); i++ )
2357 nbMps+= deposits[i]->getContentSize();
2358 uint result = RandomGenerator.rand( nbMps - 1 );
2359 nbMps = 0;
2360 for (uint i = 0; i < deposits.size(); i++ )
2362 if ( result < nbMps + deposits[i]->getContentSize() )
2364 nlerror( "deposits[i]->harvestInfo(user->getId(),user->getHarvestInfos());" );
2365 break;
2367 nbMps += deposits[i]->getContentSize();
2370 if (user->getHarvestInfos().Sheet == CSheetId::Unknown)
2372 // no raw material found, return
2373 return;
2376 user->getHarvestInfos().EndCherchingTime = CTickEventHandler::getGameCycle() + DepositSearchTime;
2377 user->setCurrentAction( CLIENT_ACTION_TYPE::Harvest, user->getHarvestInfos().EndCherchingTime );
2379 }// CZoneManager harvestDeposit
2383 //-----------------------------------------------
2384 // CZoneManager displayAllDeposit
2385 //-----------------------------------------------
2386 void CZoneManager::dumpDeposits( NLMISC::CLog & log, const std::string& depName, bool extendedInfo )
2388 bool displayAll = (depName == "ALL");
2389 for( uint i = 0; i < _Deposits.size(); i++ )
2391 if ( _Deposits[i] )
2393 if ( displayAll || (_Deposits[i]->name() == depName) )
2394 _Deposits[i]->displayContent( &log, extendedInfo );
2396 else
2397 log.displayNL( "===== Deposit %d is NULL" );
2399 }// CZoneManager displayAllDeposit
2402 //-----------------------------------------------
2403 // CZoneManager getStartPointVector
2404 //-----------------------------------------------
2405 vector<CZoneManager::CStartPoint> CZoneManager::getStartPointVector( uint16 startPointIdx ) const
2407 if ( startPointIdx >= _StartPoints.size() )
2409 nlwarning("bad start point index %u ( count %u )",startPointIdx , _StartPoints.size() );
2410 return vector<CStartPoint>();
2413 return _StartPoints[startPointIdx];
2414 }// CZoneManager getStartPointVector
2417 //-----------------------------------------------
2418 // Get the ecotype zone under the position.
2419 // If not found, a NULL pointer is returned.
2420 //-----------------------------------------------
2421 ECOSYSTEM::EECosystem CZoneManager::getEcotype( const NLMISC::CVector& pos )
2423 // The ecotypes must not be overlapped: only the first one found is returned
2424 for ( CEcotypeZones::iterator it=_EcotypeZones.begin(); it!=_EcotypeZones.end(); ++it )
2426 CEcotypeZone *ecotypeZone = (*it);
2427 if ( ecotypeZone->contains( pos ) )
2429 return ecotypeZone->ecotype();
2432 return ECOSYSTEM::unknown;
2436 //-----------------------------------------------
2437 // Clear ecotype information
2438 //-----------------------------------------------
2439 void CZoneManager::clearEcotypes()
2441 for ( CEcotypeZones::iterator iez=_EcotypeZones.begin(); iez!=_EcotypeZones.end(); ++iez )
2443 delete (*iez);
2445 _EcotypeZones.clear();
2449 //-----------------------------------------------
2450 // deposit auto spawn
2451 //-----------------------------------------------
2452 void CZoneManager::registerDepositToAutoSpawnUpdate(CDeposit *deposit)
2454 if(deposit)
2455 _DepositNeedingAutoSpawnUpdate.insert(deposit);
2457 void CZoneManager::unregisterDepositToAutoSpawnUpdate(CDeposit *deposit)
2459 if(deposit)
2460 _DepositNeedingAutoSpawnUpdate.erase(deposit);
2465 // dump the world organisation
2466 NLMISC_COMMAND(dumpWorld," dump the world organisation","")
2468 if (args.size() == 0)
2470 CZoneManager::getInstance().dumpWorld(log);
2471 return true;
2473 return false;
2476 NLMISC_COMMAND(dumpTpSpawnZones, "dump the tp spawn zones", "")
2478 if (args.size() == 0)
2480 CZoneManager::getInstance().dumpTpSpawnZones(log);
2481 return true;
2483 return false;
2487 addRegionTrigger uiR2_Jungle18 app_arcc action=mScript_Run&script=7624&command=reset_all
2489 NLMISC_COMMAND(addRegionTrigger,"add region trigger","<region_name> <app> <params>")
2491 if (args.size() == 3)
2493 CZoneManager::getInstance().addRegionTrigger(args[0], args[1]+" "+args[2]);
2494 return true;
2496 return false;