Add infos into target window
[ryzomcore.git] / ryzom / server / src / gpm_service / world_entity.cpp
blob304b072d2a7439dcdb1d7fa9ca1efc6b6f910f63
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "stdpch.h"
23 #include "world_entity.h"
24 #include "sheets.h"
25 #include "world_position_manager.h"
26 #include "gpm_service.h"
28 using namespace std;
29 using namespace NLMISC;
30 using namespace NLPACS;
32 #define DUMP_VAR(var) log->displayNL("%28s: %s", #var, toString(var).c_str());
33 #define DUMP_VARPTR(var) log->displayNL("%28s: %s", #var, toStringPtr(var).c_str());
35 /****************************************************************\
36 ****************************************************************
37 CWorldEntity
38 ****************************************************************
39 \****************************************************************/
41 // Static entity allocator
42 CBlockMemory<CWorldEntity> CWorldEntity::_EntityAllocator;
45 template<class T>
46 void registerEntityProperty(const string &propertyName, CMirrorPropValue1DS<T> *property, const CEntityId &id)
48 // TODO: optimize: use entity index instead of Id, prop index instead of name
49 property->init( TheDataset, id, propertyName );
53 /// Creates a new entity (new equivalent). This must be initialised later using init();
54 CWorldEntity* CWorldEntity::create()
56 CWorldEntity* entity = _EntityAllocator.allocate();
57 if (entity != NULL)
59 entity->ListIterator = CWorldPositionManager::_EntityList.insert(CWorldPositionManager::_EntityList.end(), entity);
60 entity->PrimIterator = CWorldPositionManager::_PrimitivedList.end();
62 return entity;
65 /// Removes an entity (delete equivalent).
66 void CWorldEntity::remove(CWorldEntity* entity)
68 CWorldPositionManager::_EntityList.erase(entity->ListIterator);
69 if (entity->PrimIterator != CWorldPositionManager::_PrimitivedList.end())
71 CWorldPositionManager::_PrimitivedList.erase(entity->PrimIterator);
73 _EntityAllocator.freeBlock(entity);
78 /****************************************************************\
79 init
80 \****************************************************************/
81 void CWorldEntity::init( const CEntityId& id, const TDataSetRow &index )
83 Id = id;
84 Index = index;
86 // Keep properties local for invisible group entities (aiVision).
87 // This is obsolete, as aiVision are not used anymore. Because these entities were not
88 // in mirror, their property values always stayed in temp storage. All the code was
89 // the same for aiVision and visible entities, i.e. we used the CMirrorPropValueAlice.
90 // Now the 'Alice' version is not needed anymore, because all entities go into
91 // registerEntityProperty().
92 // if ( Id.getType() != RYZOMID::aiVision )
93 // {
95 registerEntityProperty("X", &X, id);
96 registerEntityProperty("Y", &Y, id);
97 registerEntityProperty("Z", &Z, id);
98 registerEntityProperty("LocalX", &LocalX, id);
99 registerEntityProperty("LocalY", &LocalY, id);
100 registerEntityProperty("LocalZ", &LocalZ, id);
101 registerEntityProperty("Theta", &Theta, id);
102 registerEntityProperty("Sheet", &Sheet, id);
103 registerEntityProperty("TickPos", &Tick, id);
104 registerEntityProperty("Cell", &Cell, id);
105 registerEntityProperty("VisionCounter", &VisionCounter, id);
106 registerEntityProperty("WhoSeesMe", &WhoSeesMe, id);
107 if (Cell > 0)
109 nlwarning("Entity %s Cell is preset to %d which should be 0 or negative, forced to 0", id.toString().c_str(), Cell());
110 Cell = 0;
112 // }
113 // else
114 // Cell = -1;
116 //IsStaticObject = false;
117 //IsInvisible = false;
118 //IsAgent = false;
119 //IsTrigger = false;
120 //IsInvisibleToPlayer = false;
122 RefCounter = 0;
123 TickLock = 0;
125 TempVisionState = false;
126 TempControlInVision = false;
127 TempParentInVision = false;
129 HasVision = false;
131 Previous = NULL;
132 Next = NULL;
134 PlayerInfos = NULL;
136 Parent = NULL;
137 Control = NULL;
139 Dead = false;
141 PosInitialised = false;
142 Continent = INVALID_CONTINENT_INDEX;
143 MoveContainer = NULL;
144 Primitive = NULL;
145 UsePrimitive = false;
146 ForceUsePrimitive = false;
147 ForceDontUsePrimitive = false;
149 VisionCounter = (uint8)0x0;
150 PlayersSeeingMe = 0;
151 ClosestPlayer = NULL;
153 CellPtr = NULL;
155 PatatEntryIndex = 0;
157 if (id.getType() == RYZOMID::object )
159 _Type = Object;
161 else if (id.getType() == RYZOMID::player)
163 _Type = Player;
165 else if (id.getType() == RYZOMID::trigger)
167 _Type = Trigger;
169 else if ((id.getType() >= RYZOMID::bot_ai_begin) && (id.getType() <= RYZOMID::bot_ai_end))
171 _Type = AI;
173 else
175 _Type = Unknown;
179 // commented, now set by the EGS
180 //WhoSeesMe = 0xffffffff;
182 CheckMotion = true;
184 } // CWorldEntity constructor
186 /****************************************************************\
187 CWorldEntity destructor
188 \****************************************************************/
189 CWorldEntity::~CWorldEntity()
191 // the Primitive should have been removed in the UMoveContainer, and so is already deleted
193 } // CWorldEntity destructor
198 * Display debug
200 void CWorldEntity::display(NLMISC::CLog *log) const
202 if (this == NULL)
203 log->displayNL("CWorldEntity::display called on NULL");
205 log->displayNL("--- Display Entity %s E%u ---", Id.toString().c_str(), Index.getIndex());
207 DUMP_VAR(X());
208 DUMP_VAR(Y());
209 DUMP_VAR(Z());
210 DUMP_VAR(LocalX());
211 DUMP_VAR(LocalY());
212 DUMP_VAR(LocalZ());
213 DUMP_VAR(Theta());
214 DUMP_VAR(Sheet());
215 DUMP_VAR(Tick());
216 DUMP_VAR(Cell());
217 DUMP_VAR(VisionCounter());
218 DUMP_VAR(WhoSeesMe());
219 DUMP_VAR(PatatEntryIndex);
220 DUMP_VARPTR(CellPtr);
221 DUMP_VAR(PosInitialised);
222 DUMP_VAR(Continent);
223 DUMP_VARPTR(Primitive);
224 DUMP_VARPTR(MoveContainer);
225 DUMP_VAR(UsePrimitive);
226 DUMP_VAR(ForceUsePrimitive);
227 DUMP_VAR(ForceDontUsePrimitive);
228 DUMP_VAR(TickLock);
229 DUMP_VARPTR((CWorldEntity*)Previous);
230 DUMP_VARPTR((CWorldEntity*)Next);
231 DUMP_VARPTR((CWorldEntity*)Parent);
232 DUMP_VARPTR((CWorldEntity*)Control);
233 DUMP_VAR(HasVision);
234 DUMP_VAR(CheckMotion);
235 DUMP_VAR(TempVisionState);
236 DUMP_VAR(RefCounter);
238 log->displayNL("--- End of Display ---");
240 if (PlayerInfos != NULL)
241 PlayerInfos->display(log);
245 /****************************************************************\
246 create primitive for fiche type entity
247 \****************************************************************/
248 void CWorldEntity::createPrimitive(NLPACS::UMoveContainer *pMoveContainer, uint8 worldImage)
250 UMovePrimitive *primitive;
252 if (PrimIterator != CWorldPositionManager::_PrimitivedList.end())
254 CWorldPositionManager::_PrimitivedList.erase(PrimIterator);
255 PrimIterator = CWorldPositionManager::_PrimitivedList.end();
258 if (!UsePrimitive && !ForceUsePrimitive)
260 nlwarning("Entity %s asked to create a PACS primitive, whereas shouldn't not, abort", Id.toString().c_str());
261 return;
264 if (pMoveContainer == NULL)
266 nlwarning("pMoveContainer == NULL in createPrimitive()");
267 return;
270 // if a primitive already exists
271 if (Primitive != NULL)
273 // previous move container must not be null
274 if (MoveContainer == NULL)
276 nlwarning("MoveContainer == NULL in createPrimitive()");
277 return;
280 // check the previous move container is different (otherwise does not create a primitive)
281 if (MoveContainer == pMoveContainer)
282 return;
284 // depending on the type of the previous primitive, creates a copy of it
285 if (Primitive->isCollisionable())
287 primitive = pMoveContainer->addCollisionablePrimitive(CWorldPositionManager::_FirstDynamicWorldImage, CWorldPositionManager::_NbDynamicWorldImages, Primitive);
289 else
291 primitive = pMoveContainer->addNonCollisionablePrimitive(Primitive);
294 // removes previous primitive
295 MoveContainer->removePrimitive(Primitive);
297 // and set new one as entity primitive
298 Primitive = primitive;
299 MoveContainer = pMoveContainer;
301 if (Primitive == NULL)
303 MoveContainer = NULL;
304 nlwarning("Can't create PACS primitive for entity %s", Id.toString().c_str());
305 return;
308 PrimIterator = CWorldPositionManager::_PrimitivedList.insert(CWorldPositionManager::_PrimitivedList.end(), this);
310 // and leave...
311 return;
314 Primitive = NULL;
315 MoveContainer = NULL;
317 const CGpmSheets::CSheet *sheet = CGpmSheets::lookup(CSheetId(Sheet()));
319 float primRadius = 0.5f;
320 float primHeight = 2.0f;
322 if (sheet != NULL)
324 primRadius = sheet->Radius * sheet->Scale;
325 primHeight = sheet->Height * sheet->Scale;
328 primitive = pMoveContainer->addNonCollisionablePrimitive();
330 if (primitive == NULL)
332 nlwarning("Can't create PACS primitive for entity %s", Id.toString().c_str());
333 return;
335 primitive->UserData = ((uint64)(Index.getIndex()) << 16);
336 //nldebug("Set entity E%u to %" NL_I64 "d", Index.getIndex(), primitive->UserData);
337 primitive->setPrimitiveType( UMovePrimitive::_2DOrientedCylinder );
338 primitive->setReactionType( UMovePrimitive::Slide );
339 primitive->setTriggerType( UMovePrimitive::NotATrigger );
340 primitive->setCollisionMask( 0xffffffff );
341 primitive->setOcclusionMask( 0x00000000 );
342 primitive->setObstacle( false );
343 primitive->setAbsorbtion( 0 );
344 primitive->setHeight( primHeight );
345 primitive->setRadius( primRadius-0.1f ); // decrease primitive usable radius to lessen pacs load (avoid collision test)
347 Primitive = primitive;
348 MoveContainer = pMoveContainer;
350 PrimIterator = CWorldPositionManager::_PrimitivedList.insert(CWorldPositionManager::_PrimitivedList.end(), this);
353 /****************************************************************\
354 removePrimitive
355 \****************************************************************/
356 void CWorldEntity::removePrimitive()
358 if (PrimIterator != CWorldPositionManager::_PrimitivedList.end())
360 CWorldPositionManager::_PrimitivedList.erase(PrimIterator);
361 PrimIterator = CWorldPositionManager::_PrimitivedList.end();
364 if (MoveContainer != NULL && Primitive != NULL)
366 MoveContainer->removePrimitive(Primitive);
367 Primitive = NULL;
368 MoveContainer = NULL;
370 else if (MoveContainer != NULL && Primitive == NULL || MoveContainer == NULL && Primitive != NULL)
372 nlwarning("Entity %s asked to remove PACS primitive, unable to continue (MoveContainer=%p, Primitive=%p)", Id.toString().c_str(), MoveContainer, Primitive);
378 /****************************************************************\
379 updatePositionUsingMovePrimitive
380 \****************************************************************/
381 void CWorldEntity::updatePositionUsingMovePrimitive(uint wi)
383 if (Primitive == NULL || Continent == INVALID_CONTINENT_INDEX || Continent == NO_CONTINENT_INDEX)
384 return;
386 NLPACS::UGlobalRetriever *retriever = CWorldPositionManager::getContinentContainer().getRetriever(Continent);
388 if (retriever == NULL)
389 return;
391 NLPACS::UGlobalPosition gp;
392 Primitive->getGlobalPosition(gp, wi);
394 bool interior = retriever->isInterior(gp);
395 bool local = localMotion();
397 float dummy;
398 bool water = retriever->isWaterPosition(gp, dummy);
400 NLMISC::CVectorD pos = Primitive->getFinalPosition(wi);
402 setPosition((sint32)(pos.x*1000), (sint32)(pos.y*1000), (sint32)(pos.z*1000), local, interior, water);
409 /****************************************************************\
410 ****************************************************************
411 CPlayerInfos
412 ****************************************************************
413 \****************************************************************/
415 // Static player allocator
416 CBlockMemory<CPlayerInfos> CPlayerInfos::_PlayerAllocator;
419 void CPlayerInfos::display(CLog *log) const
421 if (this == NULL)
422 log->displayNL("CPlayerInfos::display called on NULL");
424 log->displayNL("--- Display PlayerInfos %s E%u ---", _PlayerId.toString().c_str(), (Entity != NULL ? Entity->Index.getIndex() : 0));
426 DUMP_VAR(FeId.get());
427 DUMP_VAR(LastVisionTick);
428 DUMP_VAR(DelayVision);
429 DUMP_VAR(ActivateSlot0);
430 DUMP_VAR(DesactivateSlot0);
431 DUMP_VAR(Slot0Active);
432 DUMP_VAR(WhoICanSee);
434 #ifdef RECORD_LAST_PLAYER_POSITIONS
436 log->displayNL("Last positions recorded:");
437 uint i;
438 for (i=0; i<DistanceHistory.size(); ++i)
439 log->displayNL("(%+9.3f,%+9.3f,%+9.3f) %d ticks", DistanceHistory[i].first.x, DistanceHistory[i].first.y, DistanceHistory[i].first.z, DistanceHistory[i].second);
441 #endif
443 log->displayNL("--- End of Display ---");