//! `Damage` type.

use crate::durandal::{err::*, fixed::Fixed};
use bitflags::bitflags;
use std::convert::TryFrom;

/// Reads a `Damage` object.
pub fn read(b: &[u8]) -> ResultS<Damage>
{
   read_data! {
      endian: BIG, buf: b, size: 12, start: 0, data {
         let dtype    = u16[0] enum DamageType;
         let flags    = u16[2] flag DamageFlags;
         let dmg_base = u16[4];
         let dmg_rand = u16[6];
         let scale    = Fixed[8];
      }
   }

   Ok(Damage{dtype, flags, dmg_base, dmg_rand, scale})
}

/// A damage definition.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Damage
{
   pub dtype:    DamageType,
   pub flags:    DamageFlags,
   pub dmg_base: u16,
   pub dmg_rand: u16,
   pub scale:    Fixed,
}

bitflags! {
   /// The composite type of damage taken by something.
   #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
   pub struct DamageTypeFlags: u32
   {
      const EXPLOSION          = 1;
      const ELECTRICAL_STAFF   = 1 << 1;
      const PROJECTILE         = 1 << 2;
      const ABSORBED           = 1 << 3;
      const FLAME              = 1 << 4;
      const HOUND_CLAWS        = 1 << 5;
      const ALIEN_PROJECTILE   = 1 << 6;
      const HULK_SLAP          = 1 << 7;
      const COMPILER_BOLT      = 1 << 8;
      const FUSION_BOLT        = 1 << 9;
      const HUNTER_BOLT        = 1 << 10;
      const FIST               = 1 << 11;
      const TELEPORTER         = 1 << 12;
      const DEFENDER           = 1 << 13;
      const YETI_CLAWS         = 1 << 14;
      const YETI_PROJECTILE    = 1 << 15;
      const CRUSHING           = 1 << 16;
      const LAVA               = 1 << 17;
      const SUFFOCATION        = 1 << 18;
      const GOO                = 1 << 19;
      const ENERGY_DRAIN       = 1 << 20;
      const OXYGEN_DRAIN       = 1 << 21;
      const HUMMER_BOLT        = 1 << 22;
      const SHOTGUN_PROJECTILE = 1 << 23;
   }
}

bitflags! {
   /// Flags for `Damage`.
   #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
   pub struct DamageFlags: u16
   {
      const ALIEN = 1;
   }
}

c_enum! {
   /// A named type of damage taken by something.
   #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
   #[derive(Debug)]
   pub enum DamageType: u16
   {
      Explosion         = 0,
      ElectricalStaff   = 1,
      Projectile        = 2,
      Absorbed          = 3,
      Flame             = 4,
      HoundClaws        = 5,
      AlienProjectile   = 6,
      HulkSlap          = 7,
      CompilerBolt      = 8,
      FusionBolt        = 9,
      HunterBolt        = 10,
      Fist              = 11,
      Teleporter        = 12,
      Defender          = 13,
      YetiClaws         = 14,
      YetiProjectile    = 15,
      Crushing          = 16,
      Lava              = 17,
      Suffocation       = 18,
      Goo               = 19,
      EnergyDrain       = 20,
      OxygenDrain       = 21,
      HummerBolt        = 22,
      ShotgunProjectile = 23,
      None              = 0xFFFF,
   }
}

// EOF
