mirror of
https://github.com/redstrate/Kawari.git
synced 2025-05-12 14:47:46 +00:00
Add script for the Teleport action
This makes the Teleport action functional now, although it looks pretty rough as it warps you instantly instead of waiting for the action to actually finish.
This commit is contained in:
parent
1914531d89
commit
94ed036431
12 changed files with 134 additions and 15 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -575,7 +575,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "icarus"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/redstrate/Icarus?branch=ver%2F2025.04.16.0000.0000#5d5f1dded6949b790307546c9ddc0604af636451"
|
||||
source = "git+https://github.com/redstrate/Icarus?branch=ver%2F2025.04.16.0000.0000#76c7c6c18bee63927fc723d4a99e2e1fba96fcb9"
|
||||
dependencies = [
|
||||
"physis",
|
||||
]
|
||||
|
@ -1025,7 +1025,7 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
|||
[[package]]
|
||||
name = "physis"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/redstrate/physis#309726163a0d76f26831236f43740a2c8bd1b01d"
|
||||
source = "git+https://github.com/redstrate/physis#76120b2dd0843c16af648f7b18ba0f92c5d56460"
|
||||
dependencies = [
|
||||
"binrw",
|
||||
"bitflags",
|
||||
|
@ -1472,9 +1472,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tower-http"
|
||||
version = "0.6.2"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "403fa3b783d4b626a8ad51d766ab03cb6d2dbfc46b1c5d4448395e6628dc9697"
|
||||
checksum = "0fdb0c213ca27a9f57ab69ddb290fd80d970922355b83ae380b395d3986b8a2e"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bytes",
|
||||
|
|
|
@ -104,4 +104,4 @@ rkon = { version = "0.1" }
|
|||
tower-http = { version = "0.6", features = ["fs"] }
|
||||
|
||||
# excel sheet data
|
||||
icarus = { git = "https://github.com/redstrate/Icarus", branch = "ver/2025.04.16.0000.0000", features = ["Warp", "Tribe", "ClassJob", "World", "TerritoryType", "Race"], default-features = false }
|
||||
icarus = { git = "https://github.com/redstrate/Icarus", branch = "ver/2025.04.16.0000.0000", features = ["Warp", "Tribe", "ClassJob", "World", "TerritoryType", "Race", "Aetheryte"], default-features = false }
|
||||
|
|
|
@ -20,6 +20,7 @@ end
|
|||
|
||||
-- Actions
|
||||
registerAction(3, "actions/Sprint.lua")
|
||||
registerAction(5, "actions/Teleport.lua")
|
||||
registerAction(9, "actions/FastBlade.lua")
|
||||
|
||||
-- Items
|
||||
|
|
11
resources/scripts/actions/Teleport.lua
Normal file
11
resources/scripts/actions/Teleport.lua
Normal file
|
@ -0,0 +1,11 @@
|
|||
function doAction(player)
|
||||
effects = EffectsBuilder()
|
||||
|
||||
-- get the aetheryte they requested
|
||||
local id = player.teleport_query.aetheryte_id
|
||||
|
||||
-- warp there
|
||||
player:warp_aetheryte(id)
|
||||
|
||||
return effects
|
||||
end
|
|
@ -9,9 +9,9 @@ use kawari::config::get_config;
|
|||
use kawari::inventory::Item;
|
||||
use kawari::ipc::chat::{ServerChatIpcData, ServerChatIpcSegment};
|
||||
use kawari::ipc::zone::{
|
||||
ActionEffect, ActionResult, ClientZoneIpcData, CommonSpawn, EffectKind, EventStart,
|
||||
GameMasterCommandType, GameMasterRank, OnlineStatus, ServerZoneIpcData, ServerZoneIpcSegment,
|
||||
SocialListRequestType,
|
||||
ActionEffect, ActionResult, ClientTriggerCommand, ClientZoneIpcData, CommonSpawn, EffectKind,
|
||||
EventStart, GameMasterCommandType, GameMasterRank, OnlineStatus, ServerZoneIpcData,
|
||||
ServerZoneIpcSegment, SocialListRequestType,
|
||||
};
|
||||
use kawari::ipc::zone::{
|
||||
ActorControlCategory, ActorControlSelf, PlayerEntry, PlayerSpawn, PlayerStatus, SocialList,
|
||||
|
@ -371,6 +371,11 @@ async fn client_loop(
|
|||
connection.exit_rotation = None;
|
||||
}
|
||||
ClientZoneIpcData::ClientTrigger(trigger) => {
|
||||
// store the query for scripts
|
||||
if let ClientTriggerCommand::TeleportQuery { aetheryte_id } = trigger.trigger {
|
||||
connection.player_data.teleport_query.aetheryte_id = aetheryte_id as u16;
|
||||
}
|
||||
|
||||
// inform the server of our trigger, it will handle sending it to other clients
|
||||
connection.handle.send(ToServer::ClientTrigger(connection.id, connection.player_data.actor_id, trigger.clone())).await;
|
||||
}
|
||||
|
@ -851,6 +856,7 @@ async fn client_loop(
|
|||
FromServer::ActorControl(actor_id, actor_control) => connection.actor_control(actor_id, actor_control).await,
|
||||
FromServer::ActorControlTarget(actor_id, actor_control) => connection.actor_control_target(actor_id, actor_control).await,
|
||||
FromServer::SpawnNPC(npc) => connection.send_npc(npc).await,
|
||||
FromServer::ActorControlSelf(actor_control) => connection.actor_control_self(actor_control).await,
|
||||
},
|
||||
None => break,
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use icarus::Aetheryte::AetheryteSheet;
|
||||
use icarus::ClassJob::ClassJobSheet;
|
||||
use icarus::World::WorldSheet;
|
||||
use icarus::{Tribe::TribeSheet, Warp::WarpSheet};
|
||||
|
@ -106,4 +107,15 @@ impl GameData {
|
|||
|
||||
Some((*pop_range_id, *zone_id))
|
||||
}
|
||||
|
||||
pub fn get_aetheryte(&mut self, aetheryte_id: u32) -> Option<(u32, u16)> {
|
||||
let sheet = AetheryteSheet::read_from(&mut self.game_data, Language::English)?;
|
||||
let row = sheet.get_row(aetheryte_id)?;
|
||||
|
||||
// TODO: just look in the level sheet?
|
||||
let pop_range_id = row.Level()[0].into_u32()?;
|
||||
let zone_id = row.Territory().into_u16()?;
|
||||
|
||||
Some((*pop_range_id, *zone_id))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,12 @@ pub enum ActorControlCategory {
|
|||
#[bw(map = write_bool_as::<u32>)]
|
||||
unlocked: bool,
|
||||
},
|
||||
#[brw(magic = 0xCBu16)]
|
||||
TeleportStart {
|
||||
#[brw(pad_before = 2)] //padding
|
||||
insufficient_gil: u32,
|
||||
aetheryte_id: u32,
|
||||
},
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
|
|
|
@ -24,6 +24,12 @@ pub enum ClientTriggerCommand {
|
|||
unk1: u32,
|
||||
pose: u32,
|
||||
},
|
||||
#[brw(magic = 0xCAu16)]
|
||||
TeleportQuery {
|
||||
#[brw(pad_before = 2)]
|
||||
aetheryte_id: u32,
|
||||
// TODO: fill out the rest
|
||||
},
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
|
|
|
@ -10,7 +10,9 @@ use tokio::sync::mpsc::Sender;
|
|||
|
||||
use crate::{
|
||||
common::Position,
|
||||
ipc::zone::{ActorControl, ActorControlTarget, ClientTrigger, CommonSpawn, NpcSpawn},
|
||||
ipc::zone::{
|
||||
ActorControl, ActorControlSelf, ActorControlTarget, ClientTrigger, CommonSpawn, NpcSpawn,
|
||||
},
|
||||
};
|
||||
|
||||
use super::Actor;
|
||||
|
@ -29,8 +31,10 @@ pub enum FromServer {
|
|||
ActorDespawn(u32),
|
||||
/// We need to update an actor
|
||||
ActorControl(u32, ActorControl),
|
||||
/// We need to update an actor's target'
|
||||
/// We need to update an actor's target
|
||||
ActorControlTarget(u32, ActorControlTarget),
|
||||
/// We need to update the player actor
|
||||
ActorControlSelf(ActorControlSelf),
|
||||
/// Spawn an NPC
|
||||
SpawnNPC(NpcSpawn),
|
||||
}
|
||||
|
|
|
@ -32,6 +32,11 @@ use super::{
|
|||
lua::Task,
|
||||
};
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct TeleportQuery {
|
||||
pub aetheryte_id: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct PlayerData {
|
||||
// Static data
|
||||
|
@ -52,6 +57,8 @@ pub struct PlayerData {
|
|||
pub rotation: f32,
|
||||
pub zone_id: u16,
|
||||
pub inventory: Inventory,
|
||||
|
||||
pub teleport_query: TeleportQuery,
|
||||
}
|
||||
|
||||
/// Represents a single connection between an instance of the client and the world server
|
||||
|
@ -363,6 +370,35 @@ impl ZoneConnection {
|
|||
self.change_zone(territory_type as u16).await;
|
||||
}
|
||||
|
||||
pub async fn warp_aetheryte(&mut self, aetheryte_id: u32) {
|
||||
tracing::info!("Warping to aetheryte {}", aetheryte_id);
|
||||
|
||||
let territory_type;
|
||||
// find the pop range on the other side
|
||||
{
|
||||
let mut game_data = self.gamedata.lock().unwrap();
|
||||
let (pop_range_id, zone_id) = game_data
|
||||
.get_aetheryte(aetheryte_id)
|
||||
.expect("Failed to find the aetheryte!");
|
||||
|
||||
let new_zone = Zone::load(&mut game_data.game_data, zone_id);
|
||||
|
||||
// find it on the other side
|
||||
let (object, _) = new_zone.find_pop_range(pop_range_id).unwrap();
|
||||
|
||||
// set the exit position
|
||||
self.exit_position = Some(Position {
|
||||
x: object.transform.translation[0],
|
||||
y: object.transform.translation[1],
|
||||
z: object.transform.translation[2],
|
||||
});
|
||||
|
||||
territory_type = zone_id;
|
||||
}
|
||||
|
||||
self.change_zone(territory_type as u16).await;
|
||||
}
|
||||
|
||||
pub async fn change_weather(&mut self, new_weather_id: u16) {
|
||||
let ipc = ServerZoneIpcSegment {
|
||||
op_code: ServerZoneIpcType::WeatherId,
|
||||
|
@ -519,6 +555,9 @@ impl ZoneConnection {
|
|||
self.player_data.classjob_id = *classjob_id;
|
||||
self.update_class_info().await;
|
||||
}
|
||||
Task::WarpAetheryte { aetheryte_id } => {
|
||||
self.warp_aetheryte(*aetheryte_id).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
player.queued_tasks.clear();
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
packet::{PacketSegment, SegmentData, SegmentType},
|
||||
};
|
||||
|
||||
use super::{PlayerData, StatusEffects, Zone};
|
||||
use super::{PlayerData, StatusEffects, Zone, connection::TeleportQuery};
|
||||
|
||||
pub enum Task {
|
||||
ChangeTerritory { zone_id: u16 },
|
||||
|
@ -19,6 +19,7 @@ pub enum Task {
|
|||
BeginLogOut,
|
||||
FinishEvent { handler_id: u32 },
|
||||
SetClassJob { classjob_id: u8 },
|
||||
WarpAetheryte { aetheryte_id: u32 },
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -129,6 +130,10 @@ impl LuaPlayer {
|
|||
fn set_classjob(&mut self, classjob_id: u8) {
|
||||
self.queued_tasks.push(Task::SetClassJob { classjob_id });
|
||||
}
|
||||
|
||||
fn warp_aetheryte(&mut self, aetheryte_id: u32) {
|
||||
self.queued_tasks.push(Task::WarpAetheryte { aetheryte_id });
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for LuaPlayer {
|
||||
|
@ -181,6 +186,10 @@ impl UserData for LuaPlayer {
|
|||
this.set_classjob(classjob_id);
|
||||
Ok(())
|
||||
});
|
||||
methods.add_method_mut("warp_aetheryte", |_, this, aetheryte_id: u32| {
|
||||
this.warp_aetheryte(aetheryte_id);
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
|
@ -190,6 +199,16 @@ impl UserData for LuaPlayer {
|
|||
object_type: 0,
|
||||
})
|
||||
});
|
||||
|
||||
fields.add_field_method_get("teleport_query", |_, this| {
|
||||
Ok(this.player_data.teleport_query.clone())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for TeleportQuery {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("aetheryte_id", |_, this| Ok(this.aetheryte_id));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use tokio::sync::mpsc::Receiver;
|
|||
use crate::{
|
||||
common::{ObjectId, Position},
|
||||
ipc::zone::{
|
||||
ActorControl, ActorControlCategory, ActorControlTarget, BattleNpcSubKind,
|
||||
ActorControl, ActorControlCategory, ActorControlSelf, ActorControlTarget, BattleNpcSubKind,
|
||||
ClientTriggerCommand, CommonSpawn, NpcSpawn, ObjectKind,
|
||||
},
|
||||
};
|
||||
|
@ -208,13 +208,28 @@ pub async fn server_main_loop(mut recv: Receiver<ToServer>) -> Result<(), std::i
|
|||
for (id, (handle, _)) in &mut data.clients {
|
||||
let id = *id;
|
||||
|
||||
// there's no reason to tell the actor what it just did
|
||||
tracing::info!("{:#?}", trigger);
|
||||
|
||||
// handle player-to-server actions
|
||||
if id == from_id {
|
||||
match &trigger.trigger {
|
||||
ClientTriggerCommand::TeleportQuery { aetheryte_id } => {
|
||||
let msg = FromServer::ActorControlSelf(ActorControlSelf {
|
||||
category: ActorControlCategory::TeleportStart {
|
||||
insufficient_gil: 0,
|
||||
aetheryte_id: *aetheryte_id,
|
||||
},
|
||||
});
|
||||
|
||||
if handle.send(msg).is_err() {
|
||||
to_remove.push(id);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
tracing::info!("{:#?}", trigger);
|
||||
|
||||
match &trigger.trigger {
|
||||
ClientTriggerCommand::SetTarget { actor_id } => {
|
||||
let msg = FromServer::ActorControlTarget(
|
||||
|
|
Loading…
Add table
Reference in a new issue