/* base/cargo.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 "sys/sys.h" #include "filesystem/inifile.h" #include "auxiliary/functions.h" #include "core/func.h" #include "base/game.h" #include "base/cargo.h" #include "base/cargopod.h" namespace game { core::InfoType *Cargo::cargo_infotype = 0; void func_list_cargo(const std::string &args) { Cargo::list(); } // loads cargo types from ini file bool Cargo::init() { // initialize cargo InfoType cargo_infotype = new core::InfoType("cargo"); filesystem::IniFile cargoini; cargoini.open("ini/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; float f; while (cargoini.getline()) { if (cargoini.got_key()) { if (cargoini.section().compare("cargo") == 0) { if (cargoini.got_key_label("label", str)) { cargo->set_label(str); 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 if (cargoini.got_key_float("volume", f)) { cargo->set_volume(f); continue; } else { cargoini.unkown_key(); } } } else if (cargoini.got_section()) { if (cargoini.got_section("cargo")) { cargo = new Cargo(); count++; } else if (cargoini.got_section()) { cargoini.unknown_section(); } } } // add cargo infos con_debug << " " << cargoini.name() << " " << count << " cargo types" << std::endl; cargoini.close(); core::Func *func = core::Func::add("list_cargo", func_list_cargo); func->set_info("list available cargo types"); return true; } /* ---- class Cargo -------------------------------------------- */ Cargo::Cargo() : core::Info(cargo_infotype) { set_volume(1); } Cargo::~Cargo() { } Cargo *Cargo::find(const std::string & label) { if (!label.size()) { return 0; } return (Cargo *) core::Info::find(cargo_infotype, label); } // main 'sell cargo' function void Cargo::sell(core::EntityControlable *seller, core::Entity *buyer, const int amount) { if (!buyer || !seller) return; // can only sell at planets and stations if ((buyer->moduletype() != station_enttype) && (buyer->moduletype() != planet_enttype)) { seller->owner()->send("^WCan not sell here"); return; } if (!seller->owner()) return; if (!buyer->inventory() || !seller->inventory()) { seller->owner()->send("^WCan not sell here"); return; } if (!amount) { return; } // seller is the player core::Item *seller_item = seller->inventory()->find(this); if (!seller_item) { if (seller->owner()) { seller->owner()->send("^WYou do not own any " + name()); } return; } // buyer is the station or planer core::Item *buyer_item = buyer->inventory()->find(this); if (!buyer_item) { seller->owner()->send("^W" + buyer->name() + " ^Bdoes not buy " + name()); return; } int negotiated_amount = amount; if (negotiated_amount < 0) { negotiated_amount = seller_item->amount(); } else if (negotiated_amount > seller_item->amount()) { negotiated_amount = seller_item->amount(); } int negotiated_price = buyer_item->price(); seller_item->dec_amount(negotiated_amount); seller->owner()->set_credits(seller->owner()->credits() + negotiated_price * negotiated_amount); seller->owner()->set_dirty(); seller->inventory()->set_dirty(); if (buyer_item->amount() >= 0) { buyer_item->inc_amount(negotiated_amount); buyer->inventory()->set_dirty(); } // send a cargo purchased message std::stringstream msgstr; msgstr << "^BSold " << negotiated_amount << " " << aux::plural("unit", negotiated_amount) << " of " << name() << " for " << negotiated_price * negotiated_amount << " credits"; seller->owner()->send(msgstr.str()); seller->owner()->sound("game/buy"); } // main 'buy cargo' function void Cargo::buy(core::EntityControlable *buyer, core::Entity *seller, const int amount) { if (!buyer || !seller) return; // can only buy at planets and stations if ((seller->moduletype() != station_enttype) && (seller->moduletype() != planet_enttype)) { buyer->owner()->send("^WCan not buy here"); return; } if (!buyer->owner()) return; if (!buyer->inventory() || !seller->inventory()) { buyer->owner()->send("^WCan not buy here"); return; } if (!amount) { return; } // seller is the station or planet core::Item *seller_item = seller->inventory()->find(this); if (!seller_item) { if (buyer->owner()) { buyer->owner()->send("^W" + seller->name() + " ^Bdoes not sell " + name()); } return; } else { assert(seller_item->info() == this); } int negotiated_amount = amount; int negotiated_price = seller_item->price(); long cash = buyer->owner()->credits(); // check if the player has enough cash if (negotiated_price > 0) { // negative amount means 'as much as possible' if (negotiated_amount < 0) { negotiated_amount = cash / negotiated_price; } // maximum amount the player can afford if (cash < negotiated_amount * negotiated_price) { negotiated_amount = cash / negotiated_price; } if (negotiated_amount < 1) { buyer->owner()->send("^WCan not afford transaction!"); return; } } // check cargo size - ignore zero volume cargo if (volume() > 0 ) { // maximum cargo size if (negotiated_amount * volume() > buyer->inventory()->capacity_available()) { negotiated_amount = (int)floorf(buyer->inventory()->capacity_available() / volume()); } if (negotiated_amount < 1) { buyer->owner()->send("^WNot enough cargo space available!"); return; } } if (negotiated_amount <= 0) { // unlimited amount of zero-cost cargo buyer->owner()->send("^WNo unlimited amounts of zero-cost cargo available!"); return; } // if amount is set to -1. the base has a limitless supply if (seller_item->amount() == 0) { buyer->owner()->send("^WCargo not available!"); return; } else if (seller_item->amount() > 0) { if (negotiated_amount > seller_item->amount()) { negotiated_amount = seller_item->amount(); } seller_item->dec_amount(negotiated_amount); seller->inventory()->set_dirty(); } // buyer is the player core::Item *buyer_item = buyer->inventory()->find(this); if (!buyer_item) { buyer_item = new core::Item(this); buyer->inventory()->add(buyer_item); } else { assert(buyer_item->info() == this); } buyer_item->inc_amount(negotiated_amount); buyer->owner()->set_credits(buyer->owner()->credits() - negotiated_price * negotiated_amount); buyer->owner()->set_dirty(); buyer->inventory()->set_dirty(); // 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"); } // main 'eject cargo' function void Cargo::eject(core::EntityControlable *ejector, const int amount) { if (!ejector->inventory()) { return; } if (!amount) { return; } if ((ejector->state() == core::Entity::Jump) || (ejector->state() == core::Entity::JumpInitiate)) { if (ejector->owner()) { ejector->owner()->send("^WCan not eject while hyperspace jump drive is active"); } return; } // find the cargo in the inventory core::Item *item = ejector->inventory()->find(this); if (!item || !item->amount()) { if (ejector->owner()) { ejector->owner()->send("^WYou do not own any " + name()); } return; } else { assert(item->info() == this); } int negotiated_amount = amount; if (negotiated_amount < 0) { negotiated_amount = item->amount(); } else if (negotiated_amount > item->amount()) { if (ejector->owner()) { std::stringstream msgstr; msgstr << "^WYou only own " << item->amount() << " " << aux::plural("unit", negotiated_amount) << " of " << name(); ejector->owner()->send(msgstr.str()); } return; } item->dec_amount(negotiated_amount); ejector->inventory()->set_dirty(); if (ejector->state() == core::Entity::Docked) { std::stringstream msgstr; if (ejector->owner()) { msgstr << "^BDestroyed " << negotiated_amount << " " << aux::plural("unit", negotiated_amount) << " of " << name(); ejector->owner()->send(msgstr.str()); ejector->owner()->sound("game/eject"); } return; } // create cargo pod CargoPod *pod = new CargoPod(); pod->set_color(ejector->color()); pod->set_color_second(ejector->color_second()); pod->set_zone(ejector->zone()); pod->set_location(ejector->location() + ejector->axis().up() * ejector->radius()); pod->set_axis(ejector->axis()); // add loot to inventory pod->set_inventory(new core::Inventory()); pod->inventory()->set_capacity(item->info()->volume() * negotiated_amount); core::Item *loot = new core::Item(item->info()); loot->set_amount(negotiated_amount); pod->inventory()->add(loot); pod->inventory()->set_dirty(); if (ejector->owner()) { std::stringstream msgstr; msgstr << "^BEjected " << negotiated_amount << " " << aux::plural("unit", negotiated_amount) << " of " << name(); ejector->owner()->send(msgstr.str()); ejector->owner()->sound("game/eject"); } pod->reset(); } void Cargo::list() { core::Info::list(cargo_infotype); } } // namespace game