From ca8d36e48c73f56edbef71c402f1bdaf56565de6 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Mon, 5 May 2025 23:45:22 -0400 Subject: [PATCH] Fix remaining inn warps, prevent the player from getting stuck This means the three ARR inns are now "functional" (as in, you can enter and exit them.) I also added some code to give you control of your character in case you hit an unimplemented event. --- resources/scripts/Global.lua | 7 +- resources/scripts/warp/WarpInnGridania.lua | 17 ++++- resources/scripts/warp/WarpInnUldah.lua | 16 ++++ src/bin/kawari-world.rs | 10 +++ src/world/connection.rs | 86 +++++++++++----------- 5 files changed, 90 insertions(+), 46 deletions(-) create mode 100644 resources/scripts/warp/WarpInnUldah.lua diff --git a/resources/scripts/Global.lua b/resources/scripts/Global.lua index c9959e2..406c197 100644 --- a/resources/scripts/Global.lua +++ b/resources/scripts/Global.lua @@ -13,9 +13,12 @@ registerAction(9, "actions/FastBlade.lua") registerAction(6221, "items/Fantasia.lua") -- Events -registerEvent(131078, "warp/WarpInnGridania.lua") registerEvent(131079, "warp/WarpInnLimsaLominsa.lua") +registerEvent(131080, "warp/WarpInnGridania.lua") +registerEvent(131081, "warp/WarpInnUldah.lua") registerEvent(131082, "common/GenericWarp.lua") +registerEvent(131083, "common/GenericWarp.lua") +registerEvent(131084, "common/GenericWarp.lua") registerEvent(131092, "common/GenericWarp.lua") registerEvent(131093, "common/GenericWarp.lua") registerEvent(131094, "common/GenericWarp.lua") @@ -23,3 +26,5 @@ registerEvent(720916, "custom/000/cmndefinnbed_00020.lua") registerEvent(1245185, "opening/OpeningLimsaLominsa.lua") registerEvent(1245186, "opening/OpeningGridania.lua") registerEvent(1245187, "opening/OpeningUldah.lua") + +-- TODO: Generic warps might be decided through ArrayEventHandler? diff --git a/resources/scripts/warp/WarpInnGridania.lua b/resources/scripts/warp/WarpInnGridania.lua index b63a6d3..80cea53 100644 --- a/resources/scripts/warp/WarpInnGridania.lua +++ b/resources/scripts/warp/WarpInnGridania.lua @@ -1,7 +1,18 @@ -function onTalk(actorId, player) +-- TODO: maybe de-duplicare this for all inns? + +function onTalk(target, player) -- has inn access - -- player:play_scene(131079, 00001, 1, 0) + player:play_scene(target, EVENT_ID, 00001, 8192, 0) -- doesn't have inn access - player:play_scene(actorId, EVENT_ID, 00002, 8192, 0) + --player:play_scene(actorId, EVENT_ID, 00002, 8192, 0) +end + +function onReturn(scene, results, player) + player:finish_event(EVENT_ID) + + if results[1] == 1 then + -- get warp + player:warp(EVENT_ID) + end end diff --git a/resources/scripts/warp/WarpInnUldah.lua b/resources/scripts/warp/WarpInnUldah.lua new file mode 100644 index 0000000..0a196c1 --- /dev/null +++ b/resources/scripts/warp/WarpInnUldah.lua @@ -0,0 +1,16 @@ +function onTalk(target, player) + -- has inn access + player:play_scene(target, EVENT_ID, 00001, 8192, 0) + + -- doesn't have inn access + --player:play_scene(actorId, EVENT_ID, 00002, 8192, 0) +end + +function onReturn(scene, results, player) + player:finish_event(EVENT_ID) + + if results[1] == 1 then + -- get warp + player:warp(EVENT_ID) + end +end diff --git a/src/bin/kawari-world.rs b/src/bin/kawari-world.rs index c3a1081..446b0c2 100644 --- a/src/bin/kawari-world.rs +++ b/src/bin/kawari-world.rs @@ -727,6 +727,8 @@ async fn client_loop( .await; } + let mut should_cancel = false; + { let lua = lua.lock().unwrap(); let state = lua.app_data_ref::().unwrap(); @@ -741,6 +743,14 @@ async fn client_loop( .talk(*actor_id, &mut lua_player); } else { tracing::warn!("Event {event_id} isn't scripted yet! Ignoring..."); + + should_cancel = true; + } + } + + if should_cancel { + // give control back to the player so they aren't stuck + connection.event_finish(*event_id).await; } } ClientZoneIpcData::EventHandlerReturn { handler_id, scene, error_code, num_results, results } => { diff --git a/src/world/connection.rs b/src/world/connection.rs index bba4501..f37b0d8 100644 --- a/src/world/connection.rs +++ b/src/world/connection.rs @@ -601,53 +601,55 @@ impl ZoneConnection { self.warp(*warp_id).await; } Task::BeginLogOut => self.begin_log_out().await, - Task::FinishEvent { handler_id } => { - // sent event finish - { - let ipc = ServerZoneIpcSegment { - op_code: ServerZoneIpcType::EventFinish, - timestamp: timestamp_secs(), - data: ServerZoneIpcData::EventFinish { - handler_id: *handler_id, - event: 1, - result: 1, - arg: 0, - }, - ..Default::default() - }; - - self.send_segment(PacketSegment { - source_actor: self.player_data.actor_id, - target_actor: self.player_data.actor_id, - segment_type: SegmentType::Ipc, - data: SegmentData::Ipc { data: ipc }, - }) - .await; - } - - // give back control to the player - { - let ipc = ServerZoneIpcSegment { - op_code: ServerZoneIpcType::Unk18, - timestamp: timestamp_secs(), - data: ServerZoneIpcData::Unk18 { unk: [0; 16] }, - ..Default::default() - }; - - self.send_segment(PacketSegment { - source_actor: self.player_data.actor_id, - target_actor: self.player_data.actor_id, - segment_type: SegmentType::Ipc, - data: SegmentData::Ipc { data: ipc }, - }) - .await; - } - } + Task::FinishEvent { handler_id } => self.event_finish(*handler_id).await, } } player.queued_tasks.clear(); } + pub async fn event_finish(&mut self, handler_id: u32) { + // sent event finish + { + let ipc = ServerZoneIpcSegment { + op_code: ServerZoneIpcType::EventFinish, + timestamp: timestamp_secs(), + data: ServerZoneIpcData::EventFinish { + handler_id, + event: 1, + result: 1, + arg: 0, + }, + ..Default::default() + }; + + self.send_segment(PacketSegment { + source_actor: self.player_data.actor_id, + target_actor: self.player_data.actor_id, + segment_type: SegmentType::Ipc, + data: SegmentData::Ipc { data: ipc }, + }) + .await; + } + + // give back control to the player + { + let ipc = ServerZoneIpcSegment { + op_code: ServerZoneIpcType::Unk18, + timestamp: timestamp_secs(), + data: ServerZoneIpcData::Unk18 { unk: [0; 16] }, + ..Default::default() + }; + + self.send_segment(PacketSegment { + source_actor: self.player_data.actor_id, + target_actor: self.player_data.actor_id, + segment_type: SegmentType::Ipc, + data: SegmentData::Ipc { data: ipc }, + }) + .await; + } + } + pub async fn begin_log_out(&mut self) { // write the player back to the database self.database.commit_player_data(&self.player_data);