remove meseta when buying shop items
This commit is contained in:
@@ -327,7 +327,7 @@ size_t ItemParameterTable::price_for_item(const ItemData& item) const {
|
|||||||
size_t special_stars = this->get_special_stars(item.data1[4]);
|
size_t special_stars = this->get_special_stars(item.data1[4]);
|
||||||
double special_stars_factor = 1000.0 * special_stars * special_stars;
|
double special_stars_factor = 1000.0 * special_stars * special_stars;
|
||||||
|
|
||||||
return special_stars_factor + (atp_factor * (bonus_factor / 100.0));
|
return special_stars_factor + ((atp_factor * bonus_factor) / 100.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 1: {
|
case 1: {
|
||||||
|
|||||||
+16
-11
@@ -573,10 +573,7 @@ void SavedPlayerDataBB::add_item(const PlayerInventoryItem& item) {
|
|||||||
// Annoyingly, meseta is in the disp data, not in the inventory struct. If the
|
// Annoyingly, meseta is in the disp data, not in the inventory struct. If the
|
||||||
// item is meseta, we have to modify disp instead.
|
// item is meseta, we have to modify disp instead.
|
||||||
if (pid == MESETA_IDENTIFIER) {
|
if (pid == MESETA_IDENTIFIER) {
|
||||||
this->disp.stats.meseta += item.data.data2d;
|
this->add_meseta(item.data.data2d);
|
||||||
if (this->disp.stats.meseta > 999999) {
|
|
||||||
this->disp.stats.meseta = 999999;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -657,13 +654,7 @@ PlayerInventoryItem SavedPlayerDataBB::remove_item(
|
|||||||
// If we're removing meseta (signaled by an invalid item ID), then create a
|
// If we're removing meseta (signaled by an invalid item ID), then create a
|
||||||
// meseta item.
|
// meseta item.
|
||||||
if (item_id == 0xFFFFFFFF) {
|
if (item_id == 0xFFFFFFFF) {
|
||||||
if (amount <= this->disp.stats.meseta) {
|
this->remove_meseta(amount, allow_meseta_overdraft);
|
||||||
this->disp.stats.meseta -= amount;
|
|
||||||
} else if (allow_meseta_overdraft) {
|
|
||||||
this->disp.stats.meseta = 0;
|
|
||||||
} else {
|
|
||||||
throw out_of_range("player does not have enough meseta");
|
|
||||||
}
|
|
||||||
ret.data.data1[0] = 0x04;
|
ret.data.data1[0] = 0x04;
|
||||||
ret.data.data2d = amount;
|
ret.data.data2d = amount;
|
||||||
return ret;
|
return ret;
|
||||||
@@ -697,6 +688,20 @@ PlayerInventoryItem SavedPlayerDataBB::remove_item(
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SavedPlayerDataBB::add_meseta(uint32_t amount) {
|
||||||
|
this->disp.stats.meseta = min<size_t>(static_cast<size_t>(this->disp.stats.meseta) + amount, 999999);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SavedPlayerDataBB::remove_meseta(uint32_t amount, bool allow_overdraft) {
|
||||||
|
if (amount <= this->disp.stats.meseta) {
|
||||||
|
this->disp.stats.meseta -= amount;
|
||||||
|
} else if (allow_overdraft) {
|
||||||
|
this->disp.stats.meseta = 0;
|
||||||
|
} else {
|
||||||
|
throw out_of_range("player does not have enough meseta");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PlayerBankItem PlayerBank::remove_item(uint32_t item_id, uint32_t amount) {
|
PlayerBankItem PlayerBank::remove_item(uint32_t item_id, uint32_t amount) {
|
||||||
PlayerBankItem ret;
|
PlayerBankItem ret;
|
||||||
|
|
||||||
|
|||||||
@@ -452,6 +452,8 @@ struct SavedPlayerDataBB { // .nsc file format
|
|||||||
void add_item(const PlayerInventoryItem& item);
|
void add_item(const PlayerInventoryItem& item);
|
||||||
PlayerInventoryItem remove_item(
|
PlayerInventoryItem remove_item(
|
||||||
uint32_t item_id, uint32_t amount, bool allow_meseta_overdraft);
|
uint32_t item_id, uint32_t amount, bool allow_meseta_overdraft);
|
||||||
|
void add_meseta(uint32_t amount);
|
||||||
|
void remove_meseta(uint32_t amount, bool allow_overdraft);
|
||||||
|
|
||||||
void print_inventory(FILE* stream) const;
|
void print_inventory(FILE* stream) const;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|||||||
+19
-25
@@ -833,7 +833,7 @@ static void on_drop_partial_stack_bb(shared_ptr<ServerState>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_buy_shop_item(shared_ptr<ServerState>,
|
static void on_buy_shop_item(shared_ptr<ServerState> s,
|
||||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||||
const void* data, size_t size) {
|
const void* data, size_t size) {
|
||||||
const auto& cmd = check_size_t<G_BuyShopItem_6x5E>(data, size);
|
const auto& cmd = check_size_t<G_BuyShopItem_6x5E>(data, size);
|
||||||
@@ -853,17 +853,21 @@ static void on_buy_shop_item(shared_ptr<ServerState>,
|
|||||||
if (c->version() == GameVersion::GC) {
|
if (c->version() == GameVersion::GC) {
|
||||||
item.data.bswap_data2_if_mag();
|
item.data.bswap_data2_if_mag();
|
||||||
}
|
}
|
||||||
c->game_data.player()->add_item(item);
|
|
||||||
|
|
||||||
|
auto p = c->game_data.player();
|
||||||
|
p->add_item(item);
|
||||||
|
|
||||||
|
size_t price = s->item_parameter_table->price_for_item(item.data);
|
||||||
auto name = item.data.name(false);
|
auto name = item.data.name(false);
|
||||||
l->log.info("Player %hu bought item %08" PRIX32 " (%s) from shop",
|
l->log.info("Player %hu bought item %08" PRIX32 " (%s) from shop (%zu Meseta)",
|
||||||
cmd.header.client_id.load(), item.data.id.load(), name.c_str());
|
cmd.header.client_id.load(), item.data.id.load(), name.c_str(), price);
|
||||||
if (c->options.debug) {
|
if (c->options.debug) {
|
||||||
string name = item.data.name(true);
|
string name = item.data.name(true);
|
||||||
send_text_message_printf(c, "$C5BUY %08" PRIX32 "\n%s",
|
send_text_message_printf(c, "$C5BUY %08" PRIX32 "\n%s",
|
||||||
item.data.id.load(), name.c_str());
|
item.data.id.load(), name.c_str());
|
||||||
}
|
}
|
||||||
c->game_data.player()->print_inventory(stderr);
|
p->remove_meseta(price, c->version() != GameVersion::BB);
|
||||||
|
p->print_inventory(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
forward_subcommand_with_mag_bswap_t(l, c, command, flag, cmd);
|
forward_subcommand_with_mag_bswap_t(l, c, command, flag, cmd);
|
||||||
@@ -1701,15 +1705,14 @@ static void on_sell_item_at_shop_bb(shared_ptr<ServerState> s,
|
|||||||
throw logic_error("item tracking not enabled in BB game");
|
throw logic_error("item tracking not enabled in BB game");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto item = c->game_data.player()->remove_item(
|
auto p = c->game_data.player();
|
||||||
cmd.item_id, cmd.amount, c->version() != GameVersion::BB);
|
auto item = p->remove_item(cmd.item_id, cmd.amount, c->version() != GameVersion::BB);
|
||||||
size_t price = (s->item_parameter_table->price_for_item(item.data) >> 3) * cmd.amount;
|
size_t price = (s->item_parameter_table->price_for_item(item.data) >> 3) * cmd.amount;
|
||||||
c->game_data.player()->disp.stats.meseta = min<uint32_t>(
|
p->add_meseta(price);
|
||||||
c->game_data.player()->disp.stats.meseta + price, 999999);
|
|
||||||
|
|
||||||
auto name = item.data.name(false);
|
auto name = item.data.name(false);
|
||||||
l->log.info("Inventory item %hu:%08" PRIX32 " destroyed via sale (%s)",
|
l->log.info("Inventory item %hu:%08" PRIX32 " (%s) destroyed via sale (%zu Meseta)",
|
||||||
c->lobby_client_id, cmd.item_id.load(), name.c_str());
|
c->lobby_client_id, cmd.item_id.load(), name.c_str(), price);
|
||||||
c->game_data.player()->print_inventory(stderr);
|
c->game_data.player()->print_inventory(stderr);
|
||||||
if (c->options.debug) {
|
if (c->options.debug) {
|
||||||
string name = item.data.name(true);
|
string name = item.data.name(true);
|
||||||
@@ -1739,19 +1742,17 @@ static void on_buy_shop_item_bb(shared_ptr<ServerState>,
|
|||||||
|
|
||||||
size_t price = item.data.data2d * cmd.amount;
|
size_t price = item.data.data2d * cmd.amount;
|
||||||
item.data.data2d = 0;
|
item.data.data2d = 0;
|
||||||
if (c->game_data.player()->disp.stats.meseta < price) {
|
auto p = c->game_data.player();
|
||||||
throw runtime_error("player does not have enough money");
|
p->remove_meseta(price, false);
|
||||||
}
|
|
||||||
c->game_data.player()->disp.stats.meseta -= price;
|
|
||||||
|
|
||||||
item.data.id = cmd.inventory_item_id;
|
item.data.id = cmd.inventory_item_id;
|
||||||
c->game_data.player()->add_item(item);
|
p->add_item(item);
|
||||||
send_create_inventory_item(l, c, item.data);
|
send_create_inventory_item(l, c, item.data);
|
||||||
|
|
||||||
auto name = item.data.name(false);
|
auto name = item.data.name(false);
|
||||||
l->log.info("Inventory item %hu:%08" PRIX32 " created via purchase (%s) for %zu meseta",
|
l->log.info("Inventory item %hu:%08" PRIX32 " created via purchase (%s) for %zu meseta",
|
||||||
c->lobby_client_id, cmd.inventory_item_id.load(), name.c_str(), price);
|
c->lobby_client_id, cmd.inventory_item_id.load(), name.c_str(), price);
|
||||||
c->game_data.player()->print_inventory(stderr);
|
p->print_inventory(stderr);
|
||||||
if (c->options.debug) {
|
if (c->options.debug) {
|
||||||
string name = item.data.name(true);
|
string name = item.data.name(true);
|
||||||
send_text_message_printf(c, "$C5CREATE/BUY %08" PRIX32 "\n-%zu Meseta\n%s",
|
send_text_message_printf(c, "$C5CREATE/BUY %08" PRIX32 "\n-%zu Meseta\n%s",
|
||||||
@@ -1762,20 +1763,13 @@ static void on_buy_shop_item_bb(shared_ptr<ServerState>,
|
|||||||
|
|
||||||
static void on_medical_center_bb(shared_ptr<ServerState>,
|
static void on_medical_center_bb(shared_ptr<ServerState>,
|
||||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t, uint8_t, const void*, size_t) {
|
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t, uint8_t, const void*, size_t) {
|
||||||
|
|
||||||
if (l->version == GameVersion::BB) {
|
if (l->version == GameVersion::BB) {
|
||||||
if (c->game_data.player()->disp.stats.meseta < 10) {
|
c->game_data.player()->remove_meseta(10, false);
|
||||||
throw runtime_error("insufficient funds");
|
|
||||||
}
|
|
||||||
c->game_data.player()->disp.stats.meseta -= 10;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Subcommands are described by four fields: the minimum size and maximum size (in DWORDs),
|
|
||||||
// the handler function, and flags that tell when to allow the command. See command-input-subs.h
|
|
||||||
// for more information on flags. The maximum size is not enforced if it's zero.
|
|
||||||
typedef void (*subcommand_handler_t)(shared_ptr<ServerState> s,
|
typedef void (*subcommand_handler_t)(shared_ptr<ServerState> s,
|
||||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||||
const void* data, size_t size);
|
const void* data, size_t size);
|
||||||
|
|||||||
Reference in New Issue
Block a user