Skip to content

Commit

Permalink
pal4: fix gob parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
dontpanic92 committed May 14, 2024
1 parent b843a15 commit 9f02edc
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 32 deletions.
110 changes: 99 additions & 11 deletions yaobow/fileformats/src/pal4/gob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,11 @@ pub struct GobEntry {
pub unknown7: f32,
pub unknown8: u32,

pub game_object_magic: u32,
pub game_object: GobPropertyI32,

#[br(count = game_object.value)]
pub properties: Vec<GobProperty>,

pub prameters_magic: u32,
pub prameters_begin: GobPropertyI32,

#[br(parse_with = parse_properties)]
Expand Down Expand Up @@ -113,28 +111,84 @@ fn parse_properties() -> BinResult<Vec<GobProperty>> {
reader.seek(SeekFrom::Current(-4))?;
}

println!(
" parse_properties cursor position: {}",
reader.stream_position()?
);

let property = GobProperty::read_options(reader, endian, ())?;
println!(
" parse_properties completed cursor position: {}",
reader.stream_position()?
);
properties.push(property);
}

Ok(properties)
}

#[derive(Debug, BinRead, Serialize)]
#[brw(little)]
#[derive(Debug, Serialize)]
pub enum GobProperty {
#[br(magic(0x1u32))]
GobPropertyI32(GobPropertyI32),

#[br(magic(0x2u32))]
GobPropertyF32(GobPropertyF32),

#[br(magic(0x3u32))]
GobPropertyString(GobPropertyString),

GobPropertyObjectArray(GobPropertyObjectArray),
}

impl BinRead for GobProperty {
type Args<'a> = ();

fn read_options<R: std::io::prelude::Read + std::io::prelude::Seek>(
reader: &mut R,
endian: binrw::Endian,
_: Self::Args<'_>,
) -> BinResult<Self> {
let start_position = reader.stream_position()?;
println!(
"GobProperty::read_options cursor position: {}",
start_position
);
let ty = reader.read_u32_le()?;
let name = SizedString::read_options(reader, endian, ())?;
reader.seek(SeekFrom::Start(start_position))?;

if name == "PAL4_GameObject-machine-condition" || name == "PAL4-GOMTask-[ 0 ]" {
return Ok(Self::GobPropertyObjectArray(
GobPropertyObjectArray::read_options(reader, endian, ())?,
));
} else {
println!(
"GobProperty::read_options reading ty {} at cursor position: {}",
ty, start_position
);
match ty {
1 => Ok(Self::GobPropertyI32(GobPropertyI32::read_options(
reader,
endian,
(),
)?)),
2 => Ok(Self::GobPropertyF32(GobPropertyF32::read_options(
reader,
endian,
(),
)?)),
3 => Ok(Self::GobPropertyString(GobPropertyString::read_options(
reader,
endian,
(),
)?)),
_ => {
unreachable!(
"Unknown array name: {:?} at position {}",
name.to_string(),
start_position
);
}
}
}
}
}

impl GobProperty {
pub fn name(&self) -> &str {
match self {
Expand Down Expand Up @@ -189,11 +243,21 @@ impl BinRead for GobPropertyObjectArray {

let count = reader.read_u32_le()?;
reader.seek(SeekFrom::Current(-4))?;
for _ in 0..count {
for i in 0..count {
println!(
" GobPropertyObjectArray::read_options {} cursor position: {}",
i,
reader.stream_position()?
);
let _ = reader.read_u32_le()?;

let obj = GobObject::read_options(reader, endian, ())?;
properties.push(obj);
println!(
" GobPropertyObjectArray::read_options {} completed cursor position: {}",
i,
reader.stream_position()?
);
}

Ok(Self(properties))
Expand All @@ -203,6 +267,8 @@ impl BinRead for GobPropertyObjectArray {
#[derive(Debug, BinRead, Serialize)]
#[brw(little)]
pub struct GobPropertyI32 {
pub ty: u32,

#[br(parse_with = parse_sized_string)]
pub name: String,
pub value: i32,
Expand All @@ -211,6 +277,8 @@ pub struct GobPropertyI32 {
#[derive(Debug, BinRead, Serialize)]
#[brw(little)]
pub struct GobPropertyF32 {
pub ty: u32,

#[br(parse_with = parse_sized_string)]
pub name: String,
pub value: f32,
Expand All @@ -219,6 +287,8 @@ pub struct GobPropertyF32 {
#[derive(Debug, BinRead, Serialize)]
#[brw(little)]
pub struct GobPropertyString {
pub ty: u32,

#[br(parse_with = parse_sized_string)]
pub name: String,

Expand All @@ -236,3 +306,21 @@ pub struct GobObject {
#[br(count = prop_count)]
pub properties: Vec<GobProperty>,
}

#[cfg(test)]
mod tests {
use std::fs::File;
use std::io::BufReader;

use super::*;

#[test]
fn test_gob() {
let file =
File::open("F:\\PAL4\\gamedata\\scenedata\\scenedata\\M01\\1\\GameObjs.gob").unwrap();
let mut reader = BufReader::new(file);
let gob_file = GobFile::read(&mut reader).unwrap();

println!("{:#?}", gob_file);
}
}
2 changes: 1 addition & 1 deletion yaobow/shared/src/openpal4/actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ fn get_camera_height(
current_height: f32,
delta_sec: f32,
) -> f32 {
const SPEED: f32 = 50.;
const SPEED: f32 = 100.;

let mut height = current_height;
if input
Expand Down
62 changes: 44 additions & 18 deletions yaobow/shared/src/openpal4/scene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ pub struct Pal4Scene {
pub(crate) triggers: Vec<Rc<SceneEventTrigger>>,
}

const SHOW_TRIGGER_POINT: bool = false;
const SHOW_FLOOR: bool = false;
const SHOW_WALL: bool = false;

impl Pal4Scene {
const ID_YUN_TIANHE: usize = 0;
const ID_HAN_LINGSHA: usize = 1;
Expand Down Expand Up @@ -114,13 +118,17 @@ impl Pal4Scene {
let wall = asset_loader.load_scene_wall(scene_name, block_name);
let ray_caster = create_floor_wall_ray_caster(floor.clone(), wall.clone());

/*if let Some(floor) = floor {
scene.add_entity(floor);
if SHOW_FLOOR {
if let Some(floor) = floor {
scene.add_entity(floor);
}
}

if let Some(wall) = wall {
scene.add_entity(wall);
}*/
if SHOW_WALL {
if let Some(wall) = wall {
scene.add_entity(wall);
}
}

let players = [
load_player(asset_loader, Player::YunTianhe),
Expand All @@ -133,10 +141,6 @@ impl Pal4Scene {

let mut triggers = vec![];
for (i, event) in events.events.iter().enumerate() {
if event.vertex_count != 8 {
continue;
}

let trigger = event
.vertices
.iter()
Expand All @@ -149,8 +153,18 @@ impl Pal4Scene {
})
.collect::<Vec<_>>();

// let entity = create_box_entity2(asset_loader.component_factory(), trigger.clone());
// scene.add_entity(entity);
if SHOW_TRIGGER_POINT {
for point in &trigger {
let entity =
radiance::debug::create_box_entity(asset_loader.component_factory());
entity.transform().borrow_mut().set_position(point);
scene.add_entity(entity);
}
}

if event.vertex_count != 8 && event.vertex_count != 4 {
continue;
}

let ray_caster = create_trigger_ray_caster(trigger);
triggers.push(Rc::new(SceneEventTrigger {
Expand Down Expand Up @@ -422,15 +436,27 @@ impl SceneEventTrigger {
}
}

lazy_static::lazy_static! {
pub static ref BOX_TRIGGER_INDICES: Vec<u32> = vec![
0, 2, 1, 0, 3, 2, 0, 4, 7, 0, 7, 3, 0, 5, 4, 0, 1, 5, 6, 1, 2, 6, 5, 1, 6, 2, 3, 6, 3,
7, 6, 7, 4, 6, 4, 5,
];

pub static ref PLANE_TRIGGER_INDICES: Vec<u32> = vec![0, 1, 2, 2, 1, 3];
}

fn create_trigger_ray_caster(trigger: Vec<Vec3>) -> RayCaster {
let mut ray_caster = RayCaster::new();
ray_caster.add_mesh(
trigger,
vec![
0, 2, 1, 0, 3, 2, 0, 4, 7, 0, 7, 3, 0, 5, 4, 0, 1, 5, 6, 1, 2, 6, 5, 1, 6, 2, 3, 6, 3,
7, 6, 7, 4, 6, 4, 5,
],
);
match trigger.len() {
4 => {
println!("trigger: {:?}", trigger);
ray_caster.add_mesh(trigger, PLANE_TRIGGER_INDICES.clone());
}
8 => {
ray_caster.add_mesh(trigger, BOX_TRIGGER_INDICES.clone());
}
_ => panic!("Invalid trigger point count"),
}

ray_caster
}
3 changes: 2 additions & 1 deletion yaobow/shared/src/openpal4/scripting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2038,7 +2038,8 @@ fn talk(_: &str, vm: &mut ScriptVm<Pal4AppContext>) -> Pal4FunctionState {
let input = input.borrow();
let completed = ui.ui().is_mouse_released(MouseButton::Left)
|| input.get_key_state(Key::GamePadEast).pressed()
|| input.get_key_state(Key::GamePadSouth).pressed();
|| input.get_key_state(Key::GamePadSouth).pressed()
|| input.get_key_state(Key::Space).pressed();
if completed {
vm.app_context
.dialog_box
Expand Down
2 changes: 1 addition & 1 deletion yaobow/yaobow/src/openpal4/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl OpenPal4ApplicationLoader {
fn new(app: ComRc<IApplication>, app_name: &str) -> Self {
Self {
app,
root_path: PathBuf::from("F:\\PAL4_test"), //PathBuf::from("F:\\SteamLibrary\\steamapps\\common\\Chinese Paladin 4"),
root_path: PathBuf::from("F:\\SteamLibrary\\steamapps\\common\\Chinese Paladin 4"), //PathBuf::from("F:\\PAL4_test"),
app_name: app_name.to_owned(),
}
}
Expand Down

0 comments on commit 9f02edc

Please sign in to comment.