don't use client's floor for 6x0A and 6x0B
This commit is contained in:
+42
@@ -6307,6 +6307,32 @@ uint16_t MapState::index_for_event_state(Version version, shared_ptr<const Event
|
|||||||
: (relative_index + this->floor_config(ev_st->super_ev->floor).base_indexes_for_version(version).base_event_index);
|
: (relative_index + this->floor_config(ev_st->super_ev->floor).base_indexes_for_version(version).base_event_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shared_ptr<MapState::ObjectState> MapState::object_state_for_index(Version version, uint16_t object_index) {
|
||||||
|
size_t dynamic_obj_base_index = this->dynamic_obj_base_index_for_version.at(static_cast<size_t>(version));
|
||||||
|
if (object_index < dynamic_obj_base_index) {
|
||||||
|
int8_t floor;
|
||||||
|
for (floor = this->floor_config_entries.size() - 1; floor >= 0; floor--) {
|
||||||
|
const auto& fc = this->floor_config_entries[floor];
|
||||||
|
size_t base_object_index = fc.base_indexes_for_version(version).base_object_index;
|
||||||
|
if (object_index >= base_object_index) {
|
||||||
|
if (!fc.super_map) {
|
||||||
|
throw out_of_range("there are no objects on the specified floor");
|
||||||
|
}
|
||||||
|
const auto& obj = fc.super_map->version(version).objects.at(object_index - base_object_index);
|
||||||
|
return this->object_states.at(fc.base_super_ids.base_object_index + obj->super_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw out_of_range("the specified enemy does not exist");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
size_t k_id_delta = object_index - dynamic_obj_base_index;
|
||||||
|
auto obj_st = make_shared<ObjectState>();
|
||||||
|
obj_st->k_id = this->dynamic_obj_base_k_id + k_id_delta;
|
||||||
|
obj_st->super_obj = nullptr;
|
||||||
|
return obj_st;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
shared_ptr<MapState::ObjectState> MapState::object_state_for_index(Version version, uint8_t floor, uint16_t object_index) {
|
shared_ptr<MapState::ObjectState> MapState::object_state_for_index(Version version, uint8_t floor, uint16_t object_index) {
|
||||||
size_t dynamic_obj_base_index = this->dynamic_obj_base_index_for_version.at(static_cast<size_t>(version));
|
size_t dynamic_obj_base_index = this->dynamic_obj_base_index_for_version.at(static_cast<size_t>(version));
|
||||||
if (object_index < dynamic_obj_base_index) {
|
if (object_index < dynamic_obj_base_index) {
|
||||||
@@ -6354,6 +6380,22 @@ vector<shared_ptr<MapState::ObjectState>> MapState::door_states_for_switch_flag(
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shared_ptr<MapState::EnemyState> MapState::enemy_state_for_index(Version version, uint16_t enemy_index) {
|
||||||
|
int8_t floor;
|
||||||
|
for (floor = this->floor_config_entries.size() - 1; floor >= 0; floor--) {
|
||||||
|
const auto& fc = this->floor_config_entries[floor];
|
||||||
|
size_t base_enemy_index = fc.base_indexes_for_version(version).base_enemy_index;
|
||||||
|
if (enemy_index >= base_enemy_index) {
|
||||||
|
if (!fc.super_map) {
|
||||||
|
throw out_of_range("there are no enemies on the specified floor");
|
||||||
|
}
|
||||||
|
const auto& ene = fc.super_map->version(version).enemies.at(enemy_index - base_enemy_index);
|
||||||
|
return this->enemy_states.at(fc.base_super_ids.base_enemy_index + ene->super_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw out_of_range("the specified enemy does not exist");
|
||||||
|
}
|
||||||
|
|
||||||
shared_ptr<MapState::EnemyState> MapState::enemy_state_for_index(Version version, uint8_t floor, uint16_t enemy_index) {
|
shared_ptr<MapState::EnemyState> MapState::enemy_state_for_index(Version version, uint8_t floor, uint16_t enemy_index) {
|
||||||
const auto& fc = this->floor_config(floor);
|
const auto& fc = this->floor_config(floor);
|
||||||
size_t base_enemy_index = fc.base_indexes_for_version(version).base_enemy_index;
|
size_t base_enemy_index = fc.base_indexes_for_version(version).base_enemy_index;
|
||||||
|
|||||||
@@ -945,12 +945,14 @@ public:
|
|||||||
uint16_t set_index_for_enemy_state(Version version, std::shared_ptr<const EnemyState> ene_st) const;
|
uint16_t set_index_for_enemy_state(Version version, std::shared_ptr<const EnemyState> ene_st) const;
|
||||||
uint16_t index_for_event_state(Version version, std::shared_ptr<const EventState> evt_st) const;
|
uint16_t index_for_event_state(Version version, std::shared_ptr<const EventState> evt_st) const;
|
||||||
|
|
||||||
|
std::shared_ptr<ObjectState> object_state_for_index(Version version, uint16_t object_index);
|
||||||
std::shared_ptr<ObjectState> object_state_for_index(Version version, uint8_t floor, uint16_t object_index);
|
std::shared_ptr<ObjectState> object_state_for_index(Version version, uint8_t floor, uint16_t object_index);
|
||||||
std::vector<std::shared_ptr<ObjectState>> object_states_for_floor_room_group(
|
std::vector<std::shared_ptr<ObjectState>> object_states_for_floor_room_group(
|
||||||
Version version, uint8_t floor, uint16_t room, uint16_t group);
|
Version version, uint8_t floor, uint16_t room, uint16_t group);
|
||||||
std::vector<std::shared_ptr<ObjectState>> door_states_for_switch_flag(
|
std::vector<std::shared_ptr<ObjectState>> door_states_for_switch_flag(
|
||||||
Version version, uint8_t floor, uint8_t switch_flag);
|
Version version, uint8_t floor, uint8_t switch_flag);
|
||||||
|
|
||||||
|
std::shared_ptr<EnemyState> enemy_state_for_index(Version version, uint16_t enemy_index);
|
||||||
std::shared_ptr<EnemyState> enemy_state_for_index(Version version, uint8_t floor, uint16_t enemy_index);
|
std::shared_ptr<EnemyState> enemy_state_for_index(Version version, uint8_t floor, uint16_t enemy_index);
|
||||||
std::shared_ptr<EnemyState> enemy_state_for_set_index(Version version, uint8_t floor, uint16_t enemy_set_index);
|
std::shared_ptr<EnemyState> enemy_state_for_set_index(Version version, uint8_t floor, uint16_t enemy_set_index);
|
||||||
std::shared_ptr<EnemyState> enemy_state_for_floor_type(Version version, uint8_t floor, EnemyType type);
|
std::shared_ptr<EnemyState> enemy_state_for_floor_type(Version version, uint8_t floor, EnemyType type);
|
||||||
|
|||||||
@@ -1005,7 +1005,7 @@ static asio::awaitable<HandlerResult> S_6x(shared_ptr<Client> c, Channel::Messag
|
|||||||
if (c->proxy_session->map_state) {
|
if (c->proxy_session->map_state) {
|
||||||
shared_ptr<MapState::ObjectState> obj_st;
|
shared_ptr<MapState::ObjectState> obj_st;
|
||||||
try {
|
try {
|
||||||
obj_st = c->proxy_session->map_state->object_state_for_index(c->version(), c->floor, cmd.header.entity_id - 0x4000);
|
obj_st = c->proxy_session->map_state->object_state_for_index(c->version(), cmd.header.entity_id - 0x4000);
|
||||||
} catch (const exception& e) {
|
} catch (const exception& e) {
|
||||||
c->log.warning_f("Invalid object reference ({})", e.what());
|
c->log.warning_f("Invalid object reference ({})", e.what());
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-13
@@ -381,9 +381,9 @@ asio::awaitable<void> forward_subcommand_with_entity_id_transcode_t(shared_ptr<C
|
|||||||
shared_ptr<const MapState::EnemyState> ene_st;
|
shared_ptr<const MapState::EnemyState> ene_st;
|
||||||
shared_ptr<const MapState::ObjectState> obj_st;
|
shared_ptr<const MapState::ObjectState> obj_st;
|
||||||
if ((cmd_entity_id >= 0x1000) && (cmd_entity_id < 0x4000)) {
|
if ((cmd_entity_id >= 0x1000) && (cmd_entity_id < 0x4000)) {
|
||||||
ene_st = l->map_state->enemy_state_for_index(c->version(), c->floor, cmd_entity_id - 0x1000);
|
ene_st = l->map_state->enemy_state_for_index(c->version(), cmd_entity_id - 0x1000);
|
||||||
} else if ((cmd_entity_id >= 0x4000) && (cmd_entity_id < 0xFFFF)) {
|
} else if ((cmd_entity_id >= 0x4000) && (cmd_entity_id < 0xFFFF)) {
|
||||||
obj_st = l->map_state->object_state_for_index(c->version(), c->floor, cmd_entity_id - 0x4000);
|
obj_st = l->map_state->object_state_for_index(c->version(), cmd_entity_id - 0x4000);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& lc : l->clients) {
|
for (auto& lc : l->clients) {
|
||||||
@@ -446,9 +446,9 @@ asio::awaitable<void> forward_subcommand_with_entity_targets_transcode_t(shared_
|
|||||||
for (size_t z = 0; z < header.target_count; z++) {
|
for (size_t z = 0; z < header.target_count; z++) {
|
||||||
auto& res = resolutions.emplace_back(TargetResolution{nullptr, nullptr, targets[z].entity_id});
|
auto& res = resolutions.emplace_back(TargetResolution{nullptr, nullptr, targets[z].entity_id});
|
||||||
if ((res.entity_id >= 0x1000) && (res.entity_id < 0x4000)) {
|
if ((res.entity_id >= 0x1000) && (res.entity_id < 0x4000)) {
|
||||||
res.ene_st = l->map_state->enemy_state_for_index(c->version(), c->floor, res.entity_id - 0x1000);
|
res.ene_st = l->map_state->enemy_state_for_index(c->version(), res.entity_id - 0x1000);
|
||||||
} else if ((res.entity_id >= 0x4000) && (res.entity_id < 0xFFFF)) {
|
} else if ((res.entity_id >= 0x4000) && (res.entity_id < 0xFFFF)) {
|
||||||
res.obj_st = l->map_state->object_state_for_index(c->version(), c->floor, res.entity_id - 0x4000);
|
res.obj_st = l->map_state->object_state_for_index(c->version(), res.entity_id - 0x4000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3451,7 +3451,7 @@ 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");
|
||||||
}
|
}
|
||||||
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(), 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 == Difficulty::ULTIMATE) {
|
if (l->difficulty == Difficulty::ULTIMATE) {
|
||||||
src_flags = (src_flags & 0xFFFFFFC0) | (ene_st->game_flags & 0x0000003F);
|
src_flags = (src_flags & 0xFFFFFFC0) | (ene_st->game_flags & 0x0000003F);
|
||||||
@@ -3493,7 +3493,7 @@ static asio::awaitable<void> on_incr_enemy_damage(shared_ptr<Client> c, Subcomma
|
|||||||
if (cmd.header.entity_id < 0x1000 || cmd.header.entity_id >= 0x4000) {
|
if (cmd.header.entity_id < 0x1000 || cmd.header.entity_id >= 0x4000) {
|
||||||
throw runtime_error("6xE4 received for non-enemy entity");
|
throw runtime_error("6xE4 received for non-enemy entity");
|
||||||
}
|
}
|
||||||
auto ene_st = l->map_state->enemy_state_for_index(c->version(), c->floor, cmd.header.entity_id & 0x0FFF);
|
auto ene_st = l->map_state->enemy_state_for_index(c->version(), cmd.header.entity_id & 0x0FFF);
|
||||||
|
|
||||||
c->log.info_f("E-{:03X} damage incremented by {} with factor {}; before hit, damage was {} (cmd) or {} (ene_st) and HP was {}/{}",
|
c->log.info_f("E-{:03X} damage incremented by {} with factor {}; before hit, damage was {} (cmd) or {} (ene_st) and HP was {}/{}",
|
||||||
ene_st->e_id,
|
ene_st->e_id,
|
||||||
@@ -3523,7 +3523,7 @@ static asio::awaitable<void> on_set_enemy_low_game_flags_ultimate(shared_ptr<Cli
|
|||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
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(), cmd.header.entity_id - 0x1000);
|
||||||
if (!(ene_st->game_flags & cmd.low_game_flags)) {
|
if (!(ene_st->game_flags & cmd.low_game_flags)) {
|
||||||
ene_st->game_flags |= cmd.low_game_flags;
|
ene_st->game_flags |= cmd.low_game_flags;
|
||||||
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);
|
||||||
@@ -3544,7 +3544,7 @@ static asio::awaitable<void> on_update_object_state_t(shared_ptr<Client> c, Subc
|
|||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto obj_st = l->map_state->object_state_for_index(c->version(), c->floor, cmd.object_index);
|
auto obj_st = l->map_state->object_state_for_index(c->version(), cmd.object_index);
|
||||||
obj_st->game_flags = cmd.flags;
|
obj_st->game_flags = cmd.flags;
|
||||||
l->log.info_f("K-{:03X} updated with game_flags={:08X}", obj_st->k_id, obj_st->game_flags);
|
l->log.info_f("K-{:03X} updated with game_flags={:08X}", obj_st->k_id, obj_st->game_flags);
|
||||||
|
|
||||||
@@ -3647,7 +3647,7 @@ static asio::awaitable<void> on_dragon_actions_6x12(shared_ptr<Client> c, Subcom
|
|||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
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(), cmd.header.entity_id - 0x1000);
|
||||||
if (ene_st->super_ene->type != EnemyType::DRAGON) {
|
if (ene_st->super_ene->type != EnemyType::DRAGON) {
|
||||||
throw runtime_error("6x12 command sent for incorrect enemy type");
|
throw runtime_error("6x12 command sent for incorrect enemy type");
|
||||||
}
|
}
|
||||||
@@ -3683,7 +3683,7 @@ static asio::awaitable<void> on_gol_dragon_actions(shared_ptr<Client> c, Subcomm
|
|||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
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(), cmd.header.entity_id - 0x1000);
|
||||||
if (ene_st->super_ene->type != EnemyType::GOL_DRAGON) {
|
if (ene_st->super_ene->type != EnemyType::GOL_DRAGON) {
|
||||||
throw runtime_error("6xA8 command sent for incorrect enemy type");
|
throw runtime_error("6xA8 command sent for incorrect enemy type");
|
||||||
}
|
}
|
||||||
@@ -3786,7 +3786,7 @@ static asio::awaitable<void> on_set_boss_warp_flags_6x6A(shared_ptr<Client> c, S
|
|||||||
throw runtime_error("6x6A sent for non-object entity");
|
throw runtime_error("6x6A sent for non-object entity");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto obj_st = l->map_state->object_state_for_index(c->version(), c->floor, cmd.header.entity_id - 0x4000);
|
auto obj_st = l->map_state->object_state_for_index(c->version(), cmd.header.entity_id - 0x4000);
|
||||||
if (!obj_st->super_obj) {
|
if (!obj_st->super_obj) {
|
||||||
throw runtime_error("missing object for 6x6A command");
|
throw runtime_error("missing object for 6x6A command");
|
||||||
}
|
}
|
||||||
@@ -3981,7 +3981,7 @@ static asio::awaitable<void> on_steal_exp_bb(shared_ptr<Client> c, SubcommandMes
|
|||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& ene_st = l->map_state->enemy_state_for_index(c->version(), c->floor, cmd.enemy_index);
|
const auto& ene_st = l->map_state->enemy_state_for_index(c->version(), cmd.enemy_index);
|
||||||
if (ene_st->super_ene->floor != c->floor) {
|
if (ene_st->super_ene->floor != c->floor) {
|
||||||
throw runtime_error("enemy is on a different floor");
|
throw runtime_error("enemy is on a different floor");
|
||||||
}
|
}
|
||||||
@@ -4035,7 +4035,7 @@ static asio::awaitable<void> on_enemy_exp_request_bb(shared_ptr<Client> c, Subco
|
|||||||
throw runtime_error("client ID is too large");
|
throw runtime_error("client ID is too large");
|
||||||
}
|
}
|
||||||
|
|
||||||
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(), cmd.enemy_index);
|
||||||
string ene_str = ene_st->super_ene->str();
|
string ene_str = ene_st->super_ene->str();
|
||||||
c->log.info_f("EXP requested for E-{:03X}: {}", ene_st->e_id, ene_str);
|
c->log.info_f("EXP requested for E-{:03X}: {}", ene_st->e_id, ene_str);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user