From 9a16c4b433bba4837bc98a90b446aa0726f0d447 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Tue, 5 Nov 2013 13:17:27 +0000 Subject: Correct a bug where launch timeout is ignored for patrols with only a single member, increase dampening for cargo pods, added 'explode' cheat function to self-destruct, cleaned up cargo pod eject code, eject cargo on ship destruction, added g_cargoloss game variable. --- src/game/base/ship.cc | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) (limited to 'src/game/base/ship.cc') 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; + } } }; -- cgit v1.2.3