/* base/shipmodel.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 #include #include "auxiliary/functions.h" #include "base/shipmodel.h" #include "base/game.h" #include "base/template.h" #include "sys/sys.h" namespace game { core::InfoType *ShipModel::shipmodel_infotype = 0; void func_list_ship(const std::string &args) { ShipModel::list(); } bool ShipModel::init() { // initialize shipmodel InfoType ShipModel::shipmodel_infotype = new core::InfoType("ship"); using math::Vector3f; using math::Color; filesystem::IniFile inifile; inifile.open("ini/ships"); if (!inifile.is_open()) { con_error << "Could not open " << inifile.name() << "!" << std::endl; return false; } con_print << "^BLoading ships..." << std::endl; size_t shipmodel_count = 0; size_t template_count = 0; ShipModel *shipmodel = 0; Template *entitytemplate = 0; std::string str; long l; float f; bool b; while (inifile.getline()) { if (inifile.got_key()) { if (inifile.section().compare("template") == 0) { if (Template::got_template_key(inifile, entitytemplate)) { continue; } else { inifile.unknown_key(); } } else if (inifile.section().compare("ship") == 0) { if (inifile.got_key_label("label", str)) { if (find(str)) { inifile.unknown_error("duplicate ship type '" + str + "'"); } shipmodel->set_label(str); continue; } else if (inifile.got_key_string("name", str)) { shipmodel->set_name(str); continue; } else if (inifile.got_key_string("info", str)) { shipmodel->add_text(str); continue; } else if (inifile.got_key_string("model", str)) { shipmodel->set_modelname(str); continue; } else if (inifile.got_key_long("price", l)) { shipmodel->set_price(l); continue; } else if (inifile.got_key_float("cargo", f)) { shipmodel->set_maxcargo(f); continue; } else if (inifile.got_key_bool("jumpdrive", b)) { shipmodel->set_jumpdrive(b); continue; } else if (inifile.got_key_bool("dock", b)) { shipmodel->set_dockable(b); continue; // } else if (inifile.got_key_float("maxspeed", f)) { // shipmodel->set_maxspeed(f * 0.01f); // continue; } else if (inifile.got_key_float("impulse", f)) { shipmodel->set_impulse_force(f); continue; } else if (inifile.got_key_float("thrust", f)) { shipmodel->set_thrust_force(f); continue; } else if (inifile.got_key_float("strafe", f)) { shipmodel->set_strafe_force(f); continue; } else if (inifile.got_key_float("turn", f)) { shipmodel->set_turn_force(f); continue; } else if (inifile.got_key_float("roll", f)) { shipmodel->set_roll_force(f); continue; } else if (inifile.got_key_float("mass", f)) { shipmodel->set_mass(f); continue; } else if (inifile.got_key_float("armor", f)) { shipmodel->set_maxarmor(f); continue; } else if (inifile.got_key_float("radius", f)) { shipmodel->set_radius(f); continue; } else if (inifile.got_key_string("damping", str)) { float linear, angular; std::istringstream sstr("str"); if (sstr >> linear) { if (sstr >> angular) { shipmodel->set_linear_damping(linear); shipmodel->set_angular_damping(angular); } else { shipmodel->set_linear_damping(linear); shipmodel->set_angular_damping(linear); } } else { inifile.unknown_value(); } } else if (inifile.got_key_label("template", str)) { Template *entitytemplate = Template::find(str); if (!entitytemplate) { inifile.unknown_error("unkown template '" + str + "'"); } else { // apply the template settings to the shipmodel shipmodel->set_template(entitytemplate); if (entitytemplate->radius()) { shipmodel->set_radius(entitytemplate->radius()); } if (entitytemplate->maxarmor()) { shipmodel->set_maxarmor(entitytemplate->maxarmor()); } } } else { inifile.unknown_key(); } } } else if (inifile.got_section("template")) { template_count++; entitytemplate = new Template(); } else if (inifile.got_section("ship")) { // generate info for the last loaded ship model if (shipmodel) { shipmodel->generate_info(); } // add a new shipmodel shipmodel = new ShipModel(); // the first ship model is set as default, game.ini can override this later if (!Default::shipmodel) { Default::shipmodel = shipmodel; } shipmodel_count++; } else if (inifile.got_section()) { inifile.unknown_section(); } } // generate info for the last loaded ship model if (shipmodel) { shipmodel->generate_info(); } con_debug << " " << inifile.name() << " " << template_count << " entity templates" << std::endl; con_debug << " " << inifile.name() << " " << shipmodel_count << " ship types" << std::endl; inifile.close(); core::Func *func = core::Func::add("list_ship", func_list_ship); func->set_info("list available ship types"); return true; } void ShipModel::done() { core::Func::remove("list_ship"); } ShipModel::ShipModel() : core::Info(shipmodel_infotype) { //shipmodel_maxspeed = 0; //default specifications shipmodel_radius = 0.0f; shipmodel_mass = 0.0f; shipmodel_linear_damping = 0.8f; shipmodel_angular_damping = 0.8f; shipmodel_thrust_force = 0.8f; shipmodel_impulse_force = 4.0f; shipmodel_strafe_force = 0.1f; shipmodel_turn_force = 2.5f; shipmodel_roll_force = 1.0f; shipmodel_maxcargo = 0.0f; shipmodel_maxarmor = 100.0f; shipmodel_jumpdrive = false; // no jumpdrive capability shipmodel_dockable = false; // not dockable shipmodel_template = 0; } ShipModel::~ShipModel() { } void ShipModel::generate_info() { // default mass set_mass(radius() * 100.0f); if (text().size()) add_line(""); add_line("^BSpecifications:^N"); std::stringstream str; str << "price: ^B" << price() << " ^Ncredits"; add_line(str.str()); str.str(""); str << "cargo hold: ^B" << maxcargo() << " ^Ncubic meter"; add_line(str.str()); str.str(""); str << "mass: ^B" << mass() << " ^Nmetric tonnes"; add_line(str.str()); str.str(""); str << "hull strength: ^B" << maxarmor() << "^N"; add_line(str.str()); str.str(""); if (jumpdrive()) { add_line("^Bhyperspace jump drive"); } if (dockable()) { add_line("^Bdockable"); } if (modelname().size()) { // FIXME the model has to be loaded to got slot information /* int nbcannons = 0; int nbturrets = 0; add_line(""); add_line("^BWeapons:^N"); */ } } ShipModel *ShipModel::find(const std::string & label) { if (!label.size()) { return 0; } return (ShipModel *) core::Info::find(shipmodel_infotype, label); } ShipModel *ShipModel::search(const std::string & searchstr) { if (!searchstr.size()) { return 0; } return (ShipModel *) core::Info::search(shipmodel_infotype, searchstr); } void ShipModel::list() { core::Info::list(shipmodel_infotype); } // a player buys a ship void ShipModel::buy(core::EntityControlable *buyer, core::Entity *seller) { if (!buyer || !seller) return; // can only buy at planets and stations if ((seller->moduletype() != station_enttype) && (seller->moduletype() != planet_enttype)) { buyer->owner()->send("^BCan not buy here"); return; } if (!buyer->owner()) return; if (!seller->inventory()) { buyer->owner()->send("^BCan not buy here"); return; } core::Player *player = buyer->owner(); // seller is the station or planet core::Item *seller_item = seller->inventory()->find(this); if (!seller_item) { if (player) { player->send("^B" + seller->name() + " ^Bdoes not sell " + name()); } return; } else { assert(seller_item->info() == this); } // check if there's enough space available to transfer inventory if (player->control() && (maxcargo() < player->control()->inventory()->capacity_used())) { player->send("^WNot enough cargo space to transfer inventory!"); return; } // check price if (price() > player->credits()) { player->send("^WCan not afford transaction!"); return; } Ship * ship = new Ship(player, this); ship->set_zone(seller->zone()); ship->get_location().assign(seller->location()); ship->get_axis().assign(seller->axis()); ship->get_axis().change_direction(180.0f); ship->set_dock(seller); //ship->reset(); // reset() is done by set_dock() // transfer inventory for (core::Inventory::Items::iterator it = player->control()->inventory()->items().begin(); it != player->control()->inventory()->items().end(); it++) { core::Item *item = new core::Item(*(*it)); item->unset_flag(core::Item::Mounted); ship->inventory()->add(item); } ship->inventory()->set_dirty(); // remove old ship if (player->control()) { player->remove_asset(player->control()); } // set control to new ship player->set_control(ship); player->set_view(seller); player->add_credits(-price()); // send the ship purchased message std::stringstream msgstr; msgstr << "^BPurchased " << aux::article(name()) << " for " << price() << " credits"; player->send(msgstr.str()); player->sound("game/buy-ship"); } void ShipModel::apply(core::Entity *entity) const { // apply template settings if available if (model_template()) model_template()->apply(entity); // apply entity settings if (label().size()) entity->set_label(label()); if (name().size()) entity->set_name(name()); if (modelname().size()) entity->set_modelname(modelname()); if (radius()) entity->set_radius(radius()); } void ShipModel::apply(Ship *ship) const { // apply ship model settings apply (static_cast(ship)); ship->set_info(this); ship->set_mass(mass()); ship->set_impulse_force(impulse_force()); ship->set_thrust_force(thrust_force()); ship->set_strafe_force(strafe_force()); ship->set_turn_force(turn_force()); ship->set_roll_force(roll_force()); ship->set_jumpdrive(jumpdrive()); ship->set_maxarmor(maxarmor()); } }