mirror of
https://github.com/redstrate/Kawari.git
synced 2025-04-26 16:37:46 +00:00
Add basic Event scripting capaibilities
This implements the first event script, going from the first Ul'dah opening cutscene to the next.
This commit is contained in:
parent
bcbe62af06
commit
c4b9ad060b
8 changed files with 142 additions and 38 deletions
21
resources/scripts/opening/OpeningUldah.lua
Normal file
21
resources/scripts/opening/OpeningUldah.lua
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
--- TODO: find a way to hardcode it this way
|
||||||
|
EVENT_ID = 1245187
|
||||||
|
|
||||||
|
function Scene00000(player)
|
||||||
|
player:play_scene(EVENT_ID, 00000, 4959237, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Scene00001(player)
|
||||||
|
--- todo put player in correct position
|
||||||
|
player:play_scene(EVENT_ID, 00001, 4959237, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
function onEnterTerritory(player)
|
||||||
|
Scene00000(player);
|
||||||
|
end
|
||||||
|
|
||||||
|
function onSceneFinished(player, scene)
|
||||||
|
if scene == 0 then
|
||||||
|
Scene00001(player)
|
||||||
|
end
|
||||||
|
end
|
|
@ -76,6 +76,7 @@ async fn main() {
|
||||||
position: Position::default(),
|
position: Position::default(),
|
||||||
inventory: Inventory::new(),
|
inventory: Inventory::new(),
|
||||||
status_effects: StatusEffects::default(),
|
status_effects: StatusEffects::default(),
|
||||||
|
event: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut lua_player = LuaPlayer::default();
|
let mut lua_player = LuaPlayer::default();
|
||||||
|
@ -570,6 +571,7 @@ async fn main() {
|
||||||
ClientZoneIpcData::ChatMessage(chat_message) => {
|
ClientZoneIpcData::ChatMessage(chat_message) => {
|
||||||
ChatHandler::handle_chat_message(
|
ChatHandler::handle_chat_message(
|
||||||
&mut connection,
|
&mut connection,
|
||||||
|
&mut lua_player,
|
||||||
chat_message,
|
chat_message,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
@ -754,6 +756,10 @@ async fn main() {
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
"Recieved EventRelatedUnk! {unk1} {unk2} {unk3} {unk4}"
|
"Recieved EventRelatedUnk! {unk1} {unk2} {unk3} {unk4}"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if let Some(event) = connection.event.as_mut() {
|
||||||
|
event.scene_finished(&mut lua_player, *unk2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,17 @@ use crate::{
|
||||||
config::get_config,
|
config::get_config,
|
||||||
opcodes::ServerZoneIpcType,
|
opcodes::ServerZoneIpcType,
|
||||||
packet::{PacketSegment, SegmentType},
|
packet::{PacketSegment, SegmentType},
|
||||||
world::ipc::{
|
world::{
|
||||||
ActorControl, ActorControlCategory, BattleNpcSubKind, CommonSpawn, DisplayFlag, EventPlay,
|
Event,
|
||||||
EventStart, NpcSpawn, ObjectKind, OnlineStatus, PlayerSpawn, PlayerSubKind,
|
ipc::{
|
||||||
ServerZoneIpcData, ServerZoneIpcSegment,
|
ActorControl, ActorControlCategory, BattleNpcSubKind, CommonSpawn, DisplayFlag,
|
||||||
|
EventPlay, EventStart, NpcSpawn, ObjectKind, OnlineStatus, PlayerSpawn, PlayerSubKind,
|
||||||
|
ServerZoneIpcData, ServerZoneIpcSegment,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{ZoneConnection, ipc::ChatMessage};
|
use super::{LuaPlayer, ZoneConnection, ipc::ChatMessage};
|
||||||
|
|
||||||
pub const CUSTOMIZE_DATA: CustomizeData = CustomizeData {
|
pub const CUSTOMIZE_DATA: CustomizeData = CustomizeData {
|
||||||
race: 4,
|
race: 4,
|
||||||
|
@ -44,7 +47,11 @@ pub const CUSTOMIZE_DATA: CustomizeData = CustomizeData {
|
||||||
pub struct ChatHandler {}
|
pub struct ChatHandler {}
|
||||||
|
|
||||||
impl ChatHandler {
|
impl ChatHandler {
|
||||||
pub async fn handle_chat_message(connection: &mut ZoneConnection, chat_message: &ChatMessage) {
|
pub async fn handle_chat_message(
|
||||||
|
connection: &mut ZoneConnection,
|
||||||
|
lua_player: &mut LuaPlayer,
|
||||||
|
chat_message: &ChatMessage,
|
||||||
|
) {
|
||||||
tracing::info!("Client sent chat message: {}!", chat_message.message);
|
tracing::info!("Client sent chat message: {}!", chat_message.message);
|
||||||
|
|
||||||
let parts: Vec<&str> = chat_message.message.split(' ').collect();
|
let parts: Vec<&str> = chat_message.message.split(' ').collect();
|
||||||
|
@ -322,34 +329,12 @@ impl ChatHandler {
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
// play the scene, bart
|
connection.event = Some(Event::new("opening/OpeningUldah.lua"));
|
||||||
{
|
connection
|
||||||
let ipc = ServerZoneIpcSegment {
|
.event
|
||||||
unk1: 20,
|
.as_mut()
|
||||||
unk2: 0,
|
.unwrap()
|
||||||
op_code: ServerZoneIpcType::EventPlay,
|
.enter_territory(lua_player);
|
||||||
server_id: 0,
|
|
||||||
timestamp: timestamp_secs(),
|
|
||||||
data: ServerZoneIpcData::EventPlay(EventPlay {
|
|
||||||
actor_id: ObjectTypeId {
|
|
||||||
object_id: ObjectId(connection.player_data.actor_id),
|
|
||||||
object_type: 0,
|
|
||||||
},
|
|
||||||
event_id: 0x130003,
|
|
||||||
scene: 1,
|
|
||||||
scene_flags: 4959237,
|
|
||||||
..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: ipc },
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => tracing::info!("Unrecognized debug command!"),
|
_ => tracing::info!("Unrecognized debug command!"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Inventory, Item, LuaPlayer, Zone,
|
Event, Inventory, Item, LuaPlayer, Zone,
|
||||||
ipc::{
|
ipc::{
|
||||||
ActorSetPos, ClientZoneIpcSegment, ContainerInfo, ContainerType, InitZone, ItemInfo,
|
ActorSetPos, ClientZoneIpcSegment, ContainerInfo, ContainerType, InitZone, ItemInfo,
|
||||||
ServerZoneIpcData, ServerZoneIpcSegment, StatusEffect, StatusEffectList, UpdateClassInfo,
|
ServerZoneIpcData, ServerZoneIpcSegment, StatusEffect, StatusEffectList, UpdateClassInfo,
|
||||||
|
@ -69,6 +69,8 @@ pub struct ZoneConnection {
|
||||||
pub position: Position,
|
pub position: Position,
|
||||||
pub inventory: Inventory,
|
pub inventory: Inventory,
|
||||||
pub status_effects: StatusEffects,
|
pub status_effects: StatusEffects,
|
||||||
|
|
||||||
|
pub event: Option<Event>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ZoneConnection {
|
impl ZoneConnection {
|
||||||
|
|
52
src/world/event.rs
Normal file
52
src/world/event.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
use mlua::{Function, Lua};
|
||||||
|
|
||||||
|
use crate::config::get_config;
|
||||||
|
|
||||||
|
use super::LuaPlayer;
|
||||||
|
|
||||||
|
pub struct Event {
|
||||||
|
lua: Lua,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Event {
|
||||||
|
pub fn new(path: &str) -> Self {
|
||||||
|
let lua = Lua::new();
|
||||||
|
|
||||||
|
let config = get_config();
|
||||||
|
let file_name = format!("{}/{}", &config.world.scripts_location, path);
|
||||||
|
lua.load(std::fs::read(&file_name).expect("Failed to locate scripts directory!"))
|
||||||
|
.set_name("@".to_string() + &file_name)
|
||||||
|
.exec()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Self { lua }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enter_territory(&mut self, player: &mut LuaPlayer) {
|
||||||
|
self.lua
|
||||||
|
.scope(|scope| {
|
||||||
|
let player = scope.create_userdata_ref_mut(player).unwrap();
|
||||||
|
|
||||||
|
let func: Function = self.lua.globals().get("onEnterTerritory").unwrap();
|
||||||
|
|
||||||
|
func.call::<()>(player).unwrap();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scene_finished(&mut self, player: &mut LuaPlayer, scene: u16) {
|
||||||
|
self.lua
|
||||||
|
.scope(|scope| {
|
||||||
|
let player = scope.create_userdata_ref_mut(player).unwrap();
|
||||||
|
|
||||||
|
let func: Function = self.lua.globals().get("onSceneFinished").unwrap();
|
||||||
|
|
||||||
|
func.call::<()>((player, scene)).unwrap();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
|
@ -337,7 +337,8 @@ pub enum ClientZoneIpcData {
|
||||||
#[br(pre_assert(*magic == ClientZoneIpcType::EventRelatedUnk))]
|
#[br(pre_assert(*magic == ClientZoneIpcType::EventRelatedUnk))]
|
||||||
EventRelatedUnk {
|
EventRelatedUnk {
|
||||||
unk1: u32,
|
unk1: u32,
|
||||||
unk2: u32,
|
unk2: u16,
|
||||||
|
#[brw(pad_before = 2)]
|
||||||
unk3: u32,
|
unk3: u32,
|
||||||
unk4: u32,
|
unk4: u32,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
use mlua::{UserData, UserDataMethods};
|
use mlua::{UserData, UserDataMethods};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::timestamp_secs,
|
common::{ObjectId, ObjectTypeId, timestamp_secs},
|
||||||
opcodes::ServerZoneIpcType,
|
opcodes::ServerZoneIpcType,
|
||||||
packet::{PacketSegment, SegmentType},
|
packet::{PacketSegment, SegmentType},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
PlayerData, StatusEffects,
|
PlayerData, StatusEffects,
|
||||||
ipc::{ServerZoneIpcData, ServerZoneIpcSegment},
|
ipc::{EventPlay, ServerZoneIpcData, ServerZoneIpcSegment},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -44,6 +44,33 @@ impl LuaPlayer {
|
||||||
fn give_status_effect(&mut self, effect_id: u16, duration: f32) {
|
fn give_status_effect(&mut self, effect_id: u16, duration: f32) {
|
||||||
self.status_effects.add(effect_id, duration);
|
self.status_effects.add(effect_id, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn play_scene(&mut self, event_id: u32, scene: u16, scene_flags: u32, param: u8) {
|
||||||
|
let ipc = ServerZoneIpcSegment {
|
||||||
|
unk1: 20,
|
||||||
|
unk2: 0,
|
||||||
|
op_code: ServerZoneIpcType::EventPlay,
|
||||||
|
server_id: 0,
|
||||||
|
timestamp: timestamp_secs(),
|
||||||
|
data: ServerZoneIpcData::EventPlay(EventPlay {
|
||||||
|
actor_id: ObjectTypeId {
|
||||||
|
object_id: ObjectId(self.player_data.actor_id),
|
||||||
|
object_type: 0,
|
||||||
|
},
|
||||||
|
event_id,
|
||||||
|
scene,
|
||||||
|
scene_flags,
|
||||||
|
unk2: param,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.queue_segment(PacketSegment {
|
||||||
|
source_actor: self.player_data.actor_id,
|
||||||
|
target_actor: self.player_data.actor_id,
|
||||||
|
segment_type: SegmentType::Ipc { data: ipc },
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserData for LuaPlayer {
|
impl UserData for LuaPlayer {
|
||||||
|
@ -59,5 +86,12 @@ impl UserData for LuaPlayer {
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
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);
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,3 +17,6 @@ pub use inventory::{EquippedContainer, Inventory, Item};
|
||||||
|
|
||||||
mod lua;
|
mod lua;
|
||||||
pub use lua::LuaPlayer;
|
pub use lua::LuaPlayer;
|
||||||
|
|
||||||
|
mod event;
|
||||||
|
pub use event::Event;
|
||||||
|
|
Loading…
Add table
Reference in a new issue