mirror of
https://github.com/redstrate/Kawari.git
synced 2025-04-23 23:57:46 +00:00
Add debug command to spawn a monster (Tiny Mandragora), various fixes
This fixes various problems in CommonSpawn, adds a test for an enemy NPC spawn, and an unkwon packet I get when entering some zones.
This commit is contained in:
parent
af6f95fa61
commit
9111ef6a82
7 changed files with 111 additions and 12 deletions
3
USAGE.md
3
USAGE.md
|
@ -80,7 +80,8 @@ These special debug commands start with `!` and are custom to Kawari.
|
|||
|
||||
* `!setpos <x> <y> <z>`: Teleport to the specified location
|
||||
* `!spawnactor`: Spawn another actor for debugging
|
||||
* `!spawnnpc`: Spawn an NPC for debugging
|
||||
* `!spawnnpc`: Spawn a NPC for debugging
|
||||
* `!spawnmonster`: Spawn a monster for debugging
|
||||
|
||||
### GM commands
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ async fn main() {
|
|||
player_data: PlayerData::default(),
|
||||
spawn_index: 0,
|
||||
zone: None,
|
||||
position: Position::default(),
|
||||
};
|
||||
|
||||
tokio::spawn(async move {
|
||||
|
@ -516,8 +517,12 @@ async fn main() {
|
|||
.await;
|
||||
}
|
||||
}
|
||||
ClientZoneIpcData::UpdatePositionHandler { .. } => {
|
||||
tracing::info!("Recieved UpdatePositionHandler!");
|
||||
ClientZoneIpcData::UpdatePositionHandler {
|
||||
position, ..
|
||||
} => {
|
||||
tracing::info!("Character moved to {position:#?}");
|
||||
|
||||
connection.position = *position;
|
||||
}
|
||||
ClientZoneIpcData::LogOut { .. } => {
|
||||
tracing::info!("Recieved log out from client!");
|
||||
|
@ -707,6 +712,9 @@ async fn main() {
|
|||
.await;
|
||||
}
|
||||
}
|
||||
ClientZoneIpcData::Unk15 { .. } => {
|
||||
tracing::info!("Recieved Unk15!");
|
||||
}
|
||||
}
|
||||
}
|
||||
SegmentType::KeepAlive { id, timestamp } => {
|
||||
|
|
|
@ -133,7 +133,7 @@ impl ChatHandler {
|
|||
0, // left finger
|
||||
0, // right finger
|
||||
],
|
||||
pos: Position::default(),
|
||||
pos: connection.position,
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
|
@ -207,7 +207,48 @@ impl ChatHandler {
|
|||
0, // left finger
|
||||
0, // right finger
|
||||
],
|
||||
pos: Position::default(),
|
||||
pos: connection.position,
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}),
|
||||
};
|
||||
|
||||
connection
|
||||
.send_segment(PacketSegment {
|
||||
source_actor: 0x106ad804,
|
||||
target_actor: connection.player_data.actor_id,
|
||||
segment_type: SegmentType::Ipc { data: ipc },
|
||||
})
|
||||
.await;
|
||||
}
|
||||
}
|
||||
"!spawnmonster" => {
|
||||
// spawn a tiny mandragora
|
||||
{
|
||||
let ipc = ServerZoneIpcSegment {
|
||||
unk1: 20,
|
||||
unk2: 0,
|
||||
op_code: ServerZoneIpcType::NpcSpawn,
|
||||
server_id: 0,
|
||||
timestamp: timestamp_secs(),
|
||||
data: ServerZoneIpcData::NpcSpawn(NpcSpawn {
|
||||
common: CommonSpawn {
|
||||
hp_curr: 91,
|
||||
hp_max: 91,
|
||||
mp_curr: 100,
|
||||
mp_max: 100,
|
||||
spawn_index: connection.get_free_spawn_index(),
|
||||
bnpc_base: 13498, // TODO: changing this prevents it from spawning...
|
||||
bnpc_name: 405,
|
||||
spawner_id: connection.player_data.actor_id,
|
||||
parent_actor_id: INVALID_OBJECT_ID, // TODO: make default?
|
||||
object_kind: ObjectKind::BattleNpc,
|
||||
target_id: INVALID_OBJECT_ID as u64,
|
||||
level: 1,
|
||||
battalion: 4,
|
||||
model_chara: 297,
|
||||
pos: connection.position,
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
|
|
|
@ -32,6 +32,8 @@ pub struct ZoneConnection {
|
|||
|
||||
pub zone: Option<Zone>,
|
||||
pub spawn_index: u8,
|
||||
|
||||
pub position: Position,
|
||||
}
|
||||
|
||||
impl ZoneConnection {
|
||||
|
|
|
@ -67,8 +67,10 @@ pub struct CommonSpawn {
|
|||
|
||||
pub u14: u32,
|
||||
pub u15: u32,
|
||||
pub bnpc_base: u32, // See BNpcBase Excel sheet
|
||||
pub bnpc_name: u32, // See BNpcName Excel sheet
|
||||
/// See BNpcBase Excel sheet
|
||||
pub bnpc_base: u32,
|
||||
/// See BNpcName Excel sheet
|
||||
pub bnpc_name: u32,
|
||||
pub unk3: [u8; 8],
|
||||
pub director_id: u32, // FIXME: i think the next three are in the wrong order
|
||||
pub spawner_id: u32,
|
||||
|
@ -80,7 +82,8 @@ pub struct CommonSpawn {
|
|||
pub mp_curr: u16,
|
||||
pub mp_max: u16,
|
||||
pub unk: u16,
|
||||
pub model_chara: u16, // See ModelChara Excel sheet
|
||||
/// See ModelChara Excel sheet
|
||||
pub model_chara: u16,
|
||||
pub rotation: u16, // assumed
|
||||
pub current_mount: u16, // assumed
|
||||
pub active_minion: u16, // assumed
|
||||
|
@ -88,15 +91,20 @@ pub struct CommonSpawn {
|
|||
pub u24: u8, // assumed
|
||||
pub u25: u8, // assumed
|
||||
pub u26: u8, // assumed
|
||||
/// Must be unique for each actor.
|
||||
pub spawn_index: u8,
|
||||
pub mode: CharacterMode,
|
||||
/// Argument used in CharacterMode.
|
||||
// TODO: move to enum
|
||||
pub persistent_emote: u8,
|
||||
pub object_kind: ObjectKind,
|
||||
pub subtype: u8,
|
||||
pub voice: u8,
|
||||
pub enemy_type: u8,
|
||||
pub unk27: u8,
|
||||
/// See Battalion Excel sheet. Used for determing whether it's friendy or an enemy.
|
||||
pub battalion: u8,
|
||||
pub level: u8,
|
||||
/// See ClassJob Excel sheet.
|
||||
pub class_job: u8,
|
||||
pub unk28: u8,
|
||||
pub unk29: u8,
|
||||
|
|
|
@ -237,6 +237,8 @@ pub enum ClientZoneIpcType {
|
|||
Unk14 = 0x87,
|
||||
// Sent by the client when a character performs an action
|
||||
ActionRequest = 0x213,
|
||||
/// Sent by the client for unknown reasons, it's a bunch of numbers?
|
||||
Unk15 = 0x10B,
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
|
@ -365,7 +367,9 @@ pub enum ClientZoneIpcData {
|
|||
#[br(pre_assert(*magic == ClientZoneIpcType::UpdatePositionHandler))]
|
||||
UpdatePositionHandler {
|
||||
// TODO: full of possibly interesting information
|
||||
unk: [u8; 24],
|
||||
unk: [u8; 8], // not empty
|
||||
#[brw(pad_after = 4)] // empty
|
||||
position: Position,
|
||||
},
|
||||
#[br(pre_assert(*magic == ClientZoneIpcType::LogOut))]
|
||||
LogOut {
|
||||
|
@ -408,6 +412,8 @@ pub enum ClientZoneIpcData {
|
|||
},
|
||||
#[br(pre_assert(*magic == ClientZoneIpcType::ActionRequest))]
|
||||
ActionRequest(ActionRequest),
|
||||
#[br(pre_assert(*magic == ClientZoneIpcType::Unk15))]
|
||||
Unk15 { unk: [u8; 632] },
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -16,12 +16,15 @@ mod tests {
|
|||
|
||||
use binrw::BinRead;
|
||||
|
||||
use crate::world::ipc::{CharacterMode, ObjectKind};
|
||||
use crate::{
|
||||
common::INVALID_OBJECT_ID,
|
||||
world::ipc::{CharacterMode, ObjectKind},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn read_npcspawn() {
|
||||
fn read_carbuncle() {
|
||||
let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
d.push("resources/tests/npc_spawn.bin");
|
||||
|
||||
|
@ -44,5 +47,35 @@ mod tests {
|
|||
assert_eq!(npc_spawn.common.mode, CharacterMode::Normal);
|
||||
assert_eq!(npc_spawn.common.object_kind, ObjectKind::BattleNpc);
|
||||
assert_eq!(npc_spawn.common.subtype, 2);
|
||||
assert_eq!(npc_spawn.common.battalion, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_tiny_mandragora() {
|
||||
let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
d.push("resources/tests/tiny_mandragora.bin");
|
||||
|
||||
let buffer = read(d).unwrap();
|
||||
let mut buffer = Cursor::new(&buffer);
|
||||
|
||||
let npc_spawn = NpcSpawn::read_le(&mut buffer).unwrap();
|
||||
assert_eq!(npc_spawn.common.hp_max, 91);
|
||||
assert_eq!(npc_spawn.common.hp_curr, 91);
|
||||
assert_eq!(npc_spawn.common.mp_curr, 0);
|
||||
assert_eq!(npc_spawn.common.mp_max, 0);
|
||||
assert_eq!(npc_spawn.common.display_flags, 0);
|
||||
assert_eq!(npc_spawn.common.pos.x, 116.99154);
|
||||
assert_eq!(npc_spawn.common.pos.y, 76.64936);
|
||||
assert_eq!(npc_spawn.common.pos.z, -187.02414);
|
||||
assert_eq!(npc_spawn.common.model_chara, 297);
|
||||
assert_eq!(npc_spawn.common.bnpc_base, 118);
|
||||
assert_eq!(npc_spawn.common.bnpc_name, 405);
|
||||
assert_eq!(npc_spawn.common.spawn_index, 14);
|
||||
assert_eq!(npc_spawn.common.mode, CharacterMode::Normal);
|
||||
assert_eq!(npc_spawn.common.object_kind, ObjectKind::BattleNpc);
|
||||
assert_eq!(npc_spawn.common.subtype, 5);
|
||||
assert_eq!(npc_spawn.common.battalion, 4);
|
||||
assert_eq!(npc_spawn.common.parent_actor_id, INVALID_OBJECT_ID);
|
||||
assert_eq!(npc_spawn.common.spawner_id, INVALID_OBJECT_ID);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue