mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-01-10 04:57:02 +00:00
add support for map flags
This commit is contained in:
parent
4f34e33b57
commit
d83f58fe1b
|
@ -1,6 +1,6 @@
|
|||
use std::io;
|
||||
|
||||
use byteorder::{ReadBytesExt, WriteBytesExt, BE, LE};
|
||||
use byteorder::{BE, LE, ReadBytesExt, WriteBytesExt};
|
||||
use num_traits::{clamp, FromPrimitive};
|
||||
|
||||
use crate::common::{Direction, FadeState};
|
||||
|
@ -43,6 +43,7 @@ pub struct GameProfile {
|
|||
pub weapon_data: [WeaponData; 8],
|
||||
pub items: [u32; 32],
|
||||
pub teleporter_slots: [TeleporterSlotData; 8],
|
||||
pub map_flags: [u8; 128],
|
||||
pub flags: [u8; 1000],
|
||||
}
|
||||
|
||||
|
@ -93,6 +94,10 @@ impl GameProfile {
|
|||
state.teleporter_slots.push((slot.index as u16, slot.event_num as u16));
|
||||
}
|
||||
|
||||
for (idx, &flag) in self.map_flags.iter().enumerate() {
|
||||
state.set_map_flag(idx, flag != 0);
|
||||
}
|
||||
|
||||
for (idx, &flags) in self.flags.iter().enumerate() {
|
||||
if flags & 0b00000001 != 0 {
|
||||
state.game_flags.set(idx * 8, true);
|
||||
|
@ -197,6 +202,15 @@ impl GameProfile {
|
|||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
*out = if *map_flag { 1 } else { 0 };
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let mut bidx = 0;
|
||||
let mut flags = [0u8; 1000];
|
||||
for bits in state.game_flags.as_raw_slice() {
|
||||
|
@ -204,6 +218,8 @@ impl GameProfile {
|
|||
for b in bytes.iter() {
|
||||
if let Some(out) = flags.get_mut(bidx) {
|
||||
*out = *b;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
bidx += 1;
|
||||
}
|
||||
|
@ -226,6 +242,7 @@ impl GameProfile {
|
|||
weapon_data,
|
||||
items,
|
||||
teleporter_slots,
|
||||
map_flags,
|
||||
flags,
|
||||
}
|
||||
}
|
||||
|
@ -333,8 +350,8 @@ impl GameProfile {
|
|||
slot.event_num = data.read_u32::<LE>()?;
|
||||
}
|
||||
|
||||
let mut something = [0u8; 0x80];
|
||||
data.read_exact(&mut something)?;
|
||||
let mut map_flags = [0u8; 0x80];
|
||||
data.read_exact(&mut map_flags)?;
|
||||
|
||||
if data.read_u32::<BE>()? != 0x464c4147 {
|
||||
return Err(ResourceLoadError(str!("Invalid FLAG signature")));
|
||||
|
@ -360,6 +377,7 @@ impl GameProfile {
|
|||
weapon_data,
|
||||
items,
|
||||
teleporter_slots,
|
||||
map_flags,
|
||||
flags,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -91,6 +91,7 @@ pub struct SharedGameState {
|
|||
pub control_flags: ControlFlags,
|
||||
pub game_flags: BitVec,
|
||||
pub skip_flags: BitVec,
|
||||
pub map_flags: BitVec,
|
||||
pub fade_state: FadeState,
|
||||
/// RNG used by game state, using it for anything else might cause unintended side effects and break replays.
|
||||
pub game_rng: XorShift,
|
||||
|
@ -163,6 +164,7 @@ impl SharedGameState {
|
|||
control_flags: ControlFlags(0),
|
||||
game_flags: bitvec::bitvec![0; 8000],
|
||||
skip_flags: bitvec::bitvec![0; 64],
|
||||
map_flags: bitvec::bitvec![0; 64],
|
||||
fade_state: FadeState::Hidden,
|
||||
game_rng: XorShift::new(0),
|
||||
effect_rng: XorShift::new(123),
|
||||
|
@ -236,6 +238,8 @@ impl SharedGameState {
|
|||
next_scene.player1.cond.set_alive(true);
|
||||
next_scene.player1.x = 10 * 16 * 0x200;
|
||||
next_scene.player1.y = 8 * 16 * 0x200;
|
||||
|
||||
self.reset_map_flags();
|
||||
self.fade_state = FadeState::Hidden;
|
||||
self.textscript_vm.state = TextScriptExecutionState::Running(200, 0);
|
||||
|
||||
|
@ -253,6 +257,8 @@ impl SharedGameState {
|
|||
next_scene.player1.x = 3 * 16 * 0x200;
|
||||
next_scene.player1.y = 3 * 16 * 0x200;
|
||||
next_scene.intro_mode = true;
|
||||
|
||||
self.reset_map_flags();
|
||||
self.fade_state = FadeState::Hidden;
|
||||
self.textscript_vm.state = TextScriptExecutionState::Running(100, 0);
|
||||
|
||||
|
@ -387,4 +393,24 @@ impl SharedGameState {
|
|||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_map_flags(&mut self) {
|
||||
self.map_flags = bitvec::bitvec![0; 128];
|
||||
}
|
||||
|
||||
pub fn set_map_flag(&mut self, id: usize, value: bool) {
|
||||
if id < self.map_flags.len() {
|
||||
self.map_flags.set(id, value);
|
||||
} else {
|
||||
log::warn!("Attempted to set an out-of-bounds map flag {}:", id);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_map_flag(&self, id: usize) -> bool {
|
||||
if let Some(flag) = self.map_flags.get(id) {
|
||||
*flag
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -974,6 +974,16 @@ impl TextScriptVM {
|
|||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||
}
|
||||
}
|
||||
OpCode::MPJ => {
|
||||
let event_num = read_cur_varint(&mut cursor)? as u16;
|
||||
|
||||
if state.get_map_flag(game_scene.stage_id) {
|
||||
state.textscript_vm.clear_text_box();
|
||||
exec_state = TextScriptExecutionState::Running(event_num, 0);
|
||||
} else {
|
||||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||
}
|
||||
}
|
||||
OpCode::ITJ => {
|
||||
let item_id = read_cur_varint(&mut cursor)? as u16;
|
||||
let event_num = read_cur_varint(&mut cursor)? as u16;
|
||||
|
@ -1090,8 +1100,8 @@ impl TextScriptVM {
|
|||
npc.x = pos_x as i32 * 16 * 0x200;
|
||||
npc.y = pos_y as i32 * 16 * 0x200;
|
||||
|
||||
game_scene.npc_list.spawn(0x100, npc.clone())?;
|
||||
game_scene.npc_list.spawn(0x100, npc)?;
|
||||
let _ = game_scene.npc_list.spawn(0x100, npc.clone());
|
||||
let _ = game_scene.npc_list.spawn(0x100, npc);
|
||||
}
|
||||
|
||||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||
|
@ -1269,10 +1279,10 @@ impl TextScriptVM {
|
|||
npc.x = partner.x;
|
||||
npc.y = partner.y;
|
||||
|
||||
game_scene.npc_list.spawn(0x100, npc.clone())?;
|
||||
game_scene.npc_list.spawn(0x100, npc.clone())?;
|
||||
game_scene.npc_list.spawn(0x100, npc.clone())?;
|
||||
game_scene.npc_list.spawn(0x100, npc)?;
|
||||
let _ = game_scene.npc_list.spawn(0x100, npc.clone());
|
||||
let _ = game_scene.npc_list.spawn(0x100, npc.clone());
|
||||
let _ = game_scene.npc_list.spawn(0x100, npc.clone());
|
||||
let _ = game_scene.npc_list.spawn(0x100, npc);
|
||||
|
||||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||
}
|
||||
|
@ -1537,7 +1547,7 @@ impl TextScriptVM {
|
|||
npc.direction = direction;
|
||||
}
|
||||
|
||||
game_scene.npc_list.spawn(0x100, npc)?;
|
||||
let _ = game_scene.npc_list.spawn(0x100, npc);
|
||||
|
||||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||
}
|
||||
|
@ -1677,6 +1687,13 @@ impl TextScriptVM {
|
|||
|
||||
exec_state = TextScriptExecutionState::LoadProfile;
|
||||
}
|
||||
OpCode::MPp => {
|
||||
let stage_id = read_cur_varint(&mut cursor)? as u16;
|
||||
|
||||
state.set_map_flag(stage_id as usize, true);
|
||||
|
||||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||
}
|
||||
// unimplemented opcodes
|
||||
// Zero operands
|
||||
OpCode::CIL
|
||||
|
@ -1694,9 +1711,7 @@ impl TextScriptVM {
|
|||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||
}
|
||||
// One operand codes
|
||||
OpCode::MPp
|
||||
| OpCode::UNJ
|
||||
| OpCode::MPJ
|
||||
OpCode::UNJ
|
||||
| OpCode::XX1
|
||||
| OpCode::SIL
|
||||
| OpCode::SSS
|
||||
|
|
Loading…
Reference in a new issue