diff --git a/docs/implementation/quest_man0u1_court_in_the_sands.md b/docs/implementation/quest_man0u1_court_in_the_sands.md index 4a6cbee..91d5be4 100644 --- a/docs/implementation/quest_man0u1_court_in_the_sands.md +++ b/docs/implementation/quest_man0u1_court_in_the_sands.md @@ -38,7 +38,7 @@ port was built from; every retail claim below cites its source. | 050 | Miner instance #1 — F'lhaminn teaches 6 emotes | 6 emotes done → 057 | teach `051_1..6` (Furious 103, Beckon 108, Laugh 121, Deny 125, Upset 140, Soothe 135 — in order), forgot-replay `051_7(quest,player,npc,51..56)`, go-signal `051_8`; crowd `050_2..14` | | 057 | Calm the miners: Maddened = Beckon; Manic = Soothe→Furious→Laugh | both calm → ending says (109,107,108,110,111,112,113) → 058 | rebuffs Manic `055_1..3`, Maddened `056_1..3` | | 058 | Miner instance #2 (reload) — Corguevais recovered | Corguevais talk | `processEvent060` (man0u160 CS: thanks + Linette assignment + F'lhaminn volunteers) → public | -| 060 | Meet F'lhaminn at the Gate of Nald (zone 170) | gate trigger push → confirm → **escort content** (Man0u102) | gate talks (says 144/145/146), duty-start `processEvent070` (man0u170 CS) | +| 060 | Meet F'lhaminn at the Gate of Nald (zone 170) | F'lhaminn talk **or** the proximity trigger → duty-join confirm → **escort content** (Man0u102) | `processEvent070` (man0u170 CS) — F'lhaminn's greeting lines 144/145/146 ("Sorry to keep you waiting … We should get going"). This IS the single pre-duty cutscene; it plays once inside the content launch. Do **not** also emit 144/145/146 as server-side wait-text (see finding 9). | | — | Escort duty: protect F'lhaminn, Gate of Nald → Camp Black Brush. 30-min timer, chinchilla (2204010) ambushes. Runs at SEQ 060 (relog → gate re-arms → retry, no rollback state needed) | arrival → director | banners 51005/50011/25018; barks 365-370/374/375; fail 371/372 | | 065 | Camp Black Brush (public 170) — the Ascilia echo | Ascilia talk → `080` echo CS → same-zone reload; then camp leader talk → says 176-183 → warp Ul'dah | `processEvent075` (arrival CS, fired by the escort director), `080` (Ascilia/Thancred echo CS), crowd `080_2..12` | | 070 | Momodi gossip | Momodi talk | `processEvent200_2` (texts 389/390) | @@ -180,7 +180,23 @@ leader (41.1/50.4, -480.0/-481.0) · 11001017 Concern stage (-91.4, only the correct class. Live-verify: `!` over the stage F'lhaminn on approach at SEQ_075 (streaming overlay), and NO `!` at the gate copy from SEQ_080 on. -8. Accepted divergence: the stage F'lhaminn (2433) is permanently +8. **FIXED (2026-07-10, this branch):** the SEQ_060 gate meetup + double-played F'lhaminn's greeting. The port emitted texts 144/145/146 + as server-side `SendGameMessage` on the `FLHAMINN_GATE` talk (built on + the "no client event exists for these" assumption) **and** fired + `processEvent070` (man0u170) on the trigger push — but a 4-playthrough + OCR sweep (eZgcq-FMpfw, XbDE5OQ_Y2g, WlKVCvRgQs0, 6eWqFhITeeM) proves + man0u170 **is** the cutscene that speaks 144/145/146 at the Gate of + Nald, so those lines showed twice. Fix: drop the server-side wait-text; + man0u170 is now the single pre-duty cutscene, played inside + `startMan0u1Escort`. Both F'lhaminn's talk and the proximity trigger + now route through a shared `tryStartMan0u1Escort` (confirm → launch), + so talking to her is no longer a dead click. The retail geography is + unchanged and confirmed: one continuous guild cutscene (man0u160, + ending "await me at the Gate of Nald") → travel → the man0u170 gate + meetup → escort duty launches from the gate → man0u175 is the + post-duty Camp Black Brush arrival (not pre-duty). +9. Accepted divergence: the stage F'lhaminn (2433) is permanently present during SEQ_000–070 — retail keeps the stage empty until 075 ("she rarely sings anymore", csv:292). Despawn/hide isn't viable (`area:DespawnActor` is global-to-all-players, diff --git a/scripts/lua/quests/man/man0u1.lua b/scripts/lua/quests/man/man0u1.lua index 29a1262..0369d07 100644 --- a/scripts/lua/quests/man/man0u1.lua +++ b/scripts/lua/quests/man/man0u1.lua @@ -448,13 +448,17 @@ function onTalk(player, quest, npc) seq058_onTalk(player, quest, npc, classId); end elseif (sequence == SEQ_060) then - if (classId == FLHAMINN_GATE) then - -- Gate-side wait talk (texts 144-146 — no client event - -- exists for these; server-side says, man0l1 - -- seq007_endSequence precedent). - player:SendGameMessage(quest, 144, 0x20); - player:SendGameMessage(quest, 145, 0x20); - player:SendGameMessage(quest, 146, 0x20); + -- The Gate of Nald meetup: talking to F'lhaminn (like the + -- proximity trigger in onPush) opens the duty-join confirm. Her + -- greeting lines 144-146 ("Sorry to keep you waiting ... We + -- should get going") ARE the man0u170 cutscene, which plays once + -- inside startMan0u1Escort as the single pre-duty cutscene — + -- retail stages the meetup as that gate cutscene, not as loose + -- wait-text (verified across 4 playthroughs). The old server-side + -- SendGameMessage(144/145/146) here double-played those same + -- lines against the cutscene and is removed. + if (classId == FLHAMINN_GATE and tryStartMan0u1Escort(player, quest)) then + return; -- warped — nothing may follow end player:EndEvent(); elseif (sequence == SEQ_065) then @@ -829,12 +833,9 @@ function onPush(player, quest, npc) end elseif (sequence == SEQ_060) then if (classId == GATE_OF_NALD_TRIGGER) then - local result = callClientFunction(player, "delegateEvent", player, quest, "contentsJoinAskInBasaClass"); - if (result == 1) then - startMan0u1Escort(player, quest); + if (tryStartMan0u1Escort(player, quest)) then return; end - player:EndEvent(); end elseif (sequence == SEQ_090) then if (classId == WARD_DOOR) then @@ -1065,6 +1066,23 @@ function startMan0u1Coliseum(player, quest) GetWorldManager():DoZoneChangeContent(player, contentArea, -209.9, 192.0, 146.4, 0.8, 16); end +-- Gate of Nald hand-off shared by F'lhaminn's talk (onTalk SEQ_060) and +-- the proximity trigger (onPush SEQ_060): the duty-join confirm, then +-- the content launch. The man0u170 meetup cutscene (F'lhaminn's greeting +-- lines 144-146) plays inside startMan0u1Escort, so neither entry point +-- re-says those lines. Returns true when the escort launched (the caller +-- must then return — the content warp has run and nothing may follow); +-- false on decline (the confirm's own EndEvent has already closed). +function tryStartMan0u1Escort(player, quest) + local result = callClientFunction(player, "delegateEvent", player, quest, "contentsJoinAskInBasaClass"); + if (result == 1) then + startMan0u1Escort(player, quest); + return true; + end + player:EndEvent(); + return false; +end + -- ===== The F'lhaminn escort (Garlemald-Server #53) ===== -- Gate of Nald → Camp Black Brush, zone 170 (both endpoints on the -- field map per the quest_marker sheet: gate -34.5/-68.9 → camp @@ -1083,9 +1101,11 @@ function startMan0u1Escort(player, quest) player:KickEvent(director, "noticeEvent", true); player:SetLoginDirector(director); - -- man0u170: the gate-side duty-start cutscene IN PLACE (arms the - -- after-warp veil; the director's questBaseRewardSeting dismisses - -- it post-warp). + -- man0u170: the Gate of Nald meetup cutscene IN PLACE — F'lhaminn's + -- greeting ("Sorry to keep you waiting ... We should get going", + -- lines 144-146). This is the SINGLE pre-duty cutscene; it arms the + -- after-warp veil that the director's questBaseRewardSeting dismisses + -- post-warp. callClientFunction(player, "delegateEvent", player, quest, "processEvent070"); player:EndEvent(); diff --git a/scripts/tests/quests/uldah_msq2.lua b/scripts/tests/quests/uldah_msq2.lua index 274a4b9..8ac56e3 100644 --- a/scripts/tests/quests/uldah_msq2.lua +++ b/scripts/tests/quests/uldah_msq2.lua @@ -151,12 +151,17 @@ describe("Ul'dah - Court in the Sands (Man0u1)", function() :expectEnpc(FLHAMINN_GATE, QFLAG_TALK) :expectNoEnpc(FLHAMINN) - -- Gate-side wait talk: server-side says only (texts 144-146), no - -- delegate, no advance. - w:talk(FLHAMINN_GATE):expectSequence(60) - - -- SEQ_060: the gate trigger -> duty confirm -> the escort content - -- burst (man0u170 plays in place before the duty warp). + -- The Gate of Nald meetup: talking to F'lhaminn now opens the + -- duty-join confirm. Her greeting lines 144-146 ARE the man0u170 + -- cutscene (which plays once inside the content launch below), so + -- the old server-side wait-text that double-said them is gone. + -- Declining leaves the player at the gate. + w:talk(FLHAMINN_GATE):expectDelegate("contentsJoinAskInBasaClass") + :answer(0):expectSequence(60) + + -- Accepting (via F'lhaminn or the proximity trigger) launches the + -- escort: confirm -> content area -> man0u170 meetup cutscene (the + -- single pre-duty cutscene) -> duty warp. w:push(GATE_OF_NALD):expectDelegate("contentsJoinAskInBasaClass") :answer(1) :expectCreateContentArea()