Maraiah/source/marathon/map.rs

1138 lines
33 KiB
Rust

//! 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<LightFunc>
{
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<SideTex>
{
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<Point>
{
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<Minf>
{
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