1
Fork 0
mirror of https://github.com/redstrate/Kawari.git synced 2025-05-12 14:47:46 +00:00

Add inn bed handling, let event scripts decie when they are finished

The inn bed is the most complex script we have written so far, and needs
a little bit more logic to when it finishes. I also made it play the bed
animation, although you *will* sleep forever as we don't know how to
disconnect you yet.
This commit is contained in:
Joshua Goins 2025-05-05 23:04:53 -04:00
parent 00671ae741
commit 6dc8194aa8
8 changed files with 128 additions and 71 deletions

View file

@ -17,3 +17,4 @@ registerEvent(1245187, "opening/OpeningUldah.lua")
registerEvent(131078, "warp/WarpInnGridania.lua")
registerEvent(131079, "warp/WarpInnLimsaLominsa.lua")
registerEvent(131082, "tosort/LimsaInnDoor.lua")
registerEvent(720916, "custom/000/cmndefinnbed_00020.lua")

View file

@ -0,0 +1,33 @@
--- TODO: find a way to hardcode it this way
EVENT_ID = 720916
-- TODO: in retail, there is a fade in/out between the prompt and the sleep anim?
function onTalk(target, player)
--- prompt the bed menu
player:play_scene(target, EVENT_ID, 0, 8192, 0)
end
function onReturn(scene, results, player)
if scene == 0 then -- prompt
if results[1] == 1 then
-- nothing
elseif results[1] == 2 then
-- dreamfitting not implemented
elseif results[1] == 3 then
-- play sleep animation
player:play_scene(player.id, EVENT_ID, 1, 8192, 0)
player:begin_log_out()
return
elseif results[1] == 4 then
-- play sleep animation
player:play_scene(player.id, EVENT_ID, 1, 8192, 0)
player:begin_log_out()
return
end
player:finish_event(EVENT_ID)
elseif scene == 1 then -- sleep anim
player:finish_event(EVENT_ID)
end
end

View file

@ -8,7 +8,9 @@ function onTalk(target, player)
player:play_scene(target, EVENT_ID, 00000, 8192, 0)
end
function onReturn(results, player)
function onReturn(scene, results, player)
player:finish_event(EVENT_ID)
if results[1] == 1 then
-- get warp
player:warp(EVENT_ID)

View file

@ -9,7 +9,9 @@ function onTalk(target, player)
--player:play_scene(actorId, EVENT_ID, 00002, 8192, 0)
end
function onReturn(results, player)
function onReturn(scene, results, player)
player:finish_event(EVENT_ID)
if results[1] == 1 then
-- get warp
player:warp(EVENT_ID)

View file

@ -468,27 +468,7 @@ async fn client_loop(
ClientZoneIpcData::LogOut { .. } => {
tracing::info!("Recieved log out from client!");
// write the player back to the database
database.commit_player_data(&connection.player_data);
// tell the client to disconnect
{
let ipc = ServerZoneIpcSegment {
op_code: ServerZoneIpcType::LogOutComplete,
timestamp: timestamp_secs(),
data: ServerZoneIpcData::LogOutComplete { unk: [0; 8] },
..Default::default()
};
connection
.send_segment(PacketSegment {
source_actor: connection.player_data.actor_id,
target_actor: connection.player_data.actor_id,
segment_type: SegmentType::Ipc,
data: SegmentData::Ipc { data: ipc },
})
.await;
}
connection.begin_log_out().await;
}
ClientZoneIpcData::Disconnected { .. } => {
tracing::info!("Client disconnected!");
@ -770,52 +750,7 @@ async fn client_loop(
.event
.as_mut()
.unwrap()
.finish(results, &mut lua_player);
{
// TODO: handle in lua script
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()
};
connection
.send_segment(PacketSegment {
source_actor: connection.player_data.actor_id,
target_actor: connection.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()
};
connection
.send_segment(PacketSegment {
source_actor: connection.player_data.actor_id,
target_actor: connection.player_data.actor_id,
segment_type: SegmentType::Ipc,
data: SegmentData::Ipc { data: ipc },
})
.await;
}
.finish(*scene, results, &mut lua_player);
}
}
}

View file

@ -600,11 +600,77 @@ impl ZoneConnection {
Task::Warp { warp_id } => {
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;
}
}
}
}
player.queued_tasks.clear();
}
pub async fn begin_log_out(&mut self) {
// write the player back to the database
self.database.commit_player_data(&self.player_data);
// tell the client we're ready to disconnect at any moment'
{
let ipc = ServerZoneIpcSegment {
op_code: ServerZoneIpcType::LogOutComplete,
timestamp: timestamp_secs(),
data: ServerZoneIpcData::LogOutComplete { unk: [0; 8] },
..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 process_effects_list(&mut self) {
// Only update the client if absolutely nessecary (e.g. an effect is added, removed or changed duration)
if self.status_effects.dirty {

View file

@ -65,14 +65,14 @@ impl Event {
.unwrap();
}
pub fn finish(&mut self, results: &[u32], player: &mut LuaPlayer) {
pub fn finish(&mut self, scene: u16, results: &[u32], player: &mut LuaPlayer) {
self.lua
.scope(|scope| {
let player = scope.create_userdata_ref_mut(player).unwrap();
let func: Function = self.lua.globals().get("onReturn").unwrap();
func.call::<()>((results, player)).unwrap();
func.call::<()>((scene, results, player)).unwrap();
Ok(())
})

View file

@ -16,6 +16,8 @@ pub enum Task {
ChangeTerritory { zone_id: u16 },
SetRemakeMode(RemakeMode),
Warp { warp_id: u32 },
BeginLogOut,
FinishEvent { handler_id: u32 },
}
#[derive(Default)]
@ -114,6 +116,14 @@ impl LuaPlayer {
fn warp(&mut self, warp_id: u32) {
self.queued_tasks.push(Task::Warp { warp_id });
}
fn begin_log_out(&mut self) {
self.queued_tasks.push(Task::BeginLogOut);
}
fn finish_event(&mut self, handler_id: u32) {
self.queued_tasks.push(Task::FinishEvent { handler_id });
}
}
impl UserData for LuaPlayer {
@ -153,6 +163,14 @@ impl UserData for LuaPlayer {
this.warp(warp_id);
Ok(())
});
methods.add_method_mut("begin_log_out", |_, this, _: ()| {
this.begin_log_out();
Ok(())
});
methods.add_method_mut("finish_event", |_, this, handler_id: u32| {
this.finish_event(handler_id);
Ok(())
});
}
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {