From 3318b29475ffc5f462e2926f9b1141beca8305ae Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 25 Nov 2012 21:25:40 +0000 Subject: Added core::Entity::Projectile. --- src/core/Makefile.am | 2 + src/core/entityprojectile.cc | 264 +++++++++++++++++++++++++++++++++++++++++++ src/core/entityprojectile.h | 146 ++++++++++++++++++++++++ 3 files changed, 412 insertions(+) create mode 100644 src/core/entityprojectile.cc create mode 100644 src/core/entityprojectile.h (limited to 'src/core') diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 6f2a505..1a7c0ac 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -11,6 +11,7 @@ noinst_HEADERS = \ descriptions.h \ entity.h \ entityglobe.h \ + entityprojectile.h \ extension.h \ func.h \ gameconnection.h \ @@ -46,6 +47,7 @@ libcore_la_SOURCES = \ descriptions.cc \ entity.cc \ entityglobe.cc \ + entityprojectile.cc \ extension.cc \ func.cc \ gameconnection.cc \ diff --git a/src/core/entityprojectile.cc b/src/core/entityprojectile.cc new file mode 100644 index 0000000..8c6c57b --- /dev/null +++ b/src/core/entityprojectile.cc @@ -0,0 +1,264 @@ +/* + core/entityprojectile.cc + This file is part of the Osirion project and is distributed under + the terms and conditions of the GNU General Public License version 2 +*/ + +#include "core/entityprojectile.h" +#include "core/application.h" +#include "math/functions.h" +#include "sys/sys.h" + +#include + +namespace core +{ + +EntityProjectile::EntityProjectile() : EntityDynamic() +{ + set_label("projectile"); + set_flag(Entity::KeepAlive); + set_shape(Entity::Sphere); + set_radius(0.01f); + set_mass(radius()); + + projectile_damage = 0.0f; + projectile_lifespan = 0.0f; + projectile_ownerid = 0; + projectile_timestamp = game()->timestamp(); +} + +EntityProjectile::EntityProjectile(std::istream & is) : EntityDynamic(is) +{ + set_label("projectile"); + set_flag(Entity::KeepAlive); + set_shape(Entity::Sphere); + set_radius(0.01f); + set_mass(radius()); + + projectile_damage = 0.0f; + projectile_lifespan = 0.0f; + projectile_ownerid = 0; + projectile_timestamp = game()->timestamp(); +} + +EntityProjectile::~EntityProjectile() +{ + +} + +void EntityProjectile::upkeep(const unsigned long timestamp) +{ + die(); +} + +void EntityProjectile::collision(Entity *other) +{ + if (state() == Entity::Destroyed) { + return; + } + + set_state(Entity::Destroyed); + // this method is a bullet callback, we can not reset() here +} + +void EntityProjectile::frame(const unsigned long elapsed) +{ + // transfer bullet state to entity state + // do not set_dirty() as movement will be handled client-side + if (entity_body) { + body()->setLinearVelocity(math::to_btVector3(axis().forward() * speed())); + + btTransform t; + entity_motionstate->getWorldTransform(t); + get_location().assign(t.getOrigin()); + get_axis().assign(t.getBasis()); + //entity_speed = (float) entity_body->getLinearVelocity().length(); + + } + + if (projectile_timestamp + projectile_lifespan < game()->timestamp()) { + set_state(Entity::Destroyed); + set_speed(0.0f); + set_dirty(); + } + + if (state() == Entity::Destroyed) { + die(); + } +} + +void EntityProjectile::reset() +{ + // no bullet physics on NonSolid entities + if (!radius() || has_flag(NonSolid)) { + return; + } + + // remove Docked and Destroyed entities from the physics simulation + if (destroyed() || (state() == Entity::Docked) || (state() == Entity::Destroyed)) { + + if (entity_body) { + + if (entity_motionstate) { + delete entity_motionstate; + entity_motionstate = 0; + } + + if (zone() && zone()->physics()) { + entity_zone->physics()->removeRigidBody(body()); + } + + if (entity_collision_shape) { + delete entity_collision_shape; + entity_collision_shape = 0; + } + + for (CollisionShapes::iterator sit = entity_collision_child_shapes.begin(); sit != entity_collision_child_shapes.end(); sit++) { + delete (*sit); + (*sit) = 0; + } + entity_collision_child_shapes.clear(); + + if (entity_body) { + delete entity_body; + entity_body = 0; + } + + if (entity_body_info) { + delete entity_body_info; + entity_body_info = 0; + } + } + + return; + } + + // location and orientation + btTransform t; + t.setIdentity(); + t.setOrigin(to_btVector3(location())); + t.setBasis(to_btMatrix3x3(axis())); + + // construct physics body if necessary + if (!entity_body) { + // use a sphere with a radius matching the entity + btSphereShape *sphereshape = new btSphereShape(radius()); + entity_collision_shape = sphereshape; + + // set margin + //entity_collision_shape->setMargin(core::Cvar::sv_collisionmargin->value()); + + // calculate inertia + btVector3 inertia(0, 0, 0); + if (entity_mass) + entity_collision_shape->calculateLocalInertia(entity_mass, inertia); + + // create motion state + entity_motionstate = new btDefaultMotionState(t); + + // create physics body + entity_body_info = new btRigidBody::btRigidBodyConstructionInfo(entity_mass, entity_motionstate, entity_collision_shape, inertia); + entity_body = new btRigidBody(*entity_body_info); + // point the bullet user pointer to the entity + entity_body->setUserPointer((void *) this); + // enable custom collision callback + entity_body->setCollisionFlags(entity_body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + //entity_body->setCollisionFlags(entity_body->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE); + + if (entity_mass) { + entity_body->setActivationState(DISABLE_DEACTIVATION); + } else { + entity_body->setActivationState(ISLAND_SLEEPING); + } + + if (zone()) + zone()->physics()->addRigidBody(entity_body); + } + + // transfer entity location to motion state + body()->setDamping(0.0f, 0.0f); + body()->setLinearVelocity(math::to_btVector3(axis().forward() * speed())); + body()->setAngularVelocity(btVector3(0.0f, 0.0f, 0.0f)); + body()->setWorldTransform(t); + body()->clearForces(); + + if (motionstate()) { + motionstate()->setWorldTransform(t); + } + + set_dirty(); +} + +void EntityProjectile::set_projectile_modelname(const std::string modelname) +{ + projectile_modelname_str.assign(modelname); + set_modelname("maps/projectiles/" + modelname); +} + +void EntityProjectile::serialize_server_create(std::ostream & os) const +{ + os << moduletype() << " "; + os << flags() << " "; + os << (zone() ? zone()->id() : 0) << " "; + os << std::setprecision(8) << location() << " "; + os << color() << " "; + os << color_second() << " "; + os << radius() << " "; + os << std::setprecision(8) << axis().forward() << " "; + os << std::setprecision(8) << axis().left() << " "; + os << "\"" << projectile_modelname() << "\" "; + os << roundf(speed() * 100.0f) << " "; + os << state() << " ";; + os << lifespan() << " "; + os << ownerid() << " "; +} + +void EntityProjectile::receive_server_create(std::istream &is) +{ + is >> entity_moduletypeid; + + unsigned int f; + is >> f; + set_flags(f); + + unsigned int zo; + is >> zo; + set_zone(Zone::find(zo)); + if (entity_zone && !zo) { + con_warn << "Received entity " << id() << " for unknown zone " << zo << "!" << std::endl; + } + + is >> get_location(); + is >> get_color(); + is >> get_color_second(); + + float r; + is >> r; + set_radius(r) + ; + is >> get_axis()[0]; + is >> get_axis()[1]; + get_axis()[2].assign(math::crossproduct(axis().forward(), axis().left())); + + // read projectile modelname + std::string n; + char c; + n.clear(); + while ((is.get(c)) && (c != '"')); + while ((is.get(c)) && (c != '"')) + n += c; + set_projectile_modelname(n); + + is >> entity_speed; + entity_speed /= 100.0f; + + is >> entity_state; + is >> projectile_lifespan; + is >> projectile_ownerid; + + set_dirty(false); +} + +} // namespace core + diff --git a/src/core/entityprojectile.h b/src/core/entityprojectile.h new file mode 100644 index 0000000..04070ff --- /dev/null +++ b/src/core/entityprojectile.h @@ -0,0 +1,146 @@ +/* + core/entityprojectile.h + This file is part of the Osirion project and is distributed under + the terms and conditions of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_CORE_PROJECTILE_H__ +#define __INCLUDED_CORE_PROJECTILE_H__ + +#include "core/entity.h" + +namespace core +{ + +class EntityProjectile : public core::EntityDynamic +{ +public: + EntityProjectile(); + EntityProjectile(std::istream & is); + + virtual ~EntityProjectile(); + + virtual void upkeep(const unsigned long timestamp); + + virtual void collision(Entity *other); + + virtual void frame(const unsigned long elapsed); + + /* --- inspectors ------------------------------------------ */ + + /** + * @brief core type id + * */ + virtual inline const unsigned int type() const { + return Projectile; + } + + inline const unsigned long timestamp() const + { + return projectile_timestamp; + } + + /** + * @brief the lifespan of this projectile, in milliseconds + * */ + inline const unsigned long lifespan() const + { + return projectile_lifespan; + } + + /** + * @brief the amount of damage this projectile inflicts + * */ + inline const float damage() const + { + return projectile_damage; + } + + /** + * @brief id of the player who fired the projectile + * */ + inline const int ownerid() const + { + return projectile_ownerid; + } + + /** + * @brief return the projectile modelname + * */ + inline const std::string & projectile_modelname() const + { + return projectile_modelname_str; + } + + /*----- serializers ----------------------------------------------- */ + + /** + * @brief serialize the entity to a stream + * */ + virtual void serialize_server_create(std::ostream & os) const; + + /*----- mutators -------------------------------------------------- */ + + /** + * @brief receive a server-to-client create from a stream + * */ + virtual void receive_server_create(std::istream &is); + + /** + * @brief reset physics state + * */ + virtual void reset(); + + /** + * @brief set the amount of damage this projectile inflicts + * */ + inline void set_damage(const float damage) + { + projectile_damage = damage; + } + + /** + * @brief set the lifespan of the projectile + * */ + inline void set_lifespan(const unsigned long lifespan) + { + projectile_lifespan = lifespan; + } + + /** + * @brief set the id of the player who fired the projectile + * */ + inline void set_ownerid(const int ownerid) + { + projectile_ownerid = ownerid; + } + + /** + * @brief set the projectile timestamp + * */ + inline void set_timestamp(const unsigned int timestamp) + { + projectile_timestamp = timestamp; + } + + /** + * @brief set the projectile modelname + * */ + void set_projectile_modelname(const std::string modelname); + +private: + unsigned long projectile_timestamp; + + unsigned long projectile_lifespan; + + std::string projectile_modelname_str; + + float projectile_damage; + + int projectile_ownerid; +}; + +} // namespace game + +#endif // __INCLUDED_CORE_PROJECTILE_H__ + -- cgit v1.2.3