Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/engine/core/obj_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,36 @@ RoomVnum get_room_where_obj(ObjData *obj, bool deep) {
return kNowhere;
}

// issue #3563: единый лог о пропаже вещи у игрока. Ищет игрока-владельца
// (инвентарь/экипировка/его контейнер) и пишет в syslog причину. Звать НАДО
// до отвязки вещи от владельца, иначе get_carried_by/get_worn_by уже пустые.
void LogPlayerObjLoss(ObjData *obj, const char *reason) {
if (!obj) {
return;
}
CharData *owner = obj->get_carried_by() ? obj->get_carried_by()
: (obj->get_worn_by() ? obj->get_worn_by() : nullptr);
if (!owner) {
// вещь в контейнере -- ищем игрока-владельца контейнера
for (ObjData *cont = obj->get_in_obj(); cont; cont = cont->get_in_obj()) {
if (cont->get_carried_by()) {
owner = cont->get_carried_by();
break;
}
if (cont->get_worn_by()) {
owner = cont->get_worn_by();
break;
}
}
}
if (!owner || owner->IsNpc()) {
return;
}
log("[Obj loss] у игрока %s пропала вещь '%s' vnum == %d (%s), timer == %d, прочность == %d/%d",
GET_NAME(owner), obj->get_PName(grammar::ECase::kNom).c_str(), GET_OBJ_VNUM(obj),
reason, obj->get_timer(), obj->get_current_durability(), obj->get_maximum_durability());
}

void ExtractObjFromWorld(ObjData *obj, bool showlog) {
timechange_unregister_obj(obj);
char name[kMaxStringLength];
Expand Down
2 changes: 2 additions & 0 deletions src/engine/core/obj_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ void RemoveObjFromObj(ObjData *obj);
void object_list_new_owner(ObjData *list, CharData *ch);
RoomVnum get_room_where_obj(ObjData *obj, bool deep = false);
void ExtractObjFromWorld(ObjData *obj, bool showlog = false);
// issue #3563: пишет в syslog о пропаже вещи у игрока; звать до отвязки от владельца.
void LogPlayerObjLoss(ObjData *obj, const char *reason);
void UpdateCharObjects(CharData *ch);
void DropObjOnZoneReset(CharData *ch, ObjData *obj, bool inv, bool zone_reset);
int get_object_low_rent(ObjData *obj);
Expand Down
5 changes: 5 additions & 0 deletions src/engine/ui/cmd/do_steal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ void go_steal(CharData *ch, CharData *vict, char *obj_name) {
} else {
act("Вы раздели $N3 и взяли $o3.", false, ch, obj, vict, kToChar);
act("$n украл$g $o3 у $N1.", false, ch, obj, vict, kToNotVict | kToArenaListen);
// issue #3563: кража НАДЕТОЙ вещи (имм или у спящей жертвы) -- она уходит
// через UnequipChar, без obj_from_char, поэтому логируем отдельно.
log("[Steal eq] %s украл надетую вещь '%s' (vnum %d) у %s",
GET_NAME(ch), obj->get_PName(grammar::ECase::kNom).c_str(),
GET_OBJ_VNUM(obj), GET_NAME(vict));
PlaceObjToInventory(UnequipChar(vict, eq_pos, CharEquipFlags()), ch);
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/gameplay/core/game_limits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1307,6 +1307,8 @@ void obj_point_update() {
timer_otrigger(j);
continue;
}
// issue #3563: логируем пропажу до отвязки вещи от игрока (ниже RemoveObjFromChar).
LogPlayerObjLoss(j, "истёк таймер жизни / decay");
// *** рассыпание объекта
ObjData *jj, *next_thing2;
for (jj = j->get_contains(); jj; jj = next_thing2) {
Expand Down
2 changes: 2 additions & 0 deletions src/gameplay/mechanics/equipment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ void DamageObj(ObjData *obj, int dam, int chance) {
char_get_custom_label(obj, obj->get_carried_by()).c_str());
act(buf, false, obj->get_carried_by(), obj, nullptr, kToChar);
}
// issue #3563: логируем пропажу до отложенного удаления, пока владелец известен.
LogPlayerObjLoss(obj, "рассыпалась по прочности");
// issue.obj-casting: deferred extraction (freed at heartbeat end) so a live ctx.ovict
// (acid corrode etc.) is left flagged purged() rather than dangling.
world_objects.AddToExtractedList(obj);
Expand Down
15 changes: 12 additions & 3 deletions src/gameplay/skills/punctual_style.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -645,11 +645,20 @@ void PerformPunctualHit(CharData *ch, CharData *victim, HitData &hit_data) {
act(buf, true, ch, nullptr, victim, kToNotVict | kToArenaListen);
break;
}
if (!victim->IsNpc() && ROOM_FLAGGED(victim->in_room, ERoomFlag::kArena))
if (!victim->IsNpc() && ROOM_FLAGGED(victim->in_room, ERoomFlag::kArena)) {
PlaceObjToInventory(obj, victim);
else
} else {
// issue #3563: точный стиль выбил вещь НА ЗЕМЛЮ (не в инвентарь). Для игрока
// логируем -- иначе потом непонятно, куда делось оружие (валяется в комнате,
// владелец не находит). Мобов не логируем, чтобы не шуметь.
if (!victim->IsNpc()) {
log("[Punctual -> ground] %s выбил точным стилем '%s' (vnum %d) из рук %s -> комната [%d] %s",
GET_NAME(ch), obj->get_PName(grammar::ECase::kNom).c_str(), GET_OBJ_VNUM(obj),
GET_NAME(victim), world[victim->in_room]->vnum, world[victim->in_room]->name);
}
PlaceObjToRoom(obj, victim->in_room);
CheckObjDecay(obj);
CheckObjDecay(obj);
}
}
if (!victim->IsNpc()) {
hit_data.dam /= 5;
Expand Down
Loading