From d8be908233fd7b85492d7a9e87f07bb207173990 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 25 Nov 2012 12:06:13 +0000 Subject: Moved core::EntityGlobe into a separate file, added various methods to core::Item and core::Slot, added r_slots cvar to draw entity slots and docks, added game methods for mounting and umounting of weapons, added playerlist to chat window. --- src/game/base/game.cc | 155 ++++++++++++++++++++++++++++++++++++++++++-- src/game/base/game.h | 2 + src/game/base/planet.h | 2 +- src/game/base/projectile.cc | 115 ++++++++++++++++++++++++++++++-- src/game/base/projectile.h | 13 ++-- src/game/base/ship.cc | 17 +++-- src/game/base/shipmodel.cc | 7 +- src/game/base/star.h | 2 +- src/game/base/weapon.h | 8 +++ 9 files changed, 293 insertions(+), 28 deletions(-) (limited to 'src/game/base') diff --git a/src/game/base/game.cc b/src/game/base/game.cc index 2355a9e..1020fa8 100644 --- a/src/game/base/game.cc +++ b/src/game/base/game.cc @@ -340,9 +340,10 @@ void Game::func_give(core::Player *player, const std::string &args) } // transfer inventory - for (core::Inventory::Items::iterator it = player->control()->inventory()->items().begin(); - it != player->control()->inventory()->items().end(); it++) { - ship->inventory()->add(new core::Item(*(*it))); + for (core::Inventory::Items::iterator it = player->control()->inventory()->items().begin(); it != player->control()->inventory()->items().end(); it++) { + core::Item *item = new core::Item(*(*it)); + item->unset_flag(core::Item::Mounted); + ship->inventory()->add(item); } ship->inventory()->set_dirty(); @@ -973,7 +974,7 @@ void Game::func_drop(core::Player *player, const std::string &args) // cannot drop items while jumping if ((ship->state() == core::Entity::Jump) || (ship->state() == core::Entity::JumpInitiate)) { - player->send("^WCan not eject while hyperspace jump drive is active"); + player->send("^WCan not drop items while hyperspace jump drive is active"); return; } @@ -1112,9 +1113,10 @@ void Game::func_eject(core::Player *player, const std::string &args) pod->add_inventory(); pod->inventory()->set_capacity(item->info()->volume() * amount); - core::Item *loot = new core::Item(item->info()); + core::Item *loot = new core::Item(item->info()); loot->set_amount(amount); loot->set_flags(item->flags()); + loot->unset_flag(core::Item::Mounted); pod->inventory()->add(loot); pod->inventory()->set_dirty(); @@ -1134,11 +1136,147 @@ void Game::func_eject(core::Player *player, const std::string &args) } if (item->amount() == 0) { + if (item->has_flag(core::Item::Mounted)) { + // unmount + core::Slot *slot = 0; + + for(core::Slots::iterator it = ejector->slots()->begin(); (!slot) && (it != ejector->slots()->end()); ++it) { + if ((*it)->item() == item) { + slot = (*it); + } + } + + if (slot) { + slot->set_item(0); + slot->unset_flag(core::Slot::Active); + slot->unset_flag(core::Slot::Mounted); + item->unset_flag(core::Item::Mounted); + } + + } ejector->inventory()->erase(item->id()); } ejector->inventory()->set_dirty(); } +// mount weapons into slots +void Game::func_mount(core::Player *player, const std::string &args) +{ + if (!player->control()) { + return; + } + + Ship *ship = static_cast(player->control()); + + if (!ship->slots()) { + return; + } + + std::istringstream is(args); + unsigned int id = 0; + + if (!(is >> id)) { + ship->owner()->send("Usage: mount [id] mount weapon with id into the first available slot"); + return; + } + + // find item to be mounted + core::Item *item = ship->inventory()->find(id); + if (!item) { + if (ship->owner()) { + std::stringstream msgstr; + msgstr << "^WItem " << id << " not in inventory"; + ship->owner()->send(msgstr.str()); + } + return; + } + + // verify item is mountable + if (item->info()->type() != Weapon::infotype()) { + if (ship->owner()) { + std::stringstream msgstr; + msgstr << "^WItem " << id << " can not be mounted"; + ship->owner()->send(msgstr.str()); + } + return; + } + const Weapon *weapon = static_cast(item->info()); + + if (!item->unique() || (weapon->subtype() != Weapon::Cannon)) { + if (ship->owner()) { + std::stringstream msgstr; + msgstr << "^WItem " << id << " can not be mounted"; + ship->owner()->send(msgstr.str()); + } + return; + } + + if (item->has_flag(core::Item::Mounted)) { + // unmount + core::Slot *slot = 0; + + for(core::Slots::iterator it = ship->slots()->begin(); (!slot) && (it != ship->slots()->end()); ++it) { + if ((*it)->item() == item) { + slot = (*it); + } + } + + if (slot) { + slot->set_item(0); + slot->unset_flag(core::Slot::Active); + slot->unset_flag(core::Slot::Mounted); + item->unset_flag(core::Item::Mounted); + + if (ship->owner()) { + std::stringstream msgstr; + msgstr << "^BUnmounted " << weapon->name(); + ship->owner()->send(msgstr.str()); + } + } + + } else { + // mount + core::Slot *slot = 0; + + for(core::Slots::iterator it = ship->slots()->begin(); (!slot) && (it != ship->slots()->end()); ++it) { + if (!(*it)->has_flag(core::Slot::Mounted)) { + slot = (*it); + } + } + + if (!slot) { + if (ship->owner()) { + std::stringstream msgstr; + msgstr << "^WNo slot available to mount item " << id; + ship->owner()->send(msgstr.str()); + } + return; + } else { + slot->set_item(item); + slot->set_flag(core::Slot::Active); + slot->set_flag(core::Slot::Mounted); + item->set_flag(core::Item::Mounted); + + slot->set_projectile_damage(weapon->damage()); + slot->set_projectile_speed(weapon->projectile_speed()); + slot->set_projectile_lifespan(weapon->projectile_lifespan()); + slot->set_projectile_interval(weapon->projectile_interval()); + slot->set_projectile_modelname(weapon->projectile_modelname()); + + if (ship->owner()) { + std::stringstream msgstr; + msgstr << "^BMounted " << weapon->name(); + ship->owner()->send(msgstr.str()); + } + } + } +} + +// unmount weapons from slots +void Game::func_unmount(core::Player *player, const std::string &args) +{ +} + // beam in nearby cargo pods void Game::func_beam(core::Player *player, const std::string &args) { @@ -1180,6 +1318,8 @@ void Game::func_beam(core::Player *player, const std::string &args) } if (!iteminv) { iteminv = new core::Item(item->info()); + iteminv->set_flags(item->flags()); + iteminv->unset_flag(core::Item::Mounted); inventory->add(iteminv); } item->dec_amount(negotiated_amount); @@ -1424,7 +1564,10 @@ Game::Game() : core::Module("Project::OSiRiON", true) func->set_info("[label] drop an item and activate it"); func = core::Func::add("eject", Game::func_eject); - func->set_info("[string] [string] [int] eject an item from inventory: specify type, label and amount"); + func->set_info("[int] eject item with id from inventory"); + + func = core::Func::add("mount", Game::func_mount); + func->set_info("[int] mount a weapon into the first available slot"); func = core::Func::add("beam", Game::func_beam); func->set_info("beam nearby cargo pods in"); diff --git a/src/game/base/game.h b/src/game/base/game.h index d030367..f535ec9 100644 --- a/src/game/base/game.h +++ b/src/game/base/game.h @@ -133,6 +133,8 @@ private: static void func_specs(core::Player *player, const std::string &args); static void func_eject(core::Player *player, const std::string &args); static void func_drop(core::Player *player, std::string const &args); + static void func_mount(core::Player *player, const std::string &args); + static void func_unmount(core::Player *player, const std::string &args); static void func_beam(core::Player *player, const std::string &args); /* ---- target functions ----------------------------------- */ diff --git a/src/game/base/planet.h b/src/game/base/planet.h index 337bab2..6b97d40 100644 --- a/src/game/base/planet.h +++ b/src/game/base/planet.h @@ -7,7 +7,7 @@ #ifndef __INCLUDED_BASE_PLANET_H__ #define __INCLUDED_BASE_PLANET_H__ -#include "core/entity.h" +#include "core/entityglobe.h" #include "math/mathlib.h" #include diff --git a/src/game/base/projectile.cc b/src/game/base/projectile.cc index 6bcbad9..4dd483d 100644 --- a/src/game/base/projectile.cc +++ b/src/game/base/projectile.cc @@ -13,16 +13,16 @@ namespace game { -Projectile::Projectile(unsigned long lifespan) : EntityDynamic() +EntityProjectile::EntityProjectile(unsigned long lifespan) : EntityDynamic() { entity_moduletypeid = projectile_enttype; //set_name(""); - //set_label(""); + set_label("projectile"); //set_serverside(true); set_flag(core::Entity::KeepAlive); set_shape(core::Entity::Sphere); - set_radius(0.02f); + set_radius(0.01f); set_mass(radius()); //reset(); @@ -36,17 +36,17 @@ Projectile::Projectile(unsigned long lifespan) : EntityDynamic() projectile_ownerid = 0; } -Projectile::~Projectile() +EntityProjectile::~EntityProjectile() { } -void Projectile::upkeep(const unsigned long timestamp) +void EntityProjectile::upkeep(const unsigned long timestamp) { die(); } -void Projectile::collision(core::Entity *other) +void EntityProjectile::collision(core::Entity *other) { if (state() == core::Entity::Destroyed) { return; @@ -56,7 +56,7 @@ void Projectile::collision(core::Entity *other) // this method is a bullet callback, we can not reset() here } -void Projectile::frame(const unsigned long elapsed) +void EntityProjectile::frame(const unsigned long elapsed) { EntityDynamic::frame(elapsed); @@ -69,5 +69,106 @@ void Projectile::frame(const unsigned long elapsed) } } +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 diff --git a/src/game/base/projectile.h b/src/game/base/projectile.h index f9cda64..2513901 100644 --- a/src/game/base/projectile.h +++ b/src/game/base/projectile.h @@ -1,5 +1,5 @@ /* - base/spacemine.h + base/projectile.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 */ @@ -12,11 +12,11 @@ namespace game { -class Projectile : public core::EntityDynamic +class EntityProjectile : public core::EntityDynamic { public: - Projectile(unsigned long lifespan); - virtual ~Projectile(); + EntityProjectile(unsigned long lifespan); + virtual ~EntityProjectile(); virtual void upkeep(const unsigned long timestamp); @@ -57,6 +57,11 @@ public: /* --- mutators -------------------------------------------- */ + /** + * @brief reset physics state + * */ + virtual void reset(); + /** * @brief set the amount of damage this projectile inflicts * */ diff --git a/src/game/base/ship.cc b/src/game/base/ship.cc index 7282fe1..fc01b5c 100644 --- a/src/game/base/ship.cc +++ b/src/game/base/ship.cc @@ -9,13 +9,15 @@ #include #include "auxiliary/functions.h" +#include "math/functions.h" + #include "core/gameserver.h" #include "core/entity.h" + #include "base/game.h" #include "base/ship.h" #include "base/projectile.h" #include "base/spacemine.h" -#include "math/functions.h" using math::degrees360f; using math::degrees180f; @@ -85,14 +87,16 @@ Ship::Ship(core::Player *owner, const ShipModel *shipmodel) : core::EntityContro if (model()) { add_slots(); slots()->load(model()); - +/* for (core::Slots::iterator it = slots()->begin(); it != slots()->end(); it++) { // default fire rate: 1 projectile / second (*it)->set_projectile_interval(1000); (*it)->set_projectile_lifespan(5000); (*it)->set_projectile_speed(5.0f); (*it)->set_projectile_damage(10.0f); + (*it)->set_projectile_modelname("laser1"); } +*/ } // menus for docked players @@ -529,7 +533,7 @@ void Ship::collision(core::Entity *other) } else if (other->moduletype() == projectile_enttype) { // hit by projectile - Projectile * projectile = static_cast(other); + game::EntityProjectile *projectile = static_cast(other); if (projectile->state() != core::Entity::Destroyed) { ship_armor -= projectile->damage(); } @@ -877,10 +881,10 @@ void Ship::frame(const unsigned long elapsed) for (core::Slots::iterator it = slots()->begin(); it != slots()->end(); it++) { // create projectiles - if ((*it)->projectile_interval() > 0) { + if ( ((*it)->projectile_interval() > 0) && ((*it)->has_flag(core::Slot::Mounted)) && ((*it)->has_flag(core::Slot::Active))) { if ((*it)->last_fired() + (*it)->projectile_interval() <= core::server()->timestamp()) { (*it)->set_last_fired(core::server()->timestamp()); - Projectile * projectile = new Projectile((*it)->projectile_lifespan()); + EntityProjectile * projectile = new EntityProjectile((*it)->projectile_lifespan()); projectile->set_damage((*it)->projectile_damage()); projectile->set_color(color()); if (owner()) { @@ -889,7 +893,8 @@ void Ship::frame(const unsigned long elapsed) projectile->set_zone(zone()); projectile->set_axis(axis() * (*it)->axis()); projectile->set_location(location() + (axis() * (*it)->location() * modelscale) + projectile->axis().forward() * projectile->radius()); - + projectile->set_modelname("maps/projectiles/" + (*it)->projectile_modelname()); + projectile->reset(); projectile->body()->setDamping(0.0f, 0.0f); projectile->body()->setLinearVelocity(math::to_btVector3(projectile->axis().forward() * (*it)->projectile_speed())); diff --git a/src/game/base/shipmodel.cc b/src/game/base/shipmodel.cc index fe8889d..ba01765 100644 --- a/src/game/base/shipmodel.cc +++ b/src/game/base/shipmodel.cc @@ -337,9 +337,10 @@ void ShipModel::buy(core::EntityControlable *buyer, core::Entity *seller) //ship->reset(); // reset() is done by set_dock() // transfer inventory - for (core::Inventory::Items::iterator it = player->control()->inventory()->items().begin(); - it != player->control()->inventory()->items().end(); it++) { - ship->inventory()->add(new core::Item(*(*it))); + for (core::Inventory::Items::iterator it = player->control()->inventory()->items().begin(); it != player->control()->inventory()->items().end(); it++) { + core::Item *item = new core::Item(*(*it)); + item->unset_flag(core::Item::Mounted); + ship->inventory()->add(item); } ship->inventory()->set_dirty(); diff --git a/src/game/base/star.h b/src/game/base/star.h index 12bec07..1e45dbb 100644 --- a/src/game/base/star.h +++ b/src/game/base/star.h @@ -8,7 +8,7 @@ #define __INCLUDED_BASE_STAR_H__ // project headers -#include "core/entity.h" +#include "core/entityglobe.h" #include "math/mathlib.h" // C++ headers diff --git a/src/game/base/weapon.h b/src/game/base/weapon.h index 94fdce6..b4a790c 100644 --- a/src/game/base/weapon.h +++ b/src/game/base/weapon.h @@ -44,6 +44,14 @@ public: return weapon_damage; } + /** + * @brief lifespan of projectiles generated by this weapon, in milliseconds + * */ + inline const unsigned long projectile_lifespan() const + { + return weapon_projectile_lifespan; + } + /** * @brief speed of projectiles generated by this weapon * */ -- cgit v1.2.3