split phy module
parent
fb0ecffd74
commit
7a231fb351
|
@ -1,707 +1,12 @@
|
|||
//! Structures used by Marathon's Physics format.
|
||||
|
||||
use crate::{durandal::{bin::*, err::*, fixed::*}};
|
||||
use bitflags::bitflags;
|
||||
|
||||
/// Reads a `PXpx` chunk.
|
||||
pub fn read_pxpx(b: &[u8]) -> ResultS<(Physics, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 104, start: 0, data {
|
||||
let vel_fwd = Fixed[0];
|
||||
let vel_bkw = Fixed[4];
|
||||
let vel_prp = Fixed[8];
|
||||
let acc_nrm = Fixed[12];
|
||||
let dec_nrm = Fixed[16];
|
||||
let dec_air = Fixed[20];
|
||||
let acc_grv = Fixed[24];
|
||||
let acc_cli = Fixed[28];
|
||||
let vel_trm = Fixed[32];
|
||||
let dec_ext = Fixed[36];
|
||||
let acc_ang = Fixed[40];
|
||||
let dec_ang = Fixed[44];
|
||||
let vel_ang = Fixed[48];
|
||||
let vel_rec = Fixed[52];
|
||||
let fng_vel = Fixed[56];
|
||||
let fng_max = Fixed[60];
|
||||
let ele_max = Fixed[64];
|
||||
let dec_xng = Fixed[68];
|
||||
let stp_dta = Fixed[72];
|
||||
let stp_amp = Fixed[76];
|
||||
let ply_rad = Fixed[80];
|
||||
let ply_hei = Fixed[84];
|
||||
let ply_dhi = Fixed[88];
|
||||
let ply_cam = Fixed[92];
|
||||
let ply_spl = Fixed[96];
|
||||
let ply_hcm = Fixed[100];
|
||||
}
|
||||
}
|
||||
|
||||
Ok((Physics{acc_ang, acc_cli, acc_grv, acc_nrm, dec_air, dec_ang, dec_ext,
|
||||
dec_nrm, dec_xng, ele_max, fng_max, fng_vel, ply_cam, ply_dhi,
|
||||
ply_hcm, ply_hei, ply_rad, ply_spl, stp_amp, stp_dta, vel_ang,
|
||||
vel_bkw, vel_fwd, vel_prp, vel_rec, vel_trm}, 104))
|
||||
}
|
||||
|
||||
/// Reads a `FXpx` chunk.
|
||||
pub fn read_fxpx(b: &[u8]) -> ResultS<(Effect, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 14, start: 0, data {
|
||||
let collection = u16[0];
|
||||
let shape = u16[2];
|
||||
let pitch = Fixed[4];
|
||||
let flags = u16[8] flag EffectFlags;
|
||||
let delay = OptU16[10];
|
||||
let delay_snd = OptU16[12];
|
||||
}
|
||||
}
|
||||
|
||||
Ok((Effect{collection, shape, pitch, flags, delay, delay_snd}, 14))
|
||||
}
|
||||
|
||||
/// Reads a `WPpx` chunk.
|
||||
pub fn read_wppx(b: &[u8]) -> ResultS<(Weapon, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 134, start: 0, data {
|
||||
let typ_item = u16[0];
|
||||
let typ_powerup = OptU16[2];
|
||||
let typ_weapon = u16[4] enum WeaponType;
|
||||
let flags = u16[6] flag WeaponFlags;
|
||||
let lit_value = Fixed[8];
|
||||
let lit_decay = u16[12];
|
||||
let hei_idle = Fixed[14];
|
||||
let amp_bob = Fixed[18];
|
||||
let hei_kick = Fixed[22];
|
||||
let hei_reload = Fixed[26];
|
||||
let wid_idle = Fixed[30];
|
||||
let amp_horz = Fixed[34];
|
||||
let collection = u16[38];
|
||||
let frm_idle = u16[40];
|
||||
let frm_firing = u16[42];
|
||||
let frm_reload = OptU16[44];
|
||||
let frm_charge = OptU16[48];
|
||||
let frm_charged = OptU16[50];
|
||||
let tic_ready = u16[52];
|
||||
let tic_load_beg = u16[54];
|
||||
let tic_load_mid = u16[56];
|
||||
let tic_load_end = u16[58];
|
||||
let tic_powerup = u16[60];
|
||||
let trig_pri = read_trigger[62; 36];
|
||||
let trig_sec = read_trigger[98; 36];
|
||||
}
|
||||
}
|
||||
|
||||
Ok((Weapon{amp_bob, amp_horz, collection, flags, frm_charge, frm_charged,
|
||||
frm_firing, frm_idle, frm_reload, hei_idle, hei_kick, hei_reload,
|
||||
lit_decay, lit_value, tic_load_beg, tic_load_end, tic_load_mid,
|
||||
tic_powerup, tic_ready, trig_pri, trig_sec, typ_item,
|
||||
typ_powerup, typ_weapon, wid_idle}, 134))
|
||||
}
|
||||
|
||||
/// Reads a `PRpx` chunk.
|
||||
pub fn read_prpx(b: &[u8]) -> ResultS<(Projectile, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 48, start: 0, data {
|
||||
let collection = OptU16[0];
|
||||
let shape = u16[2];
|
||||
let fxt_explode = OptU16[4];
|
||||
let fxt_exp_media = OptU16[6];
|
||||
let fxt_trail = OptU16[8];
|
||||
let tic_trail = u16[10];
|
||||
let max_trail = OptU16[12];
|
||||
let typ_media = OptU16[14];
|
||||
let radius = Unit[16];
|
||||
let dmg_rad = Unit[18];
|
||||
let dmg_def = read_damage[20; 12];
|
||||
let flags = u32[32] flag ProjectileFlags;
|
||||
let speed = Unit[36];
|
||||
let range = Unit[38];
|
||||
let snd_pitch = Fixed[40];
|
||||
let snd_fly = OptU16[44];
|
||||
let snd_bounce = OptU16[46];
|
||||
}
|
||||
}
|
||||
|
||||
Ok((Projectile{collection, shape, fxt_explode, fxt_exp_media, fxt_trail,
|
||||
tic_trail, max_trail, typ_media, radius, dmg_rad, dmg_def,
|
||||
flags, speed, range, snd_pitch, snd_fly, snd_bounce}, 48))
|
||||
}
|
||||
|
||||
/// Reads a `MNpx` chunk.
|
||||
pub fn read_mnpx(b: &[u8]) -> ResultS<(Monster, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 156, start: 0, data {
|
||||
let collection = u16[0];
|
||||
let vitality = u16[2];
|
||||
let dty_immune = u32[4] flag DamageTypeFlags;
|
||||
let dty_weak = u32[8] flag DamageTypeFlags;
|
||||
let flags = u32[12] flag MonsterFlags;
|
||||
let cls_self = u32[16] flag MonsterClass;
|
||||
let cls_friend = u32[20];
|
||||
let cls_enemy = u32[24];
|
||||
let snd_pitch = Fixed[28];
|
||||
let snd_see_enemy = OptU16[32];
|
||||
let snd_see_friend = OptU16[34];
|
||||
let snd_seeclear = OptU16[36];
|
||||
let snd_kill = OptU16[38];
|
||||
let snd_apologize = OptU16[40];
|
||||
let snd_amicide = OptU16[42];
|
||||
let snd_flaming = OptU16[44];
|
||||
let snd_active = OptU16[46];
|
||||
let snd_active_mask = u16[48];
|
||||
let typ_item = OptU16[50];
|
||||
let radius = Unit[52];
|
||||
let height = Unit[54];
|
||||
let height_hover = Unit[56];
|
||||
let ledge_min = Unit[58];
|
||||
let ledge_max = Unit[60];
|
||||
let ext_vel_scale = Fixed[62];
|
||||
let fxt_impact = OptU16[66];
|
||||
let fxt_impact_melee = OptU16[68];
|
||||
let fxt_trail = OptU16[70];
|
||||
let half_fov_horz = u16[72];
|
||||
let half_fov_vert = u16[74];
|
||||
let view_range = Unit[76];
|
||||
let view_range_dark = Unit[78];
|
||||
let intelligence = u16[80];
|
||||
let speed = u16[82];
|
||||
let gravity = u16[84];
|
||||
let vel_terminal = u16[86];
|
||||
let door_try_mask = u16[88];
|
||||
let expl_radius = OptU16[90];
|
||||
let expl_damage = read_damage[92; 12];
|
||||
let seq_hit = OptU16[104];
|
||||
let seq_dying_hard = OptU16[106];
|
||||
let seq_dying_soft = OptU16[108];
|
||||
let seq_dead_hard = OptU16[110];
|
||||
let seq_dead_soft = OptU16[112];
|
||||
let seq_standing = u16[114];
|
||||
let seq_moving = u16[116];
|
||||
let seq_tele_in = OptU16[118];
|
||||
let seq_tele_out = OptU16[120];
|
||||
let atk_frequency = u16[122];
|
||||
let atk_melee = read_attack[124; 16];
|
||||
let atk_range = read_attack[140; 16];
|
||||
}
|
||||
}
|
||||
|
||||
// friend and enemy fields MUST truncate because the original source code
|
||||
// used `-1` to represent "all classes" which should be invalid normally
|
||||
|
||||
let cls_friend = MonsterClass::from_bits_truncate(cls_friend);
|
||||
let cls_enemy = MonsterClass::from_bits_truncate(cls_enemy);
|
||||
|
||||
Ok((Monster{collection, vitality, dty_immune, dty_weak, flags, cls_self,
|
||||
cls_friend, cls_enemy, snd_pitch, snd_see_enemy, snd_see_friend,
|
||||
snd_seeclear, snd_kill, snd_apologize, snd_amicide, snd_flaming,
|
||||
snd_active, snd_active_mask, typ_item, radius, height,
|
||||
height_hover, ledge_min, ledge_max, ext_vel_scale, fxt_impact,
|
||||
fxt_impact_melee, fxt_trail, half_fov_horz, half_fov_vert,
|
||||
view_range, view_range_dark, intelligence, speed, gravity,
|
||||
vel_terminal, door_try_mask, expl_radius, expl_damage, seq_hit,
|
||||
seq_dying_hard, seq_dying_soft, seq_dead_hard, seq_dead_soft,
|
||||
seq_standing, seq_moving, seq_tele_in, seq_tele_out,
|
||||
atk_frequency, atk_melee, atk_range}, 156))
|
||||
}
|
||||
|
||||
/// Reads a `Trigger` object.
|
||||
fn read_trigger(b: &[u8]) -> ResultS<Trigger>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 36, start: 0, data {
|
||||
let magazine = u16[0];
|
||||
let typ_ammo = OptU16[2];
|
||||
let tic_round = OptU16[4];
|
||||
let tic_recover = u16[6];
|
||||
let tic_charge = u16[8];
|
||||
let recoil = Unit[10];
|
||||
let snd_fire = OptU16[12];
|
||||
let snd_click = OptU16[14];
|
||||
let snd_charge = OptU16[16];
|
||||
let snd_casing = OptU16[18];
|
||||
let snd_reload = OptU16[20];
|
||||
let snd_charged = OptU16[22];
|
||||
let typ_proj = u16[24];
|
||||
let theta = u16[26];
|
||||
let dx = i16[28];
|
||||
let dz = i16[30];
|
||||
let typ_casing = u16[32] enum CasingType;
|
||||
let burst = u16[34];
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Trigger{burst, dx, dz, magazine, recoil, snd_casing, snd_charge,
|
||||
snd_charged, snd_click, snd_fire, snd_reload, theta, tic_charge,
|
||||
tic_recover, tic_round, typ_ammo, typ_casing, typ_proj})
|
||||
}
|
||||
|
||||
/// Reads a `Damage` object.
|
||||
fn read_damage(b: &[u8]) -> ResultS<Damage>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 12, start: 0, data {
|
||||
let dtype = u16[0] enum DamageType;
|
||||
let flags = u16[2];
|
||||
let dmg_base = u16[4];
|
||||
let dmg_rand = u16[6];
|
||||
let scale = Fixed[8];
|
||||
}
|
||||
}
|
||||
|
||||
let alien = flags != 0;
|
||||
|
||||
Ok(Damage{dtype, alien, dmg_base, dmg_rand, scale})
|
||||
}
|
||||
|
||||
/// Reads an `Attack` object.
|
||||
fn read_attack(b: &[u8]) -> ResultS<Attack>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 16, start: 0, data {
|
||||
let ptype = OptU16[0];
|
||||
let rep = u16[2];
|
||||
let error = Angle[4];
|
||||
let range = Unit[6];
|
||||
let shape = u16[8];
|
||||
let ofs_x = Unit[10];
|
||||
let ofs_y = Unit[12];
|
||||
let ofs_z = Unit[14];
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Attack{ptype, rep, error, range, shape, ofs_x, ofs_y, ofs_z})
|
||||
}
|
||||
|
||||
/// Static physics information.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Physics
|
||||
{
|
||||
pub acc_ang: Fixed,
|
||||
pub acc_cli: Fixed,
|
||||
pub acc_grv: Fixed,
|
||||
pub acc_nrm: Fixed,
|
||||
pub dec_air: Fixed,
|
||||
pub dec_ang: Fixed,
|
||||
pub dec_ext: Fixed,
|
||||
pub dec_nrm: Fixed,
|
||||
pub dec_xng: Fixed,
|
||||
pub ele_max: Fixed,
|
||||
pub fng_max: Fixed,
|
||||
pub fng_vel: Fixed,
|
||||
pub ply_cam: Fixed,
|
||||
pub ply_dhi: Fixed,
|
||||
pub ply_hcm: Fixed,
|
||||
pub ply_hei: Fixed,
|
||||
pub ply_rad: Fixed,
|
||||
pub ply_spl: Fixed,
|
||||
pub stp_amp: Fixed,
|
||||
pub stp_dta: Fixed,
|
||||
pub vel_ang: Fixed,
|
||||
pub vel_bkw: Fixed,
|
||||
pub vel_fwd: Fixed,
|
||||
pub vel_prp: Fixed,
|
||||
pub vel_rec: Fixed,
|
||||
pub vel_trm: Fixed,
|
||||
}
|
||||
|
||||
/// An effect definition.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Effect
|
||||
{
|
||||
pub collection: u16,
|
||||
pub shape: u16,
|
||||
pub pitch: Fixed,
|
||||
pub flags: EffectFlags,
|
||||
pub delay: OptU16,
|
||||
pub delay_snd: OptU16,
|
||||
}
|
||||
|
||||
/// A weapon definition.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Weapon
|
||||
{
|
||||
pub amp_bob: Fixed,
|
||||
pub amp_horz: Fixed,
|
||||
pub collection: u16,
|
||||
pub flags: WeaponFlags,
|
||||
pub frm_charge: OptU16,
|
||||
pub frm_charged: OptU16,
|
||||
pub frm_firing: u16,
|
||||
pub frm_idle: u16,
|
||||
pub frm_reload: OptU16,
|
||||
pub hei_idle: Fixed,
|
||||
pub hei_kick: Fixed,
|
||||
pub hei_reload: Fixed,
|
||||
pub lit_decay: u16,
|
||||
pub lit_value: Fixed,
|
||||
pub tic_load_beg: u16,
|
||||
pub tic_load_end: u16,
|
||||
pub tic_load_mid: u16,
|
||||
pub tic_powerup: u16,
|
||||
pub tic_ready: u16,
|
||||
pub trig_pri: Trigger,
|
||||
pub trig_sec: Trigger,
|
||||
pub typ_item: u16,
|
||||
pub typ_powerup: OptU16,
|
||||
pub typ_weapon: WeaponType,
|
||||
pub wid_idle: Fixed,
|
||||
}
|
||||
|
||||
/// The definition of one of two triggers for a weapon.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Trigger
|
||||
{
|
||||
pub burst: u16,
|
||||
pub dx: i16,
|
||||
pub dz: i16,
|
||||
pub magazine: u16,
|
||||
pub recoil: Unit,
|
||||
pub snd_casing: OptU16,
|
||||
pub snd_charge: OptU16,
|
||||
pub snd_charged: OptU16,
|
||||
pub snd_click: OptU16,
|
||||
pub snd_fire: OptU16,
|
||||
pub snd_reload: OptU16,
|
||||
pub theta: u16,
|
||||
pub tic_charge: u16,
|
||||
pub tic_recover: u16,
|
||||
pub tic_round: OptU16,
|
||||
pub typ_ammo: OptU16,
|
||||
pub typ_casing: CasingType,
|
||||
pub typ_proj: u16,
|
||||
}
|
||||
|
||||
/// A projectile definition.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Projectile
|
||||
{
|
||||
pub collection: OptU16,
|
||||
pub shape: u16,
|
||||
pub fxt_explode: OptU16,
|
||||
pub fxt_exp_media: OptU16,
|
||||
pub fxt_trail: OptU16,
|
||||
pub tic_trail: u16,
|
||||
pub max_trail: OptU16,
|
||||
pub typ_media: OptU16,
|
||||
pub radius: Unit,
|
||||
pub dmg_rad: Unit,
|
||||
pub dmg_def: Damage,
|
||||
pub flags: ProjectileFlags,
|
||||
pub speed: Unit,
|
||||
pub range: Unit,
|
||||
pub snd_pitch: Fixed,
|
||||
pub snd_fly: OptU16,
|
||||
pub snd_bounce: OptU16,
|
||||
}
|
||||
|
||||
/// A monster definition.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Monster
|
||||
{
|
||||
pub collection: u16,
|
||||
pub vitality: u16,
|
||||
pub dty_immune: DamageTypeFlags,
|
||||
pub dty_weak: DamageTypeFlags,
|
||||
pub flags: MonsterFlags,
|
||||
pub cls_self: MonsterClass,
|
||||
pub cls_friend: MonsterClass,
|
||||
pub cls_enemy: MonsterClass,
|
||||
pub snd_pitch: Fixed,
|
||||
pub snd_see_enemy: OptU16,
|
||||
pub snd_see_friend: OptU16,
|
||||
pub snd_seeclear: OptU16,
|
||||
pub snd_kill: OptU16,
|
||||
pub snd_apologize: OptU16,
|
||||
pub snd_amicide: OptU16,
|
||||
pub snd_flaming: OptU16,
|
||||
pub snd_active: OptU16,
|
||||
pub snd_active_mask: u16,
|
||||
pub typ_item: OptU16,
|
||||
pub radius: Unit,
|
||||
pub height: Unit,
|
||||
pub height_hover: Unit,
|
||||
pub ledge_min: Unit,
|
||||
pub ledge_max: Unit,
|
||||
pub ext_vel_scale: Fixed,
|
||||
pub fxt_impact: OptU16,
|
||||
pub fxt_impact_melee: OptU16,
|
||||
pub fxt_trail: OptU16,
|
||||
pub half_fov_horz: u16,
|
||||
pub half_fov_vert: u16,
|
||||
pub view_range: Unit,
|
||||
pub view_range_dark: Unit,
|
||||
pub intelligence: u16,
|
||||
pub speed: u16,
|
||||
pub gravity: u16,
|
||||
pub vel_terminal: u16,
|
||||
pub door_try_mask: u16,
|
||||
pub expl_radius: OptU16,
|
||||
pub expl_damage: Damage,
|
||||
pub seq_hit: OptU16,
|
||||
pub seq_dying_hard: OptU16,
|
||||
pub seq_dying_soft: OptU16,
|
||||
pub seq_dead_hard: OptU16,
|
||||
pub seq_dead_soft: OptU16,
|
||||
pub seq_standing: u16,
|
||||
pub seq_moving: u16,
|
||||
pub seq_tele_in: OptU16,
|
||||
pub seq_tele_out: OptU16,
|
||||
pub atk_frequency: u16,
|
||||
pub atk_melee: Attack,
|
||||
pub atk_range: Attack,
|
||||
}
|
||||
|
||||
/// A damage definition.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Damage
|
||||
{
|
||||
pub dtype: DamageType,
|
||||
pub alien: bool,
|
||||
pub dmg_base: u16,
|
||||
pub dmg_rand: u16,
|
||||
pub scale: Fixed,
|
||||
}
|
||||
|
||||
/// The definition of a monster's attack.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Attack
|
||||
{
|
||||
pub ptype: OptU16,
|
||||
pub rep: u16,
|
||||
pub error: Angle,
|
||||
pub range: Unit,
|
||||
pub shape: u16,
|
||||
pub ofs_x: Unit,
|
||||
pub ofs_y: Unit,
|
||||
pub ofs_z: Unit,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for an effect.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct EffectFlags: u16
|
||||
{
|
||||
const END_ON_LOOP = 1;
|
||||
const END_ON_XFER_LOOP = 1 << 1;
|
||||
const SOUND_ONLY = 1 << 2;
|
||||
const MAKE_TWIN_VISIBLE = 1 << 3;
|
||||
const MEDIA_EFFECT = 1 << 4;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for a weapon.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct WeaponFlags: u16
|
||||
{
|
||||
const AUTOMATIC = 1;
|
||||
const REMOVE_AFTER_USE = 1 << 1;
|
||||
const INSTANT_CASING = 1 << 2;
|
||||
const OVERLOADS = 1 << 3;
|
||||
const RANDOM_AMMO = 1 << 4;
|
||||
const TEMPORARY_POWER = 1 << 5;
|
||||
const RELOAD_ONE_HAND = 1 << 6;
|
||||
const FIRE_OUT_OF_PHASE = 1 << 7;
|
||||
const FIRE_UNDER_MEDIA = 1 << 8;
|
||||
const TRIGGER_SAME_AMMO = 1 << 9;
|
||||
const SECONDARY_FLIP = 1 << 10;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for a projectile.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct ProjectileFlags: u32
|
||||
{
|
||||
const GUIDED = 1;
|
||||
const STOP_ON_LOOP = 1 << 1;
|
||||
const PERSISTENT = 1 << 2;
|
||||
const ALIEN = 1 << 3;
|
||||
const GRAVITY = 1 << 4;
|
||||
const NO_HORZ_ERROR = 1 << 5;
|
||||
const NO_VERT_ERROR = 1 << 6;
|
||||
const TOGGLE_PANELS = 1 << 7;
|
||||
const POS_VERT_ERROR = 1 << 8;
|
||||
const MELEE = 1 << 9;
|
||||
const RIPPER = 1 << 10;
|
||||
const PASS_TRANS_RANDOM = 1 << 11;
|
||||
const PASS_TRANS_MORE = 1 << 12;
|
||||
const DOUBLE_GRAVITY = 1 << 13;
|
||||
const REBOUND_FLOOR = 1 << 14;
|
||||
const THROUGH_MEDIA = 1 << 15;
|
||||
const BECOME_ITEM = 1 << 16;
|
||||
const BLOODY = 1 << 17;
|
||||
const WANDER_HORZ = 1 << 18;
|
||||
const USE_LOW_GRAV = 1 << 19;
|
||||
const PASS_MEDIA = 1 << 20;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for a monster.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct MonsterFlags: u32
|
||||
{
|
||||
const IGNORE_LOS = 1;
|
||||
const FLYING = 1 << 1;
|
||||
const ALIEN = 1 << 2;
|
||||
const MAJOR = 1 << 3;
|
||||
const MINOR = 1 << 4;
|
||||
const NO_OMIT = 1 << 5;
|
||||
const FLOATS = 1 << 6;
|
||||
const NO_ATTACK = 1 << 7;
|
||||
const SNIPE = 1 << 8;
|
||||
const INVISIBLE = 1 << 9;
|
||||
const SUBTLY_INVISIBLE = 1 << 10;
|
||||
const KAMIKAZE = 1 << 11;
|
||||
const BERSERKER = 1 << 12;
|
||||
const ENLARGED = 1 << 13;
|
||||
const DELAYED_DEATH = 1 << 14;
|
||||
const FIRE_SYMMETRICAL = 1 << 15;
|
||||
const NUCLEAR_DEATH = 1 << 16;
|
||||
const NO_FIRE_BACKWARDS = 1 << 17;
|
||||
const CAN_DIE_IN_FLAMES = 1 << 18;
|
||||
const WAIT_FOR_GOOD_SHOT = 1 << 19;
|
||||
const TINY = 1 << 20;
|
||||
const FAST_ATTACK = 1 << 21;
|
||||
const LIKES_WATER = 1 << 22;
|
||||
const LIKES_SEWAGE = 1 << 23;
|
||||
const LIKES_LAVA = 1 << 24;
|
||||
const LIKES_GOO = 1 << 25;
|
||||
const TELE_UNDER_MEDIA = 1 << 26;
|
||||
const USE_RANDOM_WEAPON = 1 << 27;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// The composite type of a monster.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct MonsterClass: u32
|
||||
{
|
||||
const PLAYER = 1;
|
||||
const CIVILIAN = 1 << 1;
|
||||
const MADD = 1 << 2;
|
||||
const POSSESSED_HUMMER = 1 << 3;
|
||||
const DEFENDER = 1 << 4;
|
||||
const FIGHTER = 1 << 5;
|
||||
const TROOPER = 1 << 6;
|
||||
const HUNTER = 1 << 7;
|
||||
const ENFORCER = 1 << 8;
|
||||
const JUGGERNAUT = 1 << 9;
|
||||
const HUMMER = 1 << 10;
|
||||
const COMPILER = 1 << 11;
|
||||
const CYBORG = 1 << 12;
|
||||
const ASSIMILATED = 1 << 13;
|
||||
const TICK = 1 << 14;
|
||||
const YETI = 1 << 15;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// The composite type of damage taken by something.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct DamageTypeFlags: u32
|
||||
{
|
||||
const EXPLOSION = 1;
|
||||
const ELECTRICAL_STAFF = 1 << 1;
|
||||
const PROJECTILE = 1 << 2;
|
||||
const ABSORBED = 1 << 3;
|
||||
const FLAME = 1 << 4;
|
||||
const HOUND_CLAWS = 1 << 5;
|
||||
const ALIEN_PROJECTILE = 1 << 6;
|
||||
const HULK_SLAP = 1 << 7;
|
||||
const COMPILER_BOLT = 1 << 8;
|
||||
const FUSION_BOLT = 1 << 9;
|
||||
const HUNTER_BOLT = 1 << 10;
|
||||
const FIST = 1 << 11;
|
||||
const TELEPORTER = 1 << 12;
|
||||
const DEFENDER = 1 << 13;
|
||||
const YETI_CLAWS = 1 << 14;
|
||||
const YETI_PROJECTILE = 1 << 15;
|
||||
const CRUSHING = 1 << 16;
|
||||
const LAVA = 1 << 17;
|
||||
const SUFFOCATION = 1 << 18;
|
||||
const GOO = 1 << 19;
|
||||
const ENERGY_DRAIN = 1 << 20;
|
||||
const OXYGEN_DRAIN = 1 << 21;
|
||||
const HUMMER_BOLT = 1 << 22;
|
||||
const SHOTGUN_PROJECTILE = 1 << 23;
|
||||
}
|
||||
}
|
||||
|
||||
c_enum! {
|
||||
/// A bullet shell casing emitted by a weapon.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum CasingType: u16
|
||||
{
|
||||
Rifle = 0,
|
||||
Pistol = 1,
|
||||
PistolLeft = 2,
|
||||
PistolRight = 3,
|
||||
SMG = 4,
|
||||
None = 0xFFFF,
|
||||
}
|
||||
}
|
||||
|
||||
c_enum! {
|
||||
/// The type of functionality a weapon provides.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum WeaponType: u16
|
||||
{
|
||||
Melee = 0,
|
||||
Normal = 1,
|
||||
DualFunc = 2,
|
||||
DualPistol = 3,
|
||||
Multipurpose = 4,
|
||||
}
|
||||
}
|
||||
|
||||
c_enum! {
|
||||
/// A named type of damage taken by something.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum DamageType: u16
|
||||
{
|
||||
Explosion = 0,
|
||||
ElectricalStaff = 1,
|
||||
Projectile = 2,
|
||||
Absorbed = 3,
|
||||
Flame = 4,
|
||||
HoundClaws = 5,
|
||||
AlienProjectile = 6,
|
||||
HulkSlap = 7,
|
||||
CompilerBolt = 8,
|
||||
FusionBolt = 9,
|
||||
HunterBolt = 10,
|
||||
Fist = 11,
|
||||
Teleporter = 12,
|
||||
Defender = 13,
|
||||
YetiClaws = 14,
|
||||
YetiProjectile = 15,
|
||||
Crushing = 16,
|
||||
Lava = 17,
|
||||
Suffocation = 18,
|
||||
Goo = 19,
|
||||
EnergyDrain = 20,
|
||||
OxygenDrain = 21,
|
||||
HummerBolt = 22,
|
||||
ShotgunProjectile = 23,
|
||||
None = 0xFFFF,
|
||||
}
|
||||
}
|
||||
pub mod attk;
|
||||
pub mod damg;
|
||||
pub mod fxpx;
|
||||
pub mod mnpx;
|
||||
pub mod prpx;
|
||||
pub mod pxpx;
|
||||
pub mod trig;
|
||||
pub mod wppx;
|
||||
|
||||
// EOF
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
//! `Attack` type.
|
||||
|
||||
use crate::{durandal::{bin::OptU16, err::*, fixed::{Angle, Unit}}};
|
||||
|
||||
/// Reads an `Attack` object.
|
||||
pub fn read(b: &[u8]) -> ResultS<Attack>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 16, start: 0, data {
|
||||
let ptype = OptU16[0];
|
||||
let rep = u16[2];
|
||||
let error = Angle[4];
|
||||
let range = Unit[6];
|
||||
let shape = u16[8];
|
||||
let ofs_x = Unit[10];
|
||||
let ofs_y = Unit[12];
|
||||
let ofs_z = Unit[14];
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Attack{ptype, rep, error, range, shape, ofs_x, ofs_y, ofs_z})
|
||||
}
|
||||
|
||||
/// The definition of a monster's attack.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Attack
|
||||
{
|
||||
pub ptype: OptU16,
|
||||
pub rep: u16,
|
||||
pub error: Angle,
|
||||
pub range: Unit,
|
||||
pub shape: u16,
|
||||
pub ofs_x: Unit,
|
||||
pub ofs_y: Unit,
|
||||
pub ofs_z: Unit,
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,102 @@
|
|||
//! `Damage` type.
|
||||
|
||||
use crate::{durandal::{err::*, fixed::Fixed}};
|
||||
use bitflags::bitflags;
|
||||
|
||||
/// Reads a `Damage` object.
|
||||
pub fn read(b: &[u8]) -> ResultS<Damage>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 12, start: 0, data {
|
||||
let dtype = u16[0] enum DamageType;
|
||||
let flags = u16[2];
|
||||
let dmg_base = u16[4];
|
||||
let dmg_rand = u16[6];
|
||||
let scale = Fixed[8];
|
||||
}
|
||||
}
|
||||
|
||||
let alien = flags != 0;
|
||||
|
||||
Ok(Damage{dtype, alien, dmg_base, dmg_rand, scale})
|
||||
}
|
||||
|
||||
/// A damage definition.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Damage
|
||||
{
|
||||
pub dtype: DamageType,
|
||||
pub alien: bool,
|
||||
pub dmg_base: u16,
|
||||
pub dmg_rand: u16,
|
||||
pub scale: Fixed,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// The composite type of damage taken by something.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct DamageTypeFlags: u32
|
||||
{
|
||||
const EXPLOSION = 1;
|
||||
const ELECTRICAL_STAFF = 1 << 1;
|
||||
const PROJECTILE = 1 << 2;
|
||||
const ABSORBED = 1 << 3;
|
||||
const FLAME = 1 << 4;
|
||||
const HOUND_CLAWS = 1 << 5;
|
||||
const ALIEN_PROJECTILE = 1 << 6;
|
||||
const HULK_SLAP = 1 << 7;
|
||||
const COMPILER_BOLT = 1 << 8;
|
||||
const FUSION_BOLT = 1 << 9;
|
||||
const HUNTER_BOLT = 1 << 10;
|
||||
const FIST = 1 << 11;
|
||||
const TELEPORTER = 1 << 12;
|
||||
const DEFENDER = 1 << 13;
|
||||
const YETI_CLAWS = 1 << 14;
|
||||
const YETI_PROJECTILE = 1 << 15;
|
||||
const CRUSHING = 1 << 16;
|
||||
const LAVA = 1 << 17;
|
||||
const SUFFOCATION = 1 << 18;
|
||||
const GOO = 1 << 19;
|
||||
const ENERGY_DRAIN = 1 << 20;
|
||||
const OXYGEN_DRAIN = 1 << 21;
|
||||
const HUMMER_BOLT = 1 << 22;
|
||||
const SHOTGUN_PROJECTILE = 1 << 23;
|
||||
}
|
||||
}
|
||||
|
||||
c_enum! {
|
||||
/// A named type of damage taken by something.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum DamageType: u16
|
||||
{
|
||||
Explosion = 0,
|
||||
ElectricalStaff = 1,
|
||||
Projectile = 2,
|
||||
Absorbed = 3,
|
||||
Flame = 4,
|
||||
HoundClaws = 5,
|
||||
AlienProjectile = 6,
|
||||
HulkSlap = 7,
|
||||
CompilerBolt = 8,
|
||||
FusionBolt = 9,
|
||||
HunterBolt = 10,
|
||||
Fist = 11,
|
||||
Teleporter = 12,
|
||||
Defender = 13,
|
||||
YetiClaws = 14,
|
||||
YetiProjectile = 15,
|
||||
Crushing = 16,
|
||||
Lava = 17,
|
||||
Suffocation = 18,
|
||||
Goo = 19,
|
||||
EnergyDrain = 20,
|
||||
OxygenDrain = 21,
|
||||
HummerBolt = 22,
|
||||
ShotgunProjectile = 23,
|
||||
None = 0xFFFF,
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,49 @@
|
|||
//! `Effect` type.
|
||||
|
||||
use crate::{durandal::{bin::OptU16, err::*, fixed::Fixed}};
|
||||
use bitflags::bitflags;
|
||||
|
||||
/// Reads a `FXpx` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(Effect, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 14, start: 0, data {
|
||||
let collection = u16[0];
|
||||
let shape = u16[2];
|
||||
let pitch = Fixed[4];
|
||||
let flags = u16[8] flag EffectFlags;
|
||||
let delay = OptU16[10];
|
||||
let delay_snd = OptU16[12];
|
||||
}
|
||||
}
|
||||
|
||||
Ok((Effect{collection, shape, pitch, flags, delay, delay_snd}, 14))
|
||||
}
|
||||
|
||||
/// An effect definition.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Effect
|
||||
{
|
||||
pub collection: u16,
|
||||
pub shape: u16,
|
||||
pub pitch: Fixed,
|
||||
pub flags: EffectFlags,
|
||||
pub delay: OptU16,
|
||||
pub delay_snd: OptU16,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for an effect.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct EffectFlags: u16
|
||||
{
|
||||
const END_ON_LOOP = 1;
|
||||
const END_ON_XFER_LOOP = 1 << 1;
|
||||
const SOUND_ONLY = 1 << 2;
|
||||
const MAKE_TWIN_VISIBLE = 1 << 3;
|
||||
const MEDIA_EFFECT = 1 << 4;
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,204 @@
|
|||
//! `Monster` type.
|
||||
|
||||
use crate::{durandal::{bin::OptU16, err::*, fixed::{Fixed, Unit}}};
|
||||
use bitflags::bitflags;
|
||||
|
||||
use super::{attk, damg};
|
||||
|
||||
/// Reads a `MNpx` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(Monster, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 156, start: 0, data {
|
||||
let collection = u16[0];
|
||||
let vitality = u16[2];
|
||||
let dty_immune = u32[4] flag damg::DamageTypeFlags;
|
||||
let dty_weak = u32[8] flag damg::DamageTypeFlags;
|
||||
let flags = u32[12] flag MonsterFlags;
|
||||
let cls_self = u32[16] flag MonsterClass;
|
||||
let cls_friend = u32[20];
|
||||
let cls_enemy = u32[24];
|
||||
let snd_pitch = Fixed[28];
|
||||
let snd_see_enemy = OptU16[32];
|
||||
let snd_see_friend = OptU16[34];
|
||||
let snd_seeclear = OptU16[36];
|
||||
let snd_kill = OptU16[38];
|
||||
let snd_apologize = OptU16[40];
|
||||
let snd_amicide = OptU16[42];
|
||||
let snd_flaming = OptU16[44];
|
||||
let snd_active = OptU16[46];
|
||||
let snd_active_mask = u16[48];
|
||||
let typ_item = OptU16[50];
|
||||
let radius = Unit[52];
|
||||
let height = Unit[54];
|
||||
let height_hover = Unit[56];
|
||||
let ledge_min = Unit[58];
|
||||
let ledge_max = Unit[60];
|
||||
let ext_vel_scale = Fixed[62];
|
||||
let fxt_impact = OptU16[66];
|
||||
let fxt_impact_melee = OptU16[68];
|
||||
let fxt_trail = OptU16[70];
|
||||
let half_fov_horz = u16[72];
|
||||
let half_fov_vert = u16[74];
|
||||
let view_range = Unit[76];
|
||||
let view_range_dark = Unit[78];
|
||||
let intelligence = u16[80];
|
||||
let speed = u16[82];
|
||||
let gravity = u16[84];
|
||||
let vel_terminal = u16[86];
|
||||
let door_try_mask = u16[88];
|
||||
let expl_radius = OptU16[90];
|
||||
let expl_damage = damg::read[92; 12];
|
||||
let seq_hit = OptU16[104];
|
||||
let seq_dying_hard = OptU16[106];
|
||||
let seq_dying_soft = OptU16[108];
|
||||
let seq_dead_hard = OptU16[110];
|
||||
let seq_dead_soft = OptU16[112];
|
||||
let seq_standing = u16[114];
|
||||
let seq_moving = u16[116];
|
||||
let seq_tele_in = OptU16[118];
|
||||
let seq_tele_out = OptU16[120];
|
||||
let atk_frequency = u16[122];
|
||||
let atk_melee = attk::read[124; 16];
|
||||
let atk_range = attk::read[140; 16];
|
||||
}
|
||||
}
|
||||
|
||||
// friend and enemy fields MUST truncate because the original source code
|
||||
// used `-1` to represent "all classes" which should be invalid normally
|
||||
|
||||
let cls_friend = MonsterClass::from_bits_truncate(cls_friend);
|
||||
let cls_enemy = MonsterClass::from_bits_truncate(cls_enemy);
|
||||
|
||||
Ok((Monster{collection, vitality, dty_immune, dty_weak, flags, cls_self,
|
||||
cls_friend, cls_enemy, snd_pitch, snd_see_enemy, snd_see_friend,
|
||||
snd_seeclear, snd_kill, snd_apologize, snd_amicide, snd_flaming,
|
||||
snd_active, snd_active_mask, typ_item, radius, height,
|
||||
height_hover, ledge_min, ledge_max, ext_vel_scale, fxt_impact,
|
||||
fxt_impact_melee, fxt_trail, half_fov_horz, half_fov_vert,
|
||||
view_range, view_range_dark, intelligence, speed, gravity,
|
||||
vel_terminal, door_try_mask, expl_radius, expl_damage, seq_hit,
|
||||
seq_dying_hard, seq_dying_soft, seq_dead_hard, seq_dead_soft,
|
||||
seq_standing, seq_moving, seq_tele_in, seq_tele_out,
|
||||
atk_frequency, atk_melee, atk_range}, 156))
|
||||
}
|
||||
|
||||
/// A monster definition.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Monster
|
||||
{
|
||||
pub collection: u16,
|
||||
pub vitality: u16,
|
||||
pub dty_immune: damg::DamageTypeFlags,
|
||||
pub dty_weak: damg::DamageTypeFlags,
|
||||
pub flags: MonsterFlags,
|
||||
pub cls_self: MonsterClass,
|
||||
pub cls_friend: MonsterClass,
|
||||
pub cls_enemy: MonsterClass,
|
||||
pub snd_pitch: Fixed,
|
||||
pub snd_see_enemy: OptU16,
|
||||
pub snd_see_friend: OptU16,
|
||||
pub snd_seeclear: OptU16,
|
||||
pub snd_kill: OptU16,
|
||||
pub snd_apologize: OptU16,
|
||||
pub snd_amicide: OptU16,
|
||||
pub snd_flaming: OptU16,
|
||||
pub snd_active: OptU16,
|
||||
pub snd_active_mask: u16,
|
||||
pub typ_item: OptU16,
|
||||
pub radius: Unit,
|
||||
pub height: Unit,
|
||||
pub height_hover: Unit,
|
||||
pub ledge_min: Unit,
|
||||
pub ledge_max: Unit,
|
||||
pub ext_vel_scale: Fixed,
|
||||
pub fxt_impact: OptU16,
|
||||
pub fxt_impact_melee: OptU16,
|
||||
pub fxt_trail: OptU16,
|
||||
pub half_fov_horz: u16,
|
||||
pub half_fov_vert: u16,
|
||||
pub view_range: Unit,
|
||||
pub view_range_dark: Unit,
|
||||
pub intelligence: u16,
|
||||
pub speed: u16,
|
||||
pub gravity: u16,
|
||||
pub vel_terminal: u16,
|
||||
pub door_try_mask: u16,
|
||||
pub expl_radius: OptU16,
|
||||
pub expl_damage: damg::Damage,
|
||||
pub seq_hit: OptU16,
|
||||
pub seq_dying_hard: OptU16,
|
||||
pub seq_dying_soft: OptU16,
|
||||
pub seq_dead_hard: OptU16,
|
||||
pub seq_dead_soft: OptU16,
|
||||
pub seq_standing: u16,
|
||||
pub seq_moving: u16,
|
||||
pub seq_tele_in: OptU16,
|
||||
pub seq_tele_out: OptU16,
|
||||
pub atk_frequency: u16,
|
||||
pub atk_melee: attk::Attack,
|
||||
pub atk_range: attk::Attack,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for a monster.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct MonsterFlags: u32
|
||||
{
|
||||
const IGNORE_LOS = 1;
|
||||
const FLYING = 1 << 1;
|
||||
const ALIEN = 1 << 2;
|
||||
const MAJOR = 1 << 3;
|
||||
const MINOR = 1 << 4;
|
||||
const NO_OMIT = 1 << 5;
|
||||
const FLOATS = 1 << 6;
|
||||
const NO_ATTACK = 1 << 7;
|
||||
const SNIPE = 1 << 8;
|
||||
const INVISIBLE = 1 << 9;
|
||||
const SUBTLY_INVISIBLE = 1 << 10;
|
||||
const KAMIKAZE = 1 << 11;
|
||||
const BERSERKER = 1 << 12;
|
||||
const ENLARGED = 1 << 13;
|
||||
const DELAYED_DEATH = 1 << 14;
|
||||
const FIRE_SYMMETRICAL = 1 << 15;
|
||||
const NUCLEAR_DEATH = 1 << 16;
|
||||
const NO_FIRE_BACKWARDS = 1 << 17;
|
||||
const CAN_DIE_IN_FLAMES = 1 << 18;
|
||||
const WAIT_FOR_GOOD_SHOT = 1 << 19;
|
||||
const TINY = 1 << 20;
|
||||
const FAST_ATTACK = 1 << 21;
|
||||
const LIKES_WATER = 1 << 22;
|
||||
const LIKES_SEWAGE = 1 << 23;
|
||||
const LIKES_LAVA = 1 << 24;
|
||||
const LIKES_GOO = 1 << 25;
|
||||
const TELE_UNDER_MEDIA = 1 << 26;
|
||||
const USE_RANDOM_WEAPON = 1 << 27;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// The composite type of a monster.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct MonsterClass: u32
|
||||
{
|
||||
const PLAYER = 1;
|
||||
const CIVILIAN = 1 << 1;
|
||||
const MADD = 1 << 2;
|
||||
const POSSESSED_HUMMER = 1 << 3;
|
||||
const DEFENDER = 1 << 4;
|
||||
const FIGHTER = 1 << 5;
|
||||
const TROOPER = 1 << 6;
|
||||
const HUNTER = 1 << 7;
|
||||
const ENFORCER = 1 << 8;
|
||||
const JUGGERNAUT = 1 << 9;
|
||||
const HUMMER = 1 << 10;
|
||||
const COMPILER = 1 << 11;
|
||||
const CYBORG = 1 << 12;
|
||||
const ASSIMILATED = 1 << 13;
|
||||
const TICK = 1 << 14;
|
||||
const YETI = 1 << 15;
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,91 @@
|
|||
//! `Projectile` type.
|
||||
|
||||
use crate::{durandal::{bin::OptU16, err::*, fixed::{Fixed, Unit}}};
|
||||
use bitflags::bitflags;
|
||||
|
||||
use super::damg;
|
||||
|
||||
/// Reads a `PRpx` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(Projectile, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 48, start: 0, data {
|
||||
let collection = OptU16[0];
|
||||
let shape = u16[2];
|
||||
let fxt_explode = OptU16[4];
|
||||
let fxt_exp_media = OptU16[6];
|
||||
let fxt_trail = OptU16[8];
|
||||
let tic_trail = u16[10];
|
||||
let max_trail = OptU16[12];
|
||||
let typ_media = OptU16[14];
|
||||
let radius = Unit[16];
|
||||
let dmg_rad = Unit[18];
|
||||
let dmg_def = damg::read[20; 12];
|
||||
let flags = u32[32] flag ProjectileFlags;
|
||||
let speed = Unit[36];
|
||||
let range = Unit[38];
|
||||
let snd_pitch = Fixed[40];
|
||||
let snd_fly = OptU16[44];
|
||||
let snd_bounce = OptU16[46];
|
||||
}
|
||||
}
|
||||
|
||||
Ok((Projectile{collection, shape, fxt_explode, fxt_exp_media, fxt_trail,
|
||||
tic_trail, max_trail, typ_media, radius, dmg_rad, dmg_def,
|
||||
flags, speed, range, snd_pitch, snd_fly, snd_bounce}, 48))
|
||||
}
|
||||
|
||||
/// A projectile definition.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Projectile
|
||||
{
|
||||
pub collection: OptU16,
|
||||
pub shape: u16,
|
||||
pub fxt_explode: OptU16,
|
||||
pub fxt_exp_media: OptU16,
|
||||
pub fxt_trail: OptU16,
|
||||
pub tic_trail: u16,
|
||||
pub max_trail: OptU16,
|
||||
pub typ_media: OptU16,
|
||||
pub radius: Unit,
|
||||
pub dmg_rad: Unit,
|
||||
pub dmg_def: damg::Damage,
|
||||
pub flags: ProjectileFlags,
|
||||
pub speed: Unit,
|
||||
pub range: Unit,
|
||||
pub snd_pitch: Fixed,
|
||||
pub snd_fly: OptU16,
|
||||
pub snd_bounce: OptU16,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for a projectile.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct ProjectileFlags: u32
|
||||
{
|
||||
const GUIDED = 1;
|
||||
const STOP_ON_LOOP = 1 << 1;
|
||||
const PERSISTENT = 1 << 2;
|
||||
const ALIEN = 1 << 3;
|
||||
const GRAVITY = 1 << 4;
|
||||
const NO_HORZ_ERROR = 1 << 5;
|
||||
const NO_VERT_ERROR = 1 << 6;
|
||||
const TOGGLE_PANELS = 1 << 7;
|
||||
const POS_VERT_ERROR = 1 << 8;
|
||||
const MELEE = 1 << 9;
|
||||
const RIPPER = 1 << 10;
|
||||
const PASS_TRANS_RANDOM = 1 << 11;
|
||||
const PASS_TRANS_MORE = 1 << 12;
|
||||
const DOUBLE_GRAVITY = 1 << 13;
|
||||
const REBOUND_FLOOR = 1 << 14;
|
||||
const THROUGH_MEDIA = 1 << 15;
|
||||
const BECOME_ITEM = 1 << 16;
|
||||
const BLOODY = 1 << 17;
|
||||
const WANDER_HORZ = 1 << 18;
|
||||
const USE_LOW_GRAV = 1 << 19;
|
||||
const PASS_MEDIA = 1 << 20;
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,78 @@
|
|||
//! `Physics` type.
|
||||
|
||||
use crate::{durandal::{err::*, fixed::Fixed}};
|
||||
|
||||
/// Reads a `PXpx` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(Physics, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 104, start: 0, data {
|
||||
let vel_fwd = Fixed[0];
|
||||
let vel_bkw = Fixed[4];
|
||||
let vel_prp = Fixed[8];
|
||||
let acc_nrm = Fixed[12];
|
||||
let dec_nrm = Fixed[16];
|
||||
let dec_air = Fixed[20];
|
||||
let acc_grv = Fixed[24];
|
||||
let acc_cli = Fixed[28];
|
||||
let vel_trm = Fixed[32];
|
||||
let dec_ext = Fixed[36];
|
||||
let acc_ang = Fixed[40];
|
||||
let dec_ang = Fixed[44];
|
||||
let vel_ang = Fixed[48];
|
||||
let vel_rec = Fixed[52];
|
||||
let fng_vel = Fixed[56];
|
||||
let fng_max = Fixed[60];
|
||||
let ele_max = Fixed[64];
|
||||
let dec_xng = Fixed[68];
|
||||
let stp_dta = Fixed[72];
|
||||
let stp_amp = Fixed[76];
|
||||
let ply_rad = Fixed[80];
|
||||
let ply_hei = Fixed[84];
|
||||
let ply_dhi = Fixed[88];
|
||||
let ply_cam = Fixed[92];
|
||||
let ply_spl = Fixed[96];
|
||||
let ply_hcm = Fixed[100];
|
||||
}
|
||||
}
|
||||
|
||||
Ok((Physics{acc_ang, acc_cli, acc_grv, acc_nrm, dec_air, dec_ang, dec_ext,
|
||||
dec_nrm, dec_xng, ele_max, fng_max, fng_vel, ply_cam, ply_dhi,
|
||||
ply_hcm, ply_hei, ply_rad, ply_spl, stp_amp, stp_dta, vel_ang,
|
||||
vel_bkw, vel_fwd, vel_prp, vel_rec, vel_trm}, 104))
|
||||
}
|
||||
|
||||
/// Static physics information.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Physics
|
||||
{
|
||||
pub acc_ang: Fixed,
|
||||
pub acc_cli: Fixed,
|
||||
pub acc_grv: Fixed,
|
||||
pub acc_nrm: Fixed,
|
||||
pub dec_air: Fixed,
|
||||
pub dec_ang: Fixed,
|
||||
pub dec_ext: Fixed,
|
||||
pub dec_nrm: Fixed,
|
||||
pub dec_xng: Fixed,
|
||||
pub ele_max: Fixed,
|
||||
pub fng_max: Fixed,
|
||||
pub fng_vel: Fixed,
|
||||
pub ply_cam: Fixed,
|
||||
pub ply_dhi: Fixed,
|
||||
pub ply_hcm: Fixed,
|
||||
pub ply_hei: Fixed,
|
||||
pub ply_rad: Fixed,
|
||||
pub ply_spl: Fixed,
|
||||
pub stp_amp: Fixed,
|
||||
pub stp_dta: Fixed,
|
||||
pub vel_ang: Fixed,
|
||||
pub vel_bkw: Fixed,
|
||||
pub vel_fwd: Fixed,
|
||||
pub vel_prp: Fixed,
|
||||
pub vel_rec: Fixed,
|
||||
pub vel_trm: Fixed,
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,76 @@
|
|||
//! `Monster` type.
|
||||
|
||||
use crate::{durandal::{bin::OptU16, err::*, fixed::Unit}};
|
||||
|
||||
/// Reads a `Trigger` object.
|
||||
pub fn read(b: &[u8]) -> ResultS<Trigger>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 36, start: 0, data {
|
||||
let magazine = u16[0];
|
||||
let typ_ammo = OptU16[2];
|
||||
let tic_round = OptU16[4];
|
||||
let tic_recover = u16[6];
|
||||
let tic_charge = u16[8];
|
||||
let recoil = Unit[10];
|
||||
let snd_fire = OptU16[12];
|
||||
let snd_click = OptU16[14];
|
||||
let snd_charge = OptU16[16];
|
||||
let snd_casing = OptU16[18];
|
||||
let snd_reload = OptU16[20];
|
||||
let snd_charged = OptU16[22];
|
||||
let typ_proj = u16[24];
|
||||
let theta = u16[26];
|
||||
let dx = i16[28];
|
||||
let dz = i16[30];
|
||||
let typ_casing = u16[32] enum CasingType;
|
||||
let burst = u16[34];
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Trigger{burst, dx, dz, magazine, recoil, snd_casing, snd_charge,
|
||||
snd_charged, snd_click, snd_fire, snd_reload, theta, tic_charge,
|
||||
tic_recover, tic_round, typ_ammo, typ_casing, typ_proj})
|
||||
}
|
||||
|
||||
/// The definition of one of two triggers for a weapon.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Trigger
|
||||
{
|
||||
pub burst: u16,
|
||||
pub dx: i16,
|
||||
pub dz: i16,
|
||||
pub magazine: u16,
|
||||
pub recoil: Unit,
|
||||
pub snd_casing: OptU16,
|
||||
pub snd_charge: OptU16,
|
||||
pub snd_charged: OptU16,
|
||||
pub snd_click: OptU16,
|
||||
pub snd_fire: OptU16,
|
||||
pub snd_reload: OptU16,
|
||||
pub theta: u16,
|
||||
pub tic_charge: u16,
|
||||
pub tic_recover: u16,
|
||||
pub tic_round: OptU16,
|
||||
pub typ_ammo: OptU16,
|
||||
pub typ_casing: CasingType,
|
||||
pub typ_proj: u16,
|
||||
}
|
||||
|
||||
c_enum! {
|
||||
/// A bullet shell casing emitted by a weapon.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum CasingType: u16
|
||||
{
|
||||
Rifle = 0,
|
||||
Pistol = 1,
|
||||
PistolLeft = 2,
|
||||
PistolRight = 3,
|
||||
SMG = 4,
|
||||
None = 0xFFFF,
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,113 @@
|
|||
//! `Weapon` type.
|
||||
|
||||
use crate::{durandal::{bin::OptU16, err::*, fixed::Fixed}};
|
||||
use bitflags::bitflags;
|
||||
|
||||
use super::trig;
|
||||
|
||||
/// Reads a `WPpx` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(Weapon, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 134, start: 0, data {
|
||||
let typ_item = u16[0];
|
||||
let typ_powerup = OptU16[2];
|
||||
let typ_weapon = u16[4] enum WeaponType;
|
||||
let flags = u16[6] flag WeaponFlags;
|
||||
let lit_value = Fixed[8];
|
||||
let lit_decay = u16[12];
|
||||
let hei_idle = Fixed[14];
|
||||
let amp_bob = Fixed[18];
|
||||
let hei_kick = Fixed[22];
|
||||
let hei_reload = Fixed[26];
|
||||
let wid_idle = Fixed[30];
|
||||
let amp_horz = Fixed[34];
|
||||
let collection = u16[38];
|
||||
let frm_idle = u16[40];
|
||||
let frm_firing = u16[42];
|
||||
let frm_reload = OptU16[44];
|
||||
let frm_charge = OptU16[48];
|
||||
let frm_charged = OptU16[50];
|
||||
let tic_ready = u16[52];
|
||||
let tic_load_beg = u16[54];
|
||||
let tic_load_mid = u16[56];
|
||||
let tic_load_end = u16[58];
|
||||
let tic_powerup = u16[60];
|
||||
let trig_pri = trig::read[62; 36];
|
||||
let trig_sec = trig::read[98; 36];
|
||||
}
|
||||
}
|
||||
|
||||
Ok((Weapon{amp_bob, amp_horz, collection, flags, frm_charge, frm_charged,
|
||||
frm_firing, frm_idle, frm_reload, hei_idle, hei_kick, hei_reload,
|
||||
lit_decay, lit_value, tic_load_beg, tic_load_end, tic_load_mid,
|
||||
tic_powerup, tic_ready, trig_pri, trig_sec, typ_item,
|
||||
typ_powerup, typ_weapon, wid_idle}, 134))
|
||||
}
|
||||
|
||||
/// A weapon definition.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Weapon
|
||||
{
|
||||
pub amp_bob: Fixed,
|
||||
pub amp_horz: Fixed,
|
||||
pub collection: u16,
|
||||
pub flags: WeaponFlags,
|
||||
pub frm_charge: OptU16,
|
||||
pub frm_charged: OptU16,
|
||||
pub frm_firing: u16,
|
||||
pub frm_idle: u16,
|
||||
pub frm_reload: OptU16,
|
||||
pub hei_idle: Fixed,
|
||||
pub hei_kick: Fixed,
|
||||
pub hei_reload: Fixed,
|
||||
pub lit_decay: u16,
|
||||
pub lit_value: Fixed,
|
||||
pub tic_load_beg: u16,
|
||||
pub tic_load_end: u16,
|
||||
pub tic_load_mid: u16,
|
||||
pub tic_powerup: u16,
|
||||
pub tic_ready: u16,
|
||||
pub trig_pri: trig::Trigger,
|
||||
pub trig_sec: trig::Trigger,
|
||||
pub typ_item: u16,
|
||||
pub typ_powerup: OptU16,
|
||||
pub typ_weapon: WeaponType,
|
||||
pub wid_idle: Fixed,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for a weapon.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct WeaponFlags: u16
|
||||
{
|
||||
const AUTOMATIC = 1;
|
||||
const REMOVE_AFTER_USE = 1 << 1;
|
||||
const INSTANT_CASING = 1 << 2;
|
||||
const OVERLOADS = 1 << 3;
|
||||
const RANDOM_AMMO = 1 << 4;
|
||||
const TEMPORARY_POWER = 1 << 5;
|
||||
const RELOAD_ONE_HAND = 1 << 6;
|
||||
const FIRE_OUT_OF_PHASE = 1 << 7;
|
||||
const FIRE_UNDER_MEDIA = 1 << 8;
|
||||
const TRIGGER_SAME_AMMO = 1 << 9;
|
||||
const SECONDARY_FLIP = 1 << 10;
|
||||
}
|
||||
}
|
||||
|
||||
c_enum! {
|
||||
/// The type of functionality a weapon provides.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum WeaponType: u16
|
||||
{
|
||||
Melee = 0,
|
||||
Normal = 1,
|
||||
DualFunc = 2,
|
||||
DualPistol = 3,
|
||||
Multipurpose = 4,
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -46,11 +46,11 @@ pub fn read_chunks(b: &[u8], old_dat: bool, siz_cnk: usize)
|
|||
b"plat" => Chunk::Plat(rd_array(data, map::plat::read)?),
|
||||
b"NOTE" => Chunk::Note(rd_array(data, map::note::read)?),
|
||||
b"term" => Chunk::Term(rd_array(data, trm::read_term)?),
|
||||
b"FXpx" => Chunk::Fxpx(rd_array(data, phy::read_fxpx)?),
|
||||
b"MNpx" => Chunk::Mnpx(rd_array(data, phy::read_mnpx)?),
|
||||
b"PRpx" => Chunk::Prpx(rd_array(data, phy::read_prpx)?),
|
||||
b"PXpx" => Chunk::Pxpx(rd_array(data, phy::read_pxpx)?),
|
||||
b"WPpx" => Chunk::Wppx(rd_array(data, phy::read_wppx)?),
|
||||
b"FXpx" => Chunk::Fxpx(rd_array(data, phy::fxpx::read)?),
|
||||
b"MNpx" => Chunk::Mnpx(rd_array(data, phy::mnpx::read)?),
|
||||
b"PRpx" => Chunk::Prpx(rd_array(data, phy::prpx::read)?),
|
||||
b"PXpx" => Chunk::Pxpx(rd_array(data, phy::pxpx::read)?),
|
||||
b"WPpx" => Chunk::Wppx(rd_array(data, phy::wppx::read)?),
|
||||
_ => Chunk::Data{iden, data: data.to_vec()},
|
||||
});
|
||||
|
||||
|
@ -158,11 +158,11 @@ pub enum Chunk
|
|||
/** A `plat` chunk. */ Plat(Vec<map::plat::Platform>),
|
||||
/** A `NOTE` chunk. */ Note(Vec<map::note::Note>),
|
||||
/** A `term` chunk. */ Term(Vec<trm::Terminal>),
|
||||
/** A `FXpx` chunk. */ Fxpx(Vec<phy::Effect>),
|
||||
/** A `MNpx` chunk. */ Mnpx(Vec<phy::Monster>),
|
||||
/** A `PRpx` chunk. */ Prpx(Vec<phy::Projectile>),
|
||||
/** A `PXpx` chunk. */ Pxpx(Vec<phy::Physics>),
|
||||
/** A `WPpx` chunk. */ Wppx(Vec<phy::Weapon>),
|
||||
/** A `FXpx` chunk. */ Fxpx(Vec<phy::fxpx::Effect>),
|
||||
/** A `MNpx` chunk. */ Mnpx(Vec<phy::mnpx::Monster>),
|
||||
/** A `PRpx` chunk. */ Prpx(Vec<phy::prpx::Projectile>),
|
||||
/** A `PXpx` chunk. */ Pxpx(Vec<phy::pxpx::Physics>),
|
||||
/** A `WPpx` chunk. */ Wppx(Vec<phy::wppx::Weapon>),
|
||||
|
||||
/// Any other type of chunk, which may have arbitrary data in it.
|
||||
Data{/** The name of the chunk. */ iden: Ident,
|
||||
|
|
Loading…
Reference in New Issue