mirror of
https://github.com/redstrate/Kawari.git
synced 2025-05-12 14:47:46 +00:00
Begin scripting the inn NPCs
This kinda works, you can now talk to them without locking up your character but you aren't warped yet. I also need to clean up the mess of the Lua API.
This commit is contained in:
parent
85a2abb49e
commit
3139d63b91
7 changed files with 216 additions and 6 deletions
|
@ -154,6 +154,16 @@
|
|||
"name": "Delete",
|
||||
"opcode": 149,
|
||||
"size": 8
|
||||
},
|
||||
{
|
||||
"name": "EventFinish",
|
||||
"opcode": 375,
|
||||
"size": 16
|
||||
},
|
||||
{
|
||||
"name": "Unk18",
|
||||
"opcode": 116,
|
||||
"size": 16
|
||||
}
|
||||
],
|
||||
"ClientZoneIpcType": [
|
||||
|
@ -266,6 +276,16 @@
|
|||
"name": "ItemOperation",
|
||||
"opcode": 583,
|
||||
"size": 48
|
||||
},
|
||||
{
|
||||
"name": "StartTalkEvent",
|
||||
"opcode": 300,
|
||||
"size": 16
|
||||
},
|
||||
{
|
||||
"name": "EventHandlerReturn",
|
||||
"opcode": 281,
|
||||
"size": 16
|
||||
}
|
||||
],
|
||||
"ServerChatIpcType": [
|
||||
|
|
|
@ -10,3 +10,9 @@ registerAction(9, "actions/FastBlade.lua")
|
|||
-- Items
|
||||
registerAction(6221, "items/Fantasia.lua")
|
||||
|
||||
-- Events
|
||||
registerEvent(1245185, "opening/OpeningLimsaLominsa.lua")
|
||||
registerEvent(1245186, "opening/OpeningGridania.lua")
|
||||
registerEvent(1245187, "opening/OpeningUldah.lua")
|
||||
registerEvent(131078, "warp/WarpInnGridania.lua")
|
||||
registerEvent(131079, "warp/WarpInnLimsaLominsa.lua")
|
||||
|
|
10
resources/scripts/warp/WarpInnGridania.lua
Normal file
10
resources/scripts/warp/WarpInnGridania.lua
Normal file
|
@ -0,0 +1,10 @@
|
|||
--- TODO: find a way to hardcode it this way
|
||||
EVENT_ID = 131079 -- TODO: wrong, i was testing in limsa
|
||||
|
||||
function onTalk(actorId, player)
|
||||
-- has inn access
|
||||
-- player:play_scene(131079, 00001, 1, 0)
|
||||
|
||||
-- doesn't have inn access
|
||||
player:play_scene(actorId, EVENT_ID, 00002, 8192, 0)
|
||||
end
|
10
resources/scripts/warp/WarpInnLimsaLominsa.lua
Normal file
10
resources/scripts/warp/WarpInnLimsaLominsa.lua
Normal file
|
@ -0,0 +1,10 @@
|
|||
--- TODO: find a way to hardcode it this way
|
||||
EVENT_ID = 131079
|
||||
|
||||
function onTalk(actorId, player)
|
||||
-- has inn access
|
||||
player:play_scene(actorId, EVENT_ID, 00001, 8192, 0)
|
||||
|
||||
-- doesn't have inn access
|
||||
--player:play_scene(actorId, EVENT_ID, 00002, 8192, 0)
|
||||
end
|
|
@ -11,7 +11,7 @@ use kawari::inventory::{Inventory, Item};
|
|||
use kawari::ipc::chat::{ServerChatIpcData, ServerChatIpcSegment};
|
||||
use kawari::ipc::kawari::{CustomIpcData, CustomIpcSegment, CustomIpcType};
|
||||
use kawari::ipc::zone::{
|
||||
ActionEffect, ActionResult, ClientZoneIpcData, EffectKind, GameMasterCommandType,
|
||||
ActionEffect, ActionResult, ClientZoneIpcData, EffectKind, EventStart, GameMasterCommandType,
|
||||
GameMasterRank, OnlineStatus, ServerZoneIpcData, ServerZoneIpcSegment, SocialListRequestType,
|
||||
};
|
||||
use kawari::ipc::zone::{
|
||||
|
@ -40,6 +40,7 @@ use tokio::task::JoinHandle;
|
|||
#[derive(Default)]
|
||||
struct ExtraLuaState {
|
||||
action_scripts: HashMap<u32, String>,
|
||||
event_scripts: HashMap<u32, String>,
|
||||
}
|
||||
|
||||
fn spawn_main_loop() -> (ServerHandle, JoinHandle<()>) {
|
||||
|
@ -727,6 +728,119 @@ async fn client_loop(
|
|||
connection.player_data.inventory.process_action(action);
|
||||
connection.send_inventory(true).await;
|
||||
}
|
||||
ClientZoneIpcData::StartTalkEvent { actor_id, event_id } => {
|
||||
// load scene
|
||||
{
|
||||
let ipc = ServerZoneIpcSegment {
|
||||
op_code: ServerZoneIpcType::EventStart,
|
||||
timestamp: timestamp_secs(),
|
||||
data: ServerZoneIpcData::EventStart(EventStart {
|
||||
target_id: *actor_id,
|
||||
event_id: *event_id,
|
||||
event_type: 1, // talk?
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
dbg!(&ipc);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
let lua = lua.lock().unwrap();
|
||||
let state = lua.app_data_ref::<ExtraLuaState>().unwrap();
|
||||
|
||||
if let Some(event_script) =
|
||||
state.event_scripts.get(&event_id)
|
||||
{
|
||||
// run script
|
||||
lua.scope(|scope| {
|
||||
let connection_data = scope
|
||||
.create_userdata_ref_mut(&mut lua_player)
|
||||
.unwrap();
|
||||
|
||||
let config = get_config();
|
||||
|
||||
let file_name = format!(
|
||||
"{}/{}",
|
||||
&config.world.scripts_location, event_script
|
||||
);
|
||||
lua.load(
|
||||
std::fs::read(&file_name)
|
||||
.expect("Failed to locate scripts directory!"),
|
||||
)
|
||||
.set_name("@".to_string() + &file_name)
|
||||
.exec()
|
||||
.unwrap();
|
||||
|
||||
let func: Function =
|
||||
lua.globals().get("onTalk").unwrap();
|
||||
|
||||
func.call::<()>((actor_id.object_id.0, &connection_data))
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
} else {
|
||||
tracing::warn!("Event {event_id} isn't scripted yet! Ignoring...");
|
||||
}
|
||||
}
|
||||
ClientZoneIpcData::EventHandlerReturn { handler_id, scene, error_code, num_results, results } => {
|
||||
tracing::info!("Finishing this event... {handler_id} {scene} {error_code} {num_results} {results:#?}");
|
||||
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SegmentData::KeepAliveRequest { id, timestamp } => {
|
||||
|
@ -1038,10 +1152,22 @@ async fn main() {
|
|||
})
|
||||
.unwrap();
|
||||
|
||||
let register_event_func = lua
|
||||
.create_function(|lua, (event_id, event_script): (u32, String)| {
|
||||
tracing::info!("Registering {event_id} with {event_script}!");
|
||||
let mut state = lua.app_data_mut::<ExtraLuaState>().unwrap();
|
||||
let _ = state.event_scripts.insert(event_id, event_script);
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
lua.set_app_data(ExtraLuaState::default());
|
||||
lua.globals()
|
||||
.set("registerAction", register_action_func)
|
||||
.unwrap();
|
||||
lua.globals()
|
||||
.set("registerEvent", register_event_func)
|
||||
.unwrap();
|
||||
|
||||
let effectsbuilder_constructor = lua
|
||||
.create_function(|_, ()| Ok(EffectsBuilder::default()))
|
||||
|
|
|
@ -76,6 +76,7 @@ pub use item_operation::ItemOperation;
|
|||
mod equip;
|
||||
pub use equip::Equip;
|
||||
|
||||
use crate::common::ObjectTypeId;
|
||||
use crate::common::Position;
|
||||
use crate::common::read_string;
|
||||
use crate::common::write_string;
|
||||
|
@ -220,6 +221,19 @@ pub enum ServerZoneIpcData {
|
|||
#[brw(pad_before = 3)] // padding
|
||||
actor_id: u32,
|
||||
},
|
||||
/// Sent to the client to stop their currently playing event.
|
||||
EventFinish {
|
||||
handler_id: u32,
|
||||
event: u8,
|
||||
result: u8,
|
||||
#[brw(pad_before = 2)] // padding
|
||||
#[brw(pad_after = 4)] // padding
|
||||
arg: u32,
|
||||
},
|
||||
/// Sent after EventFinish? it un-occupies the character lol
|
||||
Unk18 {
|
||||
unk: [u8; 16], // all zero...
|
||||
},
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
|
@ -354,6 +368,21 @@ pub enum ClientZoneIpcData {
|
|||
},
|
||||
#[br(pre_assert(*magic == ClientZoneIpcType::ItemOperation))]
|
||||
ItemOperation(ItemOperation),
|
||||
#[br(pre_assert(*magic == ClientZoneIpcType::StartTalkEvent))]
|
||||
StartTalkEvent {
|
||||
actor_id: ObjectTypeId,
|
||||
#[brw(pad_after = 4)] // padding
|
||||
event_id: u32,
|
||||
},
|
||||
#[br(pre_assert(*magic == ClientZoneIpcType::EventHandlerReturn))]
|
||||
EventHandlerReturn {
|
||||
handler_id: u32,
|
||||
scene: u16,
|
||||
error_code: u8,
|
||||
num_results: u8,
|
||||
#[brw(pad_after = 4)] // padding
|
||||
results: [u32; 1],
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -53,14 +53,21 @@ impl LuaPlayer {
|
|||
self.status_effects.add(effect_id, duration);
|
||||
}
|
||||
|
||||
fn play_scene(&mut self, event_id: u32, scene: u16, scene_flags: u32, param: u8) {
|
||||
fn play_scene(
|
||||
&mut self,
|
||||
actor_id: u32,
|
||||
event_id: u32,
|
||||
scene: u16,
|
||||
scene_flags: u32,
|
||||
param: u8,
|
||||
) {
|
||||
let ipc = ServerZoneIpcSegment {
|
||||
op_code: ServerZoneIpcType::EventScene,
|
||||
timestamp: timestamp_secs(),
|
||||
data: ServerZoneIpcData::EventScene(EventScene {
|
||||
actor_id: ObjectTypeId {
|
||||
object_id: ObjectId(self.player_data.actor_id),
|
||||
object_type: 0,
|
||||
object_id: ObjectId(actor_id),
|
||||
object_type: 1,
|
||||
},
|
||||
event_id,
|
||||
scene,
|
||||
|
@ -71,6 +78,8 @@ impl LuaPlayer {
|
|||
..Default::default()
|
||||
};
|
||||
|
||||
dbg!(&ipc);
|
||||
|
||||
self.queue_segment(PacketSegment {
|
||||
source_actor: self.player_data.actor_id,
|
||||
target_actor: self.player_data.actor_id,
|
||||
|
@ -122,8 +131,8 @@ impl UserData for LuaPlayer {
|
|||
);
|
||||
methods.add_method_mut(
|
||||
"play_scene",
|
||||
|_, this, (event_id, scene, scene_flags, param): (u32, u16, u32, u8)| {
|
||||
this.play_scene(event_id, scene, scene_flags, param);
|
||||
|_, this, (actor_id, event_id, scene, scene_flags, param): (u32, u32, u16, u32, u8)| {
|
||||
this.play_scene(actor_id, event_id, scene, scene_flags, param);
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
|
|
Loading…
Add table
Reference in a new issue