mirror of
https://github.com/redstrate/Kawari.git
synced 2025-05-12 22:57:45 +00:00
Add commands to unlock actions, and aetherytes
This doesn't mean teleporting works *yet*, as it needs to be scripted. The unlocked action/aetheryte is also not persisted yet.
This commit is contained in:
parent
1605098c2e
commit
1914531d89
5 changed files with 40 additions and 3 deletions
2
USAGE.md
2
USAGE.md
|
@ -87,6 +87,7 @@ These special debug commands start with `!` and are custom to Kawari.
|
||||||
* Territory `183`, Event `1245186` plays the Gridania opening sequence
|
* Territory `183`, Event `1245186` plays the Gridania opening sequence
|
||||||
* `!spawnclone`: Spawn a clone of yourself
|
* `!spawnclone`: Spawn a clone of yourself
|
||||||
* `!classjob <id>`: Changes to another class/job
|
* `!classjob <id>`: Changes to another class/job
|
||||||
|
* `!unlockaction <id>`: Unlock an action, for example: `1` for Return and `4` for Teleport.
|
||||||
|
|
||||||
### GM commands
|
### GM commands
|
||||||
|
|
||||||
|
@ -97,3 +98,4 @@ These GM commands are implemented in the FFXIV protocol, but only some of them a
|
||||||
* `//gm wireframe`: Toggle wireframe rendering for the environment
|
* `//gm wireframe`: Toggle wireframe rendering for the environment
|
||||||
* `//gm item <id>`: Gives yourself an item. This can only place a single item in the first page of your inventory currently.
|
* `//gm item <id>`: Gives yourself an item. This can only place a single item in the first page of your inventory currently.
|
||||||
* `//gm lv <level>`: Sets your current level
|
* `//gm lv <level>`: Sets your current level
|
||||||
|
* `//gm aetheryte <on/off> <id>`: Unlock an Aetheryte.
|
||||||
|
|
|
@ -521,7 +521,7 @@ async fn client_loop(
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClientZoneIpcData::GMCommand { command, arg0, .. } => {
|
ClientZoneIpcData::GMCommand { command, arg0, arg1, .. } => {
|
||||||
tracing::info!("Got a game master command!");
|
tracing::info!("Got a game master command!");
|
||||||
|
|
||||||
match &command {
|
match &command {
|
||||||
|
@ -555,6 +555,13 @@ async fn client_loop(
|
||||||
connection.player_data.inventory.add_in_next_free_slot(Item { id: *arg0, quantity: 1 });
|
connection.player_data.inventory.add_in_next_free_slot(Item { id: *arg0, quantity: 1 });
|
||||||
connection.send_inventory(false).await;
|
connection.send_inventory(false).await;
|
||||||
}
|
}
|
||||||
|
GameMasterCommandType::Aetheryte => {
|
||||||
|
let on = *arg0 == 0;
|
||||||
|
let id = *arg1;
|
||||||
|
|
||||||
|
connection.actor_control_self(ActorControlSelf {
|
||||||
|
category: ActorControlCategory::LearnTeleport { id, unlocked: on } }).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClientZoneIpcData::ZoneJump {
|
ClientZoneIpcData::ZoneJump {
|
||||||
|
|
|
@ -47,6 +47,22 @@ pub enum ActorControlCategory {
|
||||||
unk1: u32,
|
unk1: u32,
|
||||||
pose: u32,
|
pose: u32,
|
||||||
},
|
},
|
||||||
|
#[brw(magic = 0x1FDu16)]
|
||||||
|
LearnTeleport {
|
||||||
|
#[brw(pad_before = 2)] //padding
|
||||||
|
id: u32,
|
||||||
|
#[br(map = read_bool_from::<u32>)]
|
||||||
|
#[bw(map = write_bool_as::<u32>)]
|
||||||
|
unlocked: bool,
|
||||||
|
},
|
||||||
|
#[brw(magic = 0x29u16)]
|
||||||
|
ToggleActionUnlock {
|
||||||
|
#[brw(pad_before = 2)] //padding
|
||||||
|
id: u32,
|
||||||
|
#[br(map = read_bool_from::<u32>)]
|
||||||
|
#[bw(map = write_bool_as::<u32>)]
|
||||||
|
unlocked: bool,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
|
|
|
@ -144,6 +144,7 @@ pub enum GameMasterCommandType {
|
||||||
ToggleWireframe = 0x26,
|
ToggleWireframe = 0x26,
|
||||||
ChangeTerritory = 0x58,
|
ChangeTerritory = 0x58,
|
||||||
GiveItem = 0xC8,
|
GiveItem = 0xC8,
|
||||||
|
Aetheryte = 0x5E,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{CustomizeData, ObjectId, ObjectTypeId, timestamp_secs},
|
common::{CustomizeData, ObjectId, ObjectTypeId, timestamp_secs},
|
||||||
ipc::zone::{
|
ipc::zone::{
|
||||||
ActorControl, ActorControlCategory, BattleNpcSubKind, ChatMessage, CommonSpawn, EventStart,
|
ActorControl, ActorControlCategory, ActorControlSelf, BattleNpcSubKind, ChatMessage,
|
||||||
NpcSpawn, ObjectKind, OnlineStatus, ServerZoneIpcData, ServerZoneIpcSegment,
|
CommonSpawn, EventStart, NpcSpawn, ObjectKind, OnlineStatus, ServerZoneIpcData,
|
||||||
|
ServerZoneIpcSegment,
|
||||||
},
|
},
|
||||||
opcodes::ServerZoneIpcType,
|
opcodes::ServerZoneIpcType,
|
||||||
packet::{PacketSegment, SegmentData, SegmentType},
|
packet::{PacketSegment, SegmentData, SegmentType},
|
||||||
|
@ -203,6 +204,16 @@ impl ChatHandler {
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
"!unlockaction" => {
|
||||||
|
let parts: Vec<&str> = chat_message.message.split(' ').collect();
|
||||||
|
let id = parts[1].parse::<u32>().unwrap();
|
||||||
|
|
||||||
|
connection
|
||||||
|
.actor_control_self(ActorControlSelf {
|
||||||
|
category: ActorControlCategory::ToggleActionUnlock { id, unlocked: true },
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue