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-10-16 20:59:08 +0000
committerStijn Buys <ingar@osirion.org>2013-10-16 20:59:08 +0000
commit71b517e154e4644fcf0f8bb3b8b40b7898ecdd9d (patch)
tree71fe2b8e08e25425893fd363e9e82730e86add83
parentce62661012a167d48bd6117940a551355eb6773b (diff)
Added support for autopilot formation flight and docking.
-rw-r--r--src/game/base/game.cc100
-rw-r--r--src/game/base/game.h10
-rw-r--r--src/game/base/ship.cc115
-rw-r--r--src/game/base/ship.h19
4 files changed, 206 insertions, 38 deletions
diff --git a/src/game/base/game.cc b/src/game/base/game.cc
index 72a684b..789f2d5 100644
--- a/src/game/base/game.cc
+++ b/src/game/base/game.cc
@@ -163,6 +163,7 @@ void Game::func_freeflight(core::Player *player, std::string const &args)
ship->set_autopilot_target(0);
ship->unset_autopilot_flag(Ship::AutoPilotEnabled);
+ // TODO replace with "autopilot disabled" voice
player->send("Autopilot disabled");
}
@@ -183,20 +184,15 @@ void Game::func_target_goto(core::Player *player, core::Entity *entity)
Ship * ship = static_cast<Ship *>(player->control());
- if (ship->has_autopilot_flag(Ship::AutoPilotEnabled) && (entity == ship->autopilot_target())) {
- ship->set_autopilot_target(0);
- ship->unset_autopilot_flag(Ship::AutoPilotEnabled);
- player->send("Autopilot disabled");
- } else {
- ship->set_autopilot_target(entity);
- ship->set_autopilot_flag(Ship::AutoPilotEnabled);
- ship->unset_autopilot_flag(Ship::AutoPilotDock);
- ship->unset_autopilot_flag(Ship::AutoPilotFormation);
- player->send("Autopilot set to " + entity->name());
- }
+ ship->set_autopilot_target(entity);
+ ship->set_autopilot_flag(Ship::AutoPilotEnabled);
+ ship->unset_autopilot_flag(Ship::AutoPilotDock);
+ ship->unset_autopilot_flag(Ship::AutoPilotFormation);
+ // TODO replace with "goto" voice
+ player->send("Autopilot set to " + entity->name());
}
-// a player sends a docking request
+/*
void Game::func_target_dock(core::Player *player, core::Entity *entity)
{
if (!player->control())
@@ -224,7 +220,7 @@ void Game::func_target_dock(core::Player *player, core::Entity *entity)
float range = entity->radius() + ship->radius();
if (entity->moduletype() == planet_enttype) {
- range += planet_safe_distance;
+ range += PLANET_SAFE_DISTANCE;
}
core::Player *owner = (entity->type() == core::Entity::Controlable ? static_cast<core::EntityControlable *>(entity)->owner() : 0 );
@@ -269,6 +265,77 @@ void Game::func_target_dock(core::Player *player, core::Entity *entity)
core::server()->module()->player_save(player);
}
}
+*/
+
+// a player sends a docking request
+void Game::func_target_dock(core::Player *player, core::Entity *entity)
+{
+ if (!player->control()) {
+ return;
+ }
+
+ if (player->control() == entity) {
+ return;
+ }
+
+ if (!entity->has_flag(core::Entity::Dockable)) {
+ return;
+ }
+
+ if (player->control()->zone() != entity->zone()) {
+ return;
+ }
+
+ if (player->control()->moduletype() != ship_enttype) {
+ return;
+ }
+
+ Ship * ship = static_cast<Ship *>(player->control());
+
+ ship->set_autopilot_target(entity);
+ ship->set_autopilot_flag(Ship::AutoPilotEnabled);
+ ship->set_autopilot_flag(Ship::AutoPilotDock);
+ ship->unset_autopilot_flag(Ship::AutoPilotFormation);
+
+ if (math::distance(player->control()->location(), entity->location()) > (player->control()->radius() + entity->radius() + PLANET_SAFE_DISTANCE)) {
+ // TODO replace with "dock" voice
+ player->send("Autopilot set to dock at " + entity->name());
+ }
+}
+
+void Game::func_target_formation(core::Player *player, core::Entity *entity)
+{
+ if (!player->control()) {
+ return;
+ }
+
+ if (player->control() == entity)
+ return;
+
+ if (entity->type() != core::Entity::Controlable) {
+ return;
+ }
+
+ if (player->control()->zone() != entity->zone()) {
+ return;
+ }
+
+ if (player->control()->moduletype() != ship_enttype) {
+ return;
+ }
+
+ Ship * ship = static_cast<Ship *>(player->control());
+
+ ship->set_autopilot_target(entity);
+ ship->set_autopilot_flag(Ship::AutoPilotEnabled);
+ ship->unset_autopilot_flag(Ship::AutoPilotDock);
+ ship->set_autopilot_flag(Ship::AutoPilotFormation);
+
+ if (math::distance(player->control()->location(), entity->location()) > (player->control()->radius() + entity->radius() + PLANET_SAFE_DISTANCE)) {
+ // TODO replace with "formation" voice
+ player->send("Autopilot set to formation with " + entity->name());
+ }
+}
// a player sends a standard hail
void Game::func_target_hail(core::Player *player, core::Entity *entity)
@@ -1561,7 +1628,7 @@ void Game::func_goto(core::Player *player, const std::string &args)
if (dock) {
if (dock->type() == core::Entity::Globe) {
// target is a planet: keep a safe distance
- ship->get_location().assign(dock->location() + (dock->axis().forward() * (planet_safe_distance + ship->radius() + dock->radius())));
+ ship->get_location().assign(dock->location() + (dock->axis().forward() * (PLANET_SAFE_DISTANCE + ship->radius() + dock->radius())));
ship->get_axis().assign(dock->axis());
ship->get_axis().change_direction(180.0f);
@@ -1696,7 +1763,10 @@ Game::Game() : core::Module("Project::OSiRiON", true)
func->set_info("set autopilot to target");
func = core::Func::add("@dock", Game::func_target_dock);
- func->set_info("send a docking request to target");
+ func->set_info("set autopilot to dock at target");
+
+ func = core::Func::add("@formation", Game::func_target_formation);
+ func->set_info("set autopilot to formation flight with target");
func = core::Func::add("@hail", Game::func_target_hail);
func->set_info("send a standard hail to target");
diff --git a/src/game/base/game.h b/src/game/base/game.h
index 645d573..2fc5d95 100644
--- a/src/game/base/game.h
+++ b/src/game/base/game.h
@@ -37,9 +37,6 @@ const unsigned int cargopod_enttype = 263;
const unsigned int spacemine_enttype = 264;
const unsigned int race_enttype = 280;
-// planet docking distance
-const float planet_safe_distance = 50.0f;
-
// ship engine delay times
const float jump_timer_delay = 5.0f;
const float jump_cooldown_delay = 2.0f;
@@ -125,7 +122,6 @@ private:
static void func_impulse(core::Player *player, std::string const &args);
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_freeflight(core::Player *player, std::string const &args);
static void func_goto(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);
@@ -136,12 +132,18 @@ private:
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);
+
+
static void func_wingmen(core::Player *player, const std::string &args);
+ static void func_freeflight(core::Player *player, std::string const &args);
+
/* ---- target functions ----------------------------------- */
static void func_target_goto(core::Player *player, core::Entity *entity);
static void func_target_dock(core::Player *player, core::Entity *entity);
+ static void func_target_formation(core::Player *player, core::Entity *entity);
+
static void func_target_hail(core::Player *player, core::Entity *entity);
static void func_target_trade(core::Player *player, core::Entity *entity);
};
diff --git a/src/game/base/ship.cc b/src/game/base/ship.cc
index d816943..c93002c 100644
--- a/src/game/base/ship.cc
+++ b/src/game/base/ship.cc
@@ -18,6 +18,8 @@
#include "base/game.h"
#include "base/ship.h"
#include "base/spacemine.h"
+#include "base/jumppoint.h"
+#include "base/racetrack.h"
using math::degrees360f;
using math::degrees180f;
@@ -359,6 +361,9 @@ void Ship::set_dock(core::Entity *dock)
return;
}
+ ship_autopilot_flags = AutoPilotDisabled;
+ ship_autopilot_target = 0;
+
get_location().assign(dock->location());
get_axis().assign(dock->axis());
ship_dock = dock;
@@ -385,13 +390,17 @@ void Ship::launch()
get_axis().assign(ship_dock->axis());
if (ship_dock->type() == core::Entity::Globe)
- get_location().assign(ship_dock->location() + (ship_dock->axis().forward() * (planet_safe_distance + this->radius() + ship_dock->radius())));
+ get_location().assign(ship_dock->location() + (ship_dock->axis().forward() * (PLANET_SAFE_DISTANCE + this->radius() + ship_dock->radius())));
else
get_location().assign(ship_dock->location() + (ship_dock->axis().forward() * (this->radius() + ship_dock->radius())));
ship_dock = 0;
set_state(core::Entity::Normal);
+
+ ship_autopilot_flags = AutoPilotDisabled;
+ ship_autopilot_target = 0;
+
reset();
}
@@ -641,15 +650,8 @@ void Ship::frame(const unsigned long elapsed)
if (has_autopilot_flag(Ship::AutoPilotEnabled) && !has_target_controlflag(core::EntityControlable::ControlFlagOverride)) {
- if (!ship_autopilot_target) {
- unset_autopilot_flag(Ship::AutoPilotEnabled);
-
- } else if (!zone()->find_entity(ship_autopilot_target)) {
- ship_autopilot_target = 0;
-
- } else {
- frame_autopilot_goto(elapsed, ship_autopilot_target);
-
+ if ((state() == core::Entity::Normal) || (state() == core::Entity::Impulse) || (state() == core::Entity::ImpulseInitiate)) {
+ frame_autopilot(elapsed);
}
}
@@ -1013,7 +1015,35 @@ void Ship::frame(const unsigned long elapsed)
}
-void Ship::frame_autopilot_goto(const unsigned long elapsed, const core::Entity *target)
+void Ship::frame_autopilot(const unsigned long elapsed)
+{
+ if (!autopilot_target()) {
+ return;
+ }
+
+ if (!zone()->find_entity(ship_autopilot_target)) {
+ set_autopilot_target(0);
+ return;
+ }
+
+ // reference radius used in calculations
+ const float r = radius() + autopilot_target()->radius();
+ const float distance = math::distance(location(), autopilot_target()->location());
+ const float dock_distance = (autopilot_target()->moduletype() == planet_enttype ? r + PLANET_SAFE_DISTANCE : r);
+
+ // thruster and speed control
+ if (has_autopilot_flag(AutoPilotFormation) && (distance < 4.0f * r)) {
+ frame_autopilot_formation(elapsed, autopilot_target());
+
+ } else if (has_autopilot_flag(AutoPilotDock) && (distance < dock_distance)) {
+ frame_autopilot_dock(elapsed, autopilot_target());
+
+ } else {
+ frame_autopilot_goto(elapsed, autopilot_target());
+ }
+}
+
+void Ship::frame_autopilot_goto(const unsigned long elapsed, core::Entity *target)
{
// reference radius used in calculations
const float r = radius() + target->radius();
@@ -1043,7 +1073,7 @@ void Ship::frame_autopilot_goto(const unsigned long elapsed, const core::Entity
target_roll = 0.0f;
// impulse or thruster
- if (distance > r + 50.0f) {
+ if (distance > r + PLANET_SAFE_DISTANCE) {
if (state() == core::Entity::Normal) {
// enable impulse drive
@@ -1083,17 +1113,70 @@ void Ship::frame_autopilot_goto(const unsigned long elapsed, const core::Entity
if (distance > 4.0f * r) {
target_thrust = 1.0f;
- } else if (distance > 2.0f * r ) {
- target_thrust = (distance - 2.0f * r ) / 2.0f * r;
+ } else if (distance > r ) {
+ target_thrust = math::max(0.1f, (distance - r ) / (3.0f * r));
} else {
target_thrust = 0.0f;
-
// TODO autolevel
}
}
-void Ship::frame_autopilot_formation(const unsigned long elapsed, const core::Entity *target)
+void Ship::frame_autopilot_dock(const unsigned long elapsed, core::Entity *target)
+{
+ // reference radius used in calculations
+ //const float r = radius() + target->radius();
+ //const float dock_distance = (target->moduletype() == planet_enttype ? r + PLANET_SAFE_DISTANCE : r);
+
+ if ((state() == core::Entity::Impulse) || (state() == core::Entity::ImpulseInitiate)) {
+ func_impulse();
+ return;
+ }
+
+ if (state() != core::Entity::Normal) {
+ return;
+ }
+
+ if (target->moduletype() == jumpgate_enttype) {
+ // jumpgates have their own docking function
+ JumpGate *jumpgate = static_cast<JumpGate *>(target);
+ jumpgate->func_dock(this);
+ unset_autopilot_flag(AutoPilotDock);
+ return;
+
+ } else if (target->moduletype() == race_enttype) {
+ if (owner()) {
+ RaceTrack *race = static_cast<RaceTrack *>(target);
+ race->func_dock(this);
+
+ }
+
+ unset_autopilot_flag(AutoPilotDock);
+ return;
+ } else {
+ set_dock(target);
+
+ if (owner()) {
+
+ if (owner()->control() == this) {
+ owner()->set_view(target);
+ }
+
+ core::Player *dock_owner = (target->type() == core::Entity::Controlable ? static_cast<core::EntityControlable *>(target)->owner() : 0 );
+
+ if (dock_owner) {
+ owner()->send("^BDocking at " + dock_owner->name() + "^B's " + target->name());
+ } else {
+ owner()->send("^BDocking at " + target->name());
+ }
+
+ // force save
+ core::server()->module()->player_save(owner());
+ }
+ }
+}
+
+void Ship::frame_autopilot_formation(const unsigned long elapsed, core::Entity *target)
{
// transform the target's axis into local coordinates
const math::Axis reference(axis().transpose() * target->axis());
diff --git a/src/game/base/ship.h b/src/game/base/ship.h
index 7b25f18..61ff1c7 100644
--- a/src/game/base/ship.h
+++ b/src/game/base/ship.h
@@ -18,6 +18,10 @@ namespace game
const float MIN_DELTA = 0.000001f;
+// planet docking distance
+const float PLANET_SAFE_DISTANCE = 50.0f;
+
+
/**
* @brief A ship in the game, controled by a player
* */
@@ -85,7 +89,7 @@ public:
return ship_autopilot_target;
}
- inline bool has_autopilot_flag(const AutoPilotFlags flag) {
+ inline bool has_autopilot_flag(const AutoPilotFlags flag) const {
return ( (ship_autopilot_flags & flag) == flag);
}
@@ -207,16 +211,25 @@ public:
void set_spawn(core::Entity *spawn);
protected:
+ /**
+ * @brief autopilot frame
+ * */
+ void frame_autopilot(const unsigned long elapsed);
+
+ /**
+ * @brief autopilot goto target
+ * */
+ void frame_autopilot_goto(const unsigned long elapsed, core::Entity *target);
/**
* @brief autopilot goto target
* */
- void frame_autopilot_goto(const unsigned long elapsed, const core::Entity *target);
+ void frame_autopilot_dock(const unsigned long elapsed, core::Entity *target);
/**
* @brief autopilot formation flying
* */
- void frame_autopilot_formation(const unsigned long elapsed, const core::Entity *target);
+ void frame_autopilot_formation(const unsigned long elapsed, core::Entity *target);
private:
JumpPoint *find_closest_jumppoint();