From a1eb1b4dc4d81df724ee43fc4e895dd22e81760f Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 9 Nov 2008 21:45:18 +0000 Subject: working jumpgates --- src/game/base/game.cc | 774 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 774 insertions(+) create mode 100644 src/game/base/game.cc (limited to 'src/game/base/game.cc') diff --git a/src/game/base/game.cc b/src/game/base/game.cc new file mode 100644 index 0000000..d20dd8c --- /dev/null +++ b/src/game/base/game.cc @@ -0,0 +1,774 @@ +/* + base/game.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include +#include +#include + +#include "auxiliary/functions.h" +#include "core/gameserver.h" +#include "core/parser.h" +#include "core/descriptions.h" +#include "filesystem/filesystem.h" +#include "filesystem/inifile.h" +#include "base/game.h" +#include "base/navpoint.h" +#include "base/jumppoint.h" +#include "base/planet.h" +#include "base/racetrack.h" +#include "base/ship.h" +#include "base/star.h" +#include "math/mathlib.h" +#include "sys/sys.h" + +namespace game +{ + +/* -- class Base static members ----------------------------------- */ + +// game variables +core::Cvar *Game::g_impulsespeed = 0; +core::Cvar *Game::g_impulseacceleration = 0; +core::Cvar *Game::g_strafespeed = 0; +core::Cvar *Game::g_jumppointrange = 0; +core::Cvar *Game::g_devel = 0; + +core::Zone *Game::default_zone = 0; +ShipModel *Game::default_shipmodel = 0; + +// list the ship model registry +void Game::func_list_ship(std::string const &args) +{ + ShipModel::list(); +} + +// a player joins the game +void Game::func_join(core::Player *player, std::string const &args) +{ + if (player->control()) + return; + + Ship *ship = new Ship(player, Game::default_shipmodel); + ship->set_zone(player->zone()); + player->set_control(ship); + + core::Entity *dock = ship->zone()->default_view(); + if (dock) { + ship->entity_location.assign(dock->location() + (dock->axis().forward() * ((ship->radius()+ dock->radius())*2.0f))); + ship->entity_axis.assign(dock->axis()); + ship->set_eventstate(core::Entity::Docked); + player->set_view(dock); + } + + std::string message("^B"); + message.append(player->name()); + message.append("^B joins the game."); + core::server()->broadcast(message); + + player->send("^BYou received " + aux::article(Game::default_shipmodel->name())); + player->sound("game/buy-ship"); + + player->player_dirty = true; +} + +// a player joins the spectators +void Game::func_spectate(core::Player *player, std::string const &args) +{ + if (!player->control()) + return; + + std::string message("^B"); + message.append(player->name()); + message.append("^B spectates."); + core::server()->broadcast(message); + + if (player->control()) { + player->remove_asset(player->control()); + } + + if (!player->zone()) + player->set_zone(Game::default_zone); + + player->set_view(0); +} + +// a player buys a ship +void Game::func_buy(core::Player *player, std::string const &args) +{ + if (!g_devel->value() && !player->view()) { + player->send("Cheats disabled."); + return; + } + + // FIXME verify the base sells this ship + + std::string shipname; + std::string helpstr; + std::istringstream is(args); + is >> shipname; + aux::to_lowercase(shipname); + + ShipModel *shipmodel = 0; + for (ShipModel::iterator smit = ShipModel::registry.begin(); smit != ShipModel::registry.end(); smit++) { + if (shipname == (*smit).first) { + shipmodel = (*smit).second; + break; + } + + if (helpstr.size()) + helpstr.append("^N|^B"); + helpstr.append((*smit).second->label()); + } + + if (shipmodel) { + // player has only ship for now + if (player->control()) { + player->remove_asset(player->control()); + } + + core::Entity *dock = player->view(); + Ship * ship = new Ship(player, shipmodel); + ship->set_zone(player->zone()); + player->set_control(ship); + + if (dock) { + player->control()->location().assign(dock->location()); + player->control()->set_eventstate(core::Entity::Docked); + ship->entity_axis.assign(dock->axis()); + ship->entity_axis.change_direction(180.0f); + player->set_view(dock); + } + + player->send("^BPurchased " + aux::article(shipmodel->name())); + player->sound("game/buy-ship"); + + } else { + player->send("Usage: buy [^B" + helpstr + "^N]"); + } +} + +// a player sends standard hails +void Game::func_hail(core::Player *player, std::string const &args) +{ + if (player->mute()) { + player->send("^WYou have been muted"); + return; + } + + std::string target; + std::istringstream is(args); + if (!(is >> target)) { + player->send("Usage: hail [player]"); + return; + } + + core::Player *targetplayer = core::server()->find_player(target); + if (!targetplayer) { + player->send("Player " + target + "^N not found"); + return; + } + + player->send("^BYou hail " + targetplayer->name()); + player->sound("com/hail"); + + targetplayer->send("^B" + player->name() + "^B hails you"); + targetplayer->sound("com/hail"); +} + +// a player actives the hyperspace jump drive on his ship +void Game::func_jump(core::Player *player, std::string const &args) +{ + if (!player->control()) + return; + if (!player->control()->moduletype() == ship_enttype) + return; + Ship * ship = static_cast(player->control()); + ship->func_jump(args); +} + +// a player actives the kinetic impulse drive on his ship +void Game::func_impulse(core::Player *player, std::string const &args) +{ + if (!player->control()) + return; + if (!player->control()->moduletype() == ship_enttype) + return; + Ship * ship = static_cast(player->control()); + ship->func_impulse(); +} + +// a player sends a docking request +void Game::func_dock(core::Player *player,core::Entity *entity) +{ + if (!player->control()) + return; + + if (player->control()->zone() != entity->zone()) + return; + + if ((entity->flags() & core::Entity::Dockable) == 0) + return; + + if (player->control()->eventstate() == core::Entity::Docked) + return; + + if (math::distance(entity->location(), player->control()->location()) > 2.0f * (entity->radius()+player->control()->radius())) { + player->send("Target out of range"); + return; + } + + if (entity->moduletype() == jumpgate_enttype) { + JumpGate *jumpgate = static_cast(entity); + if (jumpgate->target()) { + if (jumpgate->activated()) { + player->send("Jumpgate in use"); + return; + } + player->set_view(jumpgate); + Ship * ship = static_cast(player->control()); + ship->initiate_jump(jumpgate); + jumpgate->activate(); + if (jumpgate->target()->moduletype() == jumpgate_enttype) { + static_cast(jumpgate->target())->activate(); + } + } else { + player->send("Jumpgate inactive."); + } + } else { + + player->control()->location().assign(entity->location()); + player->control()->set_eventstate(core::Entity::Docked); + player->set_view(entity); + player->send("^BDocking at " + entity->name()); + } +} + +// launch request +void Game::func_launch(core::Player *player, std::string const &args) +{ + if (!player->control()) + return; + + if (!player->view()) + return; + + if (player->control()->eventstate() != core::Entity::Docked) + return; + + assert(player->view()->zone() == player->control()->zone()); + + core::Entity *dock = player->view(); + player->control()->entity_location.assign(dock->location() + (dock->axis().forward() * (player->control()->radius()+ dock->radius())*2.0f)); + player->control()->entity_axis.assign(dock->axis()); + player->control()->set_eventstate(core::Entity::Normal); + player->set_view(0); + + player->send("^BLaunching from " + dock->name()); +} + +// instantaniously goto a specified entity within the zone +void Game::func_goto(core::Player *player, const std::string &args) +{ + if (!args.size()) + return; + + if (!g_devel->value()) { + player->send("Cheats disabled"); + return; + } + + if (!player->control()) + return; + + core::Entity *dock = 0; + std::string label(args); + aux::to_label(label); + + core::Zone *zone = player->control()->zone(); + for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it ++) { + std::string str((*it)->label()); + aux::to_label(str); + if (str.find(label) != std::string::npos) { + dock = (*it); + } + } + + if (dock) { + player->control()->entity_location.assign(dock->location() + (dock->axis().forward() * (player->control()->radius()+dock->radius())*2.0f)); + player->control()->entity_axis.assign(dock->axis()); + player->control()->entity_axis.change_direction(180.0f); + player->control()->set_eventstate(core::Entity::Normal); + player->set_view(0); + player->send("Going to " + dock->name()); + } else { + player->send("Entity '" + args + "' not found"); + } +} + +/* -- class Base -------------------------------------------------- */ + +Game::Game() : core::Module("base", "Project::OSiRiON", true) +{ + default_shipmodel = 0; + default_zone = 0; +} + +Game::~Game() +{ +} + +void Game::init() +{ + ShipModel::clear(); + + if (!load_world()) { + abort(); + return; + } + + if (!load_ships()) { + abort(); + return; + } + + // add engine functions + core::Func *func = 0; + + func = core::Func::add("list_ship", Game::func_list_ship); + func->set_info("list ship statistics"); + + func = core::Func::add("join", Game::func_join); + func->set_info("join the game"); + + func = core::Func::add("hail", Game::func_hail); + func->set_info("send a standard hail"); + + func = core::Func::add("spectate", Game::func_spectate); + func->set_info("leave the game and spectate"); + + func = core::Func::add("buy", Game::func_buy); + func->set_info("buy a ship"); + + func = core::Func::add("jump", Game::func_jump); + func->set_info("[string] activate or deactivate hyperspace jump drive"); + + func = core::Func::add("impulse", Game::func_impulse); + func->set_info("activate are deactive kinetic impulse drive"); + + func = core::Func::add("launch", Game::func_launch); + func->set_info("launch to space when docked"); + + func = core::Func::add("goto", Game::func_goto); + func->set_info("[string] goto to an entity within the zone"); + + func = core::Func::add("@dock", Game::func_dock); + func->set_info("dock with target object"); + + // add engine variables + g_impulsespeed = core::Cvar::get("g_impulsespeed", "15", core::Cvar::Game | core::Cvar::Archive); + g_impulsespeed->set_info("[float] speed of the impulse drive"); + + g_impulseacceleration = core::Cvar::get("g_impulseacceleration", "5", core::Cvar::Game | core::Cvar::Archive); + g_impulseacceleration->set_info("[float] acceleration of the impulse drive"); + + g_strafespeed = core::Cvar::get("g_strafespeed", "0.01", core::Cvar::Game | core::Cvar::Archive); + g_strafespeed->set_info("[float] strafe speed"); + + g_jumppointrange = core::Cvar::get("g_jumppointrange", "512", core::Cvar::Game | core::Cvar::Archive); + g_jumppointrange->set_info("[float] jumppoint range"); + + g_devel = core::Cvar::get("g_devel", "0", core::Cvar::Archive); + g_devel->set_info("[bool] enable or disable developer mode"); +} + +void Game::shutdown() +{ + g_impulsespeed = 0; + // game functions are automaticly removed + + // remove engine core functions + core::Func::remove("list_ship"); + + ShipModel::clear(); +} + +bool Game::load_world() +{ + std::string inifilename("world"); + + filesystem::IniFile worldini; + worldini.open(inifilename); + + if (!worldini.is_open()) { + con_error << "Could not open " << worldini.name() << std::endl; + return false; + } + + con_print << "^BLoading world..." << std::endl; + + core::Zone *zone = 0; + std::string label; + + while (worldini.getline()) { + + if (worldini.got_section()) { + + if (worldini.got_section("world")) { + continue; + } else { + worldini.unknown_section(); + } + + } else if (worldini.got_key()) { + + if (worldini.in_section("world")) { + + if (worldini.got_key_string("zone", label)) { + aux::to_label(label); + zone = new core::Zone(label); + core::Zone::add(zone); + } else { + worldini.unkown_key(); + } + } + } + } + + worldini.close(); + + if (!core::Zone::registry().size()) { + con_error << "No zones found!" << std::endl; + return false; + } + + con_debug << " " << worldini.name() << " " << core::Zone::registry().size() << " zones" << std::endl; + + for (core::Zone::Registry::iterator it = core::Zone::registry().begin(); it != core::Zone::registry().end(); it++) { + if (!load_zone((*it).second)) { + return false; + } + } + + for (core::Zone::Registry::iterator it = core::Zone::registry().begin(); it != core::Zone::registry().end(); it++) { + if (!validate_zone((*it).second)) { + return false; + } + } + + if (!default_zone) { + con_error << "No default zone found!" << std::endl; + return false; + } + + return true; +} + +bool Game::load_zone(core::Zone *zone) +{ + using math::Vector3f; + using math::Color; + + std::string inifilename("zones/"); + inifilename.append(zone->label()); + + filesystem::IniFile zoneini; + zoneini.open(inifilename); + + if (!zoneini.is_open()) { + con_error << "Could not open " << zoneini.name() << std::endl; + return false; + } + + con_print << "^BLoading zone " << zone->label() << "..." << std::endl; + + size_t count = 0; + + Planet *planet = 0; + Star *star = 0; + NavPoint *navpoint = 0; + JumpPoint *jumppoint = 0; + RaceTrack *racetrack = 0; + CheckPoint *checkpoint = 0; + core::Entity *entity = 0; + + bool b; + + std::string strval; + + // set th default sky + zone->set_sky("sky"); + + while (zoneini.getline()) { + + if (zoneini.got_section()) { + if (zoneini.got_section("zone")) { + continue; + + } else if (zoneini.got_section("star")) { + star = new Star(); + star->set_zone(zone); + count ++; + + } else if (zoneini.got_section("navpoint")) { + navpoint = new NavPoint(); + navpoint->set_zone(zone); + count ++; + + } else if (zoneini.got_section("jumpgate")) { + jumppoint = new JumpGate(); + jumppoint->set_zone(zone); + count ++; + + } else if (zoneini.got_section("jumppoint")) { + jumppoint = new JumpPoint(); + jumppoint->set_zone(zone); + count ++; + + } else if(zoneini.got_section("racetrack")) { + racetrack = new RaceTrack(); + racetrack->set_zone(zone); + + } else if(zoneini.got_section("checkpoint")) { + checkpoint = new CheckPoint(racetrack); + if (!racetrack) { + con_warn << zoneini.name() << " checkpoint without racetrack at line " << zoneini.line() << std::endl; + } + + } else if (zoneini.got_section("planet")) { + planet = new Planet(); + planet->set_zone(zone); + count ++; + + } else if (zoneini.got_section("entity")) { + entity = new core::Entity(); + entity->set_flag(core::Entity::Static); + entity->set_zone(zone); + count ++; + + } else { + zoneini.unknown_section(); + } + + } else if (zoneini.got_key()) { + + if (zoneini.in_section("zone")) { + if (zoneini.got_key_string("name", strval)) { + aux::strip_quotes(strval); + zone->set_name(strval); + continue; + } else if (zoneini.got_key_string("sky", strval)) { + zone->set_sky(strval); + continue; + } else if (zoneini.got_key_bool("default", b)) { + if (b) default_zone = zone; + continue; + } else { + zoneini.unkown_key(); + } + + } else if (zoneini.in_section("star")) { + if (core::Parser::got_entity_key(zoneini, star)) { + continue; + } else if (zoneini.got_key_string("texture", star->entity_texture)) { + continue; + } else { + zoneini.unkown_key(); + } + + } else if (zoneini.in_section("navpoint")) { + if (core::Parser::got_entity_key(zoneini, navpoint)) { + continue; + } else { + zoneini.unkown_key(); + } + + } else if (zoneini.in_section("jumppoint") || zoneini.in_section("jumpgate")) { + if (core::Parser::got_entity_key(zoneini, jumppoint)) { + continue; + } else if (zoneini.got_key_string("target", strval)) { + jumppoint->set_targetlabel(strval); + continue; + } else { + zoneini.unkown_key(); + } + + } else if (zoneini.in_section("planet")) { + if (core::Parser::got_entity_key(zoneini, planet)) { + continue; + } else if (zoneini.got_key_string("texture", planet->entity_texture)) { + continue; + } else if (zoneini.got_key_float("rotationspeed", planet->entity_rotationspeed)) { + continue; + } else if (zoneini.got_key_bool("dock", b)) { + if (b) { + planet->set_flag(core::Entity::Dockable); + core::Descriptions::load_entity_menus(planet, "zones/" + zone->label() + "/" + planet->label()); + } else { + planet->unset_flag(core::Entity::Dockable); + } + } else if (zoneini.got_key_bool("default", b)) { + if (b) { + zone->set_default_view(planet); + } + continue; + } else { + zoneini.unkown_key(); + } + + } else if (zoneini.in_section("racetrack")) { + if (core::Parser::got_entity_key(zoneini, racetrack)) { + continue; + } else { + zoneini.unkown_key(); + } + + } else if (zoneini.in_section("checkpoint")) { + if (core::Parser::got_entity_key(zoneini, checkpoint)) { + continue; + } else { + zoneini.unkown_key(); + } + + } else if (zoneini.in_section("entity")) { + if (core::Parser::got_entity_key(zoneini, entity)) { + continue; + } else if (zoneini.got_key_bool("default", b)) { + if (b) { + zone->set_default_view(entity); + } + } else if (zoneini.got_key_bool("dock", b)) { + if (b) { + entity->set_flag(core::Entity::Dockable); + core::Descriptions::load_entity_menus(entity, "zones/" + zone->label() + "/" + entity->label()); + } else { + entity->unset_flag(core::Entity::Dockable); + } + } else { + zoneini.unkown_key(); + } + } + + } + } + zoneini.close(); + + con_debug << " " << zoneini.name() << " " << zone->content().size() << " entities" << std::endl; + + + return true; +} + +bool Game::validate_zone(core::Zone *zone) +{ + con_debug << " validating " << zone->name() << std::endl; + + for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { + core::Entity *entity = (*it); + if (entity->entity_moduletypeid == jumppoint_enttype) { + // validate jump points + JumpPoint *jumppoint = static_cast(entity); + jumppoint->validate(); + } else if (entity->entity_moduletypeid == jumpgate_enttype) { + // validate jump gate + JumpGate *jumpgate = static_cast(entity); + jumpgate->validate(); + } + } + + return true; +} + +// read ship model specifications +bool Game::load_ships() +{ + using math::Vector3f; + using math::Color; + + default_shipmodel = 0; + + filesystem::IniFile shipsini; + shipsini.open("ships"); + if (!shipsini.is_open()) { + con_error << "Could not open ini/ships.ini!" << std::endl; + return false; + } + + ShipModel *shipmodel = 0; + std::string label; + bool b; + + while (shipsini.getline()) { + if (shipsini.got_key()) { + if (shipsini.section().compare("ship") == 0) { + if (shipsini.got_key_string("label", label)) { + aux::to_label(label); + shipmodel->shipmodel_label.assign(label); + ShipModel::add(shipmodel); + continue; + } else if (shipsini.got_key_string("name",shipmodel->shipmodel_name)) { + continue; + } else if (shipsini.got_key_string("model", shipmodel->shipmodel_modelname)) { + continue; + } else if (shipsini.got_key_bool("default", b)) { + if (b) default_shipmodel = shipmodel; + continue; + } else if (shipsini.got_key_bool("jumpdrive", shipmodel->shipmodel_jumpdrive)) { + continue; + } else if (shipsini.got_key_float("acceleration", shipmodel->shipmodel_acceleration)) { + continue; + } else if (shipsini.got_key_float("maxspeed", shipmodel->shipmodel_maxspeed)) { + continue; + } else if (shipsini.got_key_float("turnspeed", shipmodel->shipmodel_turnspeed)) { + math::clamp(shipmodel->shipmodel_turnspeed, 0.0f, 90.0f); + continue; + } else { + con_warn << shipsini.name() << " unknown key '" << shipsini.key() << "' at line " << shipsini.line() << std::endl; + } + } + } else if (shipsini.got_section("ship")) { + shipmodel = new ShipModel(); + + if (!default_shipmodel) + default_shipmodel = shipmodel; + + } else if (shipsini.got_section()) { + con_warn << shipsini.name() << " unknown section '" << shipsini.section() << "' at line " << shipsini.line() << std::endl; + } + } + shipsini.close(); + + con_debug << " " << shipsini.name() << " " << ShipModel::registry.size() << " ship models" << std::endl; + + if (!default_shipmodel) { + con_error << "No default ship model found!\n"; + return false; + } + + return true; +} + +void Game::frame(float seconds) +{ + if (!running()) + return; +} + +void Game::player_connect(core::Player *player) +{ + std::string args; + player->set_zone(default_zone); + player->set_view(0); // not docked + + func_spectate(player, args); +} + +void Game::player_disconnect(core::Player *player) +{ + player->remove_asset(player->control()); +} + +} // namespace game + -- cgit v1.2.3