Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2012-10-20 16:35:26 +0000
committerStijn Buys <ingar@osirion.org>2012-10-20 16:35:26 +0000
commit75274ebd6ba90784f5aa837b7e5ea97fc6bfb720 (patch)
treea5d51a87bf3f20833df18bc40a3254b946716afb /src/game
parentf01629dc14b1ee05b44d2e38b3dffbc1441fd85f (diff)
Item id based inventory, support for weapon dealers.
Diffstat (limited to 'src/game')
-rw-r--r--src/game/base/cargo.cc276
-rw-r--r--src/game/base/cargo.h6
-rw-r--r--src/game/base/game.cc627
-rw-r--r--src/game/base/planet.cc34
-rw-r--r--src/game/base/planet.h2
-rw-r--r--src/game/base/savegame.cc15
-rw-r--r--src/game/base/ship.cc2
-rw-r--r--src/game/base/station.cc12
-rw-r--r--src/game/base/weapon.cc28
-rw-r--r--src/game/base/weapon.h8
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 ---------------------------------- */