/* base/projectile.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 "base/projectile.h" #include "base/game.h" #include "core/gameserver.h" #include "math/functions.h" #include "sys/sys.h" namespace game { EntityProjectile::EntityProjectile(unsigned long lifespan) : EntityDynamic() { entity_moduletypeid = projectile_enttype; //set_name(""); set_label("projectile"); //set_serverside(true); set_flag(core::Entity::KeepAlive); set_shape(core::Entity::Sphere); set_radius(0.01f); set_mass(radius()); //reset(); //const float damp = Game::g_damping->value(); //body()->setDamping(0.0f, 0.0f); projectile_damage = 0.0f; projectile_lifespan = lifespan; projectile_timestamp = core::server()->timestamp(); projectile_ownerid = 0; } EntityProjectile::~EntityProjectile() { } void EntityProjectile::upkeep(const unsigned long timestamp) { die(); } void EntityProjectile::collision(core::Entity *other) { if (state() == core::Entity::Destroyed) { return; } set_state(core::Entity::Destroyed); // this method is a bullet callback, we can not reset() here } void EntityProjectile::frame(const unsigned long elapsed) { EntityDynamic::frame(elapsed); if (projectile_timestamp + projectile_lifespan < core::server()->timestamp()) { set_state(core::Entity::Destroyed); } if (state() == core::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() == core::Entity::Docked) || (state() == core::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()->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f)); body()->setAngularVelocity(btVector3(0.0f, 0.0f, 0.0f)); body()->setWorldTransform(t); body()->clearForces(); if (motionstate()) { motionstate()->setWorldTransform(t); } set_dirty(); } } // namespace game