MNpx loader

png-branch
an 2019-02-22 16:19:52 -05:00
parent 961e0d6de0
commit 4edd1af472
3 changed files with 417 additions and 0 deletions

View File

@ -1077,6 +1077,69 @@ Projectile Definition is 48 bytes.
- `Damage` is a Damage Definition structure.
- `Flags` is a Projectile Flags bit field.
### Monster Definition ###
Monster Definition is 156 bytes.
| Name | Type | Offset |
| ---- | ---- | ------ |
| `Collection` | `u16` | `0` |
| `Vitality` | `u16` | `2` |
| `ImmuneTo` | `u32` | `4` |
| `WeakTo` | `u32` | `8` |
| `Flags` | `u32` | `12` |
| `MonsterClass` | `u32` | `16` |
| `FriendTo` | `u32` | `20` |
| `EnemyTo` | `u32` | `24` |
| `SndPitch` | `fixed` | `28` |
| `SndSeeEnemy` | `u16opt` | `32` |
| `SndSeeFriend` | `u16opt` | `34` |
| `SndSeeClear` | `u16opt` | `36` |
| `SndKill` | `u16opt` | `38` |
| `SndApologize` | `u16opt` | `40` |
| `SndAmicide` | `u16opt` | `42` |
| `SndFlaming` | `u16opt` | `44` |
| `SndActive` | `u16opt` | `46` |
| `ActiveMask` | `u16` | `48` |
| `DropItem` | `u16opt` | `50` |
| `Radius` | `unit` | `52` |
| `Height` | `unit` | `54` |
| `HoverHeight` | `unit` | `56` |
| `LedgeMin` | `unit` | `58` |
| `LedgeMax` | `unit` | `60` |
| `ExtVelScale` | `fixed` | `62` |
| `FxImpact` | `u16opt` | `66` |
| `FxMeleeImpact`| `u16opt` | `68` |
| `FxTrail` | `u16opt` | `70` |
| `HalfFOVHorz` | `u16` | `72` |
| `HalfFOVVert` | `u16` | `74` |
| `ViewRange` | `unit` | `76` |
| `ViewRangeDark`| `unit` | `78` |
| `Intelligence` | `u16` | `80` |
| `Speed` | `u16` | `82` |
| `Gravity` | `u16` | `84` |
| `TerminalVel` | `u16` | `86` |
| `DoorTryMask` | `u16` | `88` |
| `ExplodeRadius`| `u16opt` | `90` |
| `ExplodeDamage`| `struct` | `92` |
| `SeqHit` | `u16opt` | `104` |
| `SeqHardDying` | `u16opt` | `106` |
| `SeqSoftDying` | `u16opt` | `108` |
| `SeqHardDead` | `u16opt` | `110` |
| `SeqSoftDead` | `u16opt` | `112` |
| `SeqStanding` | `u16` | `114` |
| `SeqMoving` | `u16` | `116` |
| `SeqTeleIn` | `u16opt` | `118` |
| `SeqTeleOut` | `u16opt` | `120` |
| `AtkFrequency` | `u16` | `122` |
| `AtkMelee` | `struct` | `124` |
| `AtkRange` | `struct` | `140` |
- `Flags` is a Monster Flags bit field.
- `MonsterClass` is a Monster Class bit field.
- `ExplodeDamage` is a Damage Definition structure.
- `AtkMelee` and `AtkRange` are Attack Definition structures.
### Damage Definition ###
Damage Definition is 12 bytes.
@ -1092,6 +1155,21 @@ Damage Definition is 12 bytes.
- `Type` is a Damage Type enumeration.
- `Flags` is a Damage Flags enumeration.
### Attack Definition ###
Attack Definition is 16 bytes.
| Name | Type | Offset |
| ---- | ---- | ------ |
| `Type` | `u16opt` | `0` |
| `Repetitions` | `u16` | `2` |
| `Error` | `angle` | `4` |
| `Range` | `unit` | `6` |
| `Shape` | `u16` | `8` |
| `OfsX` | `unit` | `10` |
| `OfsY` | `unit` | `12` |
| `OfsZ` | `unit` | `14` |
## Images ##
### Picture Resource ###
@ -2150,4 +2228,87 @@ this actually hurts my head.
| `UseLowGrav` | `19` |
| `PassMedia` | `20` |
### Monster Flags ###
| Name | Bit |
| ---- | --- |
| `IgnoreLOS` | `0` |
| `Flying` | `1` |
| `Alien` | `2` |
| `Major` | `3` |
| `Minor` | `4` |
| `NoOmit` | `5` |
| `Floats` | `6` |
| `NoAttack` | `7` |
| `Snipe` | `8` |
| `Invisible` | `9` |
| `SubtlyInvisible` | `10` |
| `Kamikaze` | `11` |
| `Berserker` | `12` |
| `Enlarged` | `13` |
| `DelayedDeath` | `14` |
| `FireSymmetrical` | `15` |
| `NuclearDeath` | `16` |
| `NoFireBackwards` | `17` |
| `CanDieInFlames` | `18` |
| `WaitForGoodShot` | `19` |
| `Tiny` | `20` |
| `FastAttack` | `21` |
| `LikesWater` | `22` |
| `LikesSewage` | `23` |
| `LikesLava` | `24` |
| `LikesGoo` | `25` |
| `TeleUnderMedia` | `26` |
| `UseRandomWeapon` | `27` |
### Monster Class ###
| Name | Bit |
| ---- | --- |
| `Player` | `0` |
| `Civilian` | `1` |
| `Madd` | `2` |
| `PossessedHummer` | `3` |
| `Defender` | `4` |
| `Fighter` | `5` |
| `Trooper` | `6` |
| `Hunter` | `7` |
| `Enforcer` | `8` |
| `Juggernaut` | `9` |
| `Hummer` | `10` |
| `Compiler` | `11` |
| `Cyborg` | `12` |
| `Assimilated` | `13` |
| `Tick` | `14` |
| `Yeti` | `15` |
### Damage Type Flag ###
| Name | Bit |
| ---- | --- |
| `Explosion` | `0` |
| `ElectricalStaff` | `1` |
| `Projectile` | `2` |
| `Absorbed` | `3` |
| `Flame` | `4` |
| `HoundClaws` | `5` |
| `AlienProjectile` | `6` |
| `HulkSlap` | `7` |
| `CompilerBolt` | `8` |
| `FusionBolt` | `9` |
| `HunterBolt` | `10` |
| `Fist` | `11` |
| `Teleporter` | `12` |
| `Defender` | `13` |
| `YetiClaws` | `14` |
| `YetiProjectile` | `15` |
| `Crushing` | `16` |
| `Lava` | `17` |
| `Suffocation` | `18` |
| `Goo` | `19` |
| `EnergyDrain` | `20` |
| `OxygenDrain` | `21` |
| `HummerBolt` | `22` |
| `ShotgunProjectile` | `23` |
<!-- EOF -->

View File

@ -64,6 +64,7 @@ fn dump_chunk(opt: &Options, cid: Ident, cnk: &[u8], eid: u16) -> ResultS<()>
b"plat" => make_yaml(opt, &rd_array(cnk, map::read_plat)?)?,
b"term" => make_yaml(opt, &rd_array(cnk, trm::read_term)?)?,
b"FXpx" => make_yaml(opt, &rd_array(cnk, phy::read_fxpx)?)?,
b"MNpx" => make_yaml(opt, &rd_array(cnk, phy::read_mnpx)?)?,
b"PRpx" => make_yaml(opt, &rd_array(cnk, phy::read_prpx)?)?,
b"PXpx" => make_yaml(opt, &rd_array(cnk, phy::read_pxpx)?)?,
b"WPpx" => make_yaml(opt, &rd_array(cnk, phy::read_wppx)?)?,

View File

@ -128,6 +128,86 @@ pub fn read_prpx(b: &[u8]) -> ResultS<(Projectile, usize)>
flags, speed, range, snd_pitch, snd_fly, snd_bounce}, 48))
}
pub fn read_mnpx(b: &[u8]) -> ResultS<(Monster, usize)>
{
read_data! {
156, BE in b =>
collection = u16[0];
vitality = u16[2];
dty_immune = u32[4];
dty_weak = u32[8];
flags = u32[12];
cls_self = u32[16];
cls_friend = u32[20];
cls_enemy = u32[24];
snd_pitch = Fixed[28];
snd_see_enemy = OptU16[32];
snd_see_friend = OptU16[34];
snd_seeclear = OptU16[36];
snd_kill = OptU16[38];
snd_apologize = OptU16[40];
snd_amicide = OptU16[42];
snd_flaming = OptU16[44];
snd_active = OptU16[46];
snd_active_mask = u16[48];
typ_item = OptU16[50];
radius = Unit[52];
height = Unit[54];
height_hover = Unit[56];
ledge_min = Unit[58];
ledge_max = Unit[60];
ext_vel_scale = Fixed[62];
fxt_impact = OptU16[66];
fxt_impact_melee = OptU16[68];
fxt_trail = OptU16[70];
half_fov_horz = u16[72];
half_fov_vert = u16[74];
view_range = Unit[76];
view_range_dark = Unit[78];
intelligence = u16[80];
speed = u16[82];
gravity = u16[84];
vel_terminal = u16[86];
door_try_mask = u16[88];
expl_radius = OptU16[90];
expl_damage = read_damage[92..104];
seq_hit = OptU16[104];
seq_dying_hard = OptU16[106];
seq_dying_soft = OptU16[108];
seq_dead_hard = OptU16[110];
seq_dead_soft = OptU16[112];
seq_standing = u16[114];
seq_moving = u16[116];
seq_tele_in = OptU16[118];
seq_tele_out = OptU16[120];
atk_frequency = u16[122];
atk_melee = read_attack[124..140];
atk_range = read_attack[140..156];
}
// friend and enemy fields MUST truncate because the original source code
// used `-1` to represent "all classes" which should be invalid normally
let dty_immune = flag_ok!(DamageTypeFlags, dty_immune)?;
let dty_weak = flag_ok!(DamageTypeFlags, dty_weak)?;
let flags = flag_ok!(MonsterFlags, flags)?;
let cls_self = flag_ok!(MonsterClass, cls_self)?;
let cls_friend = MonsterClass::from_bits_truncate(cls_friend);
let cls_enemy = MonsterClass::from_bits_truncate(cls_enemy);
Ok((Monster{collection, vitality, dty_immune, dty_weak, flags, cls_self,
cls_friend, cls_enemy, snd_pitch, snd_see_enemy, snd_see_friend,
snd_seeclear, snd_kill, snd_apologize, snd_amicide, snd_flaming,
snd_active, snd_active_mask, typ_item, radius, height,
height_hover, ledge_min, ledge_max, ext_vel_scale, fxt_impact,
fxt_impact_melee, fxt_trail, half_fov_horz, half_fov_vert,
view_range, view_range_dark, intelligence, speed, gravity,
vel_terminal, door_try_mask, expl_radius, expl_damage, seq_hit,
seq_dying_hard, seq_dying_soft, seq_dead_hard, seq_dead_soft,
seq_standing, seq_moving, seq_tele_in, seq_tele_out,
atk_frequency, atk_melee, atk_range}, 156))
}
fn read_trigger(b: &[u8]) -> ResultS<Trigger>
{
read_data! {
@ -176,6 +256,23 @@ fn read_damage(b: &[u8]) -> ResultS<Damage>
Ok(Damage{dtype, alien, dmg_base, dmg_rand, scale})
}
fn read_attack(b: &[u8]) -> ResultS<Attack>
{
read_data! {
16, BE in b =>
ptype = OptU16[0];
rep = u16[2];
error = Angle[4];
range = Unit[6];
shape = u16[8];
ofs_x = Unit[10];
ofs_y = Unit[12];
ofs_z = Unit[14];
}
Ok(Attack{ptype, rep, error, range, shape, ofs_x, ofs_y, ofs_z})
}
#[derive(Debug, Serialize)]
pub struct Physics
{
@ -293,6 +390,62 @@ pub struct Projectile
pub snd_bounce: OptU16,
}
#[derive(Debug, Serialize)]
pub struct Monster
{
pub collection: u16,
pub vitality: u16,
pub dty_immune: DamageTypeFlags,
pub dty_weak: DamageTypeFlags,
pub flags: MonsterFlags,
pub cls_self: MonsterClass,
pub cls_friend: MonsterClass,
pub cls_enemy: MonsterClass,
pub snd_pitch: Fixed,
pub snd_see_enemy: OptU16,
pub snd_see_friend: OptU16,
pub snd_seeclear: OptU16,
pub snd_kill: OptU16,
pub snd_apologize: OptU16,
pub snd_amicide: OptU16,
pub snd_flaming: OptU16,
pub snd_active: OptU16,
pub snd_active_mask: u16,
pub typ_item: OptU16,
pub radius: Unit,
pub height: Unit,
pub height_hover: Unit,
pub ledge_min: Unit,
pub ledge_max: Unit,
pub ext_vel_scale: Fixed,
pub fxt_impact: OptU16,
pub fxt_impact_melee: OptU16,
pub fxt_trail: OptU16,
pub half_fov_horz: u16,
pub half_fov_vert: u16,
pub view_range: Unit,
pub view_range_dark: Unit,
pub intelligence: u16,
pub speed: u16,
pub gravity: u16,
pub vel_terminal: u16,
pub door_try_mask: u16,
pub expl_radius: OptU16,
pub expl_damage: Damage,
pub seq_hit: OptU16,
pub seq_dying_hard: OptU16,
pub seq_dying_soft: OptU16,
pub seq_dead_hard: OptU16,
pub seq_dead_soft: OptU16,
pub seq_standing: u16,
pub seq_moving: u16,
pub seq_tele_in: OptU16,
pub seq_tele_out: OptU16,
pub atk_frequency: u16,
pub atk_melee: Attack,
pub atk_range: Attack,
}
#[derive(Debug, Serialize)]
pub struct Damage
{
@ -303,6 +456,19 @@ pub struct Damage
pub scale: Fixed,
}
#[derive(Debug, Serialize)]
pub struct Attack
{
pub ptype: OptU16,
pub rep: u16,
pub error: Angle,
pub range: Unit,
pub shape: u16,
pub ofs_x: Unit,
pub ofs_y: Unit,
pub ofs_z: Unit,
}
bitflags! {
#[derive(Serialize)]
pub struct EffectFlags: u16
@ -361,6 +527,95 @@ bitflags! {
}
}
bitflags! {
#[derive(Serialize)]
pub struct MonsterFlags: u32
{
const IgnoreLOS = 1;
const Flying = 1 << 1;
const Alien = 1 << 2;
const Major = 1 << 3;
const Minor = 1 << 4;
const NoOmit = 1 << 5;
const Floats = 1 << 6;
const NoAttack = 1 << 7;
const Snipe = 1 << 8;
const Invisible = 1 << 9;
const SubtlyInvisible = 1 << 10;
const Kamikaze = 1 << 11;
const Berserker = 1 << 12;
const Enlarged = 1 << 13;
const DelayedDeath = 1 << 14;
const FireSymmetrical = 1 << 15;
const NuclearDeath = 1 << 16;
const NoFireBackwards = 1 << 17;
const CanDieInFlames = 1 << 18;
const WaitForGoodShot = 1 << 19;
const Tiny = 1 << 20;
const FastAttack = 1 << 21;
const LikesWater = 1 << 22;
const LikesSewage = 1 << 23;
const LikesLava = 1 << 24;
const LikesGoo = 1 << 25;
const TeleUnderMedia = 1 << 26;
const UseRandomWeapon = 1 << 27;
}
}
bitflags! {
#[derive(Serialize)]
pub struct MonsterClass: u32
{
const Player = 1;
const Civilian = 1 << 1;
const Madd = 1 << 2;
const PossessedHummer = 1 << 3;
const Defender = 1 << 4;
const Fighter = 1 << 5;
const Trooper = 1 << 6;
const Hunter = 1 << 7;
const Enforcer = 1 << 8;
const Juggernaut = 1 << 9;
const Hummer = 1 << 10;
const Compiler = 1 << 11;
const Cyborg = 1 << 12;
const Assimilated = 1 << 13;
const Tick = 1 << 14;
const Yeti = 1 << 15;
}
}
bitflags! {
#[derive(Serialize)]
pub struct DamageTypeFlags: u32
{
const Explosion = 1;
const ElectricalStaff = 1 << 1;
const Projectile = 1 << 2;
const Absorbed = 1 << 3;
const Flame = 1 << 4;
const HoundClaws = 1 << 5;
const AlienProjectile = 1 << 6;
const HulkSlap = 1 << 7;
const CompilerBolt = 1 << 8;
const FusionBolt = 1 << 9;
const HunterBolt = 1 << 10;
const Fist = 1 << 11;
const Teleporter = 1 << 12;
const Defender = 1 << 13;
const YetiClaws = 1 << 14;
const YetiProjectile = 1 << 15;
const Crushing = 1 << 16;
const Lava = 1 << 17;
const Suffocation = 1 << 18;
const Goo = 1 << 19;
const EnergyDrain = 1 << 20;
const OxygenDrain = 1 << 21;
const HummerBolt = 1 << 22;
const ShotgunProjectile = 1 << 23;
}
}
c_enum! {
#[derive(Debug, Serialize)]
pub enum CasingType: u16