diff options
Diffstat (limited to 'src/game')
-rw-r--r-- | src/game/base/cargo.cc | 276 | ||||
-rw-r--r-- | src/game/base/cargo.h | 6 | ||||
-rw-r--r-- | src/game/base/game.cc | 627 | ||||
-rw-r--r-- | src/game/base/planet.cc | 34 | ||||
-rw-r--r-- | src/game/base/planet.h | 2 | ||||
-rw-r--r-- | src/game/base/savegame.cc | 15 | ||||
-rw-r--r-- | src/game/base/ship.cc | 2 | ||||
-rw-r--r-- | src/game/base/station.cc | 12 | ||||
-rw-r--r-- | src/game/base/weapon.cc | 28 | ||||
-rw-r--r-- | src/game/base/weapon.h | 8 |
10 files changed, 585 insertions, 425 deletions
diff --git a/src/game/base/cargo.cc b/src/game/base/cargo.cc index 706bf84..5a67ebf 100644 --- a/src/game/base/cargo.cc +++ b/src/game/base/cargo.cc @@ -13,7 +13,6 @@ #include "core/func.h" #include "base/game.h" #include "base/cargo.h" -#include "base/cargopod.h" namespace game { @@ -109,6 +108,11 @@ void Cargo::done() core::Func::remove("list_cargo"); } +void Cargo::list() +{ + core::Info::list(cargo_infotype); +} + /* ---- class Cargo -------------------------------------------- */ Cargo::Cargo() : core::Info(cargo_infotype) @@ -129,275 +133,5 @@ Cargo *Cargo::find(const std::string & label) 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("fx/eject"); - } - return; - } - - // create cargo pod - CargoPod *pod = new CargoPod(); - - pod->set_color(ejector->color()); - pod->set_color_second(ejector->color_second()); - pod->set_location(ejector->location() + ejector->axis().up() * (ejector->radius() + pod->radius())); - pod->set_axis(ejector->axis()); - pod->set_zone(ejector->zone()); - pod->set_info(item->info()); - - // add loot to inventory - pod->add_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("fx/eject"); - } - - pod->reset(); -} - -void Cargo::list() -{ - core::Info::list(cargo_infotype); -} - } // namespace game diff --git a/src/game/base/cargo.h b/src/game/base/cargo.h index 4d90611..0672cec 100644 --- a/src/game/base/cargo.h +++ b/src/game/base/cargo.h @@ -16,12 +16,6 @@ class Cargo : public core::Info { public: Cargo(); ~Cargo(); - - void buy(core::EntityControlable *buyer, core::Entity *seller, const int amount); - - void sell(core::EntityControlable *seller, core::Entity *buyer, const int amount); - - void eject(core::EntityControlable *ejector, const int amount); /* --- static registry functions ---------------------------------- */ diff --git a/src/game/base/game.cc b/src/game/base/game.cc index 738edca..182c856 100644 --- a/src/game/base/game.cc +++ b/src/game/base/game.cc @@ -18,6 +18,7 @@ #include "filesystem/inifile.h" #include "base/game.h" #include "base/cargo.h" +#include "base/cargopod.h" #include "base/faction.h" #include "base/navpoint.h" #include "base/jumppoint.h" @@ -286,6 +287,11 @@ void Game::func_give(core::Player *player, const std::string &args) return; } + if (!player->control()) { + player->send("^WYou need to join the game first!"); + return; + } + std::istringstream is(args); std::string str; @@ -295,15 +301,11 @@ void Game::func_give(core::Player *player, const std::string &args) if (str.compare("ship") == 0) { std::string labelstr; - if (!player->control()) { - player->send("^WYou need to join the game first!"); - return; - } - ShipModel *shipmodel = 0; if (!(is >> labelstr)) { player->send("Usage: give ship [string]"); } else { + aux::to_label(labelstr); shipmodel = ShipModel::find(labelstr); } @@ -319,7 +321,7 @@ void Game::func_give(core::Player *player, const std::string &args) sys::ConsoleInterface::instance()->rconbuf().pop_front(); } - player->send("Unkown ship type '" + labelstr + "'"); + player->send("Unknown ship type '" + labelstr + "'"); return; } @@ -353,6 +355,12 @@ void Game::func_give(core::Player *player, const std::string &args) ship->set_thrust(player->control()->thrust()); ship->set_state(player->control()->state()); + + // remove the old ship from the physics simulation + oldship->die(); + oldship->reset(); + + // add the new ship to the physics simulation ship->reset(); //target_thrust is protected //ship->target_thrust = player->control()->target_thrust()); @@ -382,15 +390,11 @@ void Game::func_give(core::Player *player, const std::string &args) } else if (str.compare("cargo") == 0) { std::string labelstr; - if (!player->control()) { - player->send("^WYou need to join the game first!"); - return; - } - Cargo *cargo = 0; if (!(is >> labelstr)) { player->send("Usage: give cargo [string] [int]"); - } else { + } else { + aux::to_label(labelstr); cargo = Cargo::find(labelstr); } @@ -406,22 +410,31 @@ void Game::func_give(core::Player *player, const std::string &args) sys::ConsoleInterface::instance()->rconbuf().pop_front(); } - player->send("Unkown cargo type '" + labelstr + "'"); + player->send("Unknown cargo type '" + labelstr + "'"); return; } else { int amount = 0; if (!(is >> amount)) { - amount = -1; + amount = 1; } else { if (!amount) return; } + + int max = 0; + if (cargo->volume()) { + max = (int)floorf(player->control()->inventory()->capacity_available() / cargo->volume()); + } else { + max = amount; + if (max < 1) { + max = 1; + } + } - const int max = (int)floorf(player->control()->inventory()->capacity_available() / cargo->volume()); - if (amount < 0 ) { + if (amount < 0) { amount = max; } - + if ((amount == 0) || (amount > max)) { player->send("^WNot enough cargo space available!"); return; @@ -435,21 +448,19 @@ void Game::func_give(core::Player *player, const std::string &args) assert(item->info() == cargo); } item->inc_amount(amount); + player->control()->inventory()->set_dirty(); - player->sound("game/buy"); + player->control()->owner()->sound("game/buy"); } + } else if (str.compare("weapon") == 0) { std::string labelstr; - - if (!player->control()) { - player->send("^WYou need to join the game first!"); - return; - } - + Weapon *weapon = 0; if (!(is >> labelstr)) { player->send("Usage: give weapon [string] [int]"); - } else { + } else { + aux::to_label(labelstr); weapon = Weapon::find(labelstr); } @@ -465,29 +476,59 @@ void Game::func_give(core::Player *player, const std::string &args) sys::ConsoleInterface::instance()->rconbuf().pop_front(); } - player->send("Unkown weapon type '" + labelstr + "'"); + player->send("Unknown weapon type '" + labelstr + "'"); return; - } else { - core::Item *item = 0; - int amount = 1; - - if (player->control()->inventory()->capacity_available() < weapon->volume()) { + } else { + int amount = 0; + if (!(is >> amount)) { + amount = 1; + } else { + if (!amount) + return; + } + + int max = 0; + if (weapon->volume()) { + max = (int)floorf(player->control()->inventory()->capacity_available() / weapon->volume()); + } else { + max = amount; + if (max < 1) { + max = 1; + } + } + if (amount < 0) { + if (weapon->stackable()) { + amount = max; + } else { + amount = 1; + } + } + + if ((amount == 0) || (amount > max)) { player->send("^WNot enough cargo space available!"); return; } + core::Item *item = 0; + if (weapon->stackable()) { item = player->control()->inventory()->find(weapon); - } - - if (!item) { - item = new core::Item(weapon); - player->control()->inventory()->add(item); + if (!item) { + item = new core::Item(weapon); + player->control()->inventory()->add(item); + } else { + assert(item->info() == weapon); + } + item->inc_amount(amount); } else { - assert(item->info() == weapon); - } + for (int n = 0; n < amount; n++) { + item = new core::Item(weapon); + item->set_flag(core::Item::Unique); + item->set_amount(1); + player->control()->inventory()->add(item); + } + } - item->inc_amount(amount); player->control()->inventory()->set_dirty(); player->sound("game/buy"); } @@ -496,7 +537,7 @@ void Game::func_give(core::Player *player, const std::string &args) player->send("Usage: give cargo [string] [int]"); player->send(" give credits [int]"); player->send(" give ship [string]"); - player->send(" give weapon [string]"); + player->send(" give weapon [string] [int]"); return; } } @@ -615,100 +656,302 @@ void Game::func_specs(core::Player *player, const std::string &args) } -// sell request from a player +// sell items on a base void Game::func_sell(core::Player *player, const std::string &args) { + // must be joined to buy items if (!player->control()) { player->send("^WYou need to join the game first!"); return; } - std::istringstream is(args); - std::string typestr; - std::string labelstr; - - if (!(is >> typestr)) { - player->send("Usage: sell [string] [string] [int] sell an item: specify type, label and amount"); + Ship *seller = static_cast<Ship *>(player->control()); + + // must be docked to buy items + if ((seller->state() != core::Entity::Docked) || (!seller->dock())) { + player->send("^WYou need to be docked!"); return; - } else { - aux::to_label(typestr); } - - if (!(is >> labelstr)) { - player->send("Usage: sell [string] [string] [int] sell an item: specify type, label and amount"); + + core::Entity *buyer = seller->dock(); + + // can only buy at planets and stations + if ((buyer->moduletype() != station_enttype) && (buyer->moduletype() != planet_enttype)) { + player->send("^WCan not sell here"); + return; + } + + if (!seller->inventory() || !buyer->inventory()) { + player->send("^WCan not sell here"); return; - } else { - aux::to_label(labelstr); } + core::Item *seller_item = 0; + core::Item *buyer_item = 0; + unsigned int id = 0; int amount = 0; - if (!(is >> amount)) - amount = 0; - - if (typestr.compare("cargo") == 0) { - Cargo *cargo = Cargo::find(labelstr); - if (cargo) { - cargo->sell(player->control(), player->view(), amount); + + std::istringstream is(args); + if (is >> id >> amount) { + + seller_item = seller->inventory()->find(id); + if (!seller_item) { + std::stringstream msgstr; + msgstr << "^WItem " << id << " not in inventory"; + player->send(msgstr.str()); + return; + } + + if (amount == 0) { + player->send("^WNo amount specified"); + return; + } + + if (seller_item->info()->type() == Cargo::infotype()) { + // cargo has to be in demand + buyer_item = buyer->inventory()->find(seller_item->info()); + if (!buyer_item) { + player->send("^W" + buyer->name() + " ^Bdoes not buy " + seller_item->info()->name()); + return; + } + } else if (seller_item->info()->type() == Weapon::infotype()) { + // weapons can be sold anywhere + if (!seller_item->unique()) { + buyer_item = buyer->inventory()->find(seller_item->info()); + } + if (!buyer_item) { + buyer_item = new core::Item(seller_item->info()); + buyer_item->set_flags(seller_item->flags()); + buyer->inventory()->add(buyer_item); + } } else { - player->send("Unkown cargo type '" + labelstr + "'"); + player->send("^W" + buyer->name() + " ^Bdoes not buy " + seller_item->info()->name()); + return; + } + + if (amount < 0) { + amount = seller_item->amount(); + } else if (amount > seller_item->amount()) { + amount = seller_item->amount(); + } + + int price = buyer_item->price(); + + seller_item->dec_amount(amount); + seller->owner()->set_credits(seller->owner()->credits() + price * amount); + seller->owner()->set_dirty(); + seller->inventory()->set_dirty(); + + if (buyer_item->amount() >= 0) { + buyer_item->inc_amount(amount); + buyer->inventory()->set_dirty(); + } + + if (seller_item->amount() == 0) { + seller->inventory()->erase(seller_item->id()); + seller->inventory()->set_dirty(); + seller_item = 0; } + + // send a cargo sold message + std::stringstream msgstr; + if (buyer_item->unique()) { + msgstr << "^BSold " << buyer_item->info()->name(); + } else { + msgstr << "^BSold " << amount << " " << aux::plural("unit", amount) << " of " << buyer_item->info()->name() << " for " << price * amount << " credits"; + } + player->send(msgstr.str()); + player->sound("game/buy"); } else { - player->send("Unkown item type '" + typestr + "'"); + player->send("Usage: sell [id] [amount] sell item from inventory"); } - return; } -// buy request from a player +// buy items on a base void Game::func_buy(core::Player *player, const std::string &args) { + // must be joined to buy items if (!player->control()) { player->send("^WYou need to join the game first!"); return; } - std::istringstream is(args); - std::string typestr; - std::string labelstr; - - if (!(is >> typestr)) { - player->send("Usage: buy [string] [string] [int] buy an item: specify type, label and amount"); + Ship *ship = static_cast<Ship *>(player->control()); + + // must be docked to buy items + if ((ship->state() != core::Entity::Docked) || (!ship->dock())) { + player->send("^WYou need to be docked!"); return; - } else { - aux::to_label(typestr); } - - if (!(is >> labelstr)) { - player->send("Usage: buy [string] [string] [int] buy an item: specify type, label and amount"); + + core::Entity *seller = ship->dock(); + + // can only buy at planets and stations + if ((seller->moduletype() != station_enttype) && (seller->moduletype() != planet_enttype)) { + player->send("^WCan not buy here"); + return; + } + + if (!ship->inventory() || !seller->inventory()) { + player->send("^WCan not buy here"); return; - } else { - aux::to_label(labelstr); } + core::Item *item = 0; + unsigned int id = 0; int amount = 0; - if (!(is >> amount)) - amount = 0; + + std::istringstream is_int(args); + if (is_int >> id >> amount) { + + // item id based buy + item = seller->inventory()->find(id); + if (!item) { + std::stringstream msgstr; + msgstr << "^WItem " << id << " not in seller inventory"; + player->send(msgstr.str()); + return; + } + + if (item->info()->type() == ShipModel::infotype()) { + ShipModel *shipmodel = ShipModel::find(item->info()->label()); + if (shipmodel) { + shipmodel->buy(player->control(), player->view()); + } + return; + + } else if ((item->info()->type() == Cargo::infotype()) || (item->info()->type() == Weapon::infotype())) { + + int price = item->price(); + long cash = player->credits(); + + if (item->unique()) { + amount = 1; + } + + // check if the player has enough cash + if (price > 0) { + + // negative amount means 'as much as possible' + if (amount < 0) { + amount = cash / price; + } + + // maximum amount the player can afford + if (cash < (amount * price)) { + amount = cash / price; + } + + if (amount < 1) { + player->send("^WCan not afford transaction!"); + return; + } + } + + // check cargo size - ignore zero volume cargo + if (item->info()->volume() > 0 ) { + + // maximum cargo size + if (amount * item->info()->volume() > ship->inventory()->capacity_available()) { + amount = (int)floorf(ship->inventory()->capacity_available() / item->info()->volume()); + } + + if (amount < 1) { + player->send("^WNot enough cargo space available!"); + return; + } + } + + if (amount <= 0) { + // unlimited amount of zero-cost cargo + player->send("^WUnlimited amounts of free items are not supported!"); + return; + } + + // if amount is set to -1. the base has an unlimited supply + if (item->amount() == 0) { + player->send("^W" + item->info()->name() + " not available!"); + return; + + } else if (item->amount() > 0) { + + if (amount > item->amount()) { + amount = item->amount(); + } + } + + // buyer is the player + core::Item *buyer_item = 0; + if (!item->unique()) { + buyer_item = ship->inventory()->find(item->info()); + } + if (!buyer_item) { + buyer_item = new core::Item(item->info()); + buyer_item->set_flags(item->flags()); + ship->inventory()->add(buyer_item); + } + + // update buyer inventory + buyer_item->inc_amount(amount); + ship->inventory()->set_dirty(); + player->set_credits(player->credits() - price * amount); + player->set_dirty(); + + // update seller inventory + if (item->amount() >= 0) { + item->dec_amount(amount); + seller->inventory()->set_dirty(); + } + + if (item->info()->type() == Weapon::infotype()) { + if (item->amount() == 0) { + seller->inventory()->erase(item->id()); + seller->inventory()->set_dirty(); + } + } + + // send a message to the player + std::stringstream msgstr; + if (buyer_item->unique()) { + msgstr << "^BPurchased a " << buyer_item->info()->name(); + } else { + msgstr << "^BPurchased " << amount << " " << aux::plural("unit", amount) << " of " << buyer_item->info()->name() << " for " << price * amount << " credits"; + } + player->send(msgstr.str()); + player->sound("game/buy"); + } else { + player->send("^WCan not buy " + item->info()->name()); + } + + } else { + + std::istringstream is(args); + std::string typestr; + std::string labelstr; - if (typestr.compare("ship") == 0) { - ShipModel *shipmodel = ShipModel::find(labelstr); - if (shipmodel) { - shipmodel->buy(player->control(), player->view()); + if (!(is >> typestr >> labelstr)) { + player->send("Usage: buy ship [ship label] buy a ship from a base"); + player->send("Usage: buy [id] [amount] buy from base inventory"); + return; } else { - player->send("Unkown ship type '" + labelstr + "'"); + aux::to_label(typestr); + aux::to_label(labelstr); } - } else if (typestr.compare("cargo") == 0) { - Cargo *cargo = Cargo::find(labelstr); - if (cargo) { - cargo->buy(player->control(), player->view(), amount); + + if (typestr.compare("ship") == 0) { + ShipModel *shipmodel = ShipModel::find(labelstr); + if (shipmodel) { + shipmodel->buy(player->control(), player->view()); + } else { + player->send("Unknown ship type '" + labelstr + "'"); + } } else { - player->send("Unkown cargo type '" + labelstr + "'"); + player->send("Unknown item type '" + typestr + "'"); } - } else { - player->send("Unkown item type '" + typestr + "'"); } - return; } -// eject cargo request +// eject item request void Game::func_eject(core::Player *player, const std::string &args) { if (!player->control()) { @@ -717,44 +960,103 @@ void Game::func_eject(core::Player *player, const std::string &args) } std::istringstream is(args); - std::string typestr; - std::string labelstr; - - if (!(is >> typestr)) { - player->send("Usage: eject [string] [string] [int] eject an item: specify type, label and amount"); + unsigned int id; + + if (!(is >> id)) { + player->send("Usage: eject [id] [int] eject inventory item, amount"); return; - } else { - aux::to_label(typestr); } - - if (g_devel->value()) { - if (typestr.compare("mine") == 0) { - SpaceMine::eject(player->control()); - return; + + int amount = 0; + if (!(is >> amount)) + amount = -1; + + if (!amount) { + return; + } + + core::EntityControlable *ejector = player->control(); + + // cannot eject while jumping + 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; } - - if (!(is >> labelstr)) { - player->send("Usage: eject [string] [string] [int] eject an item: specify type, label and amount"); + + // find the item in the inventory + core::Item *item = ejector->inventory()->find(id); + if (!item) { + if (ejector->owner()) { + std::stringstream msgstr; + msgstr << "^WItem " << id << " not in inventory"; + ejector->owner()->send(msgstr.str()); + } return; - } else { - aux::to_label(labelstr); + } + if (!item->amount()) { + if (ejector->owner()) { + ejector->owner()->send("^WYou do not own any " + item->info()->name()); + } + return; + } + + if ((amount < 0) || (amount > item->amount())) { + amount = item->amount(); } - - int amount = 0; - if (!(is >> amount)) - amount = 0; + item->dec_amount(amount); - if (typestr.compare("cargo") == 0) { - Cargo *cargo = Cargo::find(labelstr); - if (cargo) { - cargo->eject(player->control(), amount); - } else { - player->send("Unkown cargo type '" + labelstr + "'"); + if (ejector->state() == core::Entity::Docked) { + if (ejector->owner()) { + std::stringstream msgstr; + msgstr << "^BDestroyed " << amount << " " << aux::plural("unit", amount) << " of " << item->info()->name(); + ejector->owner()->send(msgstr.str()); + ejector->owner()->sound("fx/eject"); } - } else { - player->send("Unkown item type '" + typestr + "'"); + } else { + // create cargo pod + CargoPod *pod = new CargoPod(); + + if (item->unique() && item->info()->modelname().size()) { + pod->set_modelname(item->info()->modelname()); + } + pod->set_color(ejector->color()); + pod->set_color_second(ejector->color_second()); + pod->set_location(ejector->location() + ejector->axis().up() * (ejector->radius() + pod->radius())); + pod->set_axis(ejector->axis()); + pod->set_zone(ejector->zone()); + pod->set_info(item->info()); + + // add loot to inventory + pod->add_inventory(); + pod->inventory()->set_capacity(item->info()->volume() * amount); + + core::Item *loot = new core::Item(item->info()); + loot->set_amount(amount); + loot->set_flags(item->flags()); + + pod->inventory()->add(loot); + pod->inventory()->set_dirty(); + + if (ejector->owner()) { + std::stringstream msgstr; + if (item->unique()) { + msgstr << "^BEjected " << item->info()->name(); + } else { + msgstr << "^BEjected " << amount << " " << aux::plural("unit", amount) << " of " << item->info()->name(); + } + ejector->owner()->send(msgstr.str()); + ejector->owner()->sound("fx/eject"); + } + + pod->reset(); + } + + if (item->amount() == 0) { + ejector->inventory()->erase(item->id()); } + ejector->inventory()->set_dirty(); } // beam in nearby cargo pods @@ -792,12 +1094,14 @@ void Game::func_beam(core::Player *player, const std::string &args) } if (negotiated_amount > 0) { - core::Item *iteminv = inventory->find(item->info()); + core::Item *iteminv = 0; + if (!item->has_flag(core::Item::Unique)) { + iteminv = inventory->find(item->info()); + } if (!iteminv) { iteminv = new core::Item(item->info()); inventory->add(iteminv); } - item->dec_amount(negotiated_amount); iteminv->inc_amount(negotiated_amount); @@ -1101,7 +1405,7 @@ Game::~Game() Cargo::done(); // clear Weapon - Weapon::clear(); + Weapon::done(); // clear ShipModel ShipModel::done(); @@ -1189,6 +1493,7 @@ bool Game::load_zone(core::Zone *zone) // set zone defaults zone->set_color(0.5f); zone->set_ambient_color(0.1f); + zone->set_sky("default"); std::string inifilename("ini/zones/"); inifilename.append(zone->label()); @@ -1326,6 +1631,22 @@ bool Game::load_zone(core::Zone *zone) } } + } else if (zoneini.got_section("weapon")) { + // new weapon trading definition for the current base + item = 0; + inventory = 0; + + if (!entity) { + zoneini.unknown_error("weapon definition without entity"); + } else if ((entity->moduletype() != planet_enttype) && (entity->moduletype() != station_enttype)) { + zoneini.unknown_error("weapon definition for invalid entity type"); + } else { + inventory = entity->inventory(); + if (!inventory) { + inventory = entity->add_inventory(); + } + } + } else { zoneini.unknown_section(); } @@ -1544,7 +1865,7 @@ bool Game::load_zone(core::Zone *zone) } } else if (zoneini.in_section("cargo")) { - // cargo definition for a station or planet + // cargo trade definition for a station or planet if (!entity || !inventory) { continue; } @@ -1574,9 +1895,44 @@ bool Game::load_zone(core::Zone *zone) } else { zoneini.unknown_key(); } + + } else if (zoneini.in_section("weapon")) { + // weapon trade definition for a station or planet + if (!entity || !inventory) { + continue; + } + + if (zoneini.got_key_label("label", strval)) { + Weapon *weapon = Weapon::find(strval); + if (weapon) { + item = inventory->find(weapon); + if (!item) { + item = new core::Item(weapon); + item->set_amount(-1); + item->set_price(weapon->price()); + if (!weapon->stackable()) { + item->set_flag(core::Item::Unique); + } + inventory->add(item); + } + } else { + zoneini.unknown_error("unknown weapon type '" + strval + "'"); + } + + } else if (zoneini.got_key_long("price", l)) { + if (item) { + item->set_price(l); + } + } else if (zoneini.got_key_long("amount", l)) { + if (item) { + item->set_amount(l); + } + } else { + zoneini.unknown_key(); + } } else if (zoneini.in_section("ship")) { - // ship definition for a station or planet + // ship trade definition for a station or planet if (!entity || !inventory) { continue; } @@ -1686,7 +2042,8 @@ bool Game::generate_entity_menus(core::Entity *entity) if (entity->inventory()) { entity->set_flag(core::Entity::KeepAlive); size_t nbcargo = 0; - size_t nbships = 0; + size_t nbweapon = 0; + size_t nbships = 0; for (core::Inventory::Items::const_iterator it = entity->inventory()->items().begin(); it != entity->inventory()->items().end(); it++) { core::Item *item = (*it); @@ -1694,6 +2051,9 @@ bool Game::generate_entity_menus(core::Entity *entity) if (item->info()->type() == Cargo::infotype()) { nbcargo++; + } else if (item->info()->type() == Weapon::infotype()) { + nbweapon++; + } else if (item->info()->type() == ShipModel::infotype()) { if (!menu_dealer) { menu_dealer = new MenuDescription(); @@ -1723,6 +2083,15 @@ bool Game::generate_entity_menus(core::Entity *entity) button->set_alignment(ButtonDescription::Center); menu_main->add_button(button); } + + if (nbweapon > 0) { + con_debug << " " << entity->label() << " " << nbcargo << " weapon " << aux::plural("type", nbweapon) << std::endl; + button = new ButtonDescription(); + button->set_text("Weapon Dealer"); + button->set_command("trade weapon", ButtonDescription::CommandMenu); + button->set_alignment(ButtonDescription::Center); + menu_main->add_button(button); + } if (nbships > 0) { con_debug << " " << entity->label() << " " << nbships << " ship " << aux::plural("type", nbships) << std::endl; diff --git a/src/game/base/planet.cc b/src/game/base/planet.cc index 2adb1fb..06a8219 100644 --- a/src/game/base/planet.cc +++ b/src/game/base/planet.cc @@ -6,7 +6,7 @@ #include "base/game.h" #include "base/planet.h" - +#include "base/weapon.h" namespace game { @@ -27,4 +27,36 @@ Planet::~Planet() } +void Planet::upkeep(const unsigned long timestamp) +{ + if (!inventory()) + return; + + const unsigned long deplete = (Game::g_deplete ? 1000 * (unsigned long) Game::g_deplete->value() : 0); + + if (deplete > 0) { + bool dirty = false; + for (core::Inventory::Items::iterator it = inventory()->items().begin(); it != inventory()->items().end(); ) { + core::Item *item = (*it); + if ((item->amount() > 0) && (item->timestamp() + deplete < timestamp)) { + item->dec_amount(1); + dirty = true; + } + + if ((item->info()->type() == Weapon::infotype()) && (item->amount() == 0)) { + delete (item); + (*it) = 0; + inventory()->items().erase(it++); + dirty = true; + } else { + ++it; + } + } + + if (dirty) { + inventory()->set_dirty(); + } + } +} + } // namespace game diff --git a/src/game/base/planet.h b/src/game/base/planet.h index 19db012..337bab2 100644 --- a/src/game/base/planet.h +++ b/src/game/base/planet.h @@ -21,6 +21,8 @@ class Planet : public core::EntityGlobe public: Planet(); virtual ~Planet(); + + virtual void upkeep(const unsigned long timestamp); }; } // namespace game diff --git a/src/game/base/savegame.cc b/src/game/base/savegame.cc index 0057a50..e70e143 100644 --- a/src/game/base/savegame.cc +++ b/src/game/base/savegame.cc @@ -177,6 +177,14 @@ void SaveGame::load_game(core::Player *player, filesystem::IniFile & inifile) item->unset_flag(core::Item::Tradeable); } } + } else if (inifile.got_key_bool("unique", b)) { + if (item) { + if (b) { + item->set_flag(core::Item::Unique); + } else { + item->unset_flag(core::Item::Unique); + } + } } else { inifile.unknown_key(); } @@ -291,7 +299,12 @@ void SaveGame::inventory_to_stream(core::Inventory *inventory, std::ostream & os os << "label=" << item->info()->label() << std::endl; os << "amount=" << item->amount() << std::endl; os << "price=" << item->price() << std::endl; - os << "tradeable=" << (item->has_flag(core::Item::Tradeable) ? "yes" : "no") << std::endl; + if (item->has_flag(core::Item::Tradeable)) { + os << "tradeable=" << (item->has_flag(core::Item::Tradeable) ? "yes" : "no") << std::endl; + } + if (item->has_flag(core::Item::Unique)) { + os << "unique=" << (item->has_flag(core::Item::Unique) ? "yes" : "no") << std::endl; + } } } diff --git a/src/game/base/ship.cc b/src/game/base/ship.cc index 9874337..22fb269 100644 --- a/src/game/base/ship.cc +++ b/src/game/base/ship.cc @@ -15,8 +15,6 @@ #include "base/ship.h" #include "math/functions.h" - - using math::degrees360f; using math::degrees180f; diff --git a/src/game/base/station.cc b/src/game/base/station.cc index 6493348..31e6b3e 100644 --- a/src/game/base/station.cc +++ b/src/game/base/station.cc @@ -6,6 +6,7 @@ #include "base/game.h" #include "base/station.h" +#include "base/weapon.h" #include "sys/sys.h" namespace game @@ -32,12 +33,21 @@ void Station::upkeep(const unsigned long timestamp) if (deplete > 0) { bool dirty = false; - for (core::Inventory::Items::iterator it = inventory()->items().begin(); it != inventory()->items().end(); it++) { + for (core::Inventory::Items::iterator it = inventory()->items().begin(); it != inventory()->items().end(); ) { core::Item *item = (*it); if ((item->amount() > 0) && (item->timestamp() + deplete < timestamp)) { item->dec_amount(1); dirty = true; } + + if ((item->info()->type() == Weapon::infotype()) && (item->amount() == 0)) { + delete (item); + (*it) = 0; + inventory()->items().erase(it++); + dirty = true; + } else { + ++it; + } } if (dirty) { diff --git a/src/game/base/weapon.cc b/src/game/base/weapon.cc index 7f816e2..8be9f9a 100644 --- a/src/game/base/weapon.cc +++ b/src/game/base/weapon.cc @@ -11,6 +11,7 @@ #include "filesystem/inifile.h" #include "auxiliary/functions.h" #include "core/func.h" +#include "base/cargopod.h" #include "base/game.h" #include "base/weapon.h" @@ -187,6 +188,21 @@ void Weapon::done() core::Func::remove("list_weapons"); } + +Weapon *Weapon::find(const std::string & label) +{ + if (!label.size()) { + return 0; + } + + return (Weapon *) core::Info::find(weapon_infotype, label); +} + +void Weapon::list() +{ + core::Info::list(weapon_infotype); +} + /* ---- class Weapon ------------------------------------------- */ Weapon::Weapon() : core::Info(weapon_infotype) @@ -200,18 +216,14 @@ Weapon::~Weapon() { } -Weapon *Weapon::find(const std::string & label) +void Weapon::set_stackable(bool stackable) { - if (!label.size()) { - return 0; - } - - return (Weapon *) core::Info::find(weapon_infotype, label); + weapon_stackable = stackable; } -void Weapon::list() +void Weapon::set_level(const int level) { - core::Info::list(weapon_infotype); + weapon_level = level; } } // namespace game diff --git a/src/game/base/weapon.h b/src/game/base/weapon.h index b263266..247a3e7 100644 --- a/src/game/base/weapon.h +++ b/src/game/base/weapon.h @@ -25,13 +25,9 @@ public: return weapon_level; } - inline void set_stackable(bool stackable) { - weapon_stackable = stackable; - } + void set_stackable(bool stackable); - inline void set_level(const int level) { - weapon_level = level; - } + void set_level(const int level); /* --- static registry functions ---------------------------------- */ |