add $rand command
This commit is contained in:
@@ -333,6 +333,30 @@ static void proxy_command_secid(shared_ptr<ServerState>,
|
||||
}
|
||||
}
|
||||
|
||||
static void server_command_rand(shared_ptr<ServerState>, shared_ptr<Lobby> l,
|
||||
shared_ptr<Client> c, const std::u16string& args) {
|
||||
check_is_game(l, false);
|
||||
|
||||
if (!args[0]) {
|
||||
c->override_random_seed = -1;
|
||||
send_text_message(c, u"$C6Override seed\nremoved");
|
||||
} else {
|
||||
c->override_random_seed = stoul(encode_sjis(args), 0, 16);
|
||||
send_text_message(c, u"$C6Override seed\nset");
|
||||
}
|
||||
}
|
||||
|
||||
static void proxy_command_rand(shared_ptr<ServerState>,
|
||||
ProxyServer::LinkedSession& session, const std::u16string& args) {
|
||||
if (!args[0]) {
|
||||
session.override_random_seed = -1;
|
||||
send_text_message(session.client_channel, u"$C6Override seed\nremoved");
|
||||
} else {
|
||||
session.override_random_seed = stoul(encode_sjis(args), 0, 16);
|
||||
send_text_message(session.client_channel, u"$C6Override seed\nset");
|
||||
}
|
||||
}
|
||||
|
||||
static void server_command_password(shared_ptr<ServerState>, shared_ptr<Lobby> l,
|
||||
shared_ptr<Client> c, const std::u16string& args) {
|
||||
check_is_game(l, true);
|
||||
@@ -828,6 +852,7 @@ static const unordered_map<u16string, ChatCommandDefinition> chat_commands({
|
||||
// TODO: implement this on proxy server
|
||||
{u"$next" , {server_command_next , nullptr , u"Usage:\nnext"}},
|
||||
{u"$password" , {server_command_password , nullptr , u"Usage:\nlock [password]\nomit password to\nunlock game"}},
|
||||
{u"$rand" , {server_command_rand , proxy_command_rand , u"Usage:\nrand [hex seed]\nomit seed to revert\nto default"}},
|
||||
{u"$secid" , {server_command_secid , proxy_command_secid , u"Usage:\nsecid [section ID]\nomit section ID to\nrevert to normal"}},
|
||||
{u"$silence" , {server_command_silence , nullptr , u"Usage:\nsilence <name-or-number>"}},
|
||||
// TODO: implement this on proxy server
|
||||
|
||||
@@ -47,6 +47,7 @@ Client::Client(
|
||||
prefer_high_lobby_client_id(false),
|
||||
next_exp_value(0),
|
||||
override_section_id(-1),
|
||||
override_random_seed(-1),
|
||||
infinite_hp(false),
|
||||
infinite_tp(false),
|
||||
switch_assist(false),
|
||||
|
||||
@@ -92,6 +92,7 @@ struct Client {
|
||||
// Miscellaneous (used by chat commands)
|
||||
uint32_t next_exp_value; // next EXP value to give
|
||||
int16_t override_section_id; // valid if >= 0
|
||||
int64_t override_random_seed; // valid if >= 0
|
||||
bool infinite_hp; // cheats enabled
|
||||
bool infinite_tp; // cheats enabled
|
||||
bool switch_assist; // cheats enabled
|
||||
|
||||
+57
-46
@@ -8,6 +8,13 @@ using namespace std;
|
||||
|
||||
|
||||
|
||||
uint32_t random_int(shared_ptr<mt19937> rand, uint32_t min, uint32_t max) {
|
||||
uint32_t range = max - min + 1;
|
||||
return min + ((*rand)() % range);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* these items all need some kind of special handling that hasn't been implemented yet.
|
||||
@@ -226,14 +233,13 @@ void player_use_item(shared_ptr<Client> c, size_t item_index) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// reads the non-rare item preferences from the config file.
|
||||
CommonItemCreator::CommonItemCreator(
|
||||
const vector<uint32_t>& enemy_item_categories,
|
||||
const vector<uint32_t>& box_item_categories,
|
||||
const vector<vector<uint8_t>>& unit_types) :
|
||||
enemy_item_categories(enemy_item_categories),
|
||||
box_item_categories(box_item_categories),
|
||||
unit_types(unit_types) {
|
||||
CommonItemData::CommonItemData(
|
||||
vector<uint32_t>&& enemy_item_categories,
|
||||
vector<uint32_t>&& box_item_categories,
|
||||
vector<vector<uint8_t>>&& unit_types) :
|
||||
enemy_item_categories(move(enemy_item_categories)),
|
||||
box_item_categories(move(box_item_categories)),
|
||||
unit_types(move(unit_types)) {
|
||||
|
||||
// sanity check the values
|
||||
if (this->enemy_item_categories.size() != 8) {
|
||||
@@ -267,16 +273,21 @@ CommonItemCreator::CommonItemCreator(
|
||||
}
|
||||
}
|
||||
|
||||
int32_t CommonItemCreator::decide_item_type(bool is_box) const {
|
||||
uint32_t determinant = random_object<uint32_t>();
|
||||
CommonItemCreator::CommonItemCreator(
|
||||
std::shared_ptr<const CommonItemData> data,
|
||||
std::shared_ptr<std::mt19937> random)
|
||||
: data(data), random(random) { }
|
||||
|
||||
const auto* v = is_box ? &this->box_item_categories : &this->enemy_item_categories;
|
||||
for (size_t x = 0; x < v->size(); x++) {
|
||||
uint32_t probability = v->at(x);
|
||||
if (probability > determinant) {
|
||||
int32_t CommonItemCreator::decide_item_type(bool is_box) const {
|
||||
uint32_t det = (*this->random)();
|
||||
|
||||
const auto& v = is_box ? this->data->box_item_categories : this->data->enemy_item_categories;
|
||||
for (size_t x = 0; x < v.size(); x++) {
|
||||
uint32_t probability = v.at(x);
|
||||
if (probability > det) {
|
||||
return x;
|
||||
}
|
||||
determinant -= probability;
|
||||
det -= probability;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -325,25 +336,25 @@ ItemData CommonItemCreator::create_drop_item(bool is_box, uint8_t episode,
|
||||
case 0x00: // material
|
||||
item.data1[0] = 0x03;
|
||||
item.data1[1] = 0x0B;
|
||||
item.data1[2] = random_int(0, 6);
|
||||
item.data1[2] = random_int(this->random, 0, 6);
|
||||
break;
|
||||
|
||||
case 0x01: // equipment
|
||||
switch (random_int(0, 3)) {
|
||||
switch (random_int(this->random, 0, 3)) {
|
||||
case 0x00: // weapon
|
||||
item.data1[1] = random_int(1, 12); // random normal class
|
||||
item.data1[2] = difficulty + random_int(0, 2); // special type
|
||||
item.data1[1] = random_int(this->random, 1, 12); // random normal class
|
||||
item.data1[2] = difficulty + random_int(this->random, 0, 2); // special type
|
||||
if ((item.data1[1] > 0x09) && (item.data1[2] > 0x04)) {
|
||||
item.data1[2] = 0x04; // no special classes above 4
|
||||
}
|
||||
item.data1[4] = 0x80; // untekked
|
||||
if (item.data1[2] < 0x04) {
|
||||
item.data1[4] |= random_int(0, 40); // give a special
|
||||
item.data1[4] |= random_int(this->random, 0, 40); // give a special
|
||||
}
|
||||
for (size_t x = 0, y = 0; (x < 5) && (y < 3); x++) { // percentages
|
||||
if (random_int(0, 10) == 1) { // 1/11 chance of getting each type of percentage
|
||||
if (random_int(this->random, 0, 10) == 1) { // 1/11 chance of getting each type of percentage
|
||||
item.data1[6 + (y * 2)] = x + 1;
|
||||
item.data1[7 + (y * 2)] = random_int(0, 10) * 5;
|
||||
item.data1[7 + (y * 2)] = random_int(this->random, 0, 10) * 5;
|
||||
y++;
|
||||
}
|
||||
}
|
||||
@@ -352,33 +363,33 @@ ItemData CommonItemCreator::create_drop_item(bool is_box, uint8_t episode,
|
||||
case 0x01: // armor
|
||||
item.data1[0] = 0x01;
|
||||
item.data1[1] = 0x01;
|
||||
item.data1[2] = (6 * difficulty) + random_int(0, ((area / 2) + 2) - 1); // standard type based on difficulty and area
|
||||
item.data1[2] = (6 * difficulty) + random_int(this->random, 0, ((area / 2) + 2) - 1); // standard type based on difficulty and area
|
||||
if (item.data1[2] > 0x17) {
|
||||
item.data1[2] = 0x17; // no standard types above 0x17
|
||||
}
|
||||
if (random_int(0, 10) == 0) { // +/-
|
||||
item.data1[4] = random_int(0, 5);
|
||||
item.data1[6] = random_int(0, 2);
|
||||
if (random_int(this->random, 0, 10) == 0) { // +/-
|
||||
item.data1[4] = random_int(this->random, 0, 5);
|
||||
item.data1[6] = random_int(this->random, 0, 2);
|
||||
}
|
||||
item.data1[5] = random_int(0, 4); // slots
|
||||
item.data1[5] = random_int(this->random, 0, 4); // slots
|
||||
break;
|
||||
|
||||
case 0x02: // shield
|
||||
item.data1[0] = 0x01;
|
||||
item.data1[1] = 0x02;
|
||||
item.data1[2] = (5 * difficulty) + random_int(0, ((area / 2) + 2) - 1); // standard type based on difficulty and area
|
||||
item.data1[2] = (5 * difficulty) + random_int(this->random, 0, ((area / 2) + 2) - 1); // standard type based on difficulty and area
|
||||
if (item.data1[2] > 0x14) {
|
||||
item.data1[2] = 0x14; // no standard types above 0x14
|
||||
}
|
||||
if (random_int(0, 10) == 0) { // +/-
|
||||
item.data1[4] = random_int(0, 5);
|
||||
item.data1[6] = random_int(0, 5);
|
||||
if (random_int(this->random, 0, 10) == 0) { // +/-
|
||||
item.data1[4] = random_int(this->random, 0, 5);
|
||||
item.data1[6] = random_int(this->random, 0, 5);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x03: { // unit
|
||||
const auto& type_table = this->unit_types.at(difficulty);
|
||||
uint8_t type = type_table[random_int(0, type_table.size() - 1)];
|
||||
const auto& type_table = this->data->unit_types.at(difficulty);
|
||||
uint8_t type = type_table[random_int(this->random, 0, type_table.size() - 1)];
|
||||
if (type == 0xFF) {
|
||||
throw out_of_range("no item dropped"); // 0xFF -> no item drops
|
||||
}
|
||||
@@ -393,11 +404,11 @@ ItemData CommonItemCreator::create_drop_item(bool is_box, uint8_t episode,
|
||||
case 0x02: // technique
|
||||
item.data1[0] = 0x03;
|
||||
item.data1[1] = 0x02;
|
||||
item.data1[4] = random_int(0, 18); // tech type
|
||||
item.data1[4] = random_int(this->random, 0, 18); // tech type
|
||||
if ((item.data1[4] != 14) && (item.data1[4] != 17)) { // if not ryuker or reverser, give it a level
|
||||
if (item.data1[4] == 16) { // if not anti, give it a level between 1 and 30
|
||||
if (area > 3) {
|
||||
item.data1[2] = difficulty + random_int(0, ((area - 1) / 2) - 1);
|
||||
item.data1[2] = difficulty + random_int(this->random, 0, ((area - 1) / 2) - 1);
|
||||
} else {
|
||||
item.data1[2] = difficulty;
|
||||
}
|
||||
@@ -405,7 +416,7 @@ ItemData CommonItemCreator::create_drop_item(bool is_box, uint8_t episode,
|
||||
item.data1[2] = 6;
|
||||
}
|
||||
} else {
|
||||
item.data1[2] = (5 * difficulty) + random_int(0, ((area * 3) / 2) - 1); // else between 1 and 7
|
||||
item.data1[2] = (5 * difficulty) + random_int(this->random, 0, ((area * 3) / 2) - 1); // else between 1 and 7
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -419,24 +430,24 @@ ItemData CommonItemCreator::create_drop_item(bool is_box, uint8_t episode,
|
||||
case 0x04: // grinder
|
||||
item.data1[0] = 0x03;
|
||||
item.data1[1] = 0x0A;
|
||||
item.data1[2] = random_int(0, 2); // mono, di, tri
|
||||
item.data1[2] = random_int(this->random, 0, 2); // mono, di, tri
|
||||
break;
|
||||
|
||||
case 0x05: // consumable
|
||||
item.data1[0] = 0x03;
|
||||
item.data1[5] = 0x01;
|
||||
switch (random_int(0, 2)) {
|
||||
switch (random_int(this->random, 0, 2)) {
|
||||
case 0: // antidote / antiparalysis
|
||||
item.data1[1] = 6;
|
||||
item.data1[2] = random_int(0, 1);
|
||||
item.data1[2] = random_int(this->random, 0, 1);
|
||||
break;
|
||||
|
||||
case 1: // telepipe / trap vision
|
||||
item.data1[1] = 7 + random_int(0, 1);
|
||||
item.data1[1] = 7 + random_int(this->random, 0, 1);
|
||||
break;
|
||||
|
||||
case 2: // sol / moon / star atomizer
|
||||
item.data1[1] = 3 + random_int(0, 2);
|
||||
item.data1[1] = 3 + random_int(this->random, 0, 2);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -444,19 +455,19 @@ ItemData CommonItemCreator::create_drop_item(bool is_box, uint8_t episode,
|
||||
case 0x06: // consumable
|
||||
item.data1[0] = 0x03;
|
||||
item.data1[5] = 0x01;
|
||||
item.data1[1] = random_int(0, 1); // mate or fluid
|
||||
item.data1[1] = random_int(this->random, 0, 1); // mate or fluid
|
||||
if (difficulty == 0) {
|
||||
item.data1[2] = random_int(0, 1); // only mono and di on normal
|
||||
item.data1[2] = random_int(this->random, 0, 1); // only mono and di on normal
|
||||
} else if (difficulty == 3) {
|
||||
item.data1[2] = random_int(1, 2); // only di and tri on ultimate
|
||||
item.data1[2] = random_int(this->random, 1, 2); // only di and tri on ultimate
|
||||
} else {
|
||||
item.data1[2] = random_int(0, 2); // else, any of the three
|
||||
item.data1[2] = random_int(this->random, 0, 2); // else, any of the three
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x07: // meseta
|
||||
item.data1[0] = 0x04;
|
||||
item.data2d = (90 * difficulty) + (random_int(1, 20) * (area * 2)); // meseta amount
|
||||
item.data2d = (90 * difficulty) + (random_int(this->random, 1, 20) * (area * 2)); // meseta amount
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
+17
-5
@@ -3,20 +3,32 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <random>
|
||||
|
||||
#include "Lobby.hh"
|
||||
#include "Client.hh"
|
||||
|
||||
|
||||
|
||||
void player_use_item(std::shared_ptr<Client> c, size_t item_index);
|
||||
|
||||
struct CommonItemCreator {
|
||||
struct CommonItemData {
|
||||
std::vector<uint32_t> enemy_item_categories;
|
||||
std::vector<uint32_t> box_item_categories;
|
||||
std::vector<std::vector<uint8_t>> unit_types;
|
||||
|
||||
CommonItemCreator(const std::vector<uint32_t>& enemy_item_categories,
|
||||
const std::vector<uint32_t>& box_item_categories,
|
||||
const std::vector<std::vector<uint8_t>>& unit_types);
|
||||
CommonItemData(
|
||||
std::vector<uint32_t>&& enemy_item_categories,
|
||||
std::vector<uint32_t>&& box_item_categories,
|
||||
std::vector<std::vector<uint8_t>>&& unit_types);
|
||||
};
|
||||
|
||||
struct CommonItemCreator {
|
||||
std::shared_ptr<const CommonItemData> data;
|
||||
std::shared_ptr<std::mt19937> random;
|
||||
|
||||
CommonItemCreator(
|
||||
std::shared_ptr<const CommonItemData> data,
|
||||
std::shared_ptr<std::mt19937> random);
|
||||
|
||||
int32_t decide_item_type(bool is_box) const;
|
||||
ItemData create_drop_item(bool is_box, uint8_t episode, uint8_t difficulty,
|
||||
|
||||
+2
-1
@@ -23,7 +23,8 @@ Lobby::Lobby(uint32_t id)
|
||||
episode(1),
|
||||
difficulty(0),
|
||||
mode(0),
|
||||
rare_seed(random_object<uint32_t>()),
|
||||
random_seed(random_object<uint32_t>()),
|
||||
random(new mt19937(this->random_seed)),
|
||||
event(0),
|
||||
block(0),
|
||||
type(0),
|
||||
|
||||
+6
-3
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <random>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
@@ -15,6 +16,7 @@
|
||||
#include "RareItemSet.hh"
|
||||
#include "Text.hh"
|
||||
#include "Quest.hh"
|
||||
#include "Items.hh"
|
||||
|
||||
struct Lobby {
|
||||
enum Flag {
|
||||
@@ -63,9 +65,10 @@ struct Lobby {
|
||||
uint8_t mode;
|
||||
std::u16string password;
|
||||
std::u16string name;
|
||||
uint32_t rare_seed;
|
||||
|
||||
//EP3_GAME_CONFIG* ep3; // only present if this is an Episode 3 game
|
||||
// This seed is also sent to the client for rare enemy generation
|
||||
uint32_t random_seed;
|
||||
std::shared_ptr<std::mt19937> random;
|
||||
std::shared_ptr<const CommonItemCreator> common_item_creator;
|
||||
|
||||
// lobby stuff
|
||||
uint8_t event;
|
||||
|
||||
+9
-7
@@ -74,14 +74,16 @@ void populate_state_from_config(shared_ptr<ServerState> s,
|
||||
|
||||
s->set_port_configuration(parse_port_configuration(d.at("PortConfiguration")));
|
||||
|
||||
auto enemy_categories = parse_int_vector<uint32_t>(d.at("CommonItemDropRates-Enemy"));
|
||||
auto box_categories = parse_int_vector<uint32_t>(d.at("CommonItemDropRates-Box"));
|
||||
vector<vector<uint8_t>> unit_types;
|
||||
for (const auto& item : d.at("CommonUnitTypes")->as_list()) {
|
||||
unit_types.emplace_back(parse_int_vector<uint8_t>(item));
|
||||
{
|
||||
auto enemy_categories = parse_int_vector<uint32_t>(d.at("CommonItemDropRates-Enemy"));
|
||||
auto box_categories = parse_int_vector<uint32_t>(d.at("CommonItemDropRates-Box"));
|
||||
vector<vector<uint8_t>> unit_types;
|
||||
for (const auto& item : d.at("CommonUnitTypes")->as_list()) {
|
||||
unit_types.emplace_back(parse_int_vector<uint8_t>(item));
|
||||
}
|
||||
s->common_item_data.reset(new CommonItemData(
|
||||
move(enemy_categories), move(box_categories), move(unit_types)));
|
||||
}
|
||||
s->common_item_creator.reset(new CommonItemCreator(enemy_categories,
|
||||
box_categories, unit_types));
|
||||
|
||||
auto local_address_str = d.at("LocalAddress")->as_string();
|
||||
try {
|
||||
|
||||
@@ -841,6 +841,10 @@ static HandlerResult process_server_64(shared_ptr<ServerState>,
|
||||
cmd.event = session.override_lobby_event;
|
||||
modified = true;
|
||||
}
|
||||
if (session.override_random_seed >= 0) {
|
||||
cmd.rare_seed = session.override_random_seed;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
return modified ? HandlerResult::MODIFIED : HandlerResult::FORWARD;
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ public:
|
||||
int16_t override_section_id;
|
||||
int16_t override_lobby_event;
|
||||
int16_t override_lobby_number;
|
||||
int64_t override_random_seed;
|
||||
|
||||
struct LobbyPlayer {
|
||||
uint32_t guild_card_number;
|
||||
|
||||
+2
-2
@@ -14,11 +14,11 @@ RareItemSet::RareItemSet(const char* filename, uint8_t episode,
|
||||
preadx(fd, this, sizeof(*this), offset);
|
||||
}
|
||||
|
||||
bool sample_rare_item(uint8_t pc) {
|
||||
bool sample_rare_item(mt19937& random, uint8_t pc) {
|
||||
int8_t shift = ((pc >> 3) & 0x1F) - 4;
|
||||
if (shift < 0) {
|
||||
shift = 0;
|
||||
}
|
||||
uint32_t rate = ((2 << shift) * ((pc & 7) + 7));
|
||||
return (random_object<uint32_t>() < rate);
|
||||
return (random() < rate);
|
||||
}
|
||||
|
||||
+3
-1
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <random>
|
||||
|
||||
|
||||
|
||||
struct RareItemDrop {
|
||||
@@ -24,4 +26,4 @@ struct RareItemSet {
|
||||
uint8_t secid);
|
||||
} __attribute__((packed));
|
||||
|
||||
bool sample_rare_item(uint8_t pc);
|
||||
bool sample_rare_item(std::mt19937& rand, uint8_t pc);
|
||||
|
||||
@@ -1865,6 +1865,12 @@ shared_ptr<Lobby> create_game_generic(shared_ptr<ServerState> s,
|
||||
if (solo) {
|
||||
game->mode = 3;
|
||||
}
|
||||
if (c->override_random_seed >= 0) {
|
||||
game->random_seed = c->override_random_seed;
|
||||
game->random->seed(game->random_seed);
|
||||
}
|
||||
game->common_item_creator.reset(new CommonItemCreator(
|
||||
s->common_item_data, game->random));
|
||||
game->event = Lobby::game_event_for_lobby_event(current_lobby->event);
|
||||
game->block = 0xFF;
|
||||
game->max_clients = 4;
|
||||
@@ -1927,7 +1933,7 @@ shared_ptr<Lobby> create_game_generic(shared_ptr<ServerState> s,
|
||||
|
||||
if (variation_maxes) {
|
||||
for (size_t x = 0; x < 0x20; x++) {
|
||||
game->variations.data()[x] = random_int(0, variation_maxes[x] - 1);
|
||||
game->variations.data()[x] = (*game->random)() % variation_maxes[x];
|
||||
}
|
||||
} else {
|
||||
for (size_t x = 0; x < 0x20; x++) {
|
||||
|
||||
+21
-12
@@ -544,13 +544,16 @@ static void process_subcommand_use_item(shared_ptr<ServerState>,
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
}
|
||||
|
||||
static void process_subcommand_open_shop_bb_or_unknown_ep3(shared_ptr<ServerState> s,
|
||||
static void process_subcommand_open_shop_bb_or_unknown_ep3(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
if (l->flags & Lobby::Flag::EPISODE_3_ONLY) {
|
||||
check_size_sc(data, 0x08, 0xFFFF);
|
||||
forward_subcommand(l, c, command, flag, data);
|
||||
|
||||
} else if (!l->common_item_creator.get()) {
|
||||
throw runtime_error("received shop subcommand without item creator present");
|
||||
|
||||
} else {
|
||||
const auto* p = check_size_sc(data, 0x08);
|
||||
uint32_t shop_type = p[1].dword;
|
||||
@@ -561,11 +564,11 @@ static void process_subcommand_open_shop_bb_or_unknown_ep3(shared_ptr<ServerStat
|
||||
while (c->game_data.shop_contents.size() < num_items) {
|
||||
ItemData item_data;
|
||||
if (shop_type == 0) { // tool shop
|
||||
item_data = s->common_item_creator->create_shop_item(l->difficulty, 3);
|
||||
item_data = l->common_item_creator->create_shop_item(l->difficulty, 3);
|
||||
} else if (shop_type == 1) { // weapon shop
|
||||
item_data = s->common_item_creator->create_shop_item(l->difficulty, 0);
|
||||
item_data = l->common_item_creator->create_shop_item(l->difficulty, 0);
|
||||
} else if (shop_type == 2) { // guards shop
|
||||
item_data = s->common_item_creator->create_shop_item(l->difficulty, 1);
|
||||
item_data = l->common_item_creator->create_shop_item(l->difficulty, 1);
|
||||
} else { // unknown shop... just leave it blank I guess
|
||||
break;
|
||||
}
|
||||
@@ -668,7 +671,7 @@ static void process_subcommand_sort_inventory_bb(shared_ptr<ServerState>,
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EXP/Drop Item commands
|
||||
|
||||
static void process_subcommand_enemy_drop_item_request(shared_ptr<ServerState> s,
|
||||
static void process_subcommand_enemy_drop_item_request(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
if (l->version == GameVersion::BB) {
|
||||
@@ -677,10 +680,12 @@ static void process_subcommand_enemy_drop_item_request(shared_ptr<ServerState> s
|
||||
if (!l->is_game()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
|
||||
throw logic_error("item tracking not enabled in BB game");
|
||||
}
|
||||
if (!l->common_item_creator.get()) {
|
||||
throw runtime_error("received box drop subcommand without item creator present");
|
||||
}
|
||||
|
||||
PlayerInventoryItem item;
|
||||
|
||||
@@ -692,7 +697,8 @@ static void process_subcommand_enemy_drop_item_request(shared_ptr<ServerState> s
|
||||
} else {
|
||||
if (l->rare_item_set) {
|
||||
if (cmd->enemy_id <= 0x65) {
|
||||
is_rare = sample_rare_item(l->rare_item_set->rares[cmd->enemy_id].probability);
|
||||
is_rare = sample_rare_item(*
|
||||
l->random, l->rare_item_set->rares[cmd->enemy_id].probability);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,7 +713,7 @@ static void process_subcommand_enemy_drop_item_request(shared_ptr<ServerState> s
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
item.data = s->common_item_creator->create_drop_item(false, l->episode,
|
||||
item.data = l->common_item_creator->create_drop_item(false, l->episode,
|
||||
l->difficulty, cmd->area, l->section_id);
|
||||
} catch (const out_of_range&) {
|
||||
// create_common_item throws this when it doesn't want to make an item
|
||||
@@ -726,7 +732,7 @@ static void process_subcommand_enemy_drop_item_request(shared_ptr<ServerState> s
|
||||
}
|
||||
}
|
||||
|
||||
static void process_subcommand_box_drop_item_request(shared_ptr<ServerState> s,
|
||||
static void process_subcommand_box_drop_item_request(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const string& data) {
|
||||
if (l->version == GameVersion::BB) {
|
||||
@@ -735,10 +741,12 @@ static void process_subcommand_box_drop_item_request(shared_ptr<ServerState> s,
|
||||
if (!l->is_game()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
|
||||
throw logic_error("item tracking not enabled in BB game");
|
||||
}
|
||||
if (!l->common_item_creator.get()) {
|
||||
throw runtime_error("received box drop subcommand without item creator present");
|
||||
}
|
||||
|
||||
PlayerInventoryItem item;
|
||||
|
||||
@@ -753,7 +761,8 @@ static void process_subcommand_box_drop_item_request(shared_ptr<ServerState> s,
|
||||
if (l->rare_item_set->box_areas[index] != cmd->area) {
|
||||
continue;
|
||||
}
|
||||
if (sample_rare_item(l->rare_item_set->box_rares[index].probability)) {
|
||||
if (sample_rare_item(
|
||||
*l->random, l->rare_item_set->box_rares[index].probability)) {
|
||||
is_rare = true;
|
||||
break;
|
||||
}
|
||||
@@ -771,7 +780,7 @@ static void process_subcommand_box_drop_item_request(shared_ptr<ServerState> s,
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
item.data = s->common_item_creator->create_drop_item(true, l->episode,
|
||||
item.data = l->common_item_creator->create_drop_item(true, l->episode,
|
||||
l->difficulty, cmd->area, l->section_id);
|
||||
} catch (const out_of_range&) {
|
||||
// create_common_item throws this when it doesn't want to make an item
|
||||
|
||||
+1
-1
@@ -919,7 +919,7 @@ void send_join_game_t(shared_ptr<Client> c, shared_ptr<Lobby> l) {
|
||||
cmd.event = l->event;
|
||||
cmd.section_id = l->section_id;
|
||||
cmd.challenge_mode = (l->mode == 2) ? 1 : 0;
|
||||
cmd.rare_seed = l->rare_seed;
|
||||
cmd.rare_seed = l->random_seed;
|
||||
cmd.episode = l->episode;
|
||||
cmd.unused2 = 0x01;
|
||||
cmd.solo_mode = (l->mode == 3);
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ struct ServerState {
|
||||
std::shared_ptr<const QuestIndex> quest_index;
|
||||
std::shared_ptr<const LevelTable> level_table;
|
||||
std::shared_ptr<const BattleParamTable> battle_params;
|
||||
std::shared_ptr<const CommonItemCreator> common_item_creator;
|
||||
std::shared_ptr<const CommonItemData> common_item_data;
|
||||
|
||||
std::shared_ptr<LicenseManager> license_manager;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user