diff options
-rw-r--r-- | src/game/base/cargopod.cc | 3 | ||||
-rw-r--r-- | src/game/base/game.cc | 139 | ||||
-rw-r--r-- | src/game/base/game.h | 6 | ||||
-rw-r--r-- | src/game/base/patrol.cc | 2 | ||||
-rw-r--r-- | src/game/base/ship.cc | 132 | ||||
-rw-r--r-- | src/game/base/ship.h | 7 |
6 files changed, 197 insertions, 92 deletions
diff --git a/src/game/base/cargopod.cc b/src/game/base/cargopod.cc index 67ae51e..d6e72c9 100644 --- a/src/game/base/cargopod.cc +++ b/src/game/base/cargopod.cc @@ -41,8 +41,9 @@ CargoPod::CargoPod() : EntityDynamic() set_mass(radius()); reset(); + // increased dampening for cargo pods const float damp = Game::g_damping->value(); - body()->setDamping(damp, damp); + body()->setDamping(damp * 2.0f, damp * 2.0f); } CargoPod::~CargoPod() diff --git a/src/game/base/game.cc b/src/game/base/game.cc index b3fb415..6921f72 100644 --- a/src/game/base/game.cc +++ b/src/game/base/game.cc @@ -63,6 +63,7 @@ core::Cvar *Game::g_jumppointrange = 0; core::Cvar *Game::g_devel = 0; core::Cvar *Game::g_damping = 0; core::Cvar *Game::g_deplete = 0; +core::Cvar *Game::g_cargoloss = 0; core::Module *factory() { @@ -121,8 +122,9 @@ void Game::func_spectate(core::Player *player, std::string const &args) player->remove_asset(player->control()); } - if (!player->zone()) + if (!player->zone()) { player->set_zone(Default::zone); + } player->set_view(0); } @@ -1229,109 +1231,38 @@ void Game::func_eject(core::Player *player, const std::string &args) return; } - core::EntityControlable *ejector = player->control(); + if (player->control()->moduletype() != ship_enttype) { + return; + } + Ship * ship = static_cast<Ship *>(player->control()); + // cannot eject while jumping - if ((ejector->state() == core::Entity::Jump) || (ejector->state() == core::Entity::JumpInitiate)) { - if (ejector->owner()) { - ejector->owner()->send("^WCan not eject while hyperspace jump drive is active"); + if ((ship->state() == core::Entity::Jump) || (ship->state() == core::Entity::JumpInitiate)) { + if (ship->owner()) { + ship->owner()->send("^WCan not eject while hyperspace jump drive is active"); } return; } // find the item in the inventory - core::Item *item = ejector->inventory()->find(id); + core::Item *item = ship->inventory()->find(id); if (!item) { - if (ejector->owner()) { + if (ship->owner()) { std::stringstream msgstr; msgstr << "^WItem " << id << " not in inventory"; - ejector->owner()->send(msgstr.str()); + ship->owner()->send(msgstr.str()); } return; } if (!item->amount()) { - if (ejector->owner()) { - ejector->owner()->send("^WYou do not own any " + item->info()->name()); + if (ship->owner()) { + ship->owner()->send("^WYou do not own any " + item->info()->name()); } return; - } - - if ((amount < 0) || (amount > item->amount())) { - amount = item->amount(); } - item->dec_amount(amount); - if (ejector->state() == core::Entity::Docked) { - if (ejector->owner()) { - std::stringstream msgstr; - msgstr << "^BDestroyed " << amount << " " << aux::plural("unit", amount) << " of " << item->info()->name(); - ejector->owner()->send(msgstr.str()); - ejector->owner()->sound("game/eject"); - } - } else { - // create cargo pod - CargoPod *pod = new CargoPod(); - - if (item->info()->modelname().size()) { - pod->set_name(item->info()->name()); - // setting item modesl looks silly, but can be uncommented server-side - //pod->set_modelname(item->info()->modelname()); - } - pod->set_color(ejector->color()); - pod->set_color_second(ejector->color_second()); - pod->set_location(ejector->location() + ejector->axis().up() * (ejector->radius() + pod->radius())); - pod->set_axis(ejector->axis()); - pod->set_zone(ejector->zone()); - pod->set_info(item->info()); - - // add loot to inventory - pod->add_inventory(); - pod->inventory()->set_capacity(item->info()->volume() * amount); - - 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(); - - if (ejector->owner()) { - std::stringstream msgstr; - if (item->unique()) { - msgstr << "^BEjected " << item->info()->name(); - } else { - msgstr << "^BEjected " << amount << " " << aux::plural("unit", amount) << " of " << item->info()->name(); - } - ejector->owner()->send(msgstr.str()); - ejector->owner()->sound("game/eject"); - } - - pod->reset(); - } - - 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(); + ship->eject(item, amount, true); } // mount weapons into slots @@ -1617,16 +1548,19 @@ void Game::func_respawn(core::Player *player, std::string const &args) // instantaniously goto a specified entity within the zone void Game::func_goto(core::Player *player, const std::string &args) { - if (!args.size()) - return; - if (!g_devel->value()) { player->send("Cheats disabled"); return; } - if (!player->control()) + if (!player->control()) { + player->send("^WYou need to join the game first!"); return; + } + + if (!args.size()) { + return; + } core::Entity *dock = player->control()->zone()->search_entity(args); Ship *ship = static_cast<Ship *>(player->control()); @@ -1662,6 +1596,25 @@ void Game::func_goto(core::Player *player, const std::string &args) } } +// self-destruct +void Game::func_explode(core::Player *player, const std::string &args) +{ + if (!g_devel->value()) { + player->send("Cheats disabled"); + return; + } + + if (!player->control()) { + player->send("^WYou need to join the game first!"); + return; + } + + assert(player->control()->moduletype() == ship_enttype); + Ship *ship = static_cast<Ship *>(player->control()); + + ship->explode(); +} + /* -- class Game -------------------------------------------------- */ Game::Game() : core::Module("Project::OSiRiON", true) @@ -1762,6 +1715,9 @@ Game::Game() : core::Module("Project::OSiRiON", true) func = core::Func::add("respawn", Game::func_respawn); func->set_info("respawn when your ship has been destroyed"); + func = core::Func::add("explode", Game::func_explode); + func->set_info("self-destruct"); + func = core::Func::add("goto", Game::func_goto); func->set_info("[string] goto to an entity within the zone"); @@ -1795,6 +1751,9 @@ Game::Game() : core::Module("Project::OSiRiON", true) g_deplete = core::Cvar::get("g_deplete", "60", core::Cvar::Game | core::Cvar::Archive); g_deplete->set_info("[int] number of seconds to deplete 1 unit of cargo from inventories"); + + g_cargoloss = core::Cvar::get("g_cargoloss", "100", core::Cvar::Game | core::Cvar::Archive); + g_cargoloss->set_info("[int] percentage of cargo to drop on player death"); } Game::~Game() diff --git a/src/game/base/game.h b/src/game/base/game.h index bb1c9ae..bd8d402 100644 --- a/src/game/base/game.h +++ b/src/game/base/game.h @@ -86,7 +86,7 @@ public: /* --- game variables -------------------------------------- */ - /// game variable: maximum speed of the impulse drive + /// game variable: maximum ship speed static core::Cvar *g_impulsespeed; /// game variable: jumppoint range @@ -98,6 +98,9 @@ public: /// game variable: number of seconds it takes for 1 unit of cargo to deplete from station inventories static core::Cvar *g_deplete; + /// game variable: percentage of cargo to drop on player death + static core::Cvar *g_cargoloss; + /// physics variable: default damping factor of space static core::Cvar *g_damping; @@ -124,6 +127,7 @@ private: static void func_launch(core::Player *player, std::string const &args); static void func_respawn(core::Player *player, std::string const &args); static void func_goto(core::Player *player, const std::string &args); + static void func_explode(core::Player *player, const std::string &args); static void func_buy(core::Player *player, std::string const &args); static void func_sell(core::Player *player, const std::string &args); static void func_give(core::Player *player, const std::string &args); diff --git a/src/game/base/patrol.cc b/src/game/base/patrol.cc index 48f687e..4ad16df 100644 --- a/src/game/base/patrol.cc +++ b/src/game/base/patrol.cc @@ -347,6 +347,8 @@ void Patrol::frame(const unsigned long elapsed) } else if ((patrol_leader->state() == core::Entity::Normal) || (patrol_leader->state() == core::Entity::ImpulseInitiate) || (patrol_leader->state() == core::Entity::Impulse)) { + patrol_launch_timeout = 0; + if (waypoint()->target()->zone() == patrol_leader->zone()) { patrol_leader->set_autopilot_target(waypoint()->target()); diff --git a/src/game/base/ship.cc b/src/game/base/ship.cc index e800c93..cdc860a 100644 --- a/src/game/base/ship.cc +++ b/src/game/base/ship.cc @@ -20,6 +20,8 @@ #include "base/spacemine.h" #include "base/jumppoint.h" #include "base/racetrack.h" +#include "base/cargo.h" +#include "base/cargopod.h" using math::degrees360f; using math::degrees180f; @@ -307,6 +309,112 @@ JumpPoint * Ship::find_closest_jumppoint() return 0; } +void Ship::eject(core::Item *item, const long eject_amount, const bool eject_message) +{ + // verify whe have the item in our inventory + if (!inventory()->find(item)) { + return; + } + + // clamp amount to what's available + const long amount = math::min(eject_amount, item->amount()); + if (amount < 1) { + return; + } + + // remove the requested amount + item->dec_amount(amount); + + if (state() == Docked) { + + if (eject_message && owner()) { + std::stringstream msgstr; + msgstr << "^BDestroyed " << amount << " " << aux::plural("unit", amount) << " of " << item->info()->name(); + owner()->send(msgstr.str()); + owner()->sound("game/eject"); + } + } else { + // create cargo pod + CargoPod *pod = new CargoPod(); + + if (item->info()->modelname().size()) { + pod->set_name(item->info()->name()); + /* + // setting item models looks silly, but can be uncommented server-side + //pod->set_modelname(item->info()->modelname()); + */ + } + + // randomize location + math::Axis pod_axis; + pod_axis.change_direction(math::randomf(360.0f)); + pod_axis.change_pitch(math::randomf(180.0f)); + pod_axis.change_roll(math::randomf(360.0f)); + + pod->set_color(color()); + pod->set_color_second(color_second()); + pod->set_location(location() + pod_axis.up() * (radius() + pod->radius())); + pod->set_axis(pod_axis); + pod->set_zone(zone()); + pod->set_info(item->info()); + + // add loot to inventory + pod->add_inventory(); + pod->inventory()->set_capacity(item->info()->volume() * amount); + + 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(); + + if (eject_message && owner()) { + std::stringstream msgstr; + if (item->unique()) { + msgstr << "^BEjected " << item->info()->name(); + } else { + msgstr << "^BEjected " << amount << " " << aux::plural("unit", amount) << " of " << item->info()->name(); + } + owner()->send(msgstr.str()); + owner()->sound("game/eject"); + } + + // reset cargopod physics + pod->reset(); + + assert(pod->body()); + + const float CARGOPOD_SPEED = 0.5f; + pod->set_speed(CARGOPOD_SPEED); + pod->body()->setLinearVelocity(math::to_btVector3(pod_axis.forward() * CARGOPOD_SPEED)); + } + + if (item->amount() == 0) { + if (item->has_flag(core::Item::Mounted)) { + // unmount + core::Slot *slot = 0; + + for(core::Slots::iterator it = slots()->begin(); (!slot) && (it != 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); + } + + } + inventory()->erase(item->id()); + } + inventory()->set_dirty(); +} + void Ship::explode() { target_direction = 0; @@ -322,10 +430,34 @@ void Ship::explode() set_state(core::Entity::Destroyed); + // 100 % cargo loss by default + float percentage = 100.0f; + if (owner()) { + // make the player watch his death if (owner()->control() == this) { owner()->set_view(this); } + + // cargo loss % is set by the g_cargoloss CVar + percentage = Game::g_cargoloss->value(); + percentage = floorf(percentage); + math::clamp(percentage, 0.0f, 100.0f); + } + + if (percentage > 0) { + core::Inventory::Items::iterator it = inventory()->items().begin(); + + while (it != inventory()->items().end()) { + if ((*it)->info()->type() == Cargo::infotype()) { + long loss = (*it)->amount() * ((long) percentage) / 100l; + if (loss > 0) { + eject((*it++), loss, false); + continue; + } + } + ++it; + } } }; diff --git a/src/game/base/ship.h b/src/game/base/ship.h index fa6e60d..e8a6505 100644 --- a/src/game/base/ship.h +++ b/src/game/base/ship.h @@ -214,6 +214,13 @@ public: void launch(); void set_spawn(core::Entity *spawn); + + /** + * @brief eject an item from inventory + * Ejecting an item while the ship is docked will destroy it, + * otherwise it will create a cargo pod + * */ + void eject(core::Item *item, const long eject_amount, const bool eject_message); protected: /** |