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>2008-09-28 15:05:13 +0000
committerStijn Buys <ingar@osirion.org>2008-09-28 15:05:13 +0000
commitfd778219e40c5fbb4d0af1839cbc313caaf10d9d (patch)
treeb6e413f4c1a5ba4091503ba97c784278485d3933 /src/game/base/ship.cc
parentbedcff956d253621ec00aa7d2919c22a4c88b0b2 (diff)
move base game module to new subdirectory
Diffstat (limited to 'src/game/base/ship.cc')
-rw-r--r--src/game/base/ship.cc464
1 files changed, 464 insertions, 0 deletions
diff --git a/src/game/base/ship.cc b/src/game/base/ship.cc
new file mode 100644
index 0000000..0fdfd3f
--- /dev/null
+++ b/src/game/base/ship.cc
@@ -0,0 +1,464 @@
+/*
+ base/ship.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 <cmath>
+#include <iostream>
+
+#include "auxiliary/functions.h"
+#include "core/gameserver.h"
+#include "core/entity.h"
+#include "base/base.h"
+#include "base/ship.h"
+#include "math/functions.h"
+
+
+
+using math::degrees360f;
+using math::degrees180f;
+
+namespace base {
+
+const float MIN_DELTA = 0.000001f;
+
+Ship::Ship(core::Player *owner, ShipModel *shipmodel) :
+ core::EntityControlable(owner, ship_enttype)
+{
+ entity_modelname = "ships/" + shipmodel->modelname();
+ entity_name = shipmodel->name() + ": <^B" + owner->name() + "^N>";
+ entity_label = shipmodel->label();
+
+ entity_moduletypeid = ship_enttype;
+
+ entity_color = owner->color();
+ entity_color_second = owner->color_second();
+
+ ship_shipmodel = shipmodel;
+ ship_jumpdrive = shipmodel->shipmodel_jumpdrive;
+
+ ship_impulsedrive_timer = 0;
+ ship_jumpdrive_timer = 0;
+
+ reset();
+}
+
+Ship::~Ship()
+{
+
+}
+
+void Ship::reset()
+{
+ current_target_direction = 0.0f;
+ current_target_pitch = 0.0f;;
+ current_target_roll = 0.0f;
+ current_target_strafe = 0.0f;
+ current_target_afterburner = 0.0f;
+}
+void Ship::impulse()
+{
+ if (entity_eventstate == core::Entity::Jump) {
+ return;
+
+ } else if ((entity_eventstate == core::Entity::Impulse) || (entity_eventstate == core::Entity::ImpulseInitiate)) {
+ entity_eventstate = core::Entity::Normal;
+
+ } else {
+
+ if (entity_eventstate == core::Entity::JumpInitiate) {
+ ship_jumpdrive_timer = 0;
+ entity_timer = 0;
+ }
+
+ entity_eventstate = core::Entity::ImpulseInitiate;
+ if (Base::instance()->g_devel->value()) {
+ entity_timer = 0;
+ } else {
+ entity_timer = 3;
+ }
+ ship_impulsedrive_timer = core::server()->time();
+ entity_dirty = true;
+ }
+
+ entity_dirty = true;
+}
+
+void Ship::jump(std::string const &args)
+{
+ // devel mode provides instant jump access to arbitrary systems
+ if (Base::instance()->g_devel->value() && (args.size())) {
+
+ core::Zone *jumptargetzone = 0;
+ std::string target;
+ std::istringstream is(args);
+ if (!(is >> target)) {
+ std::string helpstr;
+ for (core::Zone::Registry::iterator it = core::Zone::registry().begin(); it != core::Zone::registry().end(); it++) {
+ core::Zone *zone = (*it).second;
+ if (helpstr.size())
+ helpstr.append("^N|^B");
+ helpstr.append(zone->label());
+ }
+
+ core::server()->send(owner(), "Usage: jump [^B" + helpstr + "^N]");
+ return;
+ }
+
+ aux::to_lowercase(target);
+ jumptargetzone = core::Zone::find_zone(target);
+ if (!jumptargetzone) {
+ core::server()->send(owner(), "Unknown system '" + target + '\'');
+ return;
+ }
+
+ if (jumptargetzone == zone()) {
+ core::server()->send(owner(), "Already in the " + jumptargetzone->name() + '.');
+ return;
+ }
+
+ core::server()->send(owner(), "Jumping to the " + jumptargetzone->name());
+ set_zone(jumptargetzone);
+ if (owner()->control() == (EntityControlable*) this)
+ owner()->set_zone(jumptargetzone);
+
+ ship_jumpdrive_timer = 0;
+ entity_timer = 0;
+ entity_eventstate = core::Entity::Jump;
+ entity_dirty = true;
+ return;
+
+ } else {
+ if (!jumpdrive() && !Base::instance()->g_devel->value()) {
+ core::server()->send(owner(), "This ship is not equiped with a hyperspace drive!");
+ return;
+
+ } else if (entity_eventstate == core::Entity::Jump) {
+ return;
+
+ } else if (entity_eventstate == core::Entity::JumpInitiate) {
+ core::server()->send(owner(), "Jump aborted, hyperspace drive deactivated.");
+ ship_jumpdrive_timer = 0;
+ entity_timer = 0;
+ entity_eventstate = core::Entity::Normal;
+ return;
+ }
+
+ if (!find_closest_jumppoint()) {
+ return;
+ }
+
+ entity_eventstate = core::Entity::JumpInitiate;
+ if (Base::instance()->g_devel->value()) {
+ entity_timer = 0;
+ } else {
+ entity_timer = 8;
+ }
+
+ ship_jumpdrive_timer = core::server()->time();
+ entity_dirty = true;
+ }
+}
+
+JumpPoint * Ship::find_closest_jumppoint()
+{
+ // find closest jumppoint
+ float d = -1;
+ JumpPoint *jumppoint = 0;
+ for (core::Zone::Content::iterator it = zone()->content().begin(); it != zone()->content().end(); it++) {
+ core::Entity *entity = (*it);
+ if (entity->moduletype() == jumppoint_enttype) {
+ JumpPoint *te = static_cast<JumpPoint *>(entity);
+ float d1 = math::distance(location(), te->location());
+ if ((d < 0) || (d1 < d)) {
+ d = d1;
+ jumppoint = te;
+ }
+ }
+ }
+
+ if (jumppoint && jumppoint->target()) {
+ if (Base::instance()->g_jumppointrange->value() < d) {
+ core::server()->send(owner(), "Jumppoint out of range!");
+ return 0;
+ } else {
+ core::server()->send(owner(), "Jumping to the " + jumppoint->target()->zone()->name());
+ return jumppoint;
+ }
+ } else {
+ core::server()->send(owner(), "No jumppoints found!");
+ return 0;
+ }
+
+ return 0;
+}
+
+void Ship::frame(float seconds)
+{
+ const float direction_change_speed = 2;
+ float cosangle; // cosine of an angle
+ float angle; // angle in radians
+ math::Vector3f n; // normal of a plane
+
+ float actual_maxspeed = ship_shipmodel->maxspeed();
+ float actual_turnspeed = ship_shipmodel->turnspeed();
+ float actual_acceleration = ship_shipmodel->acceleration();
+
+ entity_movement = 0;
+
+ // speed might get set to 0 on this update
+ if (entity_speed != 0.0f)
+ entity_dirty = true;
+
+ // jumpdrive
+ // target axis
+ math::Axis target_axis(entity_axis);
+
+ if (entity_eventstate == core::Entity::JumpInitiate) {
+
+ if (ship_jumpdrive_timer + 1.0f <= core::server()->time()) {
+ entity_timer -= 1.0f;
+
+ if (entity_timer <= 0) {
+ JumpPoint *jumppoint = find_closest_jumppoint();
+
+ if (jumppoint) {
+ set_zone(jumppoint->target()->zone());
+ if (owner()->control() == (EntityControlable*) this)
+ owner()->set_zone(jumppoint->target()->zone());
+ entity_eventstate = core::Entity::Jump;
+ entity_location.assign(jumppoint->target()->location() + location() - jumppoint->location());
+ } else {
+ entity_eventstate = core::Entity::Normal;
+ }
+ ship_jumpdrive_timer = 0;
+ entity_timer = 0;
+
+ entity_dirty = true;
+ return;
+ } else {
+ ship_jumpdrive_timer = core::server()->time();
+ entity_dirty = true;
+ }
+ }
+
+ // control is disabled while the jumpdrive is activated
+ target_thrust = 0;
+ target_pitch = 0;
+ target_roll = 0;
+ target_direction = 0;
+ target_afterburner = 0.0f;
+ target_thrust = 0;
+
+ } else if (entity_eventstate == core::Entity::Jump) {
+ // control is disabled while the jumpdrive is activated
+ target_thrust = 0;
+ target_pitch = 0;
+ target_roll = 0;
+ target_direction = 0;
+ target_afterburner = 0.0f;
+ target_thrust = 0;
+
+ // FIXME jump location and axis
+ math::Axis default_axis;
+ entity_axis.assign(default_axis);
+ entity_dirty = true;
+
+ // FIXME 5 second cooldown
+ entity_eventstate = core::Entity::Normal;
+
+ } else if (entity_eventstate == core::Entity::ImpulseInitiate) {
+
+ if (ship_impulsedrive_timer + 1.0f <= core::server()->time()) {
+ entity_timer -= 1.0f;
+
+ if (entity_timer <= 0) {
+ actual_maxspeed = Base::instance()->g_impulsespeed->value();
+ actual_acceleration = Base::instance()->g_impulseacceleration->value();
+ entity_eventstate = core::Entity::Impulse;
+ entity_timer = 0;
+ entity_dirty = true;
+ } else {
+ ship_impulsedrive_timer = core::server()->time();
+ entity_dirty = true;
+ }
+ }
+
+ // clamp input values
+ target_thrust = 0.0f;
+ math::clamp(target_pitch, -1.0f, 1.0f);
+ math::clamp(target_roll, -1.0f, 1.0f);
+ math::clamp(target_direction, -1.0f, 1.0f);
+ math::clamp(target_afterburner, -1.0f, 1.0f);
+ actual_turnspeed *= 0.5;
+
+ } else if (entity_eventstate == core::Entity::Impulse) {
+
+ // clamp input values
+ target_thrust = 0.0f;
+ math::clamp(target_pitch, -1.0f, 1.0f);
+ math::clamp(target_roll, -1.0f, 1.0f);
+ math::clamp(target_direction, -1.0f, 1.0f);
+ target_afterburner = 0.0f;
+ actual_maxspeed = Base::instance()->g_impulsespeed->value();
+ actual_acceleration = Base::instance()->g_impulseacceleration->value();
+ actual_turnspeed *= 0.5;
+
+ } else if (entity_eventstate == core::Entity::Normal) {
+
+ // clamp input values
+ math::clamp(target_thrust, 0.0f, 1.0f);
+ math::clamp(target_pitch, -1.0f, 1.0f);
+ math::clamp(target_roll, -1.0f, 1.0f);
+ math::clamp(target_direction, -1.0f, 1.0f);
+ math::clamp(target_afterburner, -1.0f, 1.0f);
+
+ if (speed() > actual_maxspeed * 1.15f) {
+ actual_acceleration = Base::instance()->g_impulseacceleration->value();
+ actual_turnspeed *= 0.5;
+ }
+
+ }
+
+ // update roll
+ if (current_target_roll < target_roll) {
+ current_target_roll += direction_change_speed * seconds;
+ if (current_target_roll > target_roll)
+ current_target_roll = target_roll;
+ } else if (current_target_roll > target_roll) {
+ current_target_roll -= direction_change_speed * seconds;
+ if (current_target_roll < target_roll)
+ current_target_roll = target_roll;
+ }
+ math::clamp(current_target_roll, -1.0f, 1.0f);
+
+ if (fabs(current_target_roll) > MIN_DELTA) {
+ float roll_offset = seconds * current_target_roll;
+ entity_axis.change_roll(actual_turnspeed * roll_offset);
+ } else {
+ current_target_roll = 0.0f;
+ }
+
+ // update target_axis direction
+ if (current_target_direction < target_direction) {
+ current_target_direction += direction_change_speed * seconds;
+ if (current_target_direction > target_direction) {
+ current_target_direction = target_direction;
+ }
+ } else if (current_target_direction > target_direction) {
+ current_target_direction -= direction_change_speed * seconds;
+ if (current_target_direction < target_direction) {
+ current_target_direction = target_direction;
+ }
+ }
+
+ if (fabs(current_target_direction) > MIN_DELTA ) {
+ math::clamp(current_target_direction, -1.0f, 1.0f);
+ target_axis.change_direction(actual_turnspeed * current_target_direction);
+ } else {
+ current_target_direction = 0.0f;
+ }
+
+ if (current_target_pitch < target_pitch) {
+ current_target_pitch += direction_change_speed * seconds;
+ if (current_target_pitch > target_pitch)
+ current_target_pitch = target_pitch;
+ } else if (current_target_pitch > target_pitch) {
+ current_target_pitch -= direction_change_speed * seconds;
+ if (current_target_pitch < target_pitch)
+ current_target_pitch = target_pitch;
+ }
+
+ if (fabs(current_target_pitch) > MIN_DELTA) {
+ math::clamp(current_target_pitch, -1.0f, 1.0f);
+ target_axis.change_pitch(actual_turnspeed * current_target_pitch);
+ } else {
+ current_target_pitch = 0.0f;
+ }
+
+ n.assign(math::crossproduct(entity_axis.forward(), target_axis.forward()));
+ if (!(n.length() < MIN_DELTA)) {
+ n.normalize();
+ cosangle = math::dotproduct(entity_axis.forward(), target_axis.forward());
+ angle = acos(cosangle) * seconds; // * 180.0f / M_PI;
+ if (angle > MIN_DELTA)
+ entity_axis.rotate(n, -angle);
+ }
+
+ // update afterburner
+ if (current_target_afterburner < target_afterburner) {
+ current_target_afterburner += 2.0f * seconds;
+ if (current_target_afterburner > target_afterburner)
+ current_target_afterburner = target_afterburner;
+ } else if (current_target_afterburner > target_afterburner) {
+ current_target_afterburner -= 2.0f * seconds;
+ if (current_target_afterburner < target_afterburner)
+ current_target_afterburner = target_afterburner;
+ }
+
+ // update thrust
+ if (current_target_afterburner < 0.0f) {
+ target_thrust = 0;
+ }
+
+ if (entity_thrust < target_thrust) {
+ entity_thrust += seconds * 0.5f;
+ if (entity_thrust > target_thrust)
+ entity_thrust = target_thrust;
+ } else if (entity_thrust > target_thrust) {
+ entity_thrust -= seconds * 0.5f;
+ if (entity_thrust < target_thrust)
+ entity_thrust = target_thrust;
+ }
+ math::clamp(entity_thrust, 0.0f, 1.0f);
+ float actual_thrust = entity_thrust + current_target_afterburner * 0.15f;
+
+ if ((entity_eventstate == core::Entity::ImpulseInitiate) || (entity_eventstate == core::Entity::Impulse)) {
+ actual_thrust = 1.0f;
+ }
+
+ // update speed
+ if (entity_speed < actual_thrust * actual_maxspeed) {
+ entity_speed += actual_acceleration * seconds;
+ if (entity_speed > actual_thrust * actual_maxspeed) {
+ entity_speed = actual_thrust * actual_maxspeed;
+ }
+ } else if(entity_speed > actual_thrust * actual_maxspeed) {
+ entity_speed -= actual_acceleration * seconds;
+ if (entity_speed < actual_thrust * actual_maxspeed) {
+ entity_speed = actual_thrust * actual_maxspeed;
+ }
+ }
+
+ // update strafe
+ if (current_target_strafe < target_strafe) {
+ current_target_strafe += 2.0f * seconds;
+ if (current_target_strafe > target_strafe)
+ current_target_strafe = target_strafe;
+ } else if (current_target_strafe > target_strafe) {
+ current_target_strafe -= 2.0f * seconds;
+ if (current_target_strafe < target_strafe)
+ current_target_strafe = target_strafe;
+ }
+
+ if (fabs(current_target_strafe) > MIN_DELTA) {
+ entity_location += entity_axis.left() * (current_target_strafe * Base::instance()->g_strafespeed->value());
+ }
+
+ entity_movement = target_thrust;
+ entity_movement = math::max(entity_movement, fabs(current_target_pitch));
+ entity_movement = math::max(entity_movement, fabs(current_target_direction));
+ entity_movement = math::max(entity_movement, fabs(current_target_roll));
+ entity_movement = math::max(entity_movement, fabs(current_target_afterburner));
+ entity_movement = math::max(entity_movement, fabs(current_target_strafe));
+
+ if (entity_speed) {
+ entity_location += entity_axis.forward() * entity_speed * seconds;
+ entity_dirty = true;
+ } else if (entity_movement > 0.0f) {
+ entity_dirty = true;
+ }
+}
+
+} // namespace game