From 9c91a9767b570fdc3c3e19e1f452f9a8257f9999 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sat, 18 Sep 2010 18:50:55 +0000 Subject: trade updates --- src/game/base/cargo.cc | 133 +++++++++++++++++++- src/game/base/cargo.h | 5 + src/game/base/game.cc | 298 +++++++++++++++++++------------------------- src/game/base/game.h | 1 + src/game/base/ship.cc | 1 + src/game/base/shipdealer.cc | 75 +++++------ src/game/base/shipmodel.cc | 96 ++++++++++++++ src/game/base/shipmodel.h | 2 + 8 files changed, 390 insertions(+), 221 deletions(-) (limited to 'src/game/base') diff --git a/src/game/base/cargo.cc b/src/game/base/cargo.cc index 258aecf..420d4d3 100644 --- a/src/game/base/cargo.cc +++ b/src/game/base/cargo.cc @@ -6,16 +6,86 @@ #include "base/game.h" #include "base/cargo.h" +#include "filesystem/inifile.h" #include "auxiliary/functions.h" #include "sys/sys.h" namespace game { -/* ---- class Cargo -------------------------------------------- */ - core::InfoType *Cargo::cargo_infotype = 0; +// loads cargo types from ini file +bool Cargo::init() +{ + + // initialize commodities InfoType + Cargo::cargo_infotype = new core::InfoType("cargo"); + + filesystem::IniFile cargoini; + cargoini.open("cargo"); + if (!cargoini.is_open()) { + con_error << "Could not open " << cargoini.name() << "!" << std::endl; + return false; + } + + con_print << "^BLoading cargo..." << std::endl; + + size_t count = 0; + + Cargo *cargo = 0; + std::string str; + long l; + + while (cargoini.getline()) { + if (cargoini.got_key()) { + + if (cargoini.section().compare("cargo") == 0) { + if (cargoini.got_key_label("label", str)) { + cargo->set_label(std::string(str)); + count++; + continue; + + } else if (cargoini.got_key_string("name", str)) { + cargo->set_name(str); + continue; + + } else if (cargoini.got_key_string("info", str)) { + cargo->add_text(str); + continue; + + } else if (cargoini.got_key_string("model", str)) { + cargo->set_modelname(str); + continue; + + } else if (cargoini.got_key_long("price", l)) { + cargo->set_price(l); + continue; + } else { + cargoini.unkown_key(); + } + } + + } else if (cargoini.got_section()) { + + if (cargoini.got_section("cargo")) { + cargo = new Cargo(); + + } else if (cargoini.got_section()) { + cargoini.unknown_section(); + } + } + } + + // add cargo infos + con_debug << " " << cargoini.name() << " " << count << " cargo types" << std::endl; + + cargoini.close(); + return true; +} + +/* ---- class Cargo -------------------------------------------- */ + Cargo::Cargo() : core::Info(cargo_infotype) { } @@ -33,6 +103,65 @@ Cargo *Cargo::find(const std::string & label) return (Cargo *) core::Info::find(cargo_infotype, label); } +// main 'buy cargo' function +void Cargo::buy(core::EntityControlable *buyer, core::Entity *seller, const int amount) +{ + if (!buyer || !seller) + return; + + if (!buyer->owner()) + return; + + if (!buyer->inventory() || !seller->inventory()) { + return; + } + + if (!amount) { + return; + } + + core::Item *buyer_item = buyer->inventory()->find(this); + core::Item *seller_item = seller->inventory()->find(this); + + if (!seller_item) { + if (buyer->owner()) { + buyer->owner()->send("^B" + seller->name() + " ^Bdoes not sell " + name()); + } + return; + } + + int negotiated_amount = amount; + int negotiated_price = seller_item->price(); + long cash = buyer->owner()->credits(); + + // negative means 'as much as possible' + if (negotiated_amount < 0) { + negotiated_amount = cash / negotiated_price; + } + + if (cash < negotiated_amount * negotiated_price) { + negotiated_amount = cash / negotiated_price; + } + if (!negotiated_amount) { + buyer->owner()->send("^WCan not afford transaction!"); + return; + } + + // TODO cargo size check + + if (!buyer_item) { + buyer_item = new core::Item(this); + buyer->inventory()->add(buyer_item); + } + buyer_item->inc_amount(negotiated_amount); + buyer->owner()->set_credits(buyer->owner()->credits() - negotiated_price * negotiated_amount); + + // send a cargo purchased message + std::stringstream msgstr; + msgstr << "^BPurchased " << negotiated_amount << " " << aux::plural("unit", negotiated_amount) << " of " << name() << " for " << negotiated_price * negotiated_amount << " credits"; + buyer->owner()->send(msgstr.str()); + buyer->owner()->sound("game/buy"); +} } // namespace game diff --git a/src/game/base/cargo.h b/src/game/base/cargo.h index 808b4c0..9b2bca5 100644 --- a/src/game/base/cargo.h +++ b/src/game/base/cargo.h @@ -17,9 +17,14 @@ public: Cargo(); ~Cargo(); + void buy(core::EntityControlable *buyer, core::Entity *seller, const int amount); + + /* -- static functions -- */ static core::InfoType *cargo_infotype; static Cargo *find(const std::string & label); + + static bool init(); }; } // namespace game diff --git a/src/game/base/game.cc b/src/game/base/game.cc index bf139a3..9f8dabc 100644 --- a/src/game/base/game.cc +++ b/src/game/base/game.cc @@ -183,12 +183,97 @@ void Game::func_dock(core::Player *player, core::Entity *entity) } } +// cheats +void Game::func_give(core::Player *player, const std::string &args) +{ + if (!Game::g_devel->value()) { + player->send("Cheats disabled"); + return; + } + + std::istringstream is(args); + std::string str; + + is >> str; + aux::to_label(str); + + if (str.compare("ship") == 0) { + std::string labelstr; + + if (!player->control()) { + player->send("^WNeed a ship to swap!"); + } + + if (!(is >> labelstr)) { + player->send("Usage: give ship [string]"); + return; + } + + ShipModel *shipmodel = ShipModel::find(labelstr); + if (!shipmodel) { + // enable rcon buffering + sys::ConsoleInterface::instance()->set_rcon(true); + ShipModel::list(); + // disable rcon buffering + sys::ConsoleInterface::instance()->set_rcon(false); + + while (sys::ConsoleInterface::instance()->rconbuf().size()) { + player->send((*sys::ConsoleInterface::instance()->rconbuf().begin())); + sys::ConsoleInterface::instance()->rconbuf().pop_front(); + } + + player->send("Unkown ship type '" + labelstr + "'"); + return; + } + + Ship * ship = new Ship(player, shipmodel); + + // FIME move this into a method in the Ship class + ship->set_zone(player->control()->zone()); + ship->get_location().assign(player->control()->location()); + ship->set_state(player->control()->state()); + ship->get_axis().assign(player->control()->axis()); + ship->set_speed(player->control()->speed()); + ship->set_thrust(player->control()->thrust()); + + if (player->view() == player->control()) { + player->set_view(ship); + } + player->remove_asset(player->control()); + player->set_control(ship); + + player->sound("game/buy-ship"); + + } else if (str.compare("credits") == 0) { + long credits; + + if (!(is >> credits)) { + player->send("Usage: give credits [int]"); + return; + } + + if (player->credits() + credits > 0 ) { + player->set_credits(player->credits() + credits); + } else { + player->set_credits(0); + } + + player->sound("game/buy"); + + } else { + player->send("Usage: give ship [string]"); + player->send(" give credits [int]"); + return; + } +} + // buy request from a player void Game::func_buy(core::Player *player, const std::string &args) { std::istringstream is(args); std::string typestr; std::string labelstr; + int amount = 0; if (!(is >> typestr)) { player->send("Usage: buy [string] [string] buy an item, specify type and label"); @@ -202,11 +287,21 @@ void Game::func_buy(core::Player *player, const std::string &args) } else { aux::to_label(labelstr); } + + if (!(is >> amount)) + amount = 0; if (typestr.compare("ship") == 0) { ShipDealer::func_buy(player, labelstr); + + } else if (typestr.compare("cargo") == 0) { - player->send("Buying cargo is not supported"); + Cargo *cargo = Cargo::find(labelstr); + if (cargo) { + cargo->buy(player->control(), player->view(), amount); + } else { + player->send("Unkown cargo type '" + labelstr + "'"); + } } else { player->send("Unkown item type '" + typestr + "'"); } @@ -360,16 +455,19 @@ void Game::func_goto(core::Player *player, const std::string &args) Game::Game() : core::Module("Project::OSiRiON", true) { + // reset default player values Default::clear(); Physics::init(); - if (!load_commodities()) { + // read cargo.ini + if (!Cargo::init()) { abort(); return; } - if (!load_ships()) { + // read ships.ini + if (!ShipModel::init()) { abort(); return; } @@ -399,6 +497,9 @@ Game::Game() : core::Module("Project::OSiRiON", true) func = core::Func::add("buy", Game::func_buy); func->set_info("[string] [string] buy type of item, name of item"); + func = core::Func::add("give", Game::func_give); + func->set_info("cheat functions"); + func = core::Func::add("jump", Game::func_jump); func->set_info("[string] activate or deactivate hyperspace jump drive"); @@ -746,13 +847,12 @@ bool Game::load_menus(core::Entity *entity, const std::string &menufilename) if ((entity->moduletype() != planet_enttype) && (entity->moduletype() != station_enttype)) { return false; } - - - filesystem::IniFile inifile; std::string strval; + long l; + MenuDescription *menu_dealer = 0; ButtonDescription *button = 0; ShipDealer *shipdealer = 0; @@ -774,8 +874,8 @@ bool Game::load_menus(core::Entity *entity, const std::string &menufilename) // dealer menu if (!menu_dealer) { menu_dealer = new MenuDescription(); - menu_dealer->set_label("dealer"); - menu_dealer->set_text("Ship dealer"); + menu_dealer->set_label("ships"); + menu_dealer->set_text("Ships"); shipdealer = new ShipDealer(); if (entity->moduletype() == planet_enttype) { @@ -831,6 +931,7 @@ bool Game::load_menus(core::Entity *entity, const std::string &menufilename) if (!item) { item = new core::Item(cargo); item->set_amount(-1); + item->set_price(cargo->price()); inventory->add(item); } } else { @@ -840,6 +941,10 @@ bool Game::load_menus(core::Entity *entity, const std::string &menufilename) inifile.unknown_error(msg); } + } else if (inifile.got_key_long("price", l)) { + if (item) { + item->set_price(l); + } } else { inifile.unkown_key(); } @@ -855,6 +960,7 @@ bool Game::load_menus(core::Entity *entity, const std::string &menufilename) item = inventory->find(shipmodel); if (!item) { item = new core::Item(shipmodel); + item->set_price(shipmodel->price()); item->set_amount(-1); inventory->add(item); } @@ -864,7 +970,10 @@ bool Game::load_menus(core::Entity *entity, const std::string &menufilename) msg.append("'"); inifile.unknown_error(msg); } - + } else if (inifile.got_key_long("price", l)) { + if (item) { + item->set_price(l); + } } else { inifile.unkown_key(); } @@ -887,6 +996,12 @@ bool Game::load_menus(core::Entity *entity, const std::string &menufilename) button->set_command("launch", ButtonDescription::CommandGame); button->set_alignment(ButtonDescription::Center); menu_main->add_button(button); + + button = new ButtonDescription(); + button->set_text("Trade"); + button->set_command("trade cargo", ButtonDescription::CommandMenu); + button->set_alignment(ButtonDescription::Center); + menu_main->add_button(button); if (menu_dealer) { button = new ButtonDescription(); @@ -898,8 +1013,8 @@ bool Game::load_menus(core::Entity *entity, const std::string &menufilename) entity->add_menu(menu_dealer); button = new ButtonDescription(); - button->set_text("Ship dealer"); - button->set_command("dealer", ButtonDescription::CommandMenu); + button->set_text("Ships"); + button->set_command("ships", ButtonDescription::CommandMenu); button->set_alignment(ButtonDescription::Center); menu_main->add_button(button); } @@ -913,167 +1028,6 @@ bool Game::load_menus(core::Entity *entity, const std::string &menufilename) return true; } -// read commodities -bool Game::load_commodities() -{ - // initialize commodities InfoType - Cargo::cargo_infotype = new core::InfoType("cargo"); - - filesystem::IniFile cargoini; - cargoini.open("cargo"); - if (!cargoini.is_open()) { - con_error << "Could not open " << cargoini.name() << "!" << std::endl; - return false; - } - - con_print << "^BLoading cargo..." << std::endl; - - size_t count = 0; - - Cargo *cargo = 0; - std::string str; - - while (cargoini.getline()) { - if (cargoini.got_key()) { - - if (cargoini.section().compare("cargo") == 0) { - if (cargoini.got_key_label("label", str)) { - cargo->set_label(std::string(str)); - count++; - continue; - - } else if (cargoini.got_key_string("name", str)) { - cargo->set_name(str); - continue; - - } else if (cargoini.got_key_string("info", str)) { - cargo->add_text(str); - continue; - - } else if (cargoini.got_key_string("model", str)) { - cargo->set_modelname(str); - continue; - - } else { - cargoini.unkown_key(); - } - } - - } else if (cargoini.got_section()) { - - if (cargoini.got_section("cargo")) { - cargo = new Cargo(); - - } else if (cargoini.got_section()) { - cargoini.unknown_section(); - } - } - } - - // add cargo infos - con_debug << " " << cargoini.name() << " " << count << " cargo types" << std::endl; - - cargoini.close(); - return true; -} - -// read ship model specifications -bool Game::load_ships() -{ - // initialize shipmodel InfoType - ShipModel::shipmodel_infotype = new core::InfoType("ship"); - - using math::Vector3f; - using math::Color; - - filesystem::IniFile shipsini; - shipsini.open("ships"); - if (!shipsini.is_open()) { - con_error << "Could not open " << shipsini.name() << "!" << std::endl; - return false; - } - - con_print << "^BLoading ships..." << std::endl; - - size_t count = 0; - ShipModel *shipmodel = 0; - std::string str; - long l; - float f; - bool b; - - while (shipsini.getline()) { - if (shipsini.got_key()) { - if (shipsini.section().compare("ship") == 0) { - if (shipsini.got_key_label("label", str)) { - shipmodel->set_label(str); - count++; - continue; - } else if (shipsini.got_key_string("name", str)) { - shipmodel->set_name(str); - continue; - } else if (shipsini.got_key_string("info", str)) { - shipmodel->add_text(str); - continue; - } else if (shipsini.got_key_string("model", str)) { - shipmodel->set_modelname(str); - continue; - } else if (shipsini.got_key_long("price", l)) { - shipmodel->set_price(l); - continue; - } else if (shipsini.got_key_float("cargo", f)) { - shipmodel->set_maxcargo(f); - continue; - } else if (shipsini.got_key_bool("jumpdrive", b)) { - shipmodel->set_jumpdrive(b); - continue; - } else if (shipsini.got_key_bool("dock", b)) { - shipmodel->set_dock(b); - continue; - } else if (shipsini.got_key_float("acceleration", f)) { - shipmodel->set_acceleration(f); - continue; - } else if (shipsini.got_key_float("maxspeed", f)) { - shipmodel->set_maxspeed(f); - continue; - } else if (shipsini.got_key_float("turnspeed", f)) { - math::clamp(f, 0.0f, 90.0f); - shipmodel->set_turnspeed(f); - continue; - } else { - shipsini.unkown_key(); - } - } - } else if (shipsini.got_section("ship")) { - // generate info for the last loaded ship model - if (shipmodel) { - shipmodel->generate_info(); - } - - // add a new shipmodel - shipmodel = new ShipModel(); - - if (!Default::shipmodel) { - Default::shipmodel = shipmodel; - } - - } else if (shipsini.got_section()) { - shipsini.unknown_section(); - } - } - - // generate info for the last loaded ship model - if (shipmodel) { - shipmodel->generate_info(); - } - - con_debug << " " << shipsini.name() << " " << count << " ship types" << std::endl; - - shipsini.close(); - - return true; -} - // load default player settings bool Game::load_player() { diff --git a/src/game/base/game.h b/src/game/base/game.h index fc0274b..e091630 100644 --- a/src/game/base/game.h +++ b/src/game/base/game.h @@ -107,6 +107,7 @@ private: static void func_respawn(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_give(core::Player *player, const std::string &args); }; /// factory function diff --git a/src/game/base/ship.cc b/src/game/base/ship.cc index 0da57ab..23929ea 100644 --- a/src/game/base/ship.cc +++ b/src/game/base/ship.cc @@ -45,6 +45,7 @@ Ship::Ship(core::Player *owner, ShipModel *shipmodel) : core::EntityControlable( std::string str(aux::text_strip(owner->name())); aux::to_label(str); set_label(str); + set_inventory(new core::Inventory()); } else { set_label(shipmodel->label()); } diff --git a/src/game/base/shipdealer.cc b/src/game/base/shipdealer.cc index adb97ea..e6df18f 100644 --- a/src/game/base/shipdealer.cc +++ b/src/game/base/shipdealer.cc @@ -68,33 +68,19 @@ ShipModel *ShipDealer::find(ShipModel *shipmodel) const void ShipDealer::func_buy(core::Player *player, const std::string &args) { core::Entity *dock = player->view(); - ShipDealer *shipdealer = 0; - - // find the ship model - ShipModel *shipmodel = ShipModel::find(args); - if (!shipmodel) { - if (!Game::g_devel->value()) { - player->send("Cheats disabled"); - return; - } else { - shipmodel = ShipModel::search(args); - } + + std::istringstream is(args); + std::string labelstr; + + if (!(is >> labelstr)) { + player->send("Usage: buy ship [string]"); } - if (!shipmodel) { - // enable rcon buffering - sys::ConsoleInterface::instance()->set_rcon(true); - ShipModel::list(); - // disable rcon buffering - sys::ConsoleInterface::instance()->set_rcon(false); - - while (sys::ConsoleInterface::instance()->rconbuf().size()) { - player->send((*sys::ConsoleInterface::instance()->rconbuf().begin())); - sys::ConsoleInterface::instance()->rconbuf().pop_front(); - } - - player->send("Usage: buy ship label"); + // find the ship model + ShipModel *shipmodel = ShipModel::find(labelstr); + if (!shipmodel) { + player->send("Unkown ship type '" + labelstr + "'"); return; } @@ -107,29 +93,26 @@ void ShipDealer::func_buy(core::Player *player, const std::string &args) } } - if (!Game::g_devel->value()) { - - if (!shipdealer) { - player->send("No ship dealer available"); - return; - } - - if (!shipdealer->find(shipmodel)) { - player->send("Ship dealer does not sell the " + shipmodel->name()); - return; - } + if (!shipdealer) { + player->send("No ship dealer available"); + return; + } - // check price - if (shipmodel->price() > player->credits()) { - std::stringstream msgstr; - msgstr << "You require " << (shipmodel->price() - player->credits()) << " additional credits to buy the " << shipmodel->name(); - player->send(msgstr.str()); - return; - } + if (!shipdealer->find(shipmodel)) { + player->send("Ship dealer does not sell the " + shipmodel->name()); + return; + } - player->add_credits(-shipmodel->price()); + // check price + if (shipmodel->price() > player->credits()) { + std::stringstream msgstr; + msgstr << "You require " << (shipmodel->price() - player->credits()) << " additional credits to buy the " << shipmodel->name(); + player->send(msgstr.str()); + return; } + player->add_credits(-shipmodel->price()); + // player has only ship for now if (player->control()) { player->remove_asset(player->control()); @@ -151,10 +134,8 @@ void ShipDealer::func_buy(core::Player *player, const std::string &args) // send the ship purchased message std::stringstream msgstr; - msgstr << "^BPurchased " << aux::article(shipmodel->name()); - if (!Game::g_devel->value()) { - msgstr << " for " << shipmodel->price() << " credits"; - } + msgstr << "^BPurchased " << aux::article(shipmodel->name()) << " for " << shipmodel->price() << " credits"; + player->send(msgstr.str()); player->sound("game/buy-ship"); } diff --git a/src/game/base/shipmodel.cc b/src/game/base/shipmodel.cc index 1dc8ba1..8710aad 100644 --- a/src/game/base/shipmodel.cc +++ b/src/game/base/shipmodel.cc @@ -16,6 +16,102 @@ namespace game core::InfoType *ShipModel::shipmodel_infotype = 0; +bool ShipModel::init() +{ + // initialize shipmodel InfoType + ShipModel::shipmodel_infotype = new core::InfoType("ship"); + + using math::Vector3f; + using math::Color; + + filesystem::IniFile shipsini; + shipsini.open("ships"); + if (!shipsini.is_open()) { + con_error << "Could not open " << shipsini.name() << "!" << std::endl; + return false; + } + + con_print << "^BLoading ships..." << std::endl; + + size_t count = 0; + ShipModel *shipmodel = 0; + std::string str; + long l; + float f; + bool b; + + while (shipsini.getline()) { + if (shipsini.got_key()) { + if (shipsini.section().compare("ship") == 0) { + if (shipsini.got_key_label("label", str)) { + shipmodel->set_label(str); + count++; + continue; + } else if (shipsini.got_key_string("name", str)) { + shipmodel->set_name(str); + continue; + } else if (shipsini.got_key_string("info", str)) { + shipmodel->add_text(str); + continue; + } else if (shipsini.got_key_string("model", str)) { + shipmodel->set_modelname(str); + continue; + } else if (shipsini.got_key_long("price", l)) { + shipmodel->set_price(l); + continue; + } else if (shipsini.got_key_float("cargo", f)) { + shipmodel->set_maxcargo(f); + continue; + } else if (shipsini.got_key_bool("jumpdrive", b)) { + shipmodel->set_jumpdrive(b); + continue; + } else if (shipsini.got_key_bool("dock", b)) { + shipmodel->set_dock(b); + continue; + } else if (shipsini.got_key_float("acceleration", f)) { + shipmodel->set_acceleration(f); + continue; + } else if (shipsini.got_key_float("maxspeed", f)) { + shipmodel->set_maxspeed(f); + continue; + } else if (shipsini.got_key_float("turnspeed", f)) { + math::clamp(f, 0.0f, 90.0f); + shipmodel->set_turnspeed(f); + continue; + } else { + shipsini.unkown_key(); + } + } + } else if (shipsini.got_section("ship")) { + // generate info for the last loaded ship model + if (shipmodel) { + shipmodel->generate_info(); + } + + // add a new shipmodel + shipmodel = new ShipModel(); + + if (!Default::shipmodel) { + Default::shipmodel = shipmodel; + } + + } else if (shipsini.got_section()) { + shipsini.unknown_section(); + } + } + + // generate info for the last loaded ship model + if (shipmodel) { + shipmodel->generate_info(); + } + + con_debug << " " << shipsini.name() << " " << count << " ship types" << std::endl; + + shipsini.close(); + + return true; +} + ShipModel::ShipModel() : core::Info(shipmodel_infotype) { //default specifications diff --git a/src/game/base/shipmodel.h b/src/game/base/shipmodel.h index 38e9d5d..c5da05e 100644 --- a/src/game/base/shipmodel.h +++ b/src/game/base/shipmodel.h @@ -96,6 +96,8 @@ public: static ShipModel *search(const std::string & searchstr); + static bool init(); + static void list(); static core::InfoType *shipmodel_infotype; -- cgit v1.2.3