// 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 .
#ifndef NL_WORLD_ENTITY_H
#define NL_WORLD_ENTITY_H
#include "nel/misc/types_nl.h"
#include "nel/misc/block_memory.h"
#include "nel/misc/debug.h"
#include "nel/misc/time_nl.h"
#include "nel/pacs/u_move_container.h"
#include "nel/pacs/u_move_primitive.h"
#include "gpm_utilities.h"
#include "gpm_defs.h"
#include "game_share/mirror_prop_value.h"
#include "game_share/ryzom_mirror_properties.h"
#include "server_share/msg_gpm_service.h"
#include
class CCell;
class CPlayerInfos;
class CWorldEntity;
typedef std::list TWorldEntityList;
struct CVisionEntry
{
CVisionEntry() { }
CVisionEntry(CWorldEntity* e, uint32 m, uint32 d) : Entity(e), Mask(m), Distance(d) { }
CWorldEntity* Entity;
uint32 Mask;
uint32 Distance;
};
/**
* World entity contained all properties positions in world for an entity
* \author Alain Saffray
* \author Nevrax France
* \date 2002
*/
class CWorldEntity
{
friend class NLMISC::CBlockMemory;
public:
typedef CSimpleSmartPointer CWorldEntitySmartPointer;
enum TEntityType
{
Player = 0,
Object,
Trigger,
AI,
Unknown
};
/*
enum TVisionState // Enum of vision state for this entity
{
Ready = 0, // ready to use
Checked, // in check
Seen, // entity is seen by another
};
*/
public:
NLMISC::CEntityId Id; // Id of entity
TDataSetRow Index;
CMirrorPropValue1DS X; // Coordinate X in world in unit
CMirrorPropValue1DS Y; // Coordinate Y in world in unit
CMirrorPropValue1DS Z; // Coordinate Z in world in unit
CMirrorPropValue1DS LocalX; // Local Coordinate X in world in unit
CMirrorPropValue1DS LocalY; // Local Coordinate X in world in unit
CMirrorPropValue1DS LocalZ; // Local Coordinate X in world in unit
CMirrorPropValue1DS Theta; // Heading in world
CMirrorPropValue1DS Sheet; // Id sheet of entity
CMirrorPropValue1DS Tick; // GameCycle of other properties
CMirrorPropValue1DS Cell; // Current XY Cell where entity is
CMirrorPropValue1DS VisionCounter; // Number of times this entity is seen by players
uint32 PlayersSeeingMe;
CWorldEntity* ClosestPlayer;
CMirrorPropValue1DS WhoSeesMe;
uint32 PatatEntryIndex; // The patat entry for the _PatatSubscribeManager
CCell *CellPtr; // pointer on cell where entity is
TWorldEntityList::iterator ListIterator; // Iterator on entity in world entity list
TWorldEntityList::iterator PrimIterator; // Iterator on entity in prmitived entity list
uint8 Continent; // index on the continent on which the player is located
bool PosInitialised; // Pos was initialised by mirror
bool UsePrimitive; // entity uses a primitive normally
bool ForceUsePrimitive; // forces entity to use a primitive temporarily (mount, etc.)
NLPACS::UMovePrimitive *Primitive; // Primitive for collision systeme (PACS)
NLPACS::UMoveContainer *MoveContainer; // MoveContainer entity is in
uint32 TickLock;
CWorldEntitySmartPointer Previous;
CWorldEntitySmartPointer Next;
CPlayerInfos *PlayerInfos; // The player infos associated to this entity (if there is some)
CWorldEntitySmartPointer Parent; // Which is entity we are in/on (ex: mount, ferry)
std::vector Children; // Which are the child we contain
CWorldEntitySmartPointer Control; // Which entity is controlling us (ex: rider, pilot...)
bool ForceDontUsePrimitive; // forces entity not to use a primitive temporarily (mount, etc.)
bool CheckMotion;
bool HasVision; // Entity has vision
std::vector Content;
bool TempVisionState; // temporary flag for vision delta, telling if the entity is now visible
bool TempControlInVision; // temporary flag for vision delta, telling if the controller entity (if any) is in vision
bool TempParentInVision; // temporary flag for vision delta, telling if the parent (controlled) entity (if any) is in vision
sint32 RefCounter; // Number of references on this entity -- used by smart pointer
public:
/**
* destructor
*/
~CWorldEntity();
/**
* Init
* \param id is entity's CEntityId
*/
void init( const NLMISC::CEntityId& id, const TDataSetRow &index );
/**
* Display debug
*/
void display(NLMISC::CLog *log = NLMISC::InfoLog) const;
/**
* create primitive for fiche type entity
* \param ficheId is sheet type Id of entity
* \param pMoveContainer adress of the move container
* \param worldImage numvber of the world image in which the primitive is to be inserted
* \return pointer on PACS primitve
*/
void createPrimitive(NLPACS::UMoveContainer *pMoveContainer, uint8 worldImage);
/**
* Removes primitive allocated previously
*/
void removePrimitive();
/**
* removes entity from the cell it is in
*/
//void removeFromCellAsEntity();
/**
* removes object from the cell it is in
*/
//void removeFromCellAsObject();
/// Test if entity is linked in a cell
bool isLinked() const { return CellPtr != NULL; }
/// Get (const) CCell point in which entity is
const CCell* getCell() const { return CellPtr; }
/// Tests if entity uses a pacs primitive
bool hasPrimitive() const { return Primitive != NULL && !ForceDontUsePrimitive; }
/// local motion
bool localMotion() const { return Parent != NULL; }
/// has control ?
bool hasControl() const { return Parent != NULL && Parent->Control == this; }
/// is controlled ?
bool isControlled() const { return Control != NULL; }
/// has children
bool hasChildren() const { return !Children.empty(); }
/// remove from children
void removeFromChildren(CWorldEntity *entity)
{
std::vector::iterator it;
for (it=Children.begin(); it!=Children.end(); ++it)
if ((CWorldEntity*)(*it) == entity)
it = Children.erase(it);
entity->Parent = NULL;
Control = NULL;
}
/// get controlled
CWorldEntity *getControlled()
{
if (!hasControl())
return NULL;
CWorldEntity *parent = Parent;
while (parent->hasControl())
parent = parent->Parent;
return parent;
}
/// update local or global position
void updatePosition(sint32 x, sint32 y, sint32 z, float theta, NLMISC::TGameCycle cycle, bool interior, bool water)
{
if (localMotion())
{
LocalX = x;
LocalY = y;
LocalZ = z;
setPosition(x + Parent->X(), y + Parent->Y(), z + Parent->Z(), true, interior, water);
}
else
{
setPosition(x, y, z, false, interior, water);
}
Tick = cycle;
Theta = theta;
// force position as valid
PosInitialised = true;
}
/// update global position for local motion
void updatePosition(bool interior, bool water)
{
if (localMotion())
{
setPosition(LocalX() + Parent->X(), LocalY() + Parent->Y(), LocalZ() + Parent->Z(), true, interior, water);
}
}
/// Set position
void setPosition(sint32 x, sint32 y, sint32 z, bool local, bool interior, bool water)
{
X = x;
Y = y;
Z = (z&(~7)) + (local ? 1 : 0) + (interior ? 2 : 0) + (water ? 4 : 0);
}
/// update position using move primitive
void updatePositionUsingMovePrimitive(uint wi);
/// get Type of the entity
TEntityType getType() const
{
return _Type;
}
private:
/// Is in interior
bool interior() const
{
return (Z()&2) != 0;
}
/// Type of the entity
TEntityType _Type;
public:
/// Creates a new entity (new equivalent). This must be initialised later using init();
static CWorldEntity* create();
/// Removes an entity (delete equivalent).
static void remove(CWorldEntity *entity);
protected:
/**
* Default constructor, used because of CBlockMemory
*/
CWorldEntity() {}
private:
/// Static cell allocator
static NLMISC::CBlockMemory _EntityAllocator;
};
//
typedef CWorldEntity::CWorldEntitySmartPointer CWorldEntityPtr;
/// A list of CWorldEntity, referred by smart pointers. First template param is the pointed type, second param is the pointer storage type (here smart pointer)
typedef CObjectList TEntityList;
/**
* Player Infos : contains all information specific to players (like vision and original front end)
* \author David Fleury
* \author Nevrax France
* \date 2002
*/
class CPlayerInfos
{
friend class NLMISC::CBlockMemory;
public:
/// init
void init(const NLMISC::CEntityId &id, NLNET::TServiceId feId, CWorldEntity *entity)
{
WhoICanSee = 0xffffffff;
Next = NULL;
Previous = NULL;
ActivateSlot0 = false;
DesactivateSlot0 = false;
Slot0Active = false;
uint i;
for (i = MAX_SEEN_ENTITIES-1 ; i > 0; --i)
FreeSlots.push_back( i );
for (i = 0 ; i < MAX_SEEN_ENTITIES ; ++i)
Slots[i] = NULL;
LastVisionTick = 0;
_PlayerId = id;
FeId = feId;
Entity = entity;
CheckSpeed = true;
EnableVisionProcessing = true;
}
/// get playerId
inline const NLMISC::CEntityId &getPlayerId() const { return _PlayerId; }
/**
* Display debug
*/
void display(NLMISC::CLog *log = NLMISC::InfoLog) const;
private:
/// the player Id
NLMISC::CEntityId _PlayerId;
/// default constructor
CPlayerInfos() { }
public:
/// original front end Id
NLNET::TServiceId FeId;
/// front end datas
TMapFrontEndData::iterator ItFrontEnd;
/// iterator in the update player list
TPlayerList::iterator ItUpdatePlayer;
/// tick at last vision update
NLMISC::TGameCycle LastVisionTick;
/// Delay vision till cycle
NLMISC::TGameCycle DelayVision;
///
typedef CUnsafeConstantSizeStack TSlotStack;
/// list of free slots for vision
TSlotStack FreeSlots;
/// The world entity for this player
CWorldEntityPtr Entity;
/// Previous player in list
CPlayerInfos* Previous;
/// Next player in list
CPlayerInfos* Next;
/// slots for this player
CWorldEntityPtr Slots[MAX_SEEN_ENTITIES];
bool ActivateSlot0;
bool DesactivateSlot0;
bool Slot0Active;
bool EnableVisionProcessing;
bool CheckSpeed;
/// Who I can see flag field
uint32 WhoICanSee;
#ifdef RECORD_LAST_PLAYER_POSITIONS
/// Distance history
std::deque< std::pair > DistanceHistory;
#endif
float meanSpeed() const
{
#ifdef RECORD_LAST_PLAYER_POSITIONS
float dist = 0.0f;
uint i;
for (i=0; i+1 1 ? (dist/(DistanceHistory.size()-1)) : 0.0f;
#else
return 0.0f;
#endif
}
struct CPlayerPos
{
NLMISC::TGameCycle AtTick;
NLPACS::UGlobalPosition GPos;
NLMISC::CVectorD Motion;
float Theta;
};
std::deque PosHistory;
public:
/// Creates a new entity (new equivalent). This must be initialised later using init();
static CPlayerInfos *create() { return _PlayerAllocator.allocate(); }
/// Removes an entity (delete equivalent).
static void remove(CPlayerInfos *player) { _PlayerAllocator.free(player); }
private:
/// Static cell allocator
static NLMISC::CBlockMemory _PlayerAllocator;
};
#endif // NL_WORLD_ENTITY_H
/* End of world_entity.h */