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);
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
@@ -6354,6 +6380,22 @@ vector<shared_ptr<MapState::ObjectState>> MapState::door_states_for_switch_flag(
|
||||
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) {
|
||||
const auto& fc = this->floor_config(floor);
|
||||
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 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::vector<std::shared_ptr<ObjectState>> object_states_for_floor_room_group(
|
||||
Version version, uint8_t floor, uint16_t room, uint16_t group);
|
||||
std::vector<std::shared_ptr<ObjectState>> door_states_for_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_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);
|
||||
|
||||
@@ -1005,7 +1005,7 @@ static asio::awaitable<HandlerResult> S_6x(shared_ptr<Client> c, Channel::Messag
|
||||
if (c->proxy_session->map_state) {
|
||||
shared_ptr<MapState::ObjectState> obj_st;
|
||||
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) {
|
||||
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::ObjectState> obj_st;
|
||||
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)) {
|
||||
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) {
|
||||
@@ -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++) {
|
||||
auto& res = resolutions.emplace_back(TargetResolution{nullptr, nullptr, targets[z].entity_id});
|
||||
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)) {
|
||||
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))) {
|
||||
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();
|
||||
if (l->difficulty == Difficulty::ULTIMATE) {
|
||||
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) {
|
||||
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 {}/{}",
|
||||
ene_st->e_id,
|
||||
@@ -3523,7 +3523,7 @@ static asio::awaitable<void> on_set_enemy_low_game_flags_ultimate(shared_ptr<Cli
|
||||
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)) {
|
||||
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);
|
||||
@@ -3544,7 +3544,7 @@ static asio::awaitable<void> on_update_object_state_t(shared_ptr<Client> c, Subc
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
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");
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
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");
|
||||
}
|
||||
|
||||
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();
|
||||
c->log.info_f("EXP requested for E-{:03X}: {}", ene_st->e_id, ene_str);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user