//! Structures used by Marathon's Map format. use crate::{durandal::{bin::*, err::*, fixed::*, text::*}, marathon::xfer::TransferMode}; use bitflags::bitflags; /// Reads a `LightFunc` object. pub fn read_lightfunc(b: &[u8]) -> ResultS { read_data! { 14, BE in b => ftype = u16[0]; prd_nrm = u16[2]; prd_dta = u16[4]; val_nrm = Fixed[6]; val_dta = Fixed[10]; } let ftype = LightFuncType::from_repr(ftype)?; Ok(LightFunc{ftype, prd_nrm, prd_dta, val_nrm, val_dta}) } /// Reads a `SideTex` object. pub fn read_sidetex(b: &[u8]) -> ResultS { read_data! { 6, BE in b => offs = read_point[0..4]; tex_id = OptU16[4]; } Ok(SideTex{offs, tex_id}) } /// Reads a `Point` object. pub fn read_point(b: &[u8]) -> ResultS { read_data! { 4, BE in b => x = Unit[0]; y = Unit[2]; } Ok(Point{x, y}) } /// Reads a `Minf` chunk. pub fn read_minf(b: &[u8]) -> ResultS { read_data! { 88, BE in b => env_code = u16[0]; physi_id = u16[2]; music_id = u16[4]; missi_flags = u16[6]; envir_flags = u16[8]; level_name = mac_roman_cstr[18..84]; entry_flags = u32[84]; } let missi_flags = flag_ok!(MsnFlags, missi_flags)?; let envir_flags = flag_ok!(EnvFlags, envir_flags)?; let entry_flags = flag_ok!(EntFlags, entry_flags)?; Ok(Minf{env_code, physi_id, music_id, missi_flags, envir_flags, entry_flags, level_name}) } /// Reads an `iidx` chunk. pub fn read_iidx(b: &[u8]) -> ResultS<(u16, usize)> {Ok((u16b(b), 2))} /// Reads an `EPNT` chunk. pub fn read_epnt(b: &[u8]) -> ResultS<(Point, usize)> { read_data! { 16, BE in b => pnt = read_point[6..10]; } Ok((pnt, 16)) } /// Reads a `PNTS` chunk. pub fn read_pnts(b: &[u8]) -> ResultS<(Point, usize)> { Ok((read_point(b)?, 4)) } /// Reads a `LINS` chunk. pub fn read_lins(b: &[u8]) -> ResultS<(Line, usize)> { read_data! { 32, BE in b => pnt_beg = u16[0]; pnt_end = u16[2]; flags = u16[4]; side_fr = OptU16[12]; side_bk = OptU16[14]; poly_fr = OptU16[16]; poly_bk = OptU16[18]; } let flags = flag_ok!(LineFlags, flags)?; Ok((Line{flags, pnt_beg, pnt_end, side_fr, side_bk, poly_fr, poly_bk}, 32)) } /// Reads a `SIDS` chunk. pub fn read_sids(b: &[u8]) -> ResultS<(Side, usize)> { read_data! { 64, BE in b => stype = u16[0]; flags = u16[2]; tex_pri = read_sidetex[4..10]; tex_sec = read_sidetex[10..16]; tex_tra = read_sidetex[16..22]; paneltyp = u16[38]; paneldat = i16[40]; xfer_pri = u16[42]; xfer_sec = u16[44]; xfer_tra = u16[46]; shade = Fixed[48]; } let flags = flag_ok!(SideFlags, flags)?; let xfer_pri = TransferMode::from_repr(xfer_pri)?; let xfer_sec = TransferMode::from_repr(xfer_sec)?; let xfer_tra = TransferMode::from_repr(xfer_tra)?; let stype = SideType::from_repr(stype)?; 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_sids(b: &[u8]) -> ResultS<(Side, usize)> { let (side, siz) = read_sids(b)?; Ok((Side{tex_tra: SideTex{tex_id: OptU16::none(), ..side.tex_tra}, shade: 0.into(), flags: side.flags | SideFlags::ItemOpt, ..side}, siz)) } /// Reads a `POLY` chunk. pub fn read_poly(b: &[u8]) -> ResultS<(Polygon, usize)> { read_data! { 128, BE in b => ptype = u16[0]; pdata = i16[4]; tex_flr = OptU16[40]; tex_cei = OptU16[42]; hei_flr = Unit[44]; hei_cei = Unit[46]; lit_flr = u16[48]; lit_cei = u16[50]; xfr_flr = u16[64]; xfr_cei = u16[66]; ori_flr = read_point[108..112]; ori_cei = read_point[112..116]; med_ind = OptU16[116]; med_ctl = u16[118]; snd_ind = u16[120]; snd_amb = OptU16[122]; snd_rnd = OptU16[124]; } let xfr_flr = TransferMode::from_repr(xfr_flr)?; let xfr_cei = TransferMode::from_repr(xfr_cei)?; let ptype = PolyType::from_repr(ptype)?; Ok((Polygon{ptype, pdata, tex_flr, tex_cei, hei_flr, hei_cei, lit_flr, lit_cei, xfr_flr, xfr_cei, ori_flr, ori_cei, med_ind, med_ctl, snd_ind, snd_amb, snd_rnd}, 128)) } /// Reads an old `POLY` chunk. pub fn read_old_poly(b: &[u8]) -> ResultS<(Polygon, usize)> { let (poly, siz) = read_poly(b)?; Ok((Polygon{ptype: match poly.ptype { PolyType::Hill => PolyType::OuchMinor, PolyType::Base => PolyType::OuchMajor, PolyType::ZoneBorder => PolyType::Glue, PolyType::Goal => PolyType::GlueTrigger, PolyType::TrigMonsVis => PolyType::GlueSuper, PolyType::TrigMonsInv => PolyType::MustExplore, PolyType::TrigMonsDual => PolyType::AutoExit, ptype => ptype, }, ori_flr: Point{x: 0.into(), y: 0.into()}, ori_cei: Point{x: 0.into(), y: 0.into()}, med_ind: OptU16::none(), snd_amb: OptU16::none(), snd_rnd: OptU16::none(), ..poly}, siz)) } /// Reads a `LITE` chunk. pub fn read_lite(b: &[u8]) -> ResultS<(Light, usize)> { read_data! { 100, BE in b => ltype = u16[0]; flags = u16[2]; phase = i16[4]; act_pri = read_lightfunc[6..20]; act_sec = read_lightfunc[20..34]; act_mid = read_lightfunc[34..48]; ina_pri = read_lightfunc[48..62]; ina_sec = read_lightfunc[62..76]; ina_mid = read_lightfunc[76..90]; tag = u16[90]; } let flags = flag_ok!(LightFlags, flags)?; let ltype = LightType::from_repr(ltype)?; 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_lite(b: &[u8]) -> ResultS<(Light, usize)> { read_data! { 32, BE in b => ltype = u16[2] usize; mode = u16[4]; phase = i16[6]; min = Fixed[8]; max = Fixed[12]; 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::InitActive} 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)) } /// Reads an `OBJS` chunk. pub fn read_objs(b: &[u8]) -> ResultS<(Object, usize)> { read_data! { 16, BE in b => group = u16[0]; index = u16[2]; angle = Angle[4]; poly = u16[6]; pos_x = Unit[8]; pos_y = Unit[10]; pos_z = Unit[12]; 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)) } /// Reads a `plac` chunk. pub fn read_plac(b: &[u8]) -> ResultS<(ObjectFreq, usize)> { read_data! { 12, BE in b => flags = u16[0]; cnt_ini = u16[2]; cnt_min = u16[4]; cnt_max = u16[6]; cnt_rnd = u16[8]; chance = u16[10]; } let rnd_loc = flags != 0; Ok((ObjectFreq{rnd_loc, cnt_ini, cnt_min, cnt_max, cnt_rnd, chance}, 12)) } /// Reads an `ambi` chunk. pub fn read_ambi(b: &[u8]) -> ResultS<(SoundAmbi, usize)> { read_data! { 16, BE in b => index = u16[2]; volume = u16[4]; } Ok((SoundAmbi{index, volume}, 16)) } /// Reads a `bonk` chunk. pub fn read_bonk(b: &[u8]) -> ResultS<(SoundRand, usize)> { read_data! { 32, BE in b => flags = u16[0]; index = u16[2]; vol_nrm = u16[4]; vol_dta = u16[6]; prd_nrm = u16[8]; prd_dta = u16[10]; yaw_nrm = Angle[12]; yaw_dta = Angle[14]; pit_nrm = Fixed[16]; 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)) } /// Reads a `medi` chunk. pub fn read_medi(b: &[u8]) -> ResultS<(Media, usize)> { read_data! { 32, BE in b => mtype = u16[0]; flags = u16[2]; control = u16[4]; dir = Angle[6]; mag = Unit[8]; hei_lo = Unit[10]; hei_hi = Unit[12]; orig = read_point[14..18]; hei_nrm = Unit[18]; min_lt = Fixed[20]; texture = OptU16[24]; xfer = u16[26]; } let mtype = MediaType::from_repr(mtype)?; let xfer = TransferMode::from_repr(xfer)?; 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)) } /// Reads a `plat` chunk. pub fn read_plat(b: &[u8]) -> ResultS<(Platform, usize)> { read_data! { 32, BE in b => ptype = u16[0]; speed = u16[2]; delay = u16[4]; hei_max = Unit[6]; hei_min = Unit[8]; flags = u32[10]; index = u16[14]; tag = u16[16]; } let flags = flag_ok!(PlatformFlags, flags)?; Ok((Platform{ptype, speed, delay, hei_min, hei_max, flags, index, tag}, 32)) } /// Reads a `NOTE` chunk. pub fn read_note(b: &[u8]) -> ResultS<(Note, usize)> { read_data! { 72, BE in b => pos = read_point[2..6]; poly = u16[6]; text = mac_roman_cstr[8..72]; } Ok((Note{pos, poly, text}, 72)) } /// A point in world-space. #[derive(Clone, PartialEq, serde::Serialize)] pub struct Point { pub x: Unit, pub y: Unit, } /// A line segment. #[derive(Debug, serde::Serialize)] 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, } /// The texture of a side segment. #[derive(Debug, serde::Serialize)] pub struct SideTex { pub offs: Point, pub tex_id: OptU16, } /// One side of a line segment. #[derive(Debug, serde::Serialize)] 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, } /// A polygon segment. #[derive(Debug, serde::Serialize)] pub struct Polygon { pub ptype: PolyType, pub pdata: i16, 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, } /// A light function. #[derive(Debug, serde::Serialize)] pub struct LightFunc { pub ftype: LightFuncType, pub prd_nrm: u16, pub prd_dta: u16, pub val_nrm: Fixed, pub val_dta: Fixed, } /// A dynamic polygon light. #[derive(Debug, serde::Serialize)] 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, } /// An object in the world. #[derive(Debug, serde::Serialize)] 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, } /// The difficulty definition for various object types. #[derive(Debug, serde::Serialize)] 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, } /// An ambient sound definition. #[derive(Debug, serde::Serialize)] pub struct SoundAmbi { pub index: u16, pub volume: u16, } /// A randomly played sound definition. #[derive(Debug, serde::Serialize)] 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, } /// A media, as in a part of a polygon which goes up the middle of the wall. #[derive(Debug, serde::Serialize)] 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, } /// Extra information for polygons with platforms. #[derive(Debug, serde::Serialize)] 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, } /// Overhead map annotations. #[derive(Debug, serde::Serialize)] pub struct Note { pub pos: Point, pub poly: u16, pub text: String, } /// Static map information. #[derive(Debug, Default, PartialEq, serde::Serialize)] pub struct Minf { pub env_code: u16, pub physi_id: u16, pub music_id: u16, pub missi_flags: MsnFlags, pub envir_flags: EnvFlags, pub entry_flags: EntFlags, pub level_name: String, } bitflags! { /// Flags for `Line`. #[derive(serde::Serialize)] pub struct LineFlags: u16 { const TransSide = 1 << 9; const ElevVar = 1 << 10; const Elevation = 1 << 11; const Landscape = 1 << 12; const Transparent = 1 << 13; const Solid = 1 << 14; } } bitflags! { /// Flags for `Side`. #[derive(serde::Serialize)] pub struct SideFlags: u16 { const Status = 1; const Panel = 1 << 1; const Repair = 1 << 2; const ItemUse = 1 << 3; const Lighted = 1 << 4; const CanDestroy = 1 << 5; const HitOnly = 1 << 6; const ItemOpt = 1 << 7; } } bitflags! { /// Static environment flags. #[derive(Default, serde::Serialize)] pub struct EnvFlags: u16 { const Vacuum = 1; const Magnetic = 1 << 1; const Rebellion = 1 << 2; const LowGrav = 1 << 3; const M1Glue = 1 << 4; const LavaFloor = 1 << 5; const Rebellion2 = 1 << 6; const Music = 1 << 7; const TermPause = 1 << 8; const M1Monster = 1 << 9; const M1Weps = 1 << 10; } } bitflags! { /// Static entry point flags. #[derive(Default, serde::Serialize)] pub struct EntFlags: u32 { const Solo = 1; const CoOp = 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. #[derive(Default, 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; } } bitflags! { /// Flags for `Polygon`. #[derive(serde::Serialize)] pub struct PolyFlags: u16 { const Detached = 1 << 14; } } bitflags! { /// Flags for `Light`. #[derive(serde::Serialize)] pub struct LightFlags: u16 { const InitActive = 1; const SlaveValue = 1 << 1; const Stateless = 1 << 2; } } bitflags! { /// Flags for `Object`. #[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 NetOnly = 1 << 5; } } bitflags! { /// Flags for `Platform`. #[derive(serde::Serialize)] pub struct PlatformFlags: u32 { const InitActive = 1; const InitExtended = 1 << 1; const StopAtEachLevel = 1 << 2; const StopAtInitLevel = 1 << 3; const StartAdjOnStop = 1 << 4; const ExtendsFloorToCeil = 1 << 5; const ComesFromFloor = 1 << 6; const ComesFromCeil = 1 << 7; const CausesDamage = 1 << 8; const NoActivateParent = 1 << 9; const ActivatesOnce = 1 << 10; const ActivatesLight = 1 << 11; const DeactivatesLight = 1 << 12; const PlayerControls = 1 << 13; const MonsterControls = 1 << 14; const ReverseOnObstruct = 1 << 15; const NoExtDeactivation = 1 << 16; const UsePolygonHeights = 1 << 17; const DelayedActivation = 1 << 18; const StartAdjOnStart = 1 << 19; const StopAdjOnStart = 1 << 20; const StopAdjOnStop = 1 << 21; const Slow = 1 << 22; const StartAtEachLevel = 1 << 23; const Locked = 1 << 24; const Secret = 1 << 25; const Door = 1 << 26; } } c_enum! { /// The texture type of a `Side`. #[derive(Debug, serde::Serialize)] pub enum SideType: u16 { 0 => Full, 1 => High, 2 => Low, 3 => Composite, 4 => Split, } } c_enum! { /// The action type of a `Polygon`. #[derive(Debug, serde::Serialize)] pub enum PolyType: u16 { 0 => Normal, 1 => ImpassItem, 2 => ImpassMons, 3 => Hill, 4 => Base, 5 => Platform, 6 => TrigLightOn, 7 => TrigPlatOn, 8 => TrigLightOff, 9 => TrigPlatOff, 10 => Teleporter, 11 => ZoneBorder, 12 => Goal, 13 => TrigMonsVis, 14 => TrigMonsInv, 15 => TrigMonsDual, 16 => TrigItems, 17 => MustExplore, 18 => AutoExit, 19 => OuchMinor, 20 => OuchMajor, 21 => Glue, 22 => GlueTrigger, 23 => GlueSuper, } } c_enum! { /// The type of function for a `LightFunc`. #[derive(Debug, serde::Serialize)] pub enum LightFuncType: u16 { 0 => Constant, 1 => Linear, 2 => Smooth, 3 => Flicker, 4 => Random, 5 => Fluorescent, } } c_enum! { /// The type of a `Light`. #[derive(Debug, serde::Serialize)] pub enum LightType: u16 { 0 => Normal, 1 => Strobe, 2 => Media, } } c_enum! { /// The liquid type of a `Media`. #[derive(Debug, serde::Serialize)] pub enum MediaType: u16 { 0 => Water, 1 => Lava, 2 => Goo, 3 => Sewage, } } impl std::fmt::Debug for Point { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "({}, {})", self.x, self.y) } } pub const TICKS_PER_SECOND: u16 = 30; const OLD_LIGHT_DEFINITIONS: [Light; 8] = [ // Normal Light{ltype: LightType::Normal, flags: LightFlags::SlaveValue, 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::SlaveValue, 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::SlaveValue, 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::SlaveValue, 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::SlaveValue, 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::SlaveValue, 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::SlaveValue, 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::SlaveValue, 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