From 136549b46080bbe434a56cf293758e00d0b03cf3 Mon Sep 17 00:00:00 2001 From: stribog Date: Sat, 14 Nov 2026 08:56:15 +0100 Subject: [PATCH] fix(locate): a find inside a container obeys the same zone limit as the rest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit У "разыскать предмет" четыре ветки по месту находки. Три из них держат поиск в своей зоне: вещь в чужой комнате, у чужого моба в руках или надетую на нём заклинание не печатает вовсе. Ветка "внутри контейнера" этой отсечки не имела, и места она не называет -- только вид контейнера: "филактерия находится в каменной чаше". Каменных чаш в мире пять, две из них в одной зоне, и филактерий там же две. Игрок читал сообщение, заглядывал в чашу перед собой и находил её пустой: заклинание показало другую, хоть с другого конца мира. Зона контейнера берётся там же, где он лежит: комната, руки или надето. Игрока показываем из любой зоны -- так же, как ветка "в инвентаре". Хранилища и почта идут отдельной веткой и не затронуты, богов отсечка не касается. С доски ошибок: Ромбар, 07.06, комната 27285. Сборка с тестами: 875 тестов, 872 прошли, 3 отключены. Co-Authored-By: Claude Opus 5 --- src/gameplay/handlers/spell_locate_object.cpp | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/gameplay/handlers/spell_locate_object.cpp b/src/gameplay/handlers/spell_locate_object.cpp index 62d007538..39319bf5e 100644 --- a/src/gameplay/handlers/spell_locate_object.cpp +++ b/src/gameplay/handlers/spell_locate_object.cpp @@ -164,6 +164,27 @@ EStageResult SpellLocateObject(ActionContext &ctx) { return false; } } + // Остальные три ветки показывают только свою зону: вещь в чужой комнате, у + // чужого моба или надетую на нём заклинание просто не печатает. Ветка + // контейнера этого не делала, а места она не называет вовсе -- только вид + // контейнера ("находится в каменной чаше"). Каменных чаш в мире пять, из них + // две в одной зоне, так что игрок шёл смотреть не в ту и находил её пустой. + // Зону контейнера берём там же, где он лежит: в комнате, в руках или надет. + const auto *container = i->get_in_obj(); + const auto *holder = container->get_carried_by() ? container->get_carried_by() + : container->get_worn_by(); + bool same_zone = false; + if (holder) { + // Игрока, как и в ветке "в инвентаре", показываем из любой зоны. + same_zone = !holder->IsNpc() + || (holder->in_room != kNowhere + && world[ch->in_room]->zone_rn == world[holder->in_room]->zone_rn); + } else if (container->get_in_room() != kNowhere && container->get_in_room()) { + same_zone = world[ch->in_room]->zone_rn == world[container->get_in_room()]->zone_rn; + } + if (!same_zone) { + return false; + } } where = fmt::format("{} наход{}ся в {}.\r\n", i->get_short_description(),