From 71b517e154e4644fcf0f8bb3b8b40b7898ecdd9d Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Wed, 16 Oct 2013 20:59:08 +0000 Subject: Added support for autopilot formation flight and docking. --- src/game/base/game.cc | 100 ++++++++++++++++++++++++++++++++++++------- src/game/base/game.h | 10 +++-- src/game/base/ship.cc | 115 +++++++++++++++++++++++++++++++++++++++++++------- src/game/base/ship.h | 19 +++++++-- 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(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(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(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(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(target); + jumpgate->func_dock(this); + unset_autopilot_flag(AutoPilotDock); + return; + + } else if (target->moduletype() == race_enttype) { + if (owner()) { + RaceTrack *race = static_cast(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(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(); -- cgit v1.2.3