diff options
| author | Stijn Buys <ingar@osirion.org> | 2012-11-25 21:25:40 +0000 | 
|---|---|---|
| committer | Stijn Buys <ingar@osirion.org> | 2012-11-25 21:25:40 +0000 | 
| commit | 3318b29475ffc5f462e2926f9b1141beca8305ae (patch) | |
| tree | 15558ef704cf0aa8951618e52f7cd01769258bcc /src/core | |
| parent | 438283d0029a6d82e1669b218a2481c5c4ea2dbd (diff) | |
Added core::Entity::Projectile.
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/Makefile.am | 2 | ||||
| -rw-r--r-- | src/core/entityprojectile.cc | 264 | ||||
| -rw-r--r-- | src/core/entityprojectile.h | 146 | 
3 files changed, 412 insertions, 0 deletions
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 <iomanip> + +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__ +  | 
