1
Fork 0
mirror of https://github.com/redstrate/Kawari.git synced 2025-05-13 15:17:45 +00:00
kawari/src/world/chat_handler.rs
Joshua Goins 477380c8b9 When using the !spawnmonster command, send it to all players
You can't attack it and see it on other clients yet, that will take some
more plumbing.
2025-05-09 20:09:22 -04:00

209 lines
7.9 KiB
Rust

use crate::{
common::{CustomizeData, ObjectId, ObjectTypeId, timestamp_secs},
ipc::zone::{
ActorControl, ActorControlCategory, BattleNpcSubKind, ChatMessage, CommonSpawn, EventStart,
NpcSpawn, ObjectKind, OnlineStatus, ServerZoneIpcData, ServerZoneIpcSegment,
},
opcodes::ServerZoneIpcType,
packet::{PacketSegment, SegmentData, SegmentType},
world::{Event, ToServer},
};
use super::{LuaPlayer, ZoneConnection};
pub const CUSTOMIZE_DATA: CustomizeData = CustomizeData {
race: 4,
gender: 1,
age: 1,
height: 50,
subrace: 7,
face: 3,
hair: 5,
enable_highlights: 0,
skin_tone: 10,
right_eye_color: 75,
hair_tone: 50,
highlights: 0,
facial_features: 1,
facial_feature_color: 19,
eyebrows: 1,
left_eye_color: 75,
eyes: 1,
nose: 0,
jaw: 1,
mouth: 1,
lips_tone_fur_pattern: 169,
race_feature_size: 100,
race_feature_type: 1,
bust: 100,
face_paint: 0,
face_paint_color: 167,
};
pub struct ChatHandler {}
impl ChatHandler {
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);
let parts: Vec<&str> = chat_message.message.split(' ').collect();
match parts[0] {
"!spawnnpc" => {
let ipc = ServerZoneIpcSegment {
op_code: ServerZoneIpcType::NpcSpawn,
timestamp: timestamp_secs(),
data: ServerZoneIpcData::NpcSpawn(NpcSpawn {
common: CommonSpawn {
hp_curr: 100,
hp_max: 100,
mp_curr: 100,
mp_max: 100,
look: CUSTOMIZE_DATA,
spawn_index: connection.get_free_spawn_index(),
bnpc_base: 13498,
bnpc_name: 10261,
object_kind: ObjectKind::BattleNpc(BattleNpcSubKind::Enemy),
target_id: ObjectTypeId {
object_id: ObjectId(connection.player_data.actor_id),
object_type: 0,
}, // target the player
level: 1,
models: [
0, // head
89, // body
89, // hands
89, // legs
89, // feet
0, // ears
0, // neck
0, // wrists
0, // left finger
0, // right finger
],
pos: connection.player_data.position,
..Default::default()
},
..Default::default()
}),
..Default::default()
};
connection
.send_segment(PacketSegment {
source_actor: 0x106ad804,
target_actor: connection.player_data.actor_id,
segment_type: SegmentType::Ipc,
data: SegmentData::Ipc { data: ipc },
})
.await;
}
"!spawnmonster" => {
connection
.handle
.send(ToServer::DebugNewNpc(connection.id))
.await;
}
"!playscene" => {
let parts: Vec<&str> = chat_message.message.split(' ').collect();
let event_id = parts[1].parse::<u32>().unwrap();
// Load the game script for this event on the client
{
let ipc = ServerZoneIpcSegment {
op_code: ServerZoneIpcType::EventStart,
timestamp: timestamp_secs(),
data: ServerZoneIpcData::EventStart(EventStart {
target_id: ObjectTypeId {
object_id: ObjectId(connection.player_data.actor_id),
object_type: 0,
},
event_type: 15,
event_id,
flags: 0,
event_arg: 182, // zone?
}),
..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: SegmentData::Ipc { data: ipc },
})
.await;
}
// set our status icon to viewing cutscene
{
let ipc = ServerZoneIpcSegment {
op_code: ServerZoneIpcType::ActorControl,
timestamp: timestamp_secs(),
data: ServerZoneIpcData::ActorControl(ActorControl {
category: ActorControlCategory::SetStatusIcon {
icon: OnlineStatus::ViewingCutscene,
},
}),
..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: SegmentData::Ipc { data: ipc },
})
.await;
}
let event = match event_id {
1245185 => Event::new(1245185, "opening/OpeningLimsaLominsa.lua"),
1245186 => Event::new(1245186, "opening/OpeningGridania.lua"),
1245187 => Event::new(1245187, "opening/OpeningUldah.lua"),
_ => panic!("Unsupported event!"),
};
connection.event = Some(event);
connection
.event
.as_mut()
.unwrap()
.enter_territory(lua_player, connection.zone.as_ref().unwrap());
}
"!spawnclone" => {
// spawn another one of us
let player = &connection.player_data;
let mut common = connection
.get_player_common_spawn(Some(player.position), Some(player.rotation));
common.spawn_index = connection.get_free_spawn_index();
let ipc = ServerZoneIpcSegment {
op_code: ServerZoneIpcType::NpcSpawn,
timestamp: timestamp_secs(),
data: ServerZoneIpcData::NpcSpawn(NpcSpawn {
common,
..Default::default()
}),
..Default::default()
};
connection
.send_segment(PacketSegment {
source_actor: 0x106ad804,
target_actor: connection.player_data.actor_id,
segment_type: SegmentType::Ipc,
data: SegmentData::Ipc { data: ipc },
})
.await;
}
_ => {}
}
}
}