1
Fork 0
mirror of https://github.com/redstrate/Kawari.git synced 2025-06-30 11:47:45 +00:00

Begin implementing EXP

This doesn't actually do things like level you up, but if you use the
GM EXP command then it will update the UI.
This commit is contained in:
Joshua Goins 2025-06-22 09:18:14 -04:00
parent b38b347c15
commit fbe6862c7b
5 changed files with 26 additions and 8 deletions

View file

@ -131,3 +131,4 @@ These GM commands are implemented in the FFXIV protocol, but only some of them a
* `//gm aetheryte <on/off> <id>`: Unlock an Aetheryte. * `//gm aetheryte <on/off> <id>`: Unlock an Aetheryte.
* `//gm speed <multiplier>`: Increases your movement speed by `multiplier`. * `//gm speed <multiplier>`: Increases your movement speed by `multiplier`.
* `//gm orchestrion <on/off> <id>`: Unlock an Orchestrion song. * `//gm orchestrion <on/off> <id>`: Unlock an Orchestrion song.
* `//gm exp <amount>` Adds the specified amount of EXP to the current class/job.

View file

@ -279,7 +279,7 @@ async fn client_loop(
timestamp: timestamp_secs(), timestamp: timestamp_secs(),
data: ServerZoneIpcData::PlayerStatus(PlayerStatus { data: ServerZoneIpcData::PlayerStatus(PlayerStatus {
content_id: connection.player_data.content_id, content_id: connection.player_data.content_id,
exp: [0; 32], exp: connection.player_data.classjob_exp,
name: chara_details.name, name: chara_details.name,
char_id: connection.player_data.actor_id, char_id: connection.player_data.actor_id,
race: chara_details.chara_make.customize.race, race: chara_details.chara_make.customize.race,
@ -682,6 +682,11 @@ async fn client_loop(
category: ActorControlCategory::LearnTeleport { id, unlocked: on } }).await; category: ActorControlCategory::LearnTeleport { id, unlocked: on } }).await;
} }
} }
GameMasterCommandType::EXP => {
let amount = *arg0;
connection.player_data.set_current_exp(connection.player_data.current_exp() + amount);
connection.update_class_info().await;
}
} }
} }
ClientZoneIpcData::ZoneJump { ClientZoneIpcData::ZoneJump {

View file

@ -144,6 +144,7 @@ pub enum GameMasterCommandType {
ToggleInvisibility = 0xD, ToggleInvisibility = 0xD,
ToggleWireframe = 0x26, ToggleWireframe = 0x26,
ChangeTerritory = 0x58, ChangeTerritory = 0x58,
EXP = 0x68,
Orchestrion = 0x74, Orchestrion = 0x74,
GiveItem = 0xC8, GiveItem = 0xC8,
Aetheryte = 0x5E, Aetheryte = 0x5E,

View file

@ -3,10 +3,11 @@ use binrw::binrw;
#[binrw] #[binrw]
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
pub struct UpdateClassInfo { pub struct UpdateClassInfo {
pub class_id: u16, pub class_id: u8,
pub unknown: u8, #[brw(pad_before = 1)]
pub is_specialist: u8, pub current_level: u16,
pub synced_level: u16,
pub class_level: u16, pub class_level: u16,
pub role_actions: [u32; 2], pub synced_level: u16,
pub current_exp: u32,
pub rested_exp: u32,
} }

View file

@ -59,6 +59,7 @@ pub struct PlayerData {
pub classjob_id: u8, pub classjob_id: u8,
pub classjob_levels: [i32; 32], pub classjob_levels: [i32; 32],
pub classjob_exp: [u32; 32],
pub curr_hp: u32, pub curr_hp: u32,
pub max_hp: u32, pub max_hp: u32,
pub curr_mp: u16, pub curr_mp: u16,
@ -84,6 +85,14 @@ impl PlayerData {
pub fn set_current_level(&mut self, level: i32) { pub fn set_current_level(&mut self, level: i32) {
self.classjob_levels[self.classjob_id as usize] = level; self.classjob_levels[self.classjob_id as usize] = level;
} }
pub fn current_exp(&self) -> u32 {
self.classjob_exp[self.classjob_id as usize]
}
pub fn set_current_exp(&mut self, exp: u32) {
self.classjob_exp[self.classjob_id as usize] = exp;
}
} }
/// Represents a single connection between an instance of the client and the world server /// Represents a single connection between an instance of the client and the world server
@ -300,10 +309,11 @@ impl ZoneConnection {
op_code: ServerZoneIpcType::UpdateClassInfo, op_code: ServerZoneIpcType::UpdateClassInfo,
timestamp: timestamp_secs(), timestamp: timestamp_secs(),
data: ServerZoneIpcData::UpdateClassInfo(UpdateClassInfo { data: ServerZoneIpcData::UpdateClassInfo(UpdateClassInfo {
class_id: self.player_data.classjob_id as u16, class_id: self.player_data.classjob_id,
unknown: 1,
synced_level: self.player_data.current_level() as u16, synced_level: self.player_data.current_level() as u16,
class_level: self.player_data.current_level() as u16, class_level: self.player_data.current_level() as u16,
current_level: self.player_data.current_level() as u16,
current_exp: self.player_data.current_exp(),
..Default::default() ..Default::default()
}), }),
..Default::default() ..Default::default()