/* 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 "base/game.h" #include "base/cargo.h" #include "filesystem/inifile.h" #include "auxiliary/functions.h" #include "sys/sys.h" namespace game { 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; 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(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 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(); } 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) { 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("^BCan not sell here"); return; } if (!seller->owner()) return; if (!buyer->inventory() || !seller->inventory()) { seller->owner()->send("^BCan 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("^BYou 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("^B" + 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("^BCan not buy here"); return; } if (!buyer->owner()) return; if (!buyer->inventory() || !seller->inventory()) { buyer->owner()->send("^BCan 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("^B" + 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"); } } // namespace game