2020-09-21 23:53:46 +00:00
|
|
|
use std::io;
|
|
|
|
|
2022-11-19 17:20:03 +00:00
|
|
|
use byteorder::{BE, LE, ReadBytesExt, WriteBytesExt};
|
2020-09-21 23:53:46 +00:00
|
|
|
use num_traits::{clamp, FromPrimitive};
|
|
|
|
|
2022-11-19 17:20:03 +00:00
|
|
|
use crate::common::{Direction, FadeState, get_timestamp};
|
2021-01-27 18:20:47 +00:00
|
|
|
use crate::framework::context::Context;
|
2021-03-22 08:01:52 +00:00
|
|
|
use crate::framework::error::GameError::ResourceLoadError;
|
2021-01-27 18:20:47 +00:00
|
|
|
use crate::framework::error::GameResult;
|
2022-11-19 17:20:03 +00:00
|
|
|
use crate::game::player::ControlMode;
|
|
|
|
use crate::game::shared_game_state::{GameDifficulty, SharedGameState};
|
|
|
|
use crate::game::weapon::{WeaponLevel, WeaponType};
|
2020-09-21 23:53:46 +00:00
|
|
|
use crate::scene::game_scene::GameScene;
|
|
|
|
|
|
|
|
pub struct WeaponData {
|
|
|
|
pub weapon_id: u32,
|
|
|
|
pub level: u32,
|
|
|
|
pub exp: u32,
|
|
|
|
pub max_ammo: u32,
|
|
|
|
pub ammo: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct TeleporterSlotData {
|
|
|
|
pub index: u32,
|
|
|
|
pub event_num: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct GameProfile {
|
|
|
|
pub current_map: u32,
|
|
|
|
pub current_song: u32,
|
|
|
|
pub pos_x: i32,
|
|
|
|
pub pos_y: i32,
|
|
|
|
pub direction: Direction,
|
|
|
|
pub max_life: u16,
|
|
|
|
pub stars: u16,
|
|
|
|
pub life: u16,
|
|
|
|
pub current_weapon: u32,
|
|
|
|
pub current_item: u32,
|
|
|
|
pub equipment: u32,
|
|
|
|
pub control_mode: u32,
|
|
|
|
pub counter: u32,
|
|
|
|
pub weapon_data: [WeaponData; 8],
|
|
|
|
pub items: [u32; 32],
|
|
|
|
pub teleporter_slots: [TeleporterSlotData; 8],
|
2021-05-02 02:04:52 +00:00
|
|
|
pub map_flags: [u8; 128],
|
2020-09-21 23:53:46 +00:00
|
|
|
pub flags: [u8; 1000],
|
2022-02-27 10:21:43 +00:00
|
|
|
pub timestamp: u64,
|
|
|
|
pub difficulty: u8,
|
2020-09-21 23:53:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl GameProfile {
|
|
|
|
pub fn apply(&self, state: &mut SharedGameState, game_scene: &mut GameScene, ctx: &mut Context) {
|
|
|
|
state.fade_state = FadeState::Visible;
|
2020-09-25 12:55:28 +00:00
|
|
|
state.control_flags.set_tick_world(true);
|
2020-09-21 23:53:46 +00:00
|
|
|
state.control_flags.set_control_enabled(true);
|
|
|
|
|
2023-08-10 10:39:40 +00:00
|
|
|
let _ = state.sound_manager.play_song(self.current_song as usize, &state.constants, &state.settings, ctx, false);
|
2020-09-21 23:53:46 +00:00
|
|
|
|
2020-11-28 19:25:51 +00:00
|
|
|
game_scene.inventory_player1.current_weapon = self.current_weapon as u16;
|
|
|
|
game_scene.inventory_player1.current_item = self.current_item as u16;
|
2022-01-17 22:29:30 +00:00
|
|
|
for weapon in &self.weapon_data {
|
2021-03-22 08:01:52 +00:00
|
|
|
if weapon.weapon_id == 0 {
|
|
|
|
continue;
|
|
|
|
}
|
2022-03-15 22:18:25 +00:00
|
|
|
|
|
|
|
let _ = state.mod_requirements.append_weapon(ctx, weapon.weapon_id as u16);
|
2020-09-21 23:53:46 +00:00
|
|
|
let weapon_type: Option<WeaponType> = FromPrimitive::from_u8(weapon.weapon_id as u8);
|
|
|
|
|
|
|
|
if let Some(wtype) = weapon_type {
|
2021-03-29 21:19:07 +00:00
|
|
|
game_scene.inventory_player1.add_weapon_data(
|
2021-03-22 08:01:52 +00:00
|
|
|
wtype,
|
|
|
|
weapon.ammo as u16,
|
|
|
|
weapon.max_ammo as u16,
|
|
|
|
weapon.exp as u16,
|
|
|
|
match weapon.level {
|
|
|
|
2 => WeaponLevel::Level2,
|
|
|
|
3 => WeaponLevel::Level3,
|
|
|
|
_ => WeaponLevel::Level1,
|
|
|
|
},
|
|
|
|
);
|
2020-09-21 23:53:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for item in self.items.iter().copied() {
|
2022-02-09 00:04:36 +00:00
|
|
|
let item_id = item as u16;
|
2022-03-15 22:18:25 +00:00
|
|
|
let _ = state.mod_requirements.append_item(ctx, item_id);
|
|
|
|
|
2022-02-09 00:04:36 +00:00
|
|
|
let amount = (item >> 16) as u16;
|
|
|
|
if item_id == 0 {
|
2021-03-22 08:01:52 +00:00
|
|
|
break;
|
|
|
|
}
|
2020-10-26 08:34:54 +00:00
|
|
|
|
2022-02-09 00:04:36 +00:00
|
|
|
game_scene.inventory_player1.add_item_amount(item_id, amount + 1);
|
2020-09-21 23:53:46 +00:00
|
|
|
}
|
|
|
|
|
2022-01-17 22:29:30 +00:00
|
|
|
for slot in &self.teleporter_slots {
|
2021-03-22 08:01:52 +00:00
|
|
|
if slot.event_num == 0 {
|
|
|
|
break;
|
|
|
|
}
|
2020-10-26 08:34:54 +00:00
|
|
|
|
2020-10-02 23:52:52 +00:00
|
|
|
state.teleporter_slots.push((slot.index as u16, slot.event_num as u16));
|
|
|
|
}
|
|
|
|
|
2021-05-02 02:04:52 +00:00
|
|
|
for (idx, &flag) in self.map_flags.iter().enumerate() {
|
|
|
|
state.set_map_flag(idx, flag != 0);
|
|
|
|
}
|
|
|
|
|
2020-09-21 23:53:46 +00:00
|
|
|
for (idx, &flags) in self.flags.iter().enumerate() {
|
2021-03-22 08:01:52 +00:00
|
|
|
if flags & 0b00000001 != 0 {
|
2022-01-26 04:41:21 +00:00
|
|
|
state.set_flag(idx * 8, true);
|
2021-03-22 08:01:52 +00:00
|
|
|
}
|
|
|
|
if flags & 0b00000010 != 0 {
|
2022-01-26 04:41:21 +00:00
|
|
|
state.set_flag(idx * 8 + 1, true);
|
2021-03-22 08:01:52 +00:00
|
|
|
}
|
|
|
|
if flags & 0b00000100 != 0 {
|
2022-01-26 04:41:21 +00:00
|
|
|
state.set_flag(idx * 8 + 2, true);
|
2021-03-22 08:01:52 +00:00
|
|
|
}
|
|
|
|
if flags & 0b00001000 != 0 {
|
2022-01-26 04:41:21 +00:00
|
|
|
state.set_flag(idx * 8 + 3, true);
|
2021-03-22 08:01:52 +00:00
|
|
|
}
|
|
|
|
if flags & 0b00010000 != 0 {
|
2022-01-26 04:41:21 +00:00
|
|
|
state.set_flag(idx * 8 + 4, true);
|
2021-03-22 08:01:52 +00:00
|
|
|
}
|
|
|
|
if flags & 0b00100000 != 0 {
|
2022-01-26 04:41:21 +00:00
|
|
|
state.set_flag(idx * 8 + 5, true);
|
2021-03-22 08:01:52 +00:00
|
|
|
}
|
|
|
|
if flags & 0b01000000 != 0 {
|
2022-01-26 04:41:21 +00:00
|
|
|
state.set_flag(idx * 8 + 6, true);
|
2021-03-22 08:01:52 +00:00
|
|
|
}
|
|
|
|
if flags & 0b10000000 != 0 {
|
2022-01-26 04:41:21 +00:00
|
|
|
state.set_flag(idx * 8 + 7, true);
|
2021-03-22 08:01:52 +00:00
|
|
|
}
|
2020-09-21 23:53:46 +00:00
|
|
|
}
|
|
|
|
|
2022-02-24 00:05:19 +00:00
|
|
|
state.textscript_vm.start_script(0);
|
|
|
|
|
2020-11-28 19:25:51 +00:00
|
|
|
game_scene.player1.equip.0 = self.equipment as u16;
|
2020-09-21 23:53:46 +00:00
|
|
|
|
2021-01-01 01:46:01 +00:00
|
|
|
game_scene.player1.x = self.pos_x;
|
|
|
|
game_scene.player1.y = self.pos_y;
|
2020-09-21 23:53:46 +00:00
|
|
|
|
2021-03-22 08:01:52 +00:00
|
|
|
game_scene.player1.control_mode =
|
|
|
|
if self.control_mode == 1 { ControlMode::IronHead } else { ControlMode::Normal };
|
2020-11-28 19:25:51 +00:00
|
|
|
game_scene.player1.direction = self.direction;
|
|
|
|
game_scene.player1.life = self.life;
|
|
|
|
game_scene.player1.max_life = self.max_life;
|
|
|
|
game_scene.player1.stars = clamp(self.stars, 0, 3) as u8;
|
2020-11-29 12:06:10 +00:00
|
|
|
|
|
|
|
game_scene.player2 = game_scene.player1.clone();
|
|
|
|
game_scene.inventory_player2 = game_scene.inventory_player1.clone();
|
2020-12-04 17:37:47 +00:00
|
|
|
|
|
|
|
game_scene.player1.cond.0 = 0x80;
|
2022-02-27 10:21:43 +00:00
|
|
|
|
2022-02-27 15:27:34 +00:00
|
|
|
state.difficulty = GameDifficulty::from_primitive(self.difficulty);
|
2022-02-27 10:21:43 +00:00
|
|
|
|
|
|
|
game_scene.player1.skin.apply_gamestate(state);
|
|
|
|
game_scene.player2.skin.apply_gamestate(state);
|
2020-09-21 23:53:46 +00:00
|
|
|
}
|
|
|
|
|
2020-10-30 01:29:53 +00:00
|
|
|
pub fn dump(state: &mut SharedGameState, game_scene: &mut GameScene) -> GameProfile {
|
|
|
|
let current_map = game_scene.stage_id as u32;
|
|
|
|
let current_song = state.sound_manager.current_song() as u32;
|
2020-11-28 19:25:51 +00:00
|
|
|
let pos_x = game_scene.player1.x as i32;
|
|
|
|
let pos_y = game_scene.player1.y as i32;
|
|
|
|
let direction = game_scene.player1.direction;
|
|
|
|
let max_life = game_scene.player1.max_life;
|
|
|
|
let stars = game_scene.player1.stars as u16;
|
|
|
|
let life = game_scene.player1.life;
|
|
|
|
let current_weapon = game_scene.inventory_player1.current_weapon as u32;
|
|
|
|
let current_item = game_scene.inventory_player1.current_item as u32;
|
|
|
|
let equipment = game_scene.player1.equip.0 as u32;
|
|
|
|
let control_mode = game_scene.player1.control_mode as u32;
|
2020-10-30 01:29:53 +00:00
|
|
|
let counter = 0; // TODO
|
|
|
|
let mut weapon_data = [
|
|
|
|
WeaponData { weapon_id: 0, level: 0, exp: 0, max_ammo: 0, ammo: 0 },
|
|
|
|
WeaponData { weapon_id: 0, level: 0, exp: 0, max_ammo: 0, ammo: 0 },
|
|
|
|
WeaponData { weapon_id: 0, level: 0, exp: 0, max_ammo: 0, ammo: 0 },
|
|
|
|
WeaponData { weapon_id: 0, level: 0, exp: 0, max_ammo: 0, ammo: 0 },
|
|
|
|
WeaponData { weapon_id: 0, level: 0, exp: 0, max_ammo: 0, ammo: 0 },
|
|
|
|
WeaponData { weapon_id: 0, level: 0, exp: 0, max_ammo: 0, ammo: 0 },
|
|
|
|
WeaponData { weapon_id: 0, level: 0, exp: 0, max_ammo: 0, ammo: 0 },
|
|
|
|
WeaponData { weapon_id: 0, level: 0, exp: 0, max_ammo: 0, ammo: 0 },
|
|
|
|
];
|
|
|
|
let mut items = [0u32; 32];
|
|
|
|
let mut teleporter_slots = [
|
|
|
|
TeleporterSlotData { index: 0, event_num: 0 },
|
|
|
|
TeleporterSlotData { index: 0, event_num: 0 },
|
|
|
|
TeleporterSlotData { index: 0, event_num: 0 },
|
|
|
|
TeleporterSlotData { index: 0, event_num: 0 },
|
|
|
|
TeleporterSlotData { index: 0, event_num: 0 },
|
|
|
|
TeleporterSlotData { index: 0, event_num: 0 },
|
|
|
|
TeleporterSlotData { index: 0, event_num: 0 },
|
|
|
|
TeleporterSlotData { index: 0, event_num: 0 },
|
|
|
|
];
|
|
|
|
|
|
|
|
for (idx, weap) in weapon_data.iter_mut().enumerate() {
|
2020-11-28 19:25:51 +00:00
|
|
|
if let Some(weapon) = game_scene.inventory_player1.get_weapon(idx) {
|
2020-10-30 01:29:53 +00:00
|
|
|
weap.weapon_id = weapon.wtype as u32;
|
|
|
|
weap.level = weapon.level as u32;
|
|
|
|
weap.exp = weapon.experience as u32;
|
|
|
|
weap.max_ammo = weapon.max_ammo as u32;
|
|
|
|
weap.ammo = weapon.ammo as u32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (idx, item) in items.iter_mut().enumerate() {
|
2020-11-28 19:25:51 +00:00
|
|
|
if let Some(sitem) = game_scene.inventory_player1.get_item_idx(idx) {
|
2022-02-09 00:04:36 +00:00
|
|
|
*item = sitem.0 as u32 + (((sitem.1 - 1) as u32) << 16);
|
2020-10-30 01:29:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (idx, slot) in teleporter_slots.iter_mut().enumerate() {
|
|
|
|
if let Some(&(index, event_num)) = state.teleporter_slots.get(idx) {
|
|
|
|
slot.index = index as u32;
|
|
|
|
slot.event_num = event_num as u32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-02 02:04:52 +00:00
|
|
|
let mut map_flags = [0u8; 128];
|
|
|
|
for (idx, map_flag) in state.map_flags.iter().enumerate() {
|
|
|
|
if let Some(out) = map_flags.get_mut(idx) {
|
2022-11-19 17:20:03 +00:00
|
|
|
*out = if map_flag { 1 } else { 0 };
|
2021-05-02 02:04:52 +00:00
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-30 01:29:53 +00:00
|
|
|
let mut flags = [0u8; 1000];
|
2022-11-19 17:20:03 +00:00
|
|
|
state.game_flags.copy_to_slice(&mut flags);
|
2020-10-30 01:29:53 +00:00
|
|
|
|
2022-02-27 10:21:43 +00:00
|
|
|
let timestamp = get_timestamp();
|
2022-02-27 15:27:34 +00:00
|
|
|
let difficulty = state.difficulty as u8;
|
2022-02-27 10:21:43 +00:00
|
|
|
|
2020-10-30 01:29:53 +00:00
|
|
|
GameProfile {
|
|
|
|
current_map,
|
|
|
|
current_song,
|
|
|
|
pos_x,
|
|
|
|
pos_y,
|
|
|
|
direction,
|
|
|
|
max_life,
|
|
|
|
stars,
|
|
|
|
life,
|
|
|
|
current_weapon,
|
|
|
|
current_item,
|
|
|
|
equipment,
|
|
|
|
control_mode,
|
|
|
|
counter,
|
|
|
|
weapon_data,
|
|
|
|
items,
|
|
|
|
teleporter_slots,
|
2021-05-02 02:04:52 +00:00
|
|
|
map_flags,
|
2020-10-30 01:29:53 +00:00
|
|
|
flags,
|
2022-02-27 10:21:43 +00:00
|
|
|
timestamp,
|
|
|
|
difficulty,
|
2020-10-30 01:29:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn write_save<W: io::Write>(&self, mut data: W) -> GameResult {
|
|
|
|
data.write_u64::<BE>(0x446f303431323230)?;
|
|
|
|
|
|
|
|
data.write_u32::<LE>(self.current_map)?;
|
|
|
|
data.write_u32::<LE>(self.current_song)?;
|
|
|
|
data.write_i32::<LE>(self.pos_x)?;
|
|
|
|
data.write_i32::<LE>(self.pos_y)?;
|
|
|
|
data.write_u32::<LE>(self.direction as u32)?;
|
|
|
|
data.write_u16::<LE>(self.max_life)?;
|
|
|
|
data.write_u16::<LE>(self.stars)?;
|
|
|
|
data.write_u16::<LE>(self.life)?;
|
|
|
|
data.write_u16::<LE>(0)?;
|
|
|
|
data.write_u32::<LE>(self.current_weapon)?;
|
|
|
|
data.write_u32::<LE>(self.current_item)?;
|
|
|
|
data.write_u32::<LE>(self.equipment)?;
|
|
|
|
data.write_u32::<LE>(self.control_mode)?;
|
|
|
|
data.write_u32::<LE>(self.counter)?;
|
|
|
|
|
2022-01-17 22:29:30 +00:00
|
|
|
for weapon in &self.weapon_data {
|
2020-10-30 01:29:53 +00:00
|
|
|
data.write_u32::<LE>(weapon.weapon_id)?;
|
|
|
|
data.write_u32::<LE>(weapon.level)?;
|
|
|
|
data.write_u32::<LE>(weapon.exp)?;
|
|
|
|
data.write_u32::<LE>(weapon.max_ammo)?;
|
|
|
|
data.write_u32::<LE>(weapon.ammo)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
for item in self.items.iter().copied() {
|
|
|
|
data.write_u32::<LE>(item)?;
|
|
|
|
}
|
|
|
|
|
2022-01-17 22:29:30 +00:00
|
|
|
for slot in &self.teleporter_slots {
|
2020-10-30 01:29:53 +00:00
|
|
|
data.write_u32::<LE>(slot.index)?;
|
|
|
|
data.write_u32::<LE>(slot.event_num)?;
|
|
|
|
}
|
|
|
|
|
2020-12-25 22:39:41 +00:00
|
|
|
let something = [0u8; 0x80];
|
|
|
|
data.write(&something)?;
|
2020-10-30 01:29:53 +00:00
|
|
|
|
|
|
|
data.write_u32::<BE>(0x464c4147)?;
|
|
|
|
data.write(&self.flags)?;
|
|
|
|
|
2022-02-27 10:21:43 +00:00
|
|
|
data.write_u32::<LE>(0)?; // unused(?) CS+ space
|
|
|
|
|
|
|
|
data.write_u64::<LE>(self.timestamp)?;
|
|
|
|
data.write_u8(self.difficulty)?;
|
|
|
|
|
2020-10-30 01:29:53 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-09-21 23:53:46 +00:00
|
|
|
pub fn load_from_save<R: io::Read>(mut data: R) -> GameResult<GameProfile> {
|
|
|
|
// Do041220
|
|
|
|
if data.read_u64::<BE>()? != 0x446f303431323230 {
|
2021-10-15 14:36:05 +00:00
|
|
|
return Err(ResourceLoadError("Invalid magic".to_owned()));
|
2020-09-21 23:53:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let current_map = data.read_u32::<LE>()?;
|
|
|
|
let current_song = data.read_u32::<LE>()?;
|
|
|
|
let pos_x = data.read_i32::<LE>()?;
|
|
|
|
let pos_y = data.read_i32::<LE>()?;
|
|
|
|
let direction = data.read_u32::<LE>()?;
|
|
|
|
let max_life = data.read_u16::<LE>()?;
|
|
|
|
let stars = data.read_u16::<LE>()?;
|
|
|
|
let life = data.read_u16::<LE>()?;
|
|
|
|
let _ = data.read_u16::<LE>()?; // ???
|
|
|
|
let current_weapon = data.read_u32::<LE>()?;
|
|
|
|
let current_item = data.read_u32::<LE>()?;
|
|
|
|
let equipment = data.read_u32::<LE>()?;
|
2020-10-30 01:29:53 +00:00
|
|
|
let control_mode = data.read_u32::<LE>()?;
|
2020-09-21 23:53:46 +00:00
|
|
|
let counter = data.read_u32::<LE>()?;
|
|
|
|
let mut weapon_data = [
|
|
|
|
WeaponData { weapon_id: 0, level: 0, exp: 0, max_ammo: 0, ammo: 0 },
|
|
|
|
WeaponData { weapon_id: 0, level: 0, exp: 0, max_ammo: 0, ammo: 0 },
|
|
|
|
WeaponData { weapon_id: 0, level: 0, exp: 0, max_ammo: 0, ammo: 0 },
|
|
|
|
WeaponData { weapon_id: 0, level: 0, exp: 0, max_ammo: 0, ammo: 0 },
|
|
|
|
WeaponData { weapon_id: 0, level: 0, exp: 0, max_ammo: 0, ammo: 0 },
|
|
|
|
WeaponData { weapon_id: 0, level: 0, exp: 0, max_ammo: 0, ammo: 0 },
|
|
|
|
WeaponData { weapon_id: 0, level: 0, exp: 0, max_ammo: 0, ammo: 0 },
|
|
|
|
WeaponData { weapon_id: 0, level: 0, exp: 0, max_ammo: 0, ammo: 0 },
|
|
|
|
];
|
|
|
|
let mut items = [0u32; 32];
|
|
|
|
let mut teleporter_slots = [
|
|
|
|
TeleporterSlotData { index: 0, event_num: 0 },
|
|
|
|
TeleporterSlotData { index: 0, event_num: 0 },
|
|
|
|
TeleporterSlotData { index: 0, event_num: 0 },
|
|
|
|
TeleporterSlotData { index: 0, event_num: 0 },
|
|
|
|
TeleporterSlotData { index: 0, event_num: 0 },
|
|
|
|
TeleporterSlotData { index: 0, event_num: 0 },
|
|
|
|
TeleporterSlotData { index: 0, event_num: 0 },
|
|
|
|
TeleporterSlotData { index: 0, event_num: 0 },
|
|
|
|
];
|
|
|
|
|
2022-01-17 22:29:30 +00:00
|
|
|
for WeaponData { weapon_id, level, exp, max_ammo, ammo } in &mut weapon_data {
|
|
|
|
*weapon_id = data.read_u32::<LE>()?;
|
|
|
|
*level = data.read_u32::<LE>()?;
|
|
|
|
*exp = data.read_u32::<LE>()?;
|
|
|
|
*max_ammo = data.read_u32::<LE>()?;
|
|
|
|
*ammo = data.read_u32::<LE>()?;
|
2020-09-21 23:53:46 +00:00
|
|
|
}
|
|
|
|
|
2022-01-17 22:29:30 +00:00
|
|
|
for item in &mut items {
|
2020-09-21 23:53:46 +00:00
|
|
|
*item = data.read_u32::<LE>()?;
|
|
|
|
}
|
|
|
|
|
2022-01-17 22:29:30 +00:00
|
|
|
for TeleporterSlotData { index, event_num } in &mut teleporter_slots {
|
|
|
|
*index = data.read_u32::<LE>()?;
|
|
|
|
*event_num = data.read_u32::<LE>()?;
|
2020-09-21 23:53:46 +00:00
|
|
|
}
|
|
|
|
|
2021-05-02 02:04:52 +00:00
|
|
|
let mut map_flags = [0u8; 0x80];
|
|
|
|
data.read_exact(&mut map_flags)?;
|
2020-09-21 23:53:46 +00:00
|
|
|
|
|
|
|
if data.read_u32::<BE>()? != 0x464c4147 {
|
2021-10-15 14:36:05 +00:00
|
|
|
return Err(ResourceLoadError("Invalid FLAG signature".to_owned()));
|
2020-09-21 23:53:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let mut flags = [0u8; 1000];
|
|
|
|
data.read_exact(&mut flags)?;
|
|
|
|
|
2022-02-27 10:21:43 +00:00
|
|
|
data.read_u32::<LE>().unwrap_or(0); // unused(?) CS+ space
|
|
|
|
|
|
|
|
let timestamp = data.read_u64::<LE>().unwrap_or(0);
|
|
|
|
let difficulty = data.read_u8().unwrap_or(0);
|
|
|
|
|
2020-09-21 23:53:46 +00:00
|
|
|
Ok(GameProfile {
|
|
|
|
current_map,
|
|
|
|
current_song,
|
|
|
|
pos_x,
|
|
|
|
pos_y,
|
|
|
|
direction: Direction::from_int(direction as usize).unwrap_or(Direction::Left),
|
|
|
|
max_life,
|
|
|
|
stars,
|
|
|
|
life,
|
|
|
|
current_weapon,
|
|
|
|
current_item,
|
|
|
|
equipment,
|
2020-10-30 01:29:53 +00:00
|
|
|
control_mode,
|
2020-09-21 23:53:46 +00:00
|
|
|
counter,
|
|
|
|
weapon_data,
|
|
|
|
items,
|
|
|
|
teleporter_slots,
|
2021-05-02 02:04:52 +00:00
|
|
|
map_flags,
|
2020-09-21 23:53:46 +00:00
|
|
|
flags,
|
2022-02-27 10:21:43 +00:00
|
|
|
timestamp,
|
|
|
|
difficulty,
|
2020-09-21 23:53:46 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|