Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2013-11-05 13:17:27 +0000
committerStijn Buys <ingar@osirion.org>2013-11-05 13:17:27 +0000
commit9a16c4b433bba4837bc98a90b446aa0726f0d447 (patch)
tree162f257f40a83ae46eddbe1fa0289b2d3e496e44 /src/game/base/ship.cc
parentcbb34af067be07ad28349e64d8670c97785c53c0 (diff)
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.
Diffstat (limited to 'src/game/base/ship.cc')
-rw-r--r--src/game/base/ship.cc132
1 files changed, 132 insertions, 0 deletions
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;
+ }
}
};