/* core/entity.h This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2. */ #ifndef __INCLUDED_CORE_ENTITY_H__ #define __INCLUDED_CORE_ENTITY_H__ #include #include #include #include #include "core/level.h" #include "model/model.h" #include "math/axis.h" #include "math/mathlib.h" namespace core { class Entity; class EntityControlable; } #include "core/extension.h" #include "core/descriptions.h" #include "core/inventory.h" #include "core/label.h" #include "core/physics.h" #include "core/player.h" #include "core/slots.h" #include "core/zone.h" namespace core { /** * @brief The base world entity. All gameworld entities must derive from this class. * */ class Entity : public Label { friend class Extension; public: /** * @brief entity flags * NonSolid will exclude the entity from the bullet physics world * Bright is used by EntityGlobe, where a bright sphere is a light source * Dockable means the entity can be docked by a player * ShowOnMap will make the entity appear on the map * KeepAlive is used by EntityDynamic and marks the entity as deletable in the keepalive run * */ enum Flags { NonSolid = 2, Bright = 4, Dockable = 8, ShowOnMap = 16, KeepAlive = 32 }; /** * @brief Entity type constants * @see Entity::type() * */ enum Type { Default = 0, Dynamic = 1, Controlable = 2, Globe = 3, Projectile = 4 }; /** * @brief Entity shape constants * @see Entity::shape() * */ enum Shape { Diamond = 0, Sphere = 1, Cube = 2, Axis = 3 }; /** * @brief EntityDynamic state constants * @see EntityDynamic::state() * */ enum State { Normal = 0, NoPower = 1, ImpulseInitiate = 2, Impulse = 3, JumpInitiate = 4, Jump = 5, Docked = 6, Destroyed = 7 }; /** * @brief entity menu collection type definition * */ typedef std::list Menus; /** * @brief entity bullet shapes collection type definition * */ typedef std::list CollisionShapes; /** * @brief server-side constructor * create a new entity and add it to the registry * */ Entity(); /** * @brief client-side constructor * create an entity from stream data * */ Entity(std::istream & is); /** * @brief destructor * */ virtual ~Entity(); /** * @brief print information about the entity * */ virtual void print() const; /** * @brief print information header * */ virtual void print_header() const; /** * @brief print inventory if available * */ virtual void print_inventory() const; /*----- inspectors ------------------------------------------------ */ /// entity id inline const unsigned int id() const { return entity_id; } /// module type id inline const unsigned int moduletype() const { return entity_moduletypeid; } /// core type id virtual inline const unsigned int type() const { return Default; } /// entity flags inline const unsigned int flags() const { return entity_flags; } /// returns true of a flag is set inline const bool has_flag(const Flags flag) const { return ((entity_flags & (unsigned int)flag) == (unsigned int)flag); } /// pointer to the model, is used client-side inline model::Model * model() const { return entity_model; } /// modelname inline const std::string & modelname() const { return entity_modelname; } /// pointer to the zone the entity belongs to inline Zone *zone() const { return entity_zone; } /// the zone the entity left in case of a zone change inline Zone *oldzone() const { return entity_oldzone; } /// dirty flag inline bool dirty() const { return entity_dirty; } /// entity location inline const math::Vector3f& location() const { return entity_location; } /// local coordinates system of the entity inline const math::Axis& axis() const { return entity_axis; } /// primary entity color inline const math::Color& color() const { return entity_color; } /// secondary entity color inline const math::Color& color_second() const { return entity_color_second; } /// base shape of the entity inline const Shape shape() const { return entity_shape; } /// base radius of the entity inline const float radius() const { return entity_radius; } /** * @brief current entity level * */ inline const Level level() const { return entity_level; } /** * @brief current speed of the entity in game units per second * For a normal entity, speed is always 0. Use the EntityDynamic * and EntityControlable classes to create moving entities */ inline const float speed() const { return entity_speed; } /// physics body inline btRigidBody *body() { return entity_body; } /// physics collision shape inline btCollisionShape *collision_shape() { return entity_collision_shape; } /** * @brief physics collision child shapes * if the collision_shape is not a btcompoundShape, * this set will be empty **/ inline CollisionShapes & collision_child_shapes() { return entity_collision_child_shapes; } /// indicates a server-side entity inline const bool serverside() const { return entity_serverside; } /// general visibility inline const bool visible() const { return entity_visible; } /// entity inventory inline Inventory *inventory() const { return entity_inventory; } /// entity weapon slots inline Slots *slots() const { return entity_slots; } /// entity information record inline const Info *info() const { return entity_info; } /// entity menus inline Menus &menus() { return entity_menus; } /// extensions inline Extension *extension(size_t type) const { return entity_extension[type]; } /// find a menu MenuDescription *find_menu(const std::string &label); /// true if the entity is to be deleted inline const bool died() const { return entity_died; } /// time when the entity was last alive inline const unsigned long keepalive() const { return entity_keepalive; } inline const Info *faction() const { return entity_faction; } /* ---- mutators -------------------------------------------------- */ /// assign shape inline void set_shape(Shape shape) { entity_shape = shape; } /// assign entity color inline void set_color(const math::Color &color) { entity_color.assign(color); } /// assign entity secondary color inline void set_color_second(const math::Color &color) { entity_color_second.assign(color); } /** * @brief set dirty flag * setting the dirty flag will cause the server to broadcast changes * to the clients. */ inline void set_dirty(const bool dirty = true) { entity_dirty = dirty; } /** * @brief mark the entity as dead * die() should be called by the game module when it needs to destroy an entity, * the game server will broadcast the delete event to the clients. * The game module should not delete entities directly. */ virtual void die(); /** * @brief runs one game frame for the entity * The default implementation does nothing * @param elapsed elepased time since previous frame, in milliseconds */ virtual void frame(const unsigned long elapsed); /** * @brief runs one upkeep frame for the entity * The upkeep frame will be executed by the engine if the entity has the KeepAlive flag set * and the keepalive timeout has been elapsed. * The default implementation does nothing * @param timestamp game timestamp for the current upkeep frame */ virtual void upkeep(const unsigned long timestamp); /** * @brief set the zone the entity is currently in * this fuction removes the entity from its previous zone * and removes it to the new one, if it is not 0 */ virtual void set_zone(Zone *zone); /** * @brief set the entity level * */ inline void set_level(const Level level) { entity_level = level; } /// set visibility inline void set_visible(const bool visible = true) { entity_visible = visible; } /// set as server-side entity inline void set_serverside(const bool serverside = true) { entity_serverside = serverside; } /// set the model name and load the model void set_modelname(const std:: string &model); /// set the model void set_model(model::Model *model); /// set entity radius inline void set_radius(const float radius) { entity_radius = radius; } /// set location inline void set_location(const math::Vector3f &location) { entity_location.assign(location); } /// set location inline void set_axis(const math::Axis &axis) { entity_axis.assign(axis); } /** * @brief set flag * */ inline void set_flag(Flags flag) { entity_flags |= (unsigned int) flag; } /** * @brief unset flag * */ inline void unset_flag(Flags flag) { entity_flags &= ~((unsigned int) flag); } /** * @brief set flags * */ inline void set_flags(unsigned int flags) { entity_flags = flags; } /** * @brief add an inventory to this entity * If this entity already has an inventory, * the current inventory will be return * */ Inventory *add_inventory(); /** * @brief add equipment slots to this entity * If this entity already has slots, * the current slots will be returned. * */ Slots *add_slots(); /** * @brief set the information record for this entity * */ void set_info(const Info *info); /** * @brief set the timestamp when the entity was last alive * */ inline void set_keepalive(unsigned long timestamp) { entity_keepalive = timestamp; } /** * @brief set the faction this entity belongs to. * */ inline void set_faction(const Info *faction) { entity_faction = faction; } /* ---- actors ---------------------------------------------------- */ /** * @brief reset the physics state */ virtual void reset(); /// add an entity menu void add_menu(MenuDescription *menu); /// remove an entity menu void remove_menu(std::string const &label); /// clear all update flags virtual void clear_updates(); /** * @brief mutable reference to the location */ inline math::Vector3f& get_location() { return entity_location; } /** * @brief mutable reference to the axis */ inline math::Axis& get_axis() { return entity_axis; } /** * @brief mutable reference to the primary color */ inline math::Color& get_color() { return entity_color; } /** * @brief mutable reference to the secondary color */ inline math::Color& get_color_second() { return entity_color_second; } /* ---- deserializers -------------------------------------- */ /// receive a client-to-server update from a stream virtual void receive_client_update(std::istream &is); /// receive a server-to-client create from a stream virtual void receive_server_create(std::istream &is); /// receive a server-to-client update from a stream virtual void receive_server_update(std::istream &is); /* ---- serializers ---------------------------------------- */ /// serialize the entity to a stream virtual void serialize_server_create(std::ostream & os) const; /// serialize a client-to-server update on a stream virtual void serialize_client_update(std::ostream & os) const; /// serialize a server-to-client update on a stream virtual void serialize_server_update(std::ostream & os) const; /* ---- static --------------------------------------------- */ /// default infotype for entities static inline const InfoType *infotype() { return entity_infotype; } /// set the default infotype for entities static inline void set_infotype(const InfoType *infotype) { entity_infotype = infotype; } /// type definition for the entity registry typedef std::map Registry; /// find an entity in the registry static Entity *find(unsigned int id); /// find an entity in the registry static Entity *find(Entity * entity); /// add an entity to the registry static void add(Entity *ent, unsigned int it); /// erase an entity from the registry and delete it static void erase(unsigned int entity_id); /// print the list header static void list_header(); /// list the entity registry static void list(const Entity *entity); /// list the entity registry static void list(); /// clear the entity registry static void clear(); /// the entity registry static inline Registry & registry() { return entity_registry; } /** * @brief game module type id * this id can be assigned by the game module * */ unsigned int entity_moduletypeid; bool entity_created; bool entity_died; /// timestamp when entity data was received from the server float entity_servertimestamp; protected: btRigidBody *entity_body; btRigidBody::btRigidBodyConstructionInfo *entity_body_info; // the main bullet collision shape for this entity btCollisionShape *entity_collision_shape; // bullet collision child shapes for this entity, CollisionShapes entity_collision_child_shapes; // the zone the entity belongs to Zone* entity_zone; // the previous zone the entity belonged too Zone* entity_oldzone; float entity_speed; private: unsigned int entity_id; unsigned int entity_flags; bool entity_dirty; bool entity_visible; bool entity_serverside; math::Vector3f entity_location; math::Axis entity_axis; float entity_radius; Shape entity_shape; math::Color entity_color; math::Color entity_color_second; Level entity_level; std::string entity_modelname; model::Model* entity_model; Menus entity_menus; Inventory* entity_inventory; Slots* entity_slots; const Info* entity_info; Extension* entity_extension[4]; unsigned long entity_keepalive; const Info *entity_faction; static Registry entity_registry; static size_t entity_nextid; static void add(Entity *ent); static const InfoType *entity_infotype; }; /// an entity that can move around in the game world class EntityDynamic : public Entity { public: /// create a dynamic entity EntityDynamic(); /// create a dynamic entity from stream data EntityDynamic(std::istream & is); virtual ~EntityDynamic(); /*----- inspectors ------------------------------------------------ */ /** * @brief print information about the entity * */ virtual void print() const; /// core type id virtual inline const unsigned int type() const { return Entity::Dynamic; } /// event state inline const int state() const { return entity_state; } /// mass of the entity inline const float mass() const { return entity_mass; } /// event state timer inline const float timer() const { return entity_timer; } /// physics motion info inline btMotionState *motionstate() { return entity_motionstate; } /*----- mutators -------------------------------------------------- */ /// mass of the entity inline void set_mass(const float mass) { entity_mass = mass; } /// current speed of the entity in game units per second inline void set_speed(const float speed) { entity_speed = speed; } /*----- serializers ----------------------------------------------- */ /// serialize the entity to a stream virtual void serialize_server_create(std::ostream & os) const; /// serialize a client-to-server update on a stream virtual void serialize_client_update(std::ostream & os) const ; /// serialize a server-to-client update on a stream virtual void serialize_server_update(std::ostream & os) const; /*----- mutators -------------------------------------------------- */ /// receive a client-to-server update from a stream virtual void receive_client_update(std::istream &is); /// receive a server-to-client create from a stream virtual void receive_server_create(std::istream &is); /// receive a server-to-client update from a stream virtual void receive_server_update(std::istream &is); /// set event state virtual void set_state(int state); /** * @brief runs one game frame for the entity * The default implementation will update the position() of the entity, * determined by its speed() and axis() * @param elapsed elepased time since previous frame, in milliseconds */ virtual void frame(const unsigned long elapsed); /** * @brief reset the physics state */ virtual void reset(); /** * @brief nudge the entity out of the radius of other entities in its current zune * @param randomize if false, nudge according to axus.forward(), if false, nudge along a random axis */ void nudge(const bool randomize = true); /** * @brief physics collision callback * This funcion is called by the physics engine if the entity collides with another entity. * It can be implemented by game child classes to provide collision effects and feedback. * If the collision happens between two EntityDynamic instances (or subclasses thereof) * the method will be called on each collision partner. * Warning: this can be called multiple times for a single collision * */ virtual void collision(Entity *other); /** * @brief weapon hit callback * This method is called by the core-engine if the entity is hit by a weapon. * */ virtual void hit(Entity *other); protected: float entity_mass; float entity_timer; int entity_state; btMotionState *entity_motionstate; }; /// an entity that can be controlled by a player class EntityControlable : public EntityDynamic { friend class Player; public: /// control flags enum ControlFlags {ControlFlagNone = 0, ControlFlagFire = 1, ControlFlagOverride = 2}; /// bullet action interface class class ActionInterface: public btActionInterface { public: ActionInterface(EntityControlable *entity); virtual ~ActionInterface(); virtual void updateAction( btCollisionWorld* collisionWorld, btScalar deltaTimeStep); virtual void debugDraw(btIDebugDraw* debugDrawer); private: EntityControlable *actioninterface_entity; }; /// server-side constructor, create a controlable entity EntityControlable(); /// create a controlable entity from stream data EntityControlable(std::istream & is); virtual ~EntityControlable(); /*----- inspectors ------------------------------------------------ */ /// core type id virtual inline const unsigned int type() const { return Entity::Controlable; } /// owner of this entity inline Player *owner() const { return entity_owner; } /// thrust inline float thrust() const { return entity_thrust; } /// physics action inline ActionInterface *actioninterface() { return entity_actioninterface; } /** * @brief current health, 0 - 100 * */ inline const float health() const { return entity_health; } /** * @brief returns true if a specified control flag is set * */ inline const bool has_target_controlflag(ControlFlags controlflag) const { return ((target_controlflags & controlflag) == controlflag); } inline const math::Vector3f &aim() const { return target_aim; } /*----- serializers ----------------------------------------------- */ /// serialize the entity to a stream virtual void serialize_server_create(std::ostream & os) const; /// serialize a client-to-server update on a stream virtual void serialize_client_update(std::ostream & os) const; /// serialize a server-to-client update on a stream virtual void serialize_server_update(std::ostream & os) const; /*----- mutators -------------------------------------------------- */ /// set the target thrust void set_target_thrust(float thrust); /// set the target direction void set_target_direction(float direction); /// set the target pitch void set_target_pitch(float pitch); /// set target roll void set_target_roll(float roll); /// set target strafe void set_target_strafe(float strafe); /// set target vertical strafe void set_target_vstrafe(float vstrafe); /// set target afterburner/reverse void set_target_afterburner(float afterburner); /// set target aim void set_target_aim(const math::Vector3f &aim); /// set target controlflags void set_target_controlflags(int controlflags); /// set target control flags void set_target_controlflag(const ControlFlags controlflag); /// unset target control flag void unset_target_controlflag(const ControlFlags controlflag); /** * @brief set the zone the entity is currently in * this fuction removes the entity from its previous zone * and removes it to the new one, if it is not 0 * */ virtual void set_zone(Zone *zone); /** * @brief reset the physics state */ virtual void reset(); /// receive a client-to-server update from a stream virtual void receive_client_update(std::istream &is); /// receive a server-to-client create from a stream virtual void receive_server_create(std::istream &is); /// receive a server-to-client update from a stream virtual void receive_server_update(std::istream &is); /** * @brief set the player who owns this entity * */ void set_owner(Player *owner); /** * @brief set thrust * */ void set_thrust(float thrust); protected: /// physics action interface callback virtual void action (btScalar seconds); /// current thrust float entity_thrust; /// current health float entity_health; /* target_ variables can be set by the client */ /** * @brief target thrust as set by the client */ float target_thrust; /** * @brief target direction as set by the client * target_direction must be in the [-1, 1] range */ float target_direction; /** * @brief target pitch as set by the client * target_pitch must be in the [-1, 1] range */ float target_pitch; /** * @brief target roll as set by the client * target_roll must be in the [-1, 1] range */ float target_roll; float target_afterburner; float target_strafe; float target_vstrafe; math::Vector3f target_aim; int target_controlflags; ActionInterface *entity_actioninterface; private: /// owner of the entity Player *entity_owner; }; } // namespace core #endif // __INCLUDED_CORE_ENTITY_H__