split map module into many
parent
dc899fa058
commit
90f5d88c20
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,27 @@
|
|||
//! `SoundAmbi` type.
|
||||
|
||||
use crate::durandal::err::*;
|
||||
|
||||
/// Reads an `ambi` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(SoundAmbi, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 16, start: 0, data {
|
||||
let index = u16[2];
|
||||
let volume = u16[4];
|
||||
}
|
||||
}
|
||||
|
||||
Ok((SoundAmbi{index, volume}, 16))
|
||||
}
|
||||
|
||||
/// An ambient sound definition.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct SoundAmbi
|
||||
{
|
||||
pub index: u16,
|
||||
pub volume: u16,
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,46 @@
|
|||
//! `SoundRand` type.
|
||||
|
||||
use crate::durandal::{err::*, fixed::{Angle, Fixed}};
|
||||
|
||||
/// Reads a `bonk` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(SoundRand, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 32, start: 0, data {
|
||||
let flags = u16[0];
|
||||
let index = u16[2];
|
||||
let vol_nrm = u16[4];
|
||||
let vol_dta = u16[6];
|
||||
let prd_nrm = u16[8];
|
||||
let prd_dta = u16[10];
|
||||
let yaw_nrm = Angle[12];
|
||||
let yaw_dta = Angle[14];
|
||||
let pit_nrm = Fixed[16];
|
||||
let pit_dta = Fixed[20];
|
||||
}
|
||||
}
|
||||
|
||||
let no_dir = flags != 0;
|
||||
|
||||
Ok((SoundRand{no_dir, index, vol_nrm, vol_dta, prd_nrm, prd_dta, yaw_nrm,
|
||||
yaw_dta, pit_nrm, pit_dta}, 32))
|
||||
}
|
||||
|
||||
/// A randomly played sound definition.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct SoundRand
|
||||
{
|
||||
pub no_dir: bool,
|
||||
pub index: u16,
|
||||
pub vol_nrm: u16,
|
||||
pub vol_dta: u16,
|
||||
pub prd_nrm: u16,
|
||||
pub prd_dta: u16,
|
||||
pub yaw_nrm: Angle,
|
||||
pub yaw_dta: Angle,
|
||||
pub pit_nrm: Fixed,
|
||||
pub pit_dta: Fixed,
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,18 @@
|
|||
//! `EndPoint` type.
|
||||
|
||||
use crate::durandal::err::*;
|
||||
use super::pnts::*;
|
||||
|
||||
/// Reads an `EPNT` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(Point, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 16, start: 0, data {
|
||||
let pnt = read_point[6; 4];
|
||||
}
|
||||
}
|
||||
|
||||
Ok((pnt, 16))
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,13 @@
|
|||
//! `iidx` chunk.
|
||||
|
||||
use crate::durandal::{bin::u16b, err::*};
|
||||
|
||||
/// Reads an `iidx` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(u16, usize)>
|
||||
{
|
||||
check_data!(2, b);
|
||||
|
||||
Ok((u16b(b), 2))
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,52 @@
|
|||
//! `Line` type.
|
||||
|
||||
use crate::durandal::{bin::OptU16, err::*};
|
||||
use bitflags::bitflags;
|
||||
|
||||
/// Reads a `LINS` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(Line, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 32, start: 0, data {
|
||||
let pnt_beg = u16[0];
|
||||
let pnt_end = u16[2];
|
||||
let flags = u16[4] flag LineFlags;
|
||||
let side_fr = OptU16[12];
|
||||
let side_bk = OptU16[14];
|
||||
let poly_fr = OptU16[16];
|
||||
let poly_bk = OptU16[18];
|
||||
}
|
||||
}
|
||||
|
||||
Ok((Line{flags, pnt_beg, pnt_end, side_fr, side_bk, poly_fr, poly_bk}, 32))
|
||||
}
|
||||
|
||||
/// A line segment.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Line
|
||||
{
|
||||
pub flags: LineFlags,
|
||||
pub pnt_beg: u16,
|
||||
pub pnt_end: u16,
|
||||
pub side_fr: OptU16,
|
||||
pub side_bk: OptU16,
|
||||
pub poly_fr: OptU16,
|
||||
pub poly_bk: OptU16,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for `Line`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct LineFlags: u16
|
||||
{
|
||||
const TRANS_SIDE = 1 << 9;
|
||||
const ELEV_VAR = 1 << 10;
|
||||
const ELEVATION = 1 << 11;
|
||||
const LANDSCAPE = 1 << 12;
|
||||
const TRANSPARENT = 1 << 13;
|
||||
const SOLID = 1 << 14;
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,403 @@
|
|||
//! `Light` type.
|
||||
|
||||
use crate::durandal::{err::*, fixed::Fixed};
|
||||
use super::{ltfn::{self, LightFunc, LightFuncType}, TICKS_PER_SECOND};
|
||||
use bitflags::bitflags;
|
||||
|
||||
/// Reads a `LITE` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(Light, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 100, start: 0, data {
|
||||
let ltype = u16[0] enum LightType;
|
||||
let flags = u16[2] flag LightFlags;
|
||||
let phase = i16[4];
|
||||
let act_pri = ltfn::read[6; 14];
|
||||
let act_sec = ltfn::read[20; 14];
|
||||
let act_mid = ltfn::read[34; 14];
|
||||
let ina_pri = ltfn::read[48; 14];
|
||||
let ina_sec = ltfn::read[62; 14];
|
||||
let ina_mid = ltfn::read[76; 14];
|
||||
let tag = u16[90];
|
||||
}
|
||||
}
|
||||
|
||||
Ok((Light{ltype, flags, phase, act_pri, act_sec, act_mid, ina_pri, ina_sec,
|
||||
ina_mid, tag}, 100))
|
||||
}
|
||||
|
||||
/// Reads an old `LITE` chunk.
|
||||
pub fn read_old(b: &[u8]) -> ResultS<(Light, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 32, start: 0, data {
|
||||
let ltype = u16[2] usize;
|
||||
let mode = u16[4];
|
||||
let phase = i16[6];
|
||||
let min = Fixed[8];
|
||||
let max = Fixed[12];
|
||||
let prd = u16[16];
|
||||
}
|
||||
}
|
||||
|
||||
if OLD_LIGHT_DEFINITIONS.len() < ltype {
|
||||
bail!("bad old light type");
|
||||
}
|
||||
|
||||
let lite = &OLD_LIGHT_DEFINITIONS[ltype];
|
||||
let on = mode == 0 || mode == 1;
|
||||
let strobe = ltype == 3;
|
||||
let flags = if on {lite.flags | LightFlags::INIT_ACTIVE} else {lite.flags};
|
||||
|
||||
// modify each old light function accordingly
|
||||
let old_lfun = move |func: &LightFunc| -> LightFunc {
|
||||
LightFunc{ftype: func.ftype,
|
||||
prd_nrm: if strobe {prd / 4 + 1} else {func.prd_nrm},
|
||||
prd_dta: func.prd_dta,
|
||||
val_nrm: if func.val_nrm > 0.into() {max} else {min},
|
||||
val_dta: func.val_dta}
|
||||
};
|
||||
|
||||
Ok((Light{flags,
|
||||
phase,
|
||||
act_pri: old_lfun(&lite.act_pri),
|
||||
act_sec: old_lfun(&lite.act_sec),
|
||||
act_mid: old_lfun(&lite.act_mid),
|
||||
ina_pri: old_lfun(&lite.ina_pri),
|
||||
ina_sec: old_lfun(&lite.ina_sec),
|
||||
ina_mid: old_lfun(&lite.ina_mid),
|
||||
tag: 0,
|
||||
..*lite}, 32))
|
||||
}
|
||||
|
||||
/// A dynamic polygon light.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Light
|
||||
{
|
||||
pub ltype: LightType,
|
||||
pub flags: LightFlags,
|
||||
pub phase: i16,
|
||||
pub act_pri: LightFunc,
|
||||
pub act_sec: LightFunc,
|
||||
pub act_mid: LightFunc,
|
||||
pub ina_pri: LightFunc,
|
||||
pub ina_sec: LightFunc,
|
||||
pub ina_mid: LightFunc,
|
||||
pub tag: u16,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for `Light`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct LightFlags: u16
|
||||
{
|
||||
const INIT_ACTIVE = 1;
|
||||
const SLAVE_VALUE = 1 << 1;
|
||||
const STATELESS = 1 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
c_enum! {
|
||||
/// The type of a `Light`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum LightType: u16
|
||||
{
|
||||
Normal = 0,
|
||||
Strobe = 1,
|
||||
Media = 2,
|
||||
}
|
||||
}
|
||||
|
||||
const OLD_LIGHT_DEFINITIONS: [Light; 8] = [
|
||||
// Normal
|
||||
Light{ltype: LightType::Normal,
|
||||
flags: LightFlags::SLAVE_VALUE,
|
||||
phase: 0,
|
||||
act_pri: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
act_sec: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
act_mid: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: 1,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_pri: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_sec: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_mid: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: 1,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
tag: 0},
|
||||
|
||||
// Rheostat
|
||||
Light{ltype: LightType::Normal,
|
||||
flags: LightFlags::SLAVE_VALUE,
|
||||
phase: 0,
|
||||
act_pri: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
act_sec: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
act_mid: LightFunc{ftype: LightFuncType::Smooth,
|
||||
prd_nrm: TICKS_PER_SECOND * 3,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_pri: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_sec: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_mid: LightFunc{ftype: LightFuncType::Smooth,
|
||||
prd_nrm: TICKS_PER_SECOND * 3,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
tag: 0},
|
||||
|
||||
// Flourescent
|
||||
Light{ltype: LightType::Normal,
|
||||
flags: LightFlags::SLAVE_VALUE,
|
||||
phase: 0,
|
||||
act_pri: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
act_sec: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
act_mid: LightFunc{ftype: LightFuncType::Fluorescent,
|
||||
prd_nrm: TICKS_PER_SECOND * 3,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_pri: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_sec: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_mid: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: 1,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
tag: 0},
|
||||
|
||||
// Strobe
|
||||
Light{ltype: LightType::Normal,
|
||||
flags: LightFlags::SLAVE_VALUE,
|
||||
phase: 0,
|
||||
act_pri: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
act_sec: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
act_mid: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: 1,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_pri: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_sec: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_mid: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: 1,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
tag: 0},
|
||||
|
||||
// Flicker
|
||||
Light{ltype: LightType::Normal,
|
||||
flags: LightFlags::SLAVE_VALUE,
|
||||
phase: 0,
|
||||
act_pri: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
act_sec: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
act_mid: LightFunc{ftype: LightFuncType::Flicker,
|
||||
prd_nrm: TICKS_PER_SECOND * 3,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_pri: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_sec: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_mid: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: 1,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
tag: 0},
|
||||
|
||||
// Pulsate
|
||||
Light{ltype: LightType::Normal,
|
||||
flags: LightFlags::SLAVE_VALUE,
|
||||
phase: 0,
|
||||
act_pri: LightFunc{ftype: LightFuncType::Smooth,
|
||||
prd_nrm: TICKS_PER_SECOND * 2,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
act_sec: LightFunc{ftype: LightFuncType::Smooth,
|
||||
prd_nrm: TICKS_PER_SECOND * 2 - 1,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
act_mid: LightFunc{ftype: LightFuncType::Smooth,
|
||||
prd_nrm: TICKS_PER_SECOND * 2 - 1,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_pri: LightFunc{ftype: LightFuncType::Smooth,
|
||||
prd_nrm: TICKS_PER_SECOND * 2,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_sec: LightFunc{ftype: LightFuncType::Smooth,
|
||||
prd_nrm: TICKS_PER_SECOND * 2 - 1,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_mid: LightFunc{ftype: LightFuncType::Smooth,
|
||||
prd_nrm: TICKS_PER_SECOND * 2,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
tag: 0},
|
||||
|
||||
// Annoying
|
||||
Light{ltype: LightType::Normal,
|
||||
flags: LightFlags::SLAVE_VALUE,
|
||||
phase: 0,
|
||||
act_pri: LightFunc{ftype: LightFuncType::Random,
|
||||
prd_nrm: 2,
|
||||
prd_dta: 1,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
act_sec: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: 2,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
act_mid: LightFunc{ftype: LightFuncType::Random,
|
||||
prd_nrm: 1,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_pri: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_sec: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_mid: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
tag: 0},
|
||||
|
||||
// Energy Efficient
|
||||
Light{ltype: LightType::Normal,
|
||||
flags: LightFlags::SLAVE_VALUE,
|
||||
phase: 0,
|
||||
act_pri: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
act_sec: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
act_mid: LightFunc{ftype: LightFuncType::Linear,
|
||||
prd_nrm: TICKS_PER_SECOND * 2,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(1),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_pri: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_sec: LightFunc{ftype: LightFuncType::Constant,
|
||||
prd_nrm: TICKS_PER_SECOND,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
ina_mid: LightFunc{ftype: LightFuncType::Linear,
|
||||
prd_nrm: TICKS_PER_SECOND * 2,
|
||||
prd_dta: 0,
|
||||
val_nrm: Fixed::from_int(0),
|
||||
val_dta: Fixed::from_int(0)},
|
||||
tag: 0},
|
||||
];
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,60 @@
|
|||
//! `LightFunc` type.
|
||||
|
||||
use crate::durandal::{err::*, fixed::Fixed};
|
||||
|
||||
/// Reads a `LightFunc` object.
|
||||
pub fn read(b: &[u8]) -> ResultS<LightFunc>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 14, start: 0, data {
|
||||
let ftype = u16[0] enum LightFuncType;
|
||||
let prd_nrm = u16[2];
|
||||
let prd_dta = u16[4];
|
||||
let val_nrm = Fixed[6];
|
||||
let val_dta = Fixed[10];
|
||||
}
|
||||
}
|
||||
|
||||
Ok(LightFunc{ftype, prd_nrm, prd_dta, val_nrm, val_dta})
|
||||
}
|
||||
|
||||
/// Writes a `LightFunc` object.
|
||||
pub fn write(v: &LightFunc) -> Vec<u8>
|
||||
{
|
||||
let mut o = Vec::with_capacity(14);
|
||||
o.extend(&(v.ftype as u16).to_be_bytes());
|
||||
o.extend(&v.prd_nrm.to_be_bytes());
|
||||
o.extend(&v.prd_dta.to_be_bytes());
|
||||
o.extend(&v.val_nrm.to_be_bytes());
|
||||
o.extend(&v.val_dta.to_be_bytes());
|
||||
o
|
||||
}
|
||||
|
||||
/// A light function.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct LightFunc
|
||||
{
|
||||
pub ftype: LightFuncType,
|
||||
pub prd_nrm: u16,
|
||||
pub prd_dta: u16,
|
||||
pub val_nrm: Fixed,
|
||||
pub val_dta: Fixed,
|
||||
}
|
||||
|
||||
c_enum! {
|
||||
/// The type of function for a `LightFunc`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum LightFuncType: u16
|
||||
{
|
||||
Constant = 0,
|
||||
Linear = 1,
|
||||
Smooth = 2,
|
||||
Flicker = 3,
|
||||
Random = 4,
|
||||
Fluorescent = 5,
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,65 @@
|
|||
//! `Light` type.
|
||||
|
||||
use crate::{durandal::{bin::OptU16, err::*, fixed::{Angle, Fixed, Unit}},
|
||||
marathon::xfer::TransferMode};
|
||||
use super::pnts::*;
|
||||
|
||||
/// Reads a `medi` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(Media, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 32, start: 0, data {
|
||||
let mtype = u16[0] enum MediaType;
|
||||
let flags = u16[2];
|
||||
let control = u16[4];
|
||||
let dir = Angle[6];
|
||||
let mag = Unit[8];
|
||||
let hei_lo = Unit[10];
|
||||
let hei_hi = Unit[12];
|
||||
let orig = read_point[14; 4];
|
||||
let hei_nrm = Unit[18];
|
||||
let min_lt = Fixed[20];
|
||||
let texture = OptU16[24];
|
||||
let xfer = u16[26] enum TransferMode;
|
||||
}
|
||||
}
|
||||
|
||||
let flr_obs = flags != 0;
|
||||
|
||||
Ok((Media{mtype, flr_obs, control, dir, mag, hei_lo, hei_hi, orig, hei_nrm,
|
||||
min_lt, texture, xfer}, 32))
|
||||
}
|
||||
|
||||
/// A media, as in a part of a polygon which goes up the middle of the wall.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Media
|
||||
{
|
||||
pub mtype: MediaType,
|
||||
pub flr_obs: bool,
|
||||
pub control: u16,
|
||||
pub dir: Angle,
|
||||
pub mag: Unit,
|
||||
pub hei_lo: Unit,
|
||||
pub hei_hi: Unit,
|
||||
pub orig: Point,
|
||||
pub hei_nrm: Unit,
|
||||
pub min_lt: Fixed,
|
||||
pub texture: OptU16,
|
||||
pub xfer: TransferMode,
|
||||
}
|
||||
|
||||
c_enum! {
|
||||
/// The liquid type of a `Media`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum MediaType: u16
|
||||
{
|
||||
Water = 0,
|
||||
Lava = 1,
|
||||
Goo = 2,
|
||||
Sewage = 3,
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,133 @@
|
|||
//! `Minf` type.
|
||||
|
||||
use crate::{durandal::err::*, marathon::text::*};
|
||||
use bitflags::bitflags;
|
||||
|
||||
/// Reads a `Minf` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<Minf>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 88, start: 0, data {
|
||||
let texture_id = u16[0];
|
||||
let physics_id = u16[2];
|
||||
let skypict_id = u16[4];
|
||||
let miss_flags = u16[6] flag MsnFlags;
|
||||
let envi_flags = u16[8] flag EnvFlags;
|
||||
let level_name = mac_roman_cstr[18; 66] no_try;
|
||||
let entr_flags = u32[84] flag EntFlags;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Minf{texture_id, physics_id, skypict_id, miss_flags, envi_flags,
|
||||
entr_flags, level_name})
|
||||
}
|
||||
|
||||
/// Writes a `Minf` chunk.
|
||||
pub fn write(v: &Minf) -> Vec<u8>
|
||||
{
|
||||
let mut o = Vec::with_capacity(4);
|
||||
o.extend(&v.texture_id.to_be_bytes());
|
||||
o.extend(&v.physics_id.to_be_bytes());
|
||||
o.extend(&v.skypict_id.to_be_bytes());
|
||||
o.extend(&v.miss_flags.bits().to_be_bytes());
|
||||
o.extend(&v.envi_flags.bits().to_be_bytes());
|
||||
o.extend(&pad_zero(to_mac_roman(&v.level_name), 66));
|
||||
o.extend(&v.entr_flags.bits().to_be_bytes());
|
||||
o
|
||||
}
|
||||
|
||||
/// Reads an old `Minf` chunk.
|
||||
pub fn read_old(b: &[u8]) -> ResultS<Minf>
|
||||
{
|
||||
let minf = read(b)?;
|
||||
|
||||
let mut entr_flags = if minf.entr_flags.is_empty() {
|
||||
EntFlags::SOLO
|
||||
} else {
|
||||
minf.entr_flags
|
||||
};
|
||||
|
||||
if entr_flags.intersects(EntFlags::SOLO | EntFlags::CARNAGE) {
|
||||
entr_flags.insert(EntFlags::CO_OP)
|
||||
}
|
||||
|
||||
Ok(Minf{entr_flags, ..minf})
|
||||
}
|
||||
|
||||
impl Default for Minf
|
||||
{
|
||||
fn default() -> Self
|
||||
{
|
||||
Self{texture_id: 0,
|
||||
physics_id: 1,
|
||||
skypict_id: 0,
|
||||
miss_flags: MsnFlags::empty(),
|
||||
envi_flags: EnvFlags::empty(),
|
||||
entr_flags: EntFlags::SOLO,
|
||||
level_name: "Map".to_string()}
|
||||
}
|
||||
}
|
||||
|
||||
/// Static map information.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Minf
|
||||
{
|
||||
pub texture_id: u16,
|
||||
pub physics_id: u16,
|
||||
pub skypict_id: u16,
|
||||
pub miss_flags: MsnFlags,
|
||||
pub envi_flags: EnvFlags,
|
||||
pub entr_flags: EntFlags,
|
||||
pub level_name: String,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Static environment flags.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct EnvFlags: u16
|
||||
{
|
||||
const VACUUM = 1;
|
||||
const MAGNETIC = 1 << 1;
|
||||
const REBELLION = 1 << 2;
|
||||
const LOW_GRAV = 1 << 3;
|
||||
const M1_GLUE = 1 << 4;
|
||||
const LAVA_FLOOR = 1 << 5;
|
||||
const REBELLION2 = 1 << 6;
|
||||
const MUSIC = 1 << 7;
|
||||
const TERM_PAUSE = 1 << 8;
|
||||
const M1_MONSTER = 1 << 9;
|
||||
const M1_WEPS = 1 << 10;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Static entry point flags.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct EntFlags: u32
|
||||
{
|
||||
const SOLO = 1;
|
||||
const CO_OP = 1 << 1;
|
||||
const CARNAGE = 1 << 2;
|
||||
const KTMWTB = 1 << 3;
|
||||
const KOTH = 1 << 4;
|
||||
const DEFENSE = 1 << 5;
|
||||
const RUGBY = 1 << 6;
|
||||
const CTF = 1 << 7;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Static mission flags.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct MsnFlags: u16
|
||||
{
|
||||
const EXTERMINATION = 1;
|
||||
const EXPLORATION = 1 << 1;
|
||||
const RETRIEVAL = 1 << 2;
|
||||
const REPAIR = 1 << 3;
|
||||
const RESCUE = 1 << 4;
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,30 @@
|
|||
//! `Note` type.
|
||||
|
||||
use crate::{durandal::err::*, marathon::text::*};
|
||||
use super::pnts::*;
|
||||
|
||||
/// Reads a `NOTE` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(Note, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 72, start: 0, data {
|
||||
let pos = read_point[2; 4];
|
||||
let poly = u16[6];
|
||||
let text = mac_roman_cstr[8; 64] no_try;
|
||||
}
|
||||
}
|
||||
|
||||
Ok((Note{pos, poly, text}, 72))
|
||||
}
|
||||
|
||||
/// Overhead map annotations.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Note
|
||||
{
|
||||
pub pos: Point,
|
||||
pub poly: u16,
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,60 @@
|
|||
//! `Object` type.
|
||||
|
||||
use crate::durandal::{err::*, fixed::{Angle, Unit}};
|
||||
use bitflags::bitflags;
|
||||
|
||||
/// Reads an `OBJS` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(Object, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 16, start: 0, data {
|
||||
let group = u16[0];
|
||||
let index = u16[2];
|
||||
let angle = Angle[4];
|
||||
let poly = u16[6];
|
||||
let pos_x = Unit[8];
|
||||
let pos_y = Unit[10];
|
||||
let pos_z = Unit[12];
|
||||
let flags = u16[14];
|
||||
}
|
||||
}
|
||||
|
||||
let bias = flags & 0xF0_00;
|
||||
let flags = flags & 0x0F_FF;
|
||||
let bias = bias >> 12;
|
||||
let flags = flag_ok!(ObjectFlags, flags)?;
|
||||
|
||||
Ok((Object{group, index, angle, poly, pos_x, pos_y, pos_z, flags, bias}, 16))
|
||||
}
|
||||
|
||||
/// An object in the world.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Object
|
||||
{
|
||||
pub group: u16,
|
||||
pub index: u16,
|
||||
pub angle: Angle,
|
||||
pub poly: u16,
|
||||
pub pos_x: Unit,
|
||||
pub pos_y: Unit,
|
||||
pub pos_z: Unit,
|
||||
pub flags: ObjectFlags,
|
||||
pub bias: u16,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for `Object`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct ObjectFlags: u16
|
||||
{
|
||||
const INVISIBLE = 1;
|
||||
const CEILING = 1 << 1;
|
||||
const BLIND = 1 << 2;
|
||||
const DEAF = 1 << 3;
|
||||
const FLOATING = 1 << 4;
|
||||
const NET_ONLY = 1 << 5;
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,37 @@
|
|||
//! `ObjectFreq` type.
|
||||
|
||||
use crate::durandal::err::*;
|
||||
|
||||
/// Reads a `plac` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(ObjectFreq, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 12, start: 0, data {
|
||||
let flags = u16[0];
|
||||
let cnt_ini = u16[2];
|
||||
let cnt_min = u16[4];
|
||||
let cnt_max = u16[6];
|
||||
let cnt_rnd = u16[8];
|
||||
let chance = u16[10];
|
||||
}
|
||||
}
|
||||
|
||||
let rnd_loc = flags != 0;
|
||||
|
||||
Ok((ObjectFreq{rnd_loc, cnt_ini, cnt_min, cnt_max, cnt_rnd, chance}, 12))
|
||||
}
|
||||
|
||||
/// The difficulty definition for various object types.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct ObjectFreq
|
||||
{
|
||||
pub rnd_loc: bool,
|
||||
pub cnt_ini: u16,
|
||||
pub cnt_min: u16,
|
||||
pub cnt_max: u16,
|
||||
pub cnt_rnd: u16,
|
||||
pub chance: u16,
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,75 @@
|
|||
//! `Platform` type.
|
||||
|
||||
use crate::durandal::{err::*, fixed::Unit};
|
||||
use bitflags::bitflags;
|
||||
|
||||
/// Reads a `plat` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(Platform, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 32, start: 0, data {
|
||||
let ptype = u16[0];
|
||||
let speed = u16[2];
|
||||
let delay = u16[4];
|
||||
let hei_max = Unit[6];
|
||||
let hei_min = Unit[8];
|
||||
let flags = u32[10] flag PlatformFlags;
|
||||
let index = u16[14];
|
||||
let tag = u16[16];
|
||||
}
|
||||
}
|
||||
|
||||
Ok((Platform{ptype, speed, delay, hei_min, hei_max, flags, index, tag}, 32))
|
||||
}
|
||||
|
||||
/// Extra information for polygons with platforms.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Platform
|
||||
{
|
||||
pub ptype: u16,
|
||||
pub speed: u16,
|
||||
pub delay: u16,
|
||||
pub hei_min: Unit,
|
||||
pub hei_max: Unit,
|
||||
pub flags: PlatformFlags,
|
||||
pub index: u16,
|
||||
pub tag: u16,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for `Platform`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct PlatformFlags: u32
|
||||
{
|
||||
const INIT_ACTIVE = 1;
|
||||
const INIT_EXTENDED = 1 << 1;
|
||||
const STOP_AT_EACH_LEVEL = 1 << 2;
|
||||
const STOP_AT_INIT_LEVEL = 1 << 3;
|
||||
const START_ADJ_ON_STOP = 1 << 4;
|
||||
const EXTENDS_FLOOR_TO_CEIL = 1 << 5;
|
||||
const COMES_FROM_FLOOR = 1 << 6;
|
||||
const COMES_FROM_CEIL = 1 << 7;
|
||||
const CAUSES_DAMAGE = 1 << 8;
|
||||
const NO_ACTIVATE_PARENT = 1 << 9;
|
||||
const ACTIVATES_ONCE = 1 << 10;
|
||||
const ACTIVATES_LIGHT = 1 << 11;
|
||||
const DEACTIVATES_LIGHT = 1 << 12;
|
||||
const PLAYER_CONTROLS = 1 << 13;
|
||||
const MONSTER_CONTROLS = 1 << 14;
|
||||
const REVERSE_ON_OBSTRUCT = 1 << 15;
|
||||
const NO_EXT_DEACTIVATION = 1 << 16;
|
||||
const USE_POLYGON_HEIGHTS = 1 << 17;
|
||||
const DELAYED_ACTIVATION = 1 << 18;
|
||||
const START_ADJ_ON_START = 1 << 19;
|
||||
const STOP_ADJ_ON_START = 1 << 20;
|
||||
const STOP_ADJ_ON_STOP = 1 << 21;
|
||||
const SLOW = 1 << 22;
|
||||
const START_AT_EACH_LEVEL = 1 << 23;
|
||||
const LOCKED = 1 << 24;
|
||||
const SECRET = 1 << 25;
|
||||
const DOOR = 1 << 26;
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,42 @@
|
|||
//! `Point` type.
|
||||
|
||||
use crate::durandal::{err::*, fixed::Unit};
|
||||
|
||||
/// Reads a `Point` object.
|
||||
pub fn read_point(b: &[u8]) -> ResultS<Point>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 4, start: 0, data {
|
||||
let x = Unit[0];
|
||||
let y = Unit[2];
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Point{x, y})
|
||||
}
|
||||
|
||||
/// Writes a `Point` object.
|
||||
pub fn write_point(v: Point) -> Vec<u8>
|
||||
{
|
||||
let mut o = Vec::with_capacity(4);
|
||||
o.extend(&v.x.to_be_bytes());
|
||||
o.extend(&v.y.to_be_bytes());
|
||||
o
|
||||
}
|
||||
|
||||
/// Reads a `PNTS` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(Point, usize)>
|
||||
{
|
||||
Ok((read_point(b)?, 4))
|
||||
}
|
||||
|
||||
/// A point in world-space.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct Point
|
||||
{
|
||||
pub x: Unit,
|
||||
pub y: Unit,
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,195 @@
|
|||
//! `Polygon` type.
|
||||
|
||||
use crate::{durandal::{bin::OptU16, err::*, fixed::Unit},
|
||||
marathon::xfer::TransferMode};
|
||||
use super::pnts::*;
|
||||
use bitflags::bitflags;
|
||||
|
||||
/// Reads a polygon for either M1 or M2.
|
||||
fn read_poly_inter(b: &[u8]) -> ResultS<Polygon>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 128, start: 0, data {
|
||||
let tex_flr = OptU16[40];
|
||||
let tex_cei = OptU16[42];
|
||||
let hei_flr = Unit[44];
|
||||
let hei_cei = Unit[46];
|
||||
let lit_flr = u16[48];
|
||||
let lit_cei = u16[50];
|
||||
let xfr_flr = u16[64] enum TransferMode;
|
||||
let xfr_cei = u16[66] enum TransferMode;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Polygon{tex_flr, tex_cei, hei_flr, hei_cei, lit_flr, lit_cei, xfr_flr,
|
||||
xfr_cei, ..Polygon::default()})
|
||||
}
|
||||
|
||||
/// Reads a `POLY` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(Polygon, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 128, start: 0, data {
|
||||
let ptype = u16[0];
|
||||
let pdata = u16[4];
|
||||
let ori_flr = read_point[108; 4];
|
||||
let ori_cei = read_point[112; 4];
|
||||
let med_ind = OptU16[116];
|
||||
let med_ctl = u16[118];
|
||||
let snd_amb = OptU16[122];
|
||||
let snd_ind = u16[120];
|
||||
let snd_rnd = OptU16[124];
|
||||
}
|
||||
}
|
||||
|
||||
let poly = read_poly_inter(b)?;
|
||||
let ptype = PolyType::new(ptype, pdata)?;
|
||||
|
||||
Ok((Polygon{ptype, ori_flr, ori_cei, med_ind, med_ctl, snd_ind, snd_amb,
|
||||
snd_rnd, ..poly}, 128))
|
||||
}
|
||||
|
||||
/// Reads an old `POLY` chunk.
|
||||
pub fn read_old(b: &[u8]) -> ResultS<(Polygon, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 128, start: 0, data {
|
||||
let ptype = u16[0];
|
||||
let pdata = u16[4];
|
||||
}
|
||||
}
|
||||
|
||||
let poly = read_poly_inter(b)?;
|
||||
let ptype = PolyType::new_old(ptype, pdata)?;
|
||||
|
||||
Ok((Polygon{ptype, ..poly}, 128))
|
||||
}
|
||||
|
||||
impl PolyType
|
||||
{
|
||||
/// Creates a `PolyType` from a `n`/`pdata` pair.
|
||||
pub fn new(n: u16, pdata: u16) -> Result<Self, ReprError>
|
||||
{
|
||||
match n {
|
||||
0 => Ok(PolyType::Normal),
|
||||
1 => Ok(PolyType::ImpassItem),
|
||||
2 => Ok(PolyType::ImpassMons),
|
||||
3 => Ok(PolyType::Hill),
|
||||
4 => Ok(PolyType::Base),
|
||||
5 => Ok(PolyType::Platform(pdata)),
|
||||
6 => Ok(PolyType::TrigLightOn(pdata)),
|
||||
7 => Ok(PolyType::TrigPlatOn(pdata)),
|
||||
8 => Ok(PolyType::TrigLightOff(pdata)),
|
||||
9 => Ok(PolyType::TrigPlatOff(pdata)),
|
||||
10 => Ok(PolyType::Teleporter(pdata)),
|
||||
11 => Ok(PolyType::ZoneBorder),
|
||||
12 => Ok(PolyType::Goal),
|
||||
13 => Ok(PolyType::TrigMonsVis),
|
||||
14 => Ok(PolyType::TrigMonsInv),
|
||||
15 => Ok(PolyType::TrigMonsDual),
|
||||
16 => Ok(PolyType::TrigItems),
|
||||
17 => Ok(PolyType::MustExplore),
|
||||
18 => Ok(PolyType::AutoExit),
|
||||
19 => Ok(PolyType::OuchMinor),
|
||||
20 => Ok(PolyType::OuchMajor),
|
||||
21 => Ok(PolyType::Glue),
|
||||
22 => Ok(PolyType::GlueTrigger(pdata)),
|
||||
23 => Ok(PolyType::GlueSuper),
|
||||
n => Err(ReprError::new(n)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `PolyType` from a Marathon 1 compatible `n`/`pdata` pair.
|
||||
fn new_old(n: u16, pdata: u16) -> Result<Self, ReprError>
|
||||
{
|
||||
match n {
|
||||
0 => Ok(PolyType::Normal),
|
||||
1 => Ok(PolyType::ImpassItem),
|
||||
2 => Ok(PolyType::ImpassMons),
|
||||
3 => Ok(PolyType::OuchMinor),
|
||||
4 => Ok(PolyType::OuchMajor),
|
||||
5 => Ok(PolyType::Platform(pdata)),
|
||||
6 => Ok(PolyType::TrigLightOn(pdata)),
|
||||
7 => Ok(PolyType::TrigPlatOn(pdata)),
|
||||
8 => Ok(PolyType::TrigLightOff(pdata)),
|
||||
9 => Ok(PolyType::TrigPlatOff(pdata)),
|
||||
10 => Ok(PolyType::Teleporter(pdata)),
|
||||
11 => Ok(PolyType::Glue),
|
||||
12 => Ok(PolyType::GlueTrigger(pdata)),
|
||||
13 => Ok(PolyType::GlueSuper),
|
||||
14 => Ok(PolyType::MustExplore),
|
||||
15 => Ok(PolyType::AutoExit),
|
||||
n => Err(ReprError::new(n)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PolyType
|
||||
{
|
||||
fn default() -> Self {PolyType::Normal}
|
||||
}
|
||||
|
||||
/// A polygon segment.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Default, Eq, PartialEq)]
|
||||
pub struct Polygon
|
||||
{
|
||||
pub ptype: PolyType,
|
||||
pub tex_flr: OptU16,
|
||||
pub tex_cei: OptU16,
|
||||
pub hei_flr: Unit,
|
||||
pub hei_cei: Unit,
|
||||
pub lit_flr: u16,
|
||||
pub lit_cei: u16,
|
||||
pub xfr_flr: TransferMode,
|
||||
pub xfr_cei: TransferMode,
|
||||
pub ori_flr: Point,
|
||||
pub ori_cei: Point,
|
||||
pub med_ind: OptU16,
|
||||
pub med_ctl: u16,
|
||||
pub snd_ind: u16,
|
||||
pub snd_amb: OptU16,
|
||||
pub snd_rnd: OptU16,
|
||||
}
|
||||
|
||||
/// The action type of a `Polygon`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum PolyType
|
||||
{
|
||||
Normal,
|
||||
ImpassItem,
|
||||
ImpassMons,
|
||||
Hill,
|
||||
Base,
|
||||
Platform(u16),
|
||||
TrigLightOn(u16),
|
||||
TrigPlatOn(u16),
|
||||
TrigLightOff(u16),
|
||||
TrigPlatOff(u16),
|
||||
Teleporter(u16),
|
||||
ZoneBorder,
|
||||
Goal,
|
||||
TrigMonsVis,
|
||||
TrigMonsInv,
|
||||
TrigMonsDual,
|
||||
TrigItems,
|
||||
MustExplore,
|
||||
AutoExit,
|
||||
OuchMinor,
|
||||
OuchMajor,
|
||||
Glue,
|
||||
GlueTrigger(u16),
|
||||
GlueSuper,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for `Polygon`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct PolyFlags: u16
|
||||
{
|
||||
const DETACHED = 1 << 14;
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,90 @@
|
|||
//! `Side` type.
|
||||
|
||||
use crate::{durandal::{bin::OptU16, err::*, fixed::Fixed},
|
||||
marathon::xfer::TransferMode};
|
||||
use super::stex::{self, SideTex};
|
||||
use bitflags::bitflags;
|
||||
|
||||
/// Reads a `SIDS` chunk.
|
||||
pub fn read(b: &[u8]) -> ResultS<(Side, usize)>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 64, start: 0, data {
|
||||
let stype = u16[0] enum SideType;
|
||||
let flags = u16[2] flag SideFlags;
|
||||
let tex_pri = stex::read[4; 6];
|
||||
let tex_sec = stex::read[10; 6];
|
||||
let tex_tra = stex::read[16; 6];
|
||||
let paneltyp = u16[38];
|
||||
let paneldat = i16[40];
|
||||
let xfer_pri = u16[42] enum TransferMode;
|
||||
let xfer_sec = u16[44] enum TransferMode;
|
||||
let xfer_tra = u16[46] enum TransferMode;
|
||||
let shade = Fixed[48];
|
||||
}
|
||||
}
|
||||
|
||||
Ok((Side{stype, flags, tex_pri, tex_sec, tex_tra, paneltyp, paneldat,
|
||||
xfer_pri, xfer_sec, xfer_tra, shade}, 64))
|
||||
}
|
||||
|
||||
/// Reads an old `SIDS` chunk.
|
||||
pub fn read_old(b: &[u8]) -> ResultS<(Side, usize)>
|
||||
{
|
||||
let (side, siz) = read(b)?;
|
||||
|
||||
Ok((Side{tex_tra: SideTex{tex_id: OptU16::none(), ..side.tex_tra},
|
||||
shade: 0.into(),
|
||||
flags: side.flags | SideFlags::ITEM_OPT,
|
||||
..side}, siz))
|
||||
}
|
||||
|
||||
/// One side of a line segment.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Side
|
||||
{
|
||||
pub stype: SideType,
|
||||
pub flags: SideFlags,
|
||||
pub tex_pri: SideTex,
|
||||
pub tex_sec: SideTex,
|
||||
pub tex_tra: SideTex,
|
||||
pub paneltyp: u16,
|
||||
pub paneldat: i16,
|
||||
pub xfer_pri: TransferMode,
|
||||
pub xfer_sec: TransferMode,
|
||||
pub xfer_tra: TransferMode,
|
||||
pub shade: Fixed,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for `Side`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct SideFlags: u16
|
||||
{
|
||||
const STATUS = 1;
|
||||
const PANEL = 1 << 1;
|
||||
const REPAIR = 1 << 2;
|
||||
const ITEM_USE = 1 << 3;
|
||||
const LIGHTED = 1 << 4;
|
||||
const CAN_DESTROY = 1 << 5;
|
||||
const HIT_ONLY = 1 << 6;
|
||||
const ITEM_OPT = 1 << 7;
|
||||
}
|
||||
}
|
||||
|
||||
c_enum! {
|
||||
/// The texture type of a `Side`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum SideType: u16
|
||||
{
|
||||
Full = 0,
|
||||
High = 1,
|
||||
Low = 2,
|
||||
Composite = 3,
|
||||
Split = 4,
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,37 @@
|
|||
//! `SideTex` type.
|
||||
|
||||
use crate::durandal::{bin::OptU16, err::*};
|
||||
use super::pnts::*;
|
||||
|
||||
/// Reads a `SideTex` object.
|
||||
pub fn read(b: &[u8]) -> ResultS<SideTex>
|
||||
{
|
||||
read_data! {
|
||||
endian: BIG, buf: b, size: 6, start: 0, data {
|
||||
let offs = read_point[0; 4];
|
||||
let tex_id = OptU16[4];
|
||||
}
|
||||
}
|
||||
|
||||
Ok(SideTex{offs, tex_id})
|
||||
}
|
||||
|
||||
/// Writes a `SideTex` object.
|
||||
pub fn write(v: &SideTex) -> Vec<u8>
|
||||
{
|
||||
let mut o = Vec::with_capacity(6);
|
||||
o.extend(write_point(v.offs));
|
||||
o.extend(&v.tex_id.to_be_bytes());
|
||||
o
|
||||
}
|
||||
|
||||
/// The texture of a side segment.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct SideTex
|
||||
{
|
||||
pub offs: Point,
|
||||
pub tex_id: OptU16,
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -11,10 +11,10 @@ pub fn read_chunks(b: &[u8], old_dat: bool, siz_cnk: usize)
|
|||
let mut chunks = Vec::new();
|
||||
let mut p = 0;
|
||||
|
||||
let map_read_minfo = if old_dat {map::read_old_minf} else {map::read_minf};
|
||||
let map_read_sides = if old_dat {map::read_old_sids} else {map::read_sids};
|
||||
let map_read_polys = if old_dat {map::read_old_poly} else {map::read_poly};
|
||||
let map_read_light = if old_dat {map::read_old_lite} else {map::read_lite};
|
||||
let rd_minf = if old_dat {map::minf::read_old} else {map::minf::read};
|
||||
let rd_sids = if old_dat {map::sids::read_old} else {map::sids::read};
|
||||
let rd_poly = if old_dat {map::poly::read_old} else {map::poly::read};
|
||||
let rd_lite = if old_dat {map::lite::read_old} else {map::lite::read};
|
||||
|
||||
while p < b.len() {
|
||||
read_data! {
|
||||
|
@ -30,21 +30,21 @@ pub fn read_chunks(b: &[u8], old_dat: bool, siz_cnk: usize)
|
|||
|
||||
chunks.push(match &iden.0 {
|
||||
b"PICT" => Chunk::Pict(pict::load_pict(data)?),
|
||||
b"Minf" => Chunk::Minf(map_read_minfo(data)?),
|
||||
b"iidx" => Chunk::Iidx(rd_array(data, map::read_iidx)?),
|
||||
b"EPNT" => Chunk::Pnts(rd_array(data, map::read_epnt)?),
|
||||
b"PNTS" => Chunk::Pnts(rd_array(data, map::read_pnts)?),
|
||||
b"LINS" => Chunk::Lins(rd_array(data, map::read_lins)?),
|
||||
b"SIDS" => Chunk::Sids(rd_array(data, map_read_sides)?),
|
||||
b"POLY" => Chunk::Poly(rd_array(data, map_read_polys)?),
|
||||
b"OBJS" => Chunk::Objs(rd_array(data, map::read_objs)?),
|
||||
b"LITE" => Chunk::Lite(rd_array(data, map_read_light)?),
|
||||
b"plac" => Chunk::Plac(rd_array(data, map::read_plac)?),
|
||||
b"ambi" => Chunk::Ambi(rd_array(data, map::read_ambi)?),
|
||||
b"bonk" => Chunk::Bonk(rd_array(data, map::read_bonk)?),
|
||||
b"medi" => Chunk::Medi(rd_array(data, map::read_medi)?),
|
||||
b"plat" => Chunk::Plat(rd_array(data, map::read_plat)?),
|
||||
b"NOTE" => Chunk::Note(rd_array(data, map::read_note)?),
|
||||
b"Minf" => Chunk::Minf(rd_minf(data)?),
|
||||
b"iidx" => Chunk::Iidx(rd_array(data, map::iidx::read)?),
|
||||
b"EPNT" => Chunk::Pnts(rd_array(data, map::epnt::read)?),
|
||||
b"PNTS" => Chunk::Pnts(rd_array(data, map::pnts::read)?),
|
||||
b"LINS" => Chunk::Lins(rd_array(data, map::lins::read)?),
|
||||
b"SIDS" => Chunk::Sids(rd_array(data, rd_sids)?),
|
||||
b"POLY" => Chunk::Poly(rd_array(data, rd_poly)?),
|
||||
b"OBJS" => Chunk::Objs(rd_array(data, map::objs::read)?),
|
||||
b"LITE" => Chunk::Lite(rd_array(data, rd_lite)?),
|
||||
b"plac" => Chunk::Plac(rd_array(data, map::plac::read)?),
|
||||
b"ambi" => Chunk::Ambi(rd_array(data, map::ambi::read)?),
|
||||
b"bonk" => Chunk::Bonk(rd_array(data, map::bonk::read)?),
|
||||
b"medi" => Chunk::Medi(rd_array(data, map::medi::read)?),
|
||||
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)?),
|
||||
|
@ -143,20 +143,20 @@ pub fn read_wad(b: &[u8]) -> ResultS<Wad>
|
|||
pub enum Chunk
|
||||
{
|
||||
/** A `PICT` chunk. */ Pict(image::Image8),
|
||||
/** A `Minf` chunk. */ Minf(map::Minf),
|
||||
/** A `Minf` chunk. */ Minf(map::minf::Minf),
|
||||
/** An `iidx` chunk. */ Iidx(Vec<u16>),
|
||||
/** A `PNTS` chunk. */ Pnts(Vec<map::Point>),
|
||||
/** A `LINS` chunk. */ Lins(Vec<map::Line>),
|
||||
/** A `SIDS` chunk. */ Sids(Vec<map::Side>),
|
||||
/** A `POLY` chunk. */ Poly(Vec<map::Polygon>),
|
||||
/** A `LITE` chunk. */ Lite(Vec<map::Light>),
|
||||
/** An `OBJS` chunk. */ Objs(Vec<map::Object>),
|
||||
/** A `plac` chunk. */ Plac(Vec<map::ObjectFreq>),
|
||||
/** An `ambi` chunk. */ Ambi(Vec<map::SoundAmbi>),
|
||||
/** A `bonk` chunk. */ Bonk(Vec<map::SoundRand>),
|
||||
/** A `medi` chunk. */ Medi(Vec<map::Media>),
|
||||
/** A `plat` chunk. */ Plat(Vec<map::Platform>),
|
||||
/** A `NOTE` chunk. */ Note(Vec<map::Note>),
|
||||
/** A `PNTS` chunk. */ Pnts(Vec<map::pnts::Point>),
|
||||
/** A `LINS` chunk. */ Lins(Vec<map::lins::Line>),
|
||||
/** A `SIDS` chunk. */ Sids(Vec<map::sids::Side>),
|
||||
/** A `POLY` chunk. */ Poly(Vec<map::poly::Polygon>),
|
||||
/** A `LITE` chunk. */ Lite(Vec<map::lite::Light>),
|
||||
/** An `OBJS` chunk. */ Objs(Vec<map::objs::Object>),
|
||||
/** A `plac` chunk. */ Plac(Vec<map::plac::ObjectFreq>),
|
||||
/** An `ambi` chunk. */ Ambi(Vec<map::ambi::SoundAmbi>),
|
||||
/** A `bonk` chunk. */ Bonk(Vec<map::bonk::SoundRand>),
|
||||
/** A `medi` chunk. */ Medi(Vec<map::medi::Media>),
|
||||
/** 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>),
|
||||
|
|
|
@ -5,7 +5,7 @@ impl Default for Block
|
|||
#[inline]
|
||||
fn default() -> Self
|
||||
{
|
||||
Self{info: map::Minf::default()}
|
||||
Self{info: map::minf::Minf::default()}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ impl Default for Block
|
|||
#[derive(Clone, Debug)]
|
||||
pub(super) struct Block
|
||||
{
|
||||
pub(super) info: map::Minf,
|
||||
pub(super) info: map::minf::Minf,
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
|
Loading…
Reference in New Issue