~quf/tocs

7b806320f5eee6de81353a6067b69c328933669b — Lukas Himbert 5 months ago 561396e
ActionTable/AlgoTable research
4 files changed, 223 insertions(+), 180 deletions(-)

M sqlite_conv/src/main.rs
M tocs/src/script/deser.rs
M tocs/src/script/mod.rs
M tocs/src/script/ser.rs
M sqlite_conv/src/main.rs => sqlite_conv/src/main.rs +97 -84
@@ 222,39 222,48 @@ fn scripts_to_new_db<P: AsRef<std::path::Path>>(base_path: P, dbpath: P) {
    tx.execute(
        "create table ActionTable (
    file_name text not null,

    id int,
    unk1 int,
    unk2 blob,
    unk3 real,
    category int,
    target_type int,
    target_range int,
    target_size int,

    unk4 real,
    unk5 real,
    unk10 blob,
    unk11 int,
    unk12 int,
    unk13 int,
    unk14 int,
    unk15 int,
    unk16 int,
    unk17_1 int,
    unk17_2 int,
    unk17_3 int,
    unk17_4 int,
    unk17_5 int,
    unk17_6 int,
    unk17_7 int,
    unk17_8 int,
    unk17_9 int,
    unk17_10 int,
    unk17_11 int,
    unk17_12 int,
    unk17_13 int,
    unk17_14 int,
    unk17_15 int,
    unk6 real,

    cast_delay int,
    recovery_delay int,

    eff_1 int,
    param_1_1 int,
    param_1_2 int,
    param_1_3 int,
    eff_2 int,
    param_2_1 int,
    param_2_2 int,
    param_2_3 int,
    eff_3 int,
    param_3_1 int,
    param_3_2 int,
    param_3_3 int,
    eff_4 int,
    param_4_1 int,
    param_4_2 int,
    param_4_3 int,
    eff_5 int,
    param_5_1 int,
    param_5_2 int,
    param_5_3 int,

    unk10 int,

    unk18 int,
    unk19 int,
    flags text,
    animation text,
    name text,

    foreign key(file_name) references scripts(file_name)
) strict;",
        [],


@@ 268,15 277,15 @@ fn scripts_to_new_db<P: AsRef<std::path::Path>>(base_path: P, dbpath: P) {
    condition int,
    chance int,
    use_limit int,
    target_type int,
    target_priority int,
    unk_byte_1 int,
    unk_byte_2 int,
    param_1 int,
    param_2 int,
    param_3 int,
    param_4 int,
    param_5 int,
    param_6 int,
    cond_param_1 int,
    cond_param_2 int,
    cond_param_3 int,
    target_param int,
    use_limit_after_retry int,
    unk6 int,
    foreign key(file_name) references scripts(file_name)
) strict;",
        [],


@@ 341,60 350,59 @@ fn insert_script_entry_data(tx: &rusqlite::Transaction, script_name: &str, entry
        ScriptEntry::ActionTable(entries) => {
            for ActionTableEntry {
                id,
                unk1,
                unk2,
                unk3,
                category,
                target_type,
                target_range,
                target_size,
                unk4,
                unk5,
                unk6,
                cast_delay,
                recovery_delay,
                effects,
                unk10,
                unk11,
                unk12,
                unk13,
                unk14,
                unk15,
                unk16,
                unk17,
                unk18,
                unk19,
                flags,
                animation,
                name,
            } in entries
            {
                tx.execute(
                    "insert into ActionTable values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
                    "insert into ActionTable values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
                    &[
                        &script_name as &dyn rusqlite::types::ToSql,
                        &id as _,
                        &unk1 as _,
                        &unk2 as _,
                        &unk3 as _,
                        &category as _,
                        &target_type as _,
                        &target_range as _,
                        &target_size as _,
                        &unk4 as _,
                        &unk5 as _,
                        &unk6 as _,
                        &cast_delay as _,
                        &recovery_delay as _,
                        &effects[0].id as _,
                        &effects[0].parameters[0] as _,
                        &effects[0].parameters[1] as _,
                        &effects[0].parameters[2] as _,
                        &effects[1].id as _,
                        &effects[1].parameters[0] as _,
                        &effects[1].parameters[1] as _,
                        &effects[1].parameters[2] as _,
                        &effects[2].id as _,
                        &effects[2].parameters[0] as _,
                        &effects[2].parameters[1] as _,
                        &effects[2].parameters[2] as _,
                        &effects[3].id as _,
                        &effects[3].parameters[0] as _,
                        &effects[3].parameters[1] as _,
                        &effects[3].parameters[2] as _,
                        &effects[4].id as _,
                        &effects[4].parameters[0] as _,
                        &effects[4].parameters[1] as _,
                        &effects[4].parameters[2] as _,
                        &unk10 as _,
                        &unk11 as _,
                        &unk12 as _,
                        &unk13 as _,
                        &unk14 as _,
                        &unk15 as _,
                        &unk16 as _,
                        &unk17[0] as _,
                        &unk17[1] as _,
                        &unk17[2] as _,
                        &unk17[3] as _,
                        &unk17[4] as _,
                        &unk17[5] as _,
                        &unk17[6] as _,
                        &unk17[7] as _,
                        &unk17[8] as _,
                        &unk17[9] as _,
                        &unk17[10] as _,
                        &unk17[11] as _,
                        &unk17[12] as _,
                        &unk17[13] as _,
                        &unk17[14] as _,
                        &unk18 as _,
                        &unk19 as _,
                        &flags.as_str() as _,
                        &animation.as_str() as _,
                        &name.as_str() as _,


@@ 409,10 417,15 @@ fn insert_script_entry_data(tx: &rusqlite::Transaction, script_name: &str, entry
                condition,
                chance,
                use_limit,
                target_type,
                target_priority,
                unk_byte_1,
                unk_byte_2,
                params,
                cond_param_1,
                cond_param_2,
                cond_param_3,
                target_param,
                use_limit_after_retry,
                unk6,
            } in entries
            {
                tx.execute(


@@ 420,18 433,18 @@ fn insert_script_entry_data(tx: &rusqlite::Transaction, script_name: &str, entry
                    &[
                        &script_name as &dyn rusqlite::types::ToSql,
                        &action_or_magic_id as _,
                        &condition as &_,
                        &chance as &_,
                        &use_limit as &_,
                        &target_type as &_,
                        &unk_byte_1 as &_,
                        &unk_byte_2 as &_,
                        &params[0] as &_,
                        &params[1] as &_,
                        &params[2] as &_,
                        &params[3] as &_,
                        &params[4] as &_,
                        &params[5] as &_,
                        &condition as _,
                        &chance as _,
                        &use_limit as _,
                        &target_priority as _,
                        &unk_byte_1 as _,
                        &unk_byte_2 as _,
                        &cond_param_1 as _,
                        &cond_param_2 as _,
                        &cond_param_3 as _,
                        &target_param as _,
                        &use_limit_after_retry as _,
                        &unk6 as _,
                    ] as &[_],
                )
                .unwrap();

M tocs/src/script/deser.rs => tocs/src/script/deser.rs +64 -49
@@ 1,4 1,4 @@
use super::{ActionTableEntry, AlgoTableEntry, Script, ScriptEntry, ScriptNamePadding};
use super::{ActionTableEntry, AlgoTableEntry, Effect, Script, ScriptEntry, ScriptNamePadding};

use crate::io::MemReader;



@@ 147,42 147,53 @@ pub fn read_action_table_entries(data: &[u8]) -> Option<std::vec::Vec<ActionTabl

    while !reader.at_end() {
        let id = reader.read_i16_le()?;
        let category = reader.read_u16_le()?;

        let target_type = reader.read_u8()?;
        let target_range = reader.read_u8()?;
        let target_size = reader.read_u16_le()?;

        let unk1 = reader.read_u16_le()?;
        let unk2 = reader.read_chunk::<4>()?;
        let unk3 = reader.read_f32_le()?;
        let unk4 = reader.read_f32_le()?;
        let unk5 = reader.read_f32_le()?;
        let unk6 = reader.read_f32_le()?;

        let cast_delay = reader.read_u16_le()?;
        let recovery_delay = reader.read_u16_le()?;

        let unk10 = reader.read_chunk::<4>()?;

        let unk11 = reader.read_u16_le()?;
        let unk12 = reader.read_u16_le()?;
        let unk13 = reader.read_u16_le()?;
        let unk14 = reader.read_u16_le()?;
        let unk15 = reader.read_u16_le()?;
        let unk16 = reader.read_u16_le()?;

        let unk17: [i32; 15] = [
            reader.read_i32_le()?,
            reader.read_i32_le()?,
            reader.read_i32_le()?,
            reader.read_i32_le()?,
            reader.read_i32_le()?,
            reader.read_i32_le()?,
            reader.read_i32_le()?,
            reader.read_i32_le()?,
            reader.read_i32_le()?,
            reader.read_i32_le()?,
            reader.read_i32_le()?,
            reader.read_i32_le()?,
            reader.read_i32_le()?,
            reader.read_i32_le()?,
            reader.read_i32_le()?,
        let mut effect_ids = <[u16; 5]>::default();
        let mut all_parameters = <[i32; 15]>::default();
        for id in effect_ids.iter_mut() {
            *id = reader.read_u16_le()?;
        }
        let unk10 = reader.read_u16_le()?;
        for param in all_parameters.iter_mut() {
            *param = reader.read_i32_le()?;
        }

        let effects = [
            Effect {
                id: effect_ids[0],
                parameters: [all_parameters[0], all_parameters[1], all_parameters[2]],
            },
            Effect {
                id: effect_ids[1],
                parameters: [all_parameters[3], all_parameters[4], all_parameters[5]],
            },
            Effect {
                id: effect_ids[2],
                parameters: [all_parameters[6], all_parameters[7], all_parameters[8]],
            },
            Effect {
                id: effect_ids[3],
                parameters: [all_parameters[9], all_parameters[10], all_parameters[11]],
            },
            Effect {
                id: effect_ids[4],
                parameters: [all_parameters[12], all_parameters[13], all_parameters[14]],
            },
        ];

        let unk18 = reader.read_u16_le()?;
        let unk19 = reader.read_u16_le()?;
        let unk18 = reader.read_u32_le()?;

        let flags = reader.read_padded_ascii_str::<16>().ok()?.to_owned();
        let animation = reader.read_padded_utf8_str::<32>().ok()?.to_owned();


@@ 190,21 201,18 @@ pub fn read_action_table_entries(data: &[u8]) -> Option<std::vec::Vec<ActionTabl

        entries.push(ActionTableEntry {
            id,
            unk1,
            unk2,
            unk3,
            category,
            target_type,
            target_range,
            target_size,
            unk4,
            unk5,
            unk6,
            cast_delay,
            recovery_delay,
            effects,
            unk10,
            unk11,
            unk12,
            unk13,
            unk14,
            unk15,
            unk16,
            unk17,
            unk18,
            unk19,
            flags,
            animation,
            name,


@@ 223,23 231,30 @@ pub fn read_algo_table_entries(data: &[u8]) -> Option<std::vec::Vec<AlgoTableEnt
        let condition = reader.read_byte()?;
        let chance = reader.read_byte()?;
        let use_limit = reader.read_byte()?;
        let target_type = reader.read_byte()?;
        let target_priority = reader.read_byte()?;
        let unk_byte_1 = reader.read_byte()?;
        let unk_byte_2 = reader.read_byte()?;
        let mut params = [0u32; 6];
        for x in params.iter_mut() {
            *x = reader.read_u32_le()?;
        }
        let cond_param_1 = reader.read_u32_le()?;
        let cond_param_2 = reader.read_u32_le()?;
        let cond_param_3 = reader.read_u32_le()?;
        let target_param = reader.read_u32_le()?;
        let use_limit_after_retry = reader.read_u32_le()?;
        let unk6 = reader.read_u32_le()?;

        entries.push(AlgoTableEntry {
            action_or_magic_id,
            condition,
            chance,
            use_limit,
            target_type,
            target_priority,
            unk_byte_1,
            unk_byte_2,
            params,
            cond_param_1,
            cond_param_2,
            cond_param_3,
            target_param,
            use_limit_after_retry,
            unk6,
        });
    }


M tocs/src/script/mod.rs => tocs/src/script/mod.rs +24 -16
@@ 53,39 53,47 @@ impl ScriptEntry {
#[derive(Debug)]
pub struct ActionTableEntry {
    pub id: i16,
    pub unk1: u16,
    pub unk2: [u8; 4],
    pub unk3: f32,
    pub category: u16,
    pub target_type: u8,
    pub target_range: u8,
    pub target_size: u16,

    pub unk4: f32,
    pub unk5: f32,
    pub unk6: f32,

    pub unk10: [u8; 4],

    pub unk11: u16,
    pub unk12: u16,
    pub unk13: u16,
    pub unk14: u16,
    pub unk15: u16,
    pub unk16: u16,
    pub cast_delay: u16,
    pub recovery_delay: u16,

    pub unk17: [i32; 15],
    pub effects: [Effect; 5],
    pub unk10: u16,

    pub unk18: u16,
    pub unk19: u16,
    pub unk18: u32, // cost?

    pub flags: PaddedAsciiString<16>,
    pub animation: PaddedUtf8String<32>,
    pub name: PaddedUtf8String<64>,
}

#[derive(Debug, Clone, Copy)]
pub struct Effect {
    pub id: u16,
    pub parameters: [i32; 3],
}

#[derive(Debug)]
pub struct AlgoTableEntry {
    pub action_or_magic_id: i16,
    pub condition: u8,
    pub chance: u8,
    pub use_limit: u8,
    pub target_type: u8,
    pub target_priority: u8,
    pub unk_byte_1: u8,
    pub unk_byte_2: u8,
    pub params: [u32; 6],
    pub cond_param_1: u32,
    pub cond_param_2: u32,
    pub cond_param_3: u32,
    pub target_param: u32,
    pub use_limit_after_retry: u32,
    pub unk6: u32,
}

M tocs/src/script/ser.rs => tocs/src/script/ser.rs +38 -31
@@ 144,43 144,42 @@ impl ActionTableEntry {
    fn serialize_data(&self, writer: &mut MemWriter) -> Option<()> {
        let Self {
            id,
            unk1,
            unk2,
            unk3,
            category,
            target_type,
            target_range,
            target_size,
            unk4,
            unk5,
            unk6,
            cast_delay,
            recovery_delay,
            effects,
            unk10,
            unk11,
            unk12,
            unk13,
            unk14,
            unk15,
            unk16,
            unk17,
            unk18,
            unk19,
            flags,
            animation,
            name,
        } = self;
        writer.write_i16_le(*id);
        writer.write_u16_le(*unk1);
        writer.write_data(unk2.as_slice());
        writer.write_f32_le(*unk3);
        writer.write_u16_le(*category);
        writer.write_u8(*target_type);
        writer.write_u8(*target_range);
        writer.write_u16_le(*target_size);
        writer.write_f32_le(*unk4);
        writer.write_f32_le(*unk5);
        writer.write_data(unk10.as_slice());
        writer.write_u16_le(*unk11);
        writer.write_u16_le(*unk12);
        writer.write_u16_le(*unk13);
        writer.write_u16_le(*unk14);
        writer.write_u16_le(*unk15);
        writer.write_u16_le(*unk16);
        for x in unk17 {
            writer.write_i32_le(*x);
        writer.write_f32_le(*unk6);
        writer.write_u16_le(*cast_delay);
        writer.write_u16_le(*recovery_delay);
        for eff in effects.iter() {
            writer.write_u16_le(eff.id);
        }
        writer.write_u16_le(*unk10);
        for eff in effects.iter() {
            for param in eff.parameters {
                writer.write_i32_le(param);
            }
        }
        writer.write_u16_le(*unk18);
        writer.write_u16_le(*unk19);
        writer.write_u32_le(*unk18);
        writer.write_padded_ascii_str(flags.as_padded_ascii_str());
        writer.write_padded_utf8_str(animation.as_padded_utf8_str());
        writer.write_padded_utf8_str(name.as_padded_utf8_str());


@@ 196,21 195,29 @@ impl AlgoTableEntry {
            condition,
            chance,
            use_limit,
            target_type,
            target_priority,
            unk_byte_1,
            unk_byte_2,
            params,
            cond_param_1,
            cond_param_2,
            cond_param_3,
            target_param,
            use_limit_after_retry,
            unk6,
        } = self;
        writer.write_i16_le(*action_or_magic_id);
        writer.write_u8(*condition);
        writer.write_u8(*chance);
        writer.write_u8(*use_limit);
        writer.write_u8(*target_type);
        writer.write_u8(*target_priority);
        writer.write_u8(*unk_byte_1);
        writer.write_u8(*unk_byte_2);
        for x in params {
            writer.write_u32_le(*x);
        }
        writer.write_u32_le(*cond_param_1);
        writer.write_u32_le(*cond_param_2);
        writer.write_u32_le(*cond_param_3);
        writer.write_u32_le(*target_param);
        writer.write_u32_le(*use_limit_after_retry);
        writer.write_u32_le(*unk6);
        Some(())
    }
}