From 961cb92ab13dfab71b8c5e097b0ef13fae5ba082 Mon Sep 17 00:00:00 2001 From: thedax Date: Thu, 19 Jun 2025 12:29:10 -0400 Subject: [PATCH] New Lua command proposal: !festival (#26) This command enables the user to set the current zone's festival. For example, you can toggle the Starlight festival in any of the starting cities. Thanks, OTCompa! --- USAGE.md | 3 +- resources/scripts/Global.lua | 1 + resources/scripts/commands/debug/Festival.lua | 35 +++++++++++++++++++ src/ipc/zone/actor_control.rs | 10 +++++- src/world/lua.rs | 23 +++++++++++- 5 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 resources/scripts/commands/debug/Festival.lua diff --git a/USAGE.md b/USAGE.md index f4b16a9..a06e080 100644 --- a/USAGE.md +++ b/USAGE.md @@ -109,7 +109,8 @@ These special debug commands start with `!` and are custom to Kawari. * `!unlockaction `: Unlock an action, for example: `1` for Return and `4` for Teleport. * `!equip `: Forcefully equip an item, useful for bypassing class/job and other client restrictions. This will *overwrite* any item in that slot! * `!nudge `: Teleport forward, back, up or down `distance` yalms. Specifying up or down will move the player up or down instead of forward or back. Examples: `!nudge 5 up` to move up 5 yalms, `!nudge 5` to move forward 5 yalms, `!nudge -5` to move backward 5 yalms. - +*`!festival `: Sets the festival in the current zone. Multiple festivals can be set together to create interesting effects. + ### GM commands These GM commands are implemented in the FFXIV protocol, but only some of them are implemented. diff --git a/resources/scripts/Global.lua b/resources/scripts/Global.lua index 045df37..fef7287 100644 --- a/resources/scripts/Global.lua +++ b/resources/scripts/Global.lua @@ -50,3 +50,4 @@ registerCommand("setpos", "commands/debug/SetPos.lua") registerCommand("classjob", "commands/debug/ClassJob.lua") registerCommand("setspeed", "commands/debug/SetSpeed.lua") registerCommand("nudge", "commands/debug/Nudge.lua") +registerCommand("festival", "commands/debug/Festival.lua") diff --git a/resources/scripts/commands/debug/Festival.lua b/resources/scripts/commands/debug/Festival.lua new file mode 100644 index 0000000..690b4c3 --- /dev/null +++ b/resources/scripts/commands/debug/Festival.lua @@ -0,0 +1,35 @@ +-- A list of festival ids can be found in Hyperborea's source tree: +-- https://github.com/kawaii/Hyperborea/blob/main/Hyperborea/festivals.yaml + +function onCommand(args, player) + local parts = split(args) + local argc = table.getn(parts) + local usage = "\nUsage: !festival " + local sender = "[festival] " + + local id1 = tonumber(parts[1]) + local id2 = tonumber(parts[2]) + local id3 = tonumber(parts[3]) + local id4 = tonumber(parts[4]) + + if not id1 then + player:send_message(sender.."At least one festival must be specified (for now, until the server has support for commands with no args)."..usage) + return + end + + if not id2 then + id2 = 0 + end + + if not id3 then + id3 = 0 + end + + if not id4 then + id4 = 0 + end + + player:set_festival(id1, id2, id3, id4) + local message = string.format("Festival(s) changed to %s, %s, %s and %s.", id1, id2, id3, id4) + player:send_message(message) +end diff --git a/src/ipc/zone/actor_control.rs b/src/ipc/zone/actor_control.rs index 7e375b1..f2d6cf9 100644 --- a/src/ipc/zone/actor_control.rs +++ b/src/ipc/zone/actor_control.rs @@ -73,7 +73,15 @@ pub enum ActorControlCategory { Flee { #[brw(pad_before = 2)] // padding speed: u16, - } + }, + #[brw(magic=0x386u16)] + SetFestival { + #[brw(pad_before = 2)] // padding + festival1: u32, // Multiple festivals can be set at the same time. + festival2: u32, + festival3: u32, + festival4: u32, + }, } #[binrw] diff --git a/src/world/lua.rs b/src/world/lua.rs index f7d2c23..5acc8a6 100644 --- a/src/world/lua.rs +++ b/src/world/lua.rs @@ -7,7 +7,7 @@ use crate::{ }, ipc::zone::{ ActionEffect, DamageElement, DamageKind, DamageType, EffectKind, EventScene, - ServerZoneIpcData, ServerZoneIpcSegment, Warp, + ServerZoneIpcData, ServerZoneIpcSegment, Warp, ActorControlSelf, ActorControlCategory }, opcodes::ServerZoneIpcType, packet::{PacketSegment, SegmentData, SegmentType}, @@ -104,6 +104,20 @@ impl LuaPlayer { self.create_segment_self(op_code, data); } + fn set_festival(&mut self, festival1: u32, festival2: u32, festival3: u32, festival4: u32) { + let op_code = ServerZoneIpcType::ActorControlSelf; + let data = ServerZoneIpcData::ActorControlSelf(ActorControlSelf { + category: ActorControlCategory::SetFestival { + festival1, + festival2, + festival3, + festival4 + }, + }); + + self.create_segment_self(op_code, data); + } + fn change_territory(&mut self, zone_id: u16) { self.queued_tasks.push(Task::ChangeTerritory { zone_id }); } @@ -162,6 +176,13 @@ impl UserData for LuaPlayer { Ok(()) }, ); + methods.add_method_mut( + "set_festival", + |_, this, (festival1, festival2, festival3, festival4): (u32, u32, u32, u32)| { + this.set_festival(festival1, festival2, festival3, festival4); + Ok(()) + }, + ); methods.add_method_mut("change_territory", |_, this, zone_id: u16| { this.change_territory(zone_id); Ok(())