/* game/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 "auxiliary/functions.h" #include "core/gameserver.h" #include "filesystem/filesystem.h" #include "filesystem/inifile.h" #include "game/game.h" #include "game/planet.h" #include "game/ship.h" #include "game/star.h" #include "math/mathlib.h" #include "sys/sys.h" namespace game { ShipModel *default_shipmodel = 0; core::Zone *default_zone = 0; /*----- engine game functions ------------------------------------- */ /// list the ship model registry void func_list_ship(std::string const &args) { ShipModel::list(); } /// a player joins the game void func_join(core::Player *player, std::string const &args) { if (player->control()) return; player->set_zone(default_zone); Ship *ship = new Ship(player, default_shipmodel); ship->set_zone(default_zone); player->set_control(ship); core::server()->send_sound(player, "game/buy-ship"); std::string message("^B"); message.append(player->name()); message.append("^B joins the game."); core::server()->broadcast(message); player->player_dirty = true; } /// a player joins the spectators void 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()); } } /// a player buys a ship void func_buy(core::Player *player, std::string const &args) { 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()); } Ship * ship = new Ship(player, shipmodel); if (player->zone()) { ship->set_zone(player->zone()); } else { ship->set_zone(default_zone); } player->set_control(ship); core::server()->broadcast("^B" + player->name() + " ^Bpurchased " + aux::article(shipmodel->name())); core::server()->send_sound(player, "game/buy-ship"); } else { core::server()->send(player, "Usage: buy [^B" + helpstr + "^N]"); } } /// a player sends standard hails void func_hail(core::Player *player, std::string const &args) { std::string target; std::istringstream is(args); if (!(is >> target)) { core::server()->send(player, "Usage: hail [player]"); return; } core::Player *targetplayer = core::server()->find_player(target); if (!targetplayer) { core::server()->send(player, "^BPlayer " + target + "^B not found."); return; } core::server()->send(player, "^BYou hail " + targetplayer->name() + "^B."); core::server()->send_sound(player, "com/hail"); core::server()->send(targetplayer, "^B" + player->name() + "^B hails you!"); core::server()->send_sound(targetplayer, "com/hail"); } /// a player actives the jumpdrive on his ship void 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()); if (!ship->jumpdrive()) { core::server()->send(player, "Your ship is not equiped with a jumpdrive"); return; } 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(player, "Usage: jump [^B" + helpstr + "^N]"); return; } aux::to_lowercase(target); core::Zone *zone = core::Zone::find_zone(target); if (!zone) { core::server()->send(player, "Unknown system '" + target + '\''); return; } if (zone == player->control()->zone()) return; core::server()->send(player, "Jumping to '" + zone->name() + '\''); player->control()->set_zone(zone); player->set_zone(zone); } /* ---- The Game class --------------------------------------------- */ Game *Game::game_instance = 0; Game::Game() : core::Module("Project::OSiRiON") { game_instance = this; g_impulsespeed = 0; } Game::~Game() { game_instance = 0; } void Game::init() { module_running = false; ShipModel::clear(); if (!load_world()) { abort(); return; } if (!load_ships()) { abort(); return; } // add engine game functions core::Func *func = 0; func = core::Func::add("buy", (core::GameFuncPtr) func_buy); func->set_info("buy a ship"); func = core::Func::add("jump", (core::GameFuncPtr) func_jump); func->set_info("make a hyperspace jump"); func = core::Func::add("join", (core::GameFuncPtr) func_join); func->set_info("join the game"); func = core::Func::add("hail", (core::GameFuncPtr) func_hail); func->set_info("send a standard hail"); func = core::Func::add("spectate", (core::GameFuncPtr) func_spectate); func->set_info("leave the game and spectate"); // add engine core functions func = core::Func::add("list_ship", (core::FuncPtr) func_list_ship); func->set_info("list ship statistics"); g_impulsespeed = core::Cvar::get("g_impulsespeed", "15", core::Cvar::Game | core::Cvar::Archive); g_impulsespeed->set_info("[float] speed of the impulse drive"); // indicate the module is ready to run frames module_running = true; } void Game::shutdown() { g_impulsespeed = 0; // game functions are automaticly removed // remove engine core functions core::Func::remove("list_ship"); ShipModel::clear(); module_running = false; } 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; } core::Zone *zone = 0; std::string label; while (worldini.getline()) { if (worldini.got_section()) { if (worldini.got_section("world")) { continue; } else { con_warn << worldini.name() << " unknown section '" << worldini.section() << "' at line " << worldini.line() << std::endl; } } else if (worldini.section().compare("world") == 0 ) { if (worldini.got_key_string("zone", label)) { aux::to_label(label); zone = new core::Zone(label); core::Zone::add(zone); } } } 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; } } 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; } size_t count = 0; Planet *planet = 0; Star *star = 0; core::Entity *entity = 0; float direction; float pitch; float roll; bool b; std::string strval; // set th default sky zone->set_sky("sky"); while (zoneini.getline()) { if (zoneini.got_key()) { if (zoneini.section().compare("zone") == 0) { if (zoneini.got_key_string("name", 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 { con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; } } else if (zoneini.section().compare("star") == 0) { if (zoneini.got_key_string("label", strval)) { aux::to_label(strval); star->entity_label.assign(strval); continue; } else if (zoneini.got_key_string("name", star->entity_name)) continue; else if (zoneini.got_key_vector3f("location", star->entity_location )) continue; else if (zoneini.got_key_color("color", star->entity_color)) continue; else if (zoneini.got_key_angle("radius", star->entity_radius)) continue; else con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; } else if (zoneini.section().compare("planet") == 0) { if (zoneini.got_key_string("label", strval)) { aux::to_label(strval); planet->entity_label.assign(strval); continue; } else if (zoneini.got_key_string("name", planet->entity_name)) continue; else if (zoneini.got_key_string("texture", planet->entity_texture)) continue; else if (zoneini.got_key_vector3f("location", planet->entity_location )) continue; else if (zoneini.got_key_color("color", planet->entity_color)) continue; else if (zoneini.got_key_angle("radius", planet->entity_radius)) continue; else con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; } else if (zoneini.section().compare("entity") == 0) { std::string shapename; if (zoneini.got_key_string("shape", shapename)) { if (shapename.compare("axis") == 0) { entity->entity_shape = core::Entity::Axis; } else if (shapename.compare("cube") == 0) { entity->entity_shape = core::Entity::Cube; } else if (shapename.compare("diamond") == 0) { entity->entity_shape = core::Entity::Diamond; } else if (shapename.compare("sphere") == 0) { entity->entity_shape = core::Entity::Sphere; } else { con_warn << zoneini.name() << " unknown shape '" << shapename << "' at line " << zoneini.line() << std::endl; } continue; } else if (zoneini.got_key_string("label", strval)) { aux::to_label(strval); entity->entity_label.assign(strval); continue; } else if (zoneini.got_key_string("name", entity->entity_name)) { continue; } else if (zoneini.got_key_string("model", entity->entity_modelname)) { continue; } else if (zoneini.got_key_angle("direction", direction)) { entity->axis().change_direction(direction); continue; } else if (zoneini.got_key_angle("pitch", pitch)) { entity->axis().change_pitch(pitch); continue; } else if (zoneini.got_key_angle("roll", roll)) { entity->axis().change_roll(roll); continue; } else if (zoneini.got_key_angle("radius", entity->entity_radius)) { continue; } else if (zoneini.got_key_vector3f("location", entity->entity_location)) { continue; } else if (zoneini.got_key_color("color", entity->entity_color)) { continue; } else if (zoneini.got_key_color("colorsecond", entity->entity_color_second)) { continue; } else { con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; } } } else 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("planet")) { planet = new Planet(); planet->set_zone(zone); count ++; } else if (zoneini.got_section("entity")) { entity = new core::Entity(); entity->entity_flags += core::Entity::Static; entity->set_zone(zone); count ++; } else if (zoneini.got_section()) { con_warn << zoneini.name() << " unknown section '" << zoneini.section() << "' at line " << zoneini.line() << std::endl; } } zoneini.close(); con_debug << " " << zoneini.name() << " " << zone->content().size() << " entities" << std::endl; 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); func_spectate(player, args); } void Game::player_disconnect(core::Player *player) { player->remove_asset(player->control()); } } // namespace game