From be3237bd4421f3cc6d2eedf0fbf24d9bcd66994e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Bosc=C3=A1?= Date: Wed, 8 Apr 2026 19:20:32 -0300 Subject: [PATCH 1/4] Improve quest parsing and mission mapping Normalize and harden quest handling across servers: add helpers to resolve mob names and normalize (possibly reversed) quest time windows; prefer start time for certain no-mission quests in cmdQuest. Store last killed monster nameID/time to help map hunt-only updates. Rework quest mission parsing and quest_update_mission_hunt to handle various server formats (hunt_id, hunt_id_cont, mob_id), build synthetic hunt identifiers, prefer exact mission_index matches, use packet-order and recent-kill/progress-delta fallbacks for ambiguous updates, and avoid noisy duplicate progress messages by only notifying on real changes. Add debug logging for resolved time windows and ambiguous mappings. --- src/Commands.pm | 12 ++- src/Network/Receive.pm | 183 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 171 insertions(+), 24 deletions(-) diff --git a/src/Commands.pm b/src/Commands.pm index 165172ef02..2cf4ef3a8f 100644 --- a/src/Commands.pm +++ b/src/Commands.pm @@ -7089,8 +7089,17 @@ sub cmdQuest { my $msg .= center(" " . T("Quest List") . " ", 79, '-') . "\n"; foreach my $questID (keys %{$questList}) { my $quest = $questList->{$questID}; + my $display_time = $quest->{time_expire}; + if ((!exists $quest->{missions} || !keys %{$quest->{missions}}) + && $quest->{time_start} + && $quest->{time_expire} + && $quest->{time_start} < $quest->{time_expire}) { + # For "wait/return after" quests without hunt missions, start time + # carries the meaningful availability timestamp on some servers. + $display_time = $quest->{time_start}; + } $msg .= swrite(sprintf("\@%s \@%s \@%s \@%s \@%s", ('>'x2), ('<'x5), ('<'x30), ('<'x10), ('<'x24)), - [$k, $questID, $quests_lut{$questID} ? $quests_lut{$questID}{title} : '', $quest->{active} ? T("active") : T("inactive"), $quest->{time_expire} ? scalar localtime $quest->{time_expire} : '']); + [$k, $questID, $quests_lut{$questID} ? $quests_lut{$questID}{title} : '', $quest->{active} ? T("active") : T("inactive"), $display_time ? scalar localtime $display_time : '']); foreach my $mobID (sort { ($quest->{missions}{$a}{mission_index} // 9999) <=> ($quest->{missions}{$b}{mission_index} // 9999) || $a <=> $b } keys %{$quest->{missions}}) { @@ -8787,4 +8796,3 @@ sub cmdEden { } 1; - diff --git a/src/Network/Receive.pm b/src/Network/Receive.pm index 8a167cc457..3b84a74859 100644 --- a/src/Network/Receive.pm +++ b/src/Network/Receive.pm @@ -2435,6 +2435,8 @@ sub actor_died_or_disappeared { } elsif ($args->{type} == 1) { debug "Monster Died: " . $monster->name . " ($monster->{binID})\n", "parseMsg_damage"; $monster->{dead} = 1; + $self->{_last_killed_monster_nameID} = $monster->{nameID}; + $self->{_last_killed_monster_time} = time; if ((AI::action() ne "attack" || AI::args(0)->{ID} eq $ID) && ($config{itemsTakeAuto_party} && @@ -4625,6 +4627,32 @@ sub progress_bar_stop { # 02b1 .W .L { .L .B }*num (ZC_ALL_QUEST_LIST) # 097a .W .L { .L .B .L