fix game flag translation across v2/v3 boundary
This commit is contained in:
@@ -4982,9 +4982,7 @@ struct G_6x70_Base_DCNTE {
|
|||||||
/* 0002 */ le_uint16_t room_id = 0;
|
/* 0002 */ le_uint16_t room_id = 0;
|
||||||
/* 0004 */ le_uint32_t flags1 = 0;
|
/* 0004 */ le_uint32_t flags1 = 0;
|
||||||
/* 0008 */ VectorXYZF pos;
|
/* 0008 */ VectorXYZF pos;
|
||||||
/* 0014 */ le_uint32_t angle_x = 0;
|
/* 0014 */ VectorXYZI angle;
|
||||||
/* 0018 */ le_uint32_t angle_y = 0;
|
|
||||||
/* 001C */ le_uint32_t angle_z = 0;
|
|
||||||
/* 0020 */ le_uint16_t unknown_a3a = 0;
|
/* 0020 */ le_uint16_t unknown_a3a = 0;
|
||||||
/* 0022 */ le_uint16_t current_hp = 0;
|
/* 0022 */ le_uint16_t current_hp = 0;
|
||||||
} __packed_ws__(G_6x70_Base_DCNTE, 0x24);
|
} __packed_ws__(G_6x70_Base_DCNTE, 0x24);
|
||||||
|
|||||||
@@ -28,6 +28,23 @@ static void set_log_level_from_json(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_all_log_levels(phosg::LogLevel level) {
|
||||||
|
channel_exceptions_log.min_level = level;
|
||||||
|
client_log.min_level = level;
|
||||||
|
command_data_log.min_level = level;
|
||||||
|
config_log.min_level = level;
|
||||||
|
dns_server_log.min_level = level;
|
||||||
|
function_compiler_log.min_level = level;
|
||||||
|
ip_stack_simulator_log.min_level = level;
|
||||||
|
lobby_log.min_level = level;
|
||||||
|
patch_index_log.min_level = level;
|
||||||
|
player_data_log.min_level = level;
|
||||||
|
proxy_server_log.min_level = level;
|
||||||
|
replay_log.min_level = level;
|
||||||
|
server_log.min_level = level;
|
||||||
|
static_game_data_log.min_level = level;
|
||||||
|
}
|
||||||
|
|
||||||
void set_log_levels_from_json(const phosg::JSON& json) {
|
void set_log_levels_from_json(const phosg::JSON& json) {
|
||||||
set_log_level_from_json(channel_exceptions_log, json, "ChannelExceptions");
|
set_log_level_from_json(channel_exceptions_log, json, "ChannelExceptions");
|
||||||
set_log_level_from_json(client_log, json, "Clients");
|
set_log_level_from_json(client_log, json, "Clients");
|
||||||
|
|||||||
@@ -18,4 +18,5 @@ extern phosg::PrefixedLogger replay_log;
|
|||||||
extern phosg::PrefixedLogger server_log;
|
extern phosg::PrefixedLogger server_log;
|
||||||
extern phosg::PrefixedLogger static_game_data_log;
|
extern phosg::PrefixedLogger static_game_data_log;
|
||||||
|
|
||||||
|
void set_all_log_levels(phosg::LogLevel level);
|
||||||
void set_log_levels_from_json(const phosg::JSON& json);
|
void set_log_levels_from_json(const phosg::JSON& json);
|
||||||
|
|||||||
@@ -3195,6 +3195,9 @@ Action a_run_server_replay_log(
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto state = make_shared<ServerState>(get_config_filename(args));
|
auto state = make_shared<ServerState>(get_config_filename(args));
|
||||||
|
if (args.get<bool>("debug")) {
|
||||||
|
state->is_debug = true;
|
||||||
|
}
|
||||||
state->load_all(true);
|
state->load_all(true);
|
||||||
|
|
||||||
if (state->dns_server_port) {
|
if (state->dns_server_port) {
|
||||||
|
|||||||
+7
-62
@@ -5848,55 +5848,12 @@ uint32_t MapState::RareEnemyRates::for_enemy_type(EnemyType type) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const shared_ptr<const MapState::RareEnemyRates> MapState::NO_RARE_ENEMIES = make_shared<MapState::RareEnemyRates>(
|
const shared_ptr<const MapState::RareEnemyRates> MapState::NO_RARE_ENEMIES = make_shared<MapState::RareEnemyRates>(0, 0, 0);
|
||||||
0, 0, 0);
|
|
||||||
const shared_ptr<const MapState::RareEnemyRates> MapState::DEFAULT_RARE_ENEMIES = make_shared<MapState::RareEnemyRates>(
|
const shared_ptr<const MapState::RareEnemyRates> MapState::DEFAULT_RARE_ENEMIES = make_shared<MapState::RareEnemyRates>(
|
||||||
MapState::RareEnemyRates::DEFAULT_RARE_ENEMY_RATE_V3,
|
MapState::RareEnemyRates::DEFAULT_RARE_ENEMY_RATE_V3,
|
||||||
MapState::RareEnemyRates::DEFAULT_MERICARAND_RATE_V3,
|
MapState::RareEnemyRates::DEFAULT_MERICARAND_RATE_V3,
|
||||||
MapState::RareEnemyRates::DEFAULT_RARE_BOSS_RATE_V4);
|
MapState::RareEnemyRates::DEFAULT_RARE_BOSS_RATE_V4);
|
||||||
|
|
||||||
uint32_t MapState::EnemyState::convert_game_flags(uint32_t game_flags, bool to_v3) {
|
|
||||||
// The format of game_flags was changed significantly between v2 and v3, and
|
|
||||||
// not accounting for this results in odd effects like other characters not
|
|
||||||
// appearing when joining a game. Unfortunately, some bits were deleted on v3
|
|
||||||
// and other bits were added, so it doesn't suffice to simply store the most
|
|
||||||
// complete format of this field - we have to be able to convert between the
|
|
||||||
// two.
|
|
||||||
|
|
||||||
// Bits on v2: ?IHCBAzy xwvutsrq ponmlkji hgfedcba
|
|
||||||
// Bits on v3: ?IHGFEDC BAzyxwvu srqponkj hgfedcba
|
|
||||||
// The bits ilmt were removed in v3 and the bits to their left were shifted
|
|
||||||
// right. The bits DEFG were added in v3 and do not exist on v2.
|
|
||||||
// Known meanings for these bits:
|
|
||||||
// o = is dead
|
|
||||||
// n = should play hit animation
|
|
||||||
// y = is near enemy
|
|
||||||
// H = is enemy?
|
|
||||||
// I = is object? (some entities have both H and I set though)
|
|
||||||
|
|
||||||
// TODO: The above might all be wrong.
|
|
||||||
// GC 00100000 10010000 00001110 00000000
|
|
||||||
// PC 00101001 00000000 01100100 00000000
|
|
||||||
|
|
||||||
// PC 00101001 10110000 00101110 00000000
|
|
||||||
// GC 00100000 10011011 00000111 00000000
|
|
||||||
|
|
||||||
// PC 00101001 10010000 00101110 00000000
|
|
||||||
// GC 00100000 10011001 00000111 00000000
|
|
||||||
|
|
||||||
if (to_v3) {
|
|
||||||
return (game_flags & 0xE00000FF) |
|
|
||||||
((game_flags & 0x00000600) >> 1) |
|
|
||||||
((game_flags & 0x0007E000) >> 3) |
|
|
||||||
((game_flags & 0x1FF00000) >> 4);
|
|
||||||
} else {
|
|
||||||
return (game_flags & 0xE00000FF) |
|
|
||||||
((game_flags << 1) & 0x00000600) |
|
|
||||||
((game_flags << 3) & 0x0007E000) |
|
|
||||||
((game_flags << 4) & 0x1FF00000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MapState::EntityIterator::EntityIterator(MapState* map_state, Version version, bool at_end)
|
MapState::EntityIterator::EntityIterator(MapState* map_state, Version version, bool at_end)
|
||||||
: map_state(map_state),
|
: map_state(map_state),
|
||||||
version(version),
|
version(version),
|
||||||
@@ -6413,7 +6370,6 @@ void MapState::import_object_states_from_sync(
|
|||||||
void MapState::import_enemy_states_from_sync(Version from_version, const SyncEnemyStateEntry* entries, size_t entry_count) {
|
void MapState::import_enemy_states_from_sync(Version from_version, const SyncEnemyStateEntry* entries, size_t entry_count) {
|
||||||
this->log.info_f("Importing enemy state from sync command");
|
this->log.info_f("Importing enemy state from sync command");
|
||||||
size_t enemy_index = 0;
|
size_t enemy_index = 0;
|
||||||
bool is_v3 = !is_v1_or_v2(from_version);
|
|
||||||
for (const auto& fc : this->floor_config_entries) {
|
for (const auto& fc : this->floor_config_entries) {
|
||||||
if (!fc.super_map) {
|
if (!fc.super_map) {
|
||||||
continue;
|
continue;
|
||||||
@@ -6434,15 +6390,10 @@ void MapState::import_enemy_states_from_sync(Version from_version, const SyncEne
|
|||||||
if (ene_st->super_ene != ene) {
|
if (ene_st->super_ene != ene) {
|
||||||
throw logic_error("super enemy link is incorrect");
|
throw logic_error("super enemy link is incorrect");
|
||||||
}
|
}
|
||||||
if (ene_st->get_game_flags(is_v3) != entry.flags) {
|
if (ene_st->game_flags != entry.flags) {
|
||||||
this->log.warning_f("({:04X} => E-{:03X}) Flags from client ({:08X}({})) do not match game flags from map ({:08X}({}))",
|
this->log.warning_f("({:04X} => E-{:03X}) Flags from client ({:08X}) do not match game flags from map ({:08X})",
|
||||||
enemy_index,
|
enemy_index, ene_st->e_id, entry.flags, ene_st->game_flags);
|
||||||
ene_st->e_id,
|
ene_st->game_flags = entry.flags;
|
||||||
entry.flags,
|
|
||||||
is_v3 ? "v3" : "v2",
|
|
||||||
ene_st->game_flags,
|
|
||||||
(ene_st->server_flags & MapState::EnemyState::Flag::GAME_FLAGS_IS_V3) ? "v3" : "v2");
|
|
||||||
ene_st->set_game_flags(entry.flags, !is_v1_or_v2(from_version));
|
|
||||||
}
|
}
|
||||||
if (ene_st->total_damage != entry.total_damage) {
|
if (ene_st->total_damage != entry.total_damage) {
|
||||||
this->log.warning_f("({:04X} => E-{:03X}) Total damage from client ({}) does not match total damage from map ({})",
|
this->log.warning_f("({:04X} => E-{:03X}) Total damage from client ({}) does not match total damage from map ({})",
|
||||||
@@ -6771,14 +6722,8 @@ void MapState::print(FILE* stream) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
string ene_str = ene_st->super_ene->str();
|
string ene_str = ene_st->super_ene->str();
|
||||||
phosg::fwrite_fmt(stream, " {} total_damage={:04X} rare_flags={:04X} game_flags={:08X}({}) set_flags={:04X} server_flags={:04X}\n",
|
phosg::fwrite_fmt(stream, " {} total_damage={:04X} rare_flags={:04X} game_flags={:08X} set_flags={:04X} server_flags={:04X}\n",
|
||||||
ene_str,
|
ene_str, ene_st->total_damage, ene_st->rare_flags, ene_st->game_flags, ene_st->set_flags, ene_st->server_flags);
|
||||||
ene_st->total_damage,
|
|
||||||
ene_st->rare_flags,
|
|
||||||
ene_st->game_flags,
|
|
||||||
(ene_st->server_flags & MapState::EnemyState::Flag::GAME_FLAGS_IS_V3) ? "v3" : "v2",
|
|
||||||
ene_st->set_flags,
|
|
||||||
ene_st->server_flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->bb_rare_enemy_indexes.empty()) {
|
if (this->bb_rare_enemy_indexes.empty()) {
|
||||||
|
|||||||
-20
@@ -716,7 +716,6 @@ public:
|
|||||||
ITEM_DROPPED = 0x0008,
|
ITEM_DROPPED = 0x0008,
|
||||||
ALL_HITS_MASK_FIRST = 0x0010,
|
ALL_HITS_MASK_FIRST = 0x0010,
|
||||||
ALL_HITS_MASK = 0x00F0,
|
ALL_HITS_MASK = 0x00F0,
|
||||||
GAME_FLAGS_IS_V3 = 0x0100,
|
|
||||||
};
|
};
|
||||||
size_t e_id = 0;
|
size_t e_id = 0;
|
||||||
size_t set_id = 0;
|
size_t set_id = 0;
|
||||||
@@ -727,8 +726,6 @@ public:
|
|||||||
uint16_t set_flags = 0; // Only used if super_ene->child_index == 0
|
uint16_t set_flags = 0; // Only used if super_ene->child_index == 0
|
||||||
uint16_t server_flags = 0;
|
uint16_t server_flags = 0;
|
||||||
|
|
||||||
static uint32_t convert_game_flags(uint32_t game_flags, bool to_v3);
|
|
||||||
|
|
||||||
inline void reset() {
|
inline void reset() {
|
||||||
this->total_damage = 0;
|
this->total_damage = 0;
|
||||||
this->rare_flags = 0;
|
this->rare_flags = 0;
|
||||||
@@ -737,23 +734,6 @@ public:
|
|||||||
this->server_flags = 0;
|
this->server_flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set_game_flags(uint32_t game_flags, bool is_v3) {
|
|
||||||
this->game_flags = game_flags;
|
|
||||||
if (is_v3) {
|
|
||||||
this->server_flags |= Flag::GAME_FLAGS_IS_V3;
|
|
||||||
} else {
|
|
||||||
this->server_flags &= ~Flag::GAME_FLAGS_IS_V3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inline uint32_t get_game_flags(bool is_v3) const {
|
|
||||||
bool flags_is_v3 = (this->server_flags & Flag::GAME_FLAGS_IS_V3);
|
|
||||||
if (flags_is_v3 == is_v3) {
|
|
||||||
return this->game_flags;
|
|
||||||
} else {
|
|
||||||
return this->convert_game_flags(this->game_flags, is_v3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool is_rare(Version version) const {
|
inline bool is_rare(Version version) const {
|
||||||
return (((this->rare_flags >> static_cast<size_t>(version)) & 1) ||
|
return (((this->rare_flags >> static_cast<size_t>(version)) & 1) ||
|
||||||
((version == Version::BB_V4) ? this->super_ene->is_default_rare_bb : this->super_ene->is_default_rare_v123));
|
((version == Version::BB_V4) ? this->super_ene->is_default_rare_bb : this->super_ene->is_default_rare_v123));
|
||||||
|
|||||||
+41
-21
@@ -1154,10 +1154,42 @@ G_6x70_Base_V1 Parsed6x70Data::base_v1(bool is_v3) const {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t Parsed6x70Data::convert_game_flags(uint32_t game_flags, bool to_v3) {
|
||||||
|
// The format of game_flags for players was changed significantly between v2
|
||||||
|
// and v3, and not accounting for this results in odd effects like other
|
||||||
|
// characters not appearing when joining a game. Unfortunately, some bits
|
||||||
|
// were deleted on v3 and other bits were added, so it doesn't suffice to
|
||||||
|
// simply store the most complete format of this field - we have to be able
|
||||||
|
// to convert between the two.
|
||||||
|
|
||||||
|
// Bits on v2: ?IHCBAzy xwvutsrq ponmlkji hgfedcba
|
||||||
|
// Bits on v3: ?IHGFEDC BAzyxwvu srqponkj hgfedcba
|
||||||
|
// The bits ilmt were removed in v3 and the bits to their left were shifted
|
||||||
|
// right. The bits DEFG were added in v3 and do not exist on v2.
|
||||||
|
// Known meanings for these bits:
|
||||||
|
// o = is dead
|
||||||
|
// n = should play hit animation
|
||||||
|
// y = is near enemy
|
||||||
|
// H = is enemy?
|
||||||
|
// I = is object? (some entities have both H and I set though)
|
||||||
|
|
||||||
|
if (to_v3) {
|
||||||
|
return (game_flags & 0xE00000FF) |
|
||||||
|
((game_flags & 0x00000600) >> 1) |
|
||||||
|
((game_flags & 0x0007E000) >> 3) |
|
||||||
|
((game_flags & 0x1FF00000) >> 4);
|
||||||
|
} else {
|
||||||
|
return (game_flags & 0xE00000FF) |
|
||||||
|
((game_flags << 1) & 0x00000600) |
|
||||||
|
((game_flags << 3) & 0x0007E000) |
|
||||||
|
((game_flags << 4) & 0x1FF00000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t Parsed6x70Data::get_game_flags(bool is_v3) const {
|
uint32_t Parsed6x70Data::get_game_flags(bool is_v3) const {
|
||||||
return (this->game_flags_is_v3 == is_v3)
|
return (this->game_flags_is_v3 == is_v3)
|
||||||
? this->game_flags
|
? this->game_flags
|
||||||
: MapState::EnemyState::convert_game_flags(this->game_flags, is_v3);
|
: Parsed6x70Data::convert_game_flags(this->game_flags, is_v3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static asio::awaitable<void> on_sync_joining_player_disp_and_inventory(
|
static asio::awaitable<void> on_sync_joining_player_disp_and_inventory(
|
||||||
@@ -3423,36 +3455,29 @@ static asio::awaitable<void> on_update_enemy_state(shared_ptr<Client> c, Subcomm
|
|||||||
if ((cmd.enemy_index & 0xF000) || (cmd.header.entity_id != (cmd.enemy_index | 0x1000))) {
|
if ((cmd.enemy_index & 0xF000) || (cmd.header.entity_id != (cmd.enemy_index | 0x1000))) {
|
||||||
throw runtime_error("mismatched enemy id/index");
|
throw runtime_error("mismatched enemy id/index");
|
||||||
}
|
}
|
||||||
bool is_v3 = !is_v1_or_v2(c->version());
|
|
||||||
auto ene_st = l->map_state->enemy_state_for_index(c->version(), c->floor, cmd.enemy_index);
|
auto ene_st = l->map_state->enemy_state_for_index(c->version(), c->floor, cmd.enemy_index);
|
||||||
uint32_t src_flags = is_big_endian(c->version()) ? bswap32(cmd.game_flags) : cmd.game_flags.load();
|
uint32_t src_flags = is_big_endian(c->version()) ? bswap32(cmd.game_flags) : cmd.game_flags.load();
|
||||||
if (l->difficulty == 3) {
|
if (l->difficulty == 3) {
|
||||||
src_flags = (src_flags & 0xFFFFFFC0) | (ene_st->get_game_flags(is_v3) & 0x0000003F);
|
src_flags = (src_flags & 0xFFFFFFC0) | (ene_st->game_flags & 0x0000003F);
|
||||||
}
|
}
|
||||||
ene_st->set_game_flags(src_flags, is_v3);
|
ene_st->game_flags = src_flags;
|
||||||
ene_st->total_damage = cmd.total_damage;
|
ene_st->total_damage = cmd.total_damage;
|
||||||
ene_st->set_last_hit_by_client_id(c->lobby_client_id);
|
ene_st->set_last_hit_by_client_id(c->lobby_client_id);
|
||||||
l->log.info_f("E-{:03X} updated to damage={} game_flags={:08X} ({})",
|
l->log.info_f("E-{:03X} updated to damage={} game_flags={:08X}", ene_st->e_id, ene_st->total_damage, ene_st->game_flags);
|
||||||
ene_st->e_id,
|
|
||||||
ene_st->total_damage,
|
|
||||||
ene_st->game_flags,
|
|
||||||
(ene_st->server_flags & MapState::EnemyState::Flag::GAME_FLAGS_IS_V3) ? "v3" : "v2");
|
|
||||||
|
|
||||||
for (auto lc : l->clients) {
|
for (auto lc : l->clients) {
|
||||||
if (lc && (lc != c)) {
|
if (lc && (lc != c)) {
|
||||||
cmd.enemy_index = l->map_state->index_for_enemy_state(lc->version(), ene_st);
|
cmd.enemy_index = l->map_state->index_for_enemy_state(lc->version(), ene_st);
|
||||||
if (cmd.enemy_index != 0xFFFF) {
|
if (cmd.enemy_index != 0xFFFF) {
|
||||||
cmd.header.entity_id = 0x1000 | cmd.enemy_index;
|
cmd.header.entity_id = 0x1000 | cmd.enemy_index;
|
||||||
uint32_t game_flags = ene_st->get_game_flags(!is_v1_or_v2(lc->version()));
|
cmd.game_flags = is_big_endian(lc->version()) ? phosg::bswap32(ene_st->game_flags) : ene_st->game_flags;
|
||||||
cmd.game_flags = is_big_endian(lc->version()) ? phosg::bswap32(game_flags) : game_flags;
|
|
||||||
send_command_t(lc, 0x60, 0x00, cmd);
|
send_command_t(lc, 0x60, 0x00, cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static asio::awaitable<void> on_set_enemy_low_game_flags_ultimate(
|
static asio::awaitable<void> on_set_enemy_low_game_flags_ultimate(shared_ptr<Client> c, SubcommandMessage& msg) {
|
||||||
shared_ptr<Client> c, SubcommandMessage& msg) {
|
|
||||||
auto& cmd = msg.check_size_t<G_SetEnemyLowGameFlagsUltimate_6x9C>();
|
auto& cmd = msg.check_size_t<G_SetEnemyLowGameFlagsUltimate_6x9C>();
|
||||||
|
|
||||||
if (command_is_private(msg.command) ||
|
if (command_is_private(msg.command) ||
|
||||||
@@ -3467,15 +3492,10 @@ static asio::awaitable<void> on_set_enemy_low_game_flags_ultimate(
|
|||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_v3 = !is_v1_or_v2(c->version());
|
|
||||||
auto ene_st = l->map_state->enemy_state_for_index(c->version(), c->floor, cmd.header.entity_id - 0x1000);
|
auto ene_st = l->map_state->enemy_state_for_index(c->version(), c->floor, cmd.header.entity_id - 0x1000);
|
||||||
uint32_t game_flags = ene_st->get_game_flags(is_v3);
|
if (!(ene_st->game_flags & cmd.low_game_flags)) {
|
||||||
if (!(game_flags & cmd.low_game_flags)) {
|
ene_st->game_flags |= cmd.low_game_flags;
|
||||||
ene_st->set_game_flags(game_flags | cmd.low_game_flags, is_v3);
|
l->log.info_f("E-{:03X} updated to game_flags={:08X}", ene_st->e_id, ene_st->game_flags);
|
||||||
l->log.info_f("E-{:03X} updated to game_flags={:08X} ({})",
|
|
||||||
ene_st->e_id,
|
|
||||||
ene_st->game_flags,
|
|
||||||
(ene_st->server_flags & MapState::EnemyState::Flag::GAME_FLAGS_IS_V3) ? "v3" : "v2");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
co_await forward_subcommand_with_entity_id_transcode_t<G_SetEnemyLowGameFlagsUltimate_6x9C>(c, msg);
|
co_await forward_subcommand_with_entity_id_transcode_t<G_SetEnemyLowGameFlagsUltimate_6x9C>(c, msg);
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ protected:
|
|||||||
Version from_version,
|
Version from_version,
|
||||||
bool from_client_customization);
|
bool from_client_customization);
|
||||||
G_6x70_Base_V1 base_v1(bool is_v3) const;
|
G_6x70_Base_V1 base_v1(bool is_v3) const;
|
||||||
|
static uint32_t convert_game_flags(uint32_t game_flags, bool to_v3);
|
||||||
uint32_t get_game_flags(bool is_v3) const;
|
uint32_t get_game_flags(bool is_v3) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -2786,10 +2786,9 @@ void send_game_enemy_state(shared_ptr<Client> c) {
|
|||||||
auto s = c->require_server_state();
|
auto s = c->require_server_state();
|
||||||
|
|
||||||
vector<SyncEnemyStateEntry> entries;
|
vector<SyncEnemyStateEntry> entries;
|
||||||
bool is_v3 = !is_v1_or_v2(c->version());
|
|
||||||
for (auto ene_st : l->map_state->iter_enemy_states(c->version())) {
|
for (auto ene_st : l->map_state->iter_enemy_states(c->version())) {
|
||||||
auto& entry = entries.emplace_back();
|
auto& entry = entries.emplace_back();
|
||||||
entry.flags = ene_st->get_game_flags(is_v3);
|
entry.flags = ene_st->game_flags;
|
||||||
entry.item_drop_id = (ene_st->server_flags & MapState::EnemyState::Flag::ITEM_DROPPED)
|
entry.item_drop_id = (ene_st->server_flags & MapState::EnemyState::Flag::ITEM_DROPPED)
|
||||||
? 0xFFFF
|
? 0xFFFF
|
||||||
: (0xCA0 + l->map_state->index_for_enemy_state(c->version(), ene_st));
|
: (0xCA0 + l->map_state->index_for_enemy_state(c->version(), ene_st));
|
||||||
|
|||||||
+5
-1
@@ -1059,7 +1059,11 @@ void ServerState::load_config_early() {
|
|||||||
this->exp_share_multiplier = this->config_json->get_float("BBEXPShareMultiplier", 0.5);
|
this->exp_share_multiplier = this->config_json->get_float("BBEXPShareMultiplier", 0.5);
|
||||||
this->server_global_drop_rate_multiplier = this->config_json->get_float("ServerGlobalDropRateMultiplier", 1);
|
this->server_global_drop_rate_multiplier = this->config_json->get_float("ServerGlobalDropRateMultiplier", 1);
|
||||||
|
|
||||||
set_log_levels_from_json(this->config_json->get("LogLevels", phosg::JSON::dict()));
|
if (this->is_debug) {
|
||||||
|
set_all_log_levels(phosg::LogLevel::L_DEBUG);
|
||||||
|
} else {
|
||||||
|
set_log_levels_from_json(this->config_json->get("LogLevels", phosg::JSON::dict()));
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this->run_shell_behavior = this->config_json->at("RunInteractiveShell").as_bool()
|
this->run_shell_behavior = this->config_json->at("RunInteractiveShell").as_bool()
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
|
|||||||
uint64_t client_ping_interval_usecs = 30000000;
|
uint64_t client_ping_interval_usecs = 30000000;
|
||||||
uint64_t client_idle_timeout_usecs = 60000000;
|
uint64_t client_idle_timeout_usecs = 60000000;
|
||||||
uint64_t patch_client_idle_timeout_usecs = 300000000;
|
uint64_t patch_client_idle_timeout_usecs = 300000000;
|
||||||
|
bool is_debug = false;
|
||||||
bool ip_stack_debug = false;
|
bool ip_stack_debug = false;
|
||||||
bool allow_unregistered_users = false;
|
bool allow_unregistered_users = false;
|
||||||
bool allow_pc_nte = false;
|
bool allow_pc_nte = false;
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ fix_scroll_patch1_end:
|
|||||||
apply_fix_scroll_patch2:
|
apply_fix_scroll_patch2:
|
||||||
# This patch changes the TAdSinglePlyChrSelectGC::selected_index_within_view
|
# This patch changes the TAdSinglePlyChrSelectGC::selected_index_within_view
|
||||||
# to be the selected character's absolute index (including scroll_offset),
|
# to be the selected character's absolute index (including scroll_offset),
|
||||||
# not the index only within to the displayed four characters
|
# not the index only within the displayed four characters
|
||||||
push 6 # Call size
|
push 6 # Call size
|
||||||
push 0x00413CD8 # Call address
|
push 0x00413CD8 # Call address
|
||||||
call get_code_size_for_fix_scroll_patch2
|
call get_code_size_for_fix_scroll_patch2
|
||||||
@@ -166,7 +166,7 @@ selection_index_fix2_end:
|
|||||||
|
|
||||||
apply_preview_window_fix:
|
apply_preview_window_fix:
|
||||||
# This patch fixes the preview display so it will show the correct section
|
# This patch fixes the preview display so it will show the correct section
|
||||||
# ID, etc.
|
# ID, level, etc.
|
||||||
push 5 # Call size
|
push 5 # Call size
|
||||||
push 0x0040216C # Call address
|
push 0x0040216C # Call address
|
||||||
call get_code_size_for_preview_window_fix
|
call get_code_size_for_preview_window_fix
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ start:
|
|||||||
|
|
||||||
.data 0x80134FE0
|
.data 0x80134FE0
|
||||||
.data 0x00000004
|
.data 0x00000004
|
||||||
.data 0x38600000
|
li r3, 0
|
||||||
|
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ start:
|
|||||||
|
|
||||||
.data 0x80134FE0
|
.data 0x80134FE0
|
||||||
.data 0x00000004
|
.data 0x00000004
|
||||||
.data 0x38600000
|
li r3, 0
|
||||||
|
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ start:
|
|||||||
|
|
||||||
.data 0x80135050
|
.data 0x80135050
|
||||||
.data 0x00000004
|
.data 0x00000004
|
||||||
.data 0x38600000
|
li r3, 0
|
||||||
|
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ start:
|
|||||||
|
|
||||||
.data 0x80134D3C
|
.data 0x80134D3C
|
||||||
.data 0x00000004
|
.data 0x00000004
|
||||||
.data 0x38600000
|
li r3, 0
|
||||||
|
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ start:
|
|||||||
|
|
||||||
.data 0x80134FA0
|
.data 0x80134FA0
|
||||||
.data 0x00000004
|
.data 0x00000004
|
||||||
.data 0x38600000
|
li r3, 0
|
||||||
|
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ start:
|
|||||||
|
|
||||||
.data 0x80135108
|
.data 0x80135108
|
||||||
.data 0x00000004
|
.data 0x00000004
|
||||||
.data 0x38600000
|
li r3, 0
|
||||||
|
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ start:
|
|||||||
|
|
||||||
.data 0x80135040
|
.data 0x80135040
|
||||||
.data 0x00000004
|
.data 0x00000004
|
||||||
.data 0x38600000
|
li r3, 0
|
||||||
|
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ start:
|
|||||||
|
|
||||||
.data 0x801352D0
|
.data 0x801352D0
|
||||||
.data 0x00000004
|
.data 0x00000004
|
||||||
.data 0x38600000
|
li r3, 0
|
||||||
|
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ start:
|
|||||||
|
|
||||||
.data 0x80092380
|
.data 0x80092380
|
||||||
.data 0x00000004
|
.data 0x00000004
|
||||||
.data 0x38600000
|
li r3, 0
|
||||||
|
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ start:
|
|||||||
|
|
||||||
.data 0x8009242C
|
.data 0x8009242C
|
||||||
.data 0x00000004
|
.data 0x00000004
|
||||||
.data 0x38600000
|
li r3, 0
|
||||||
|
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ start:
|
|||||||
|
|
||||||
.data 0x80092C78
|
.data 0x80092C78
|
||||||
.data 0x00000004
|
.data 0x00000004
|
||||||
.data 0x38600000
|
li r3, 0
|
||||||
|
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ start:
|
|||||||
|
|
||||||
.data 0x80092588
|
.data 0x80092588
|
||||||
.data 0x00000004
|
.data 0x00000004
|
||||||
.data 0x38600000
|
li r3, 0
|
||||||
|
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
.data 0x00000000
|
.data 0x00000000
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
# This patch enables the debug menus in PSO Episode 3 USA. Specifically, it
|
# This patch enables the debug menus in PSO Episode 3 USA. Specifically, it
|
||||||
# causes them all to load, but only activates one (selected by uncommenting a
|
# causes them all to load, but only activates one (selected by uncommenting a
|
||||||
# line below). See the comments for more information. Most of these editors are
|
# line below). See the comments for more information. Most of these editors are
|
||||||
# present in PSO PC and PSOX as well, but not in GC Episodes 1 & 2. There are
|
# present in PSO PC and PSO Xbox as well, but not in GC Episodes 1 & 2. There
|
||||||
# notes in the below comments that may help get these editors working on PSO PC.
|
# are notes in the below comments that may help get these editors working on
|
||||||
|
# PSO PC.
|
||||||
|
|
||||||
# This patch must not be run from the Patches menu - it should only be run with
|
# This patch must not be run from the Patches menu - it should only be run with
|
||||||
# the $patch command, since the client will likely crash if the player is not
|
# the $patch command, since the client will likely crash if the player is not
|
||||||
|
|||||||
Reference in New Issue
Block a user