321
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/DragonMan/DragonMan.h"
%}

uses "Entities/EnemyFly";
uses "Entities/Projectile";

enum DragonmanType {
  0 DT_SOLDIER    "Soldier",
  1 DT_SERGEANT   "Sergeant",
  2 DT_MONSTER    "Monster",
};

%{
// info structure
static EntityInfo eiDragonmanStand1 = {
  EIBT_FLESH, 200.0f,
  0.0f, 1.55f, 0.0f,
  0.0f, 1.0f, 0.0f,
};
static EntityInfo eiDragonmanStand2 = {
  EIBT_FLESH, 200.0f*2,
  0.0f, 1.55f*2, 0.0f,
  0.0f, 1.0f*2, 0.0f,
};
static EntityInfo eiDragonmanStand4 = {
  EIBT_FLESH, 200.0f*4,
  0.0f, 1.55f*4, 0.0f,
  0.0f, 1.0f*4, 0.0f,
};

static EntityInfo eiDragonmanFly1 = {
  EIBT_FLESH, 100.0f*1,
  0.0f, 0.0f, 0.0f,
  0.0f, 0.0f, 0.0f,
};
static EntityInfo eiDragonmanFly2 = {
  EIBT_FLESH, 100.0f*2,
  0.0f, 0.0f, 0.0f,
  0.0f, 0.0f, 0.0f,
};
static EntityInfo eiDragonmanFly4 = {
  EIBT_FLESH, 100.0f*4,
  0.0f, 0.0f, 0.0f,
  0.0f, 0.0f, 0.0f,
};

#define FLY_FIRE1           FLOAT3D( 0.0f, 0.25f, -1.5f)
#define GROUND_RIGHT_FIRE1  FLOAT3D( 0.3f, 2.2f, -0.85f)
#define GROUND_LEFT_FIRE1   FLOAT3D(-0.3f, 1.7f, -0.85f)
#define FLAME_AIR1          FLOAT3D( 0.0f, 0.1f, -1.75f)
#define FLAME_GROUND1       FLOAT3D( 0.0f, 2.7f, -0.85f)
%}


class CDragonman : CEnemyFly {
name      "Dragonman";
thumbnail "Thumbnails\\Dragonman.tbn";

properties:
  1 enum DragonmanType m_EdtType "Character" 'C' = DT_SOLDIER,       // type
  2 FLOAT3D m_vFlameSource = FLOAT3D(0,0,0),
  3 CEntityPointer m_penFlame,
  4 BOOL m_bBurnEnemy = FALSE,
  5 FLOAT m_fFireTime = 0.0f,

components:
  0 class   CLASS_BASE          "Classes\\EnemyFly.ecl",
  1 class   CLASS_PROJECTILE    "Classes\\Projectile.ecl",

  5 model   MODEL_DRAGONMAN     "Models\\Enemies\\Dragonman\\Dragonman.mdl",
  6 texture TEXTURE_DRAGONMAN1  "Models\\Enemies\\Dragonman\\Dragonman01.tex",
  7 texture TEXTURE_DRAGONMAN2  "Models\\Enemies\\Dragonman\\Dragonman02.tex",
  8 texture TEXTURE_DRAGONMAN3  "Models\\Enemies\\Dragonman\\Dragonman03.tex",

// ************** SOUNDS **************
 50 sound   SOUND_IDLE      "Models\\Enemies\\Dragonman\\Sounds\\Idle.wav",
 51 sound   SOUND_SIGHT     "Models\\Enemies\\Dragonman\\Sounds\\Sight.wav",
 52 sound   SOUND_WOUND     "Models\\Enemies\\Dragonman\\Sounds\\Wound.wav",
 53 sound   SOUND_FIRE      "Models\\Enemies\\Dragonman\\Sounds\\Fire.wav",
 54 sound   SOUND_KICK      "Models\\Enemies\\Dragonman\\Sounds\\Kick.wav",
 55 sound   SOUND_DEATH     "Models\\Enemies\\Dragonman\\Sounds\\Death.wav",

functions:
  /* Entity info */
  void *GetEntityInfo(void) {
    if (m_bInAir) {
      switch(m_EdtType) {
      case DT_SOLDIER:
        return &eiDragonmanFly1;
        break;
      case DT_SERGEANT:
        return &eiDragonmanFly2;
        break;
      case DT_MONSTER:
        return &eiDragonmanFly4;
        break;
      default: {
        return &eiDragonmanFly1;
               } break;
      }
    } else {
      switch(m_EdtType) {
      case DT_SOLDIER:
        return &eiDragonmanStand1;
        break;
      case DT_SERGEANT:
        return &eiDragonmanStand2;
        break;
      case DT_MONSTER:
        return &eiDragonmanStand4;
        break;
      default: {
        return &eiDragonmanStand1;
               } break;
      }
    }
  };

  /* Fill in entity statistics - for AI purposes only */
  BOOL FillEntityStatistics(EntityStats *pes)
  {
    CEnemyBase::FillEntityStatistics(pes);
    switch(m_EdtType) {
    case DT_SOLDIER  : { pes->es_strName+=" Soldier"; } break;
    case DT_SERGEANT : { pes->es_strName+=" Sergeant"; } break;
    case DT_MONSTER  : { pes->es_strName+=" Monster"; } break;
    }
    return TRUE;
  }

  /* Receive damage */
  void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
    FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) 
  {
    // woman can't harm woman
    if (!IsOfClass(penInflictor, "Dragonman")) {
      CEnemyFly::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
    }
  };

  FLOAT3D GetStretchedVector(const FLOAT3D&v)
  {
    switch(m_EdtType) {
    case DT_SOLDIER:
      return v;
      break;
    case DT_SERGEANT:
      return v*2.0f;
      break;
    case DT_MONSTER:
      return v*4.0f;
      break;
    default:
      ASSERT(FALSE);
      return v;
    }
  }

  // damage anim
  INDEX AnimForDamage(FLOAT fDamage) {
    INDEX iAnim;
    if (m_bInAir) {
      switch (IRnd()%2) {
        case 0: iAnim = DRAGONMAN_ANIM_AIRWOUNDSLIGHT; break;
        case 1: iAnim = DRAGONMAN_ANIM_AIRWOUND02CRITICAL; break;
        default: ASSERTALWAYS("Dragonman unknown fly damage");
      }
    } else {
      switch (IRnd()%3) {
        case 0: iAnim = DRAGONMAN_ANIM_GROUNDWOUNDCRITICALBACK; break;
        case 1: iAnim = DRAGONMAN_ANIM_GROUNDWOUNDCRITICALFRONT; break;
        case 2: iAnim = DRAGONMAN_ANIM_GROUNDWOUNDCRITICALBACK2; break;
        default: ASSERTALWAYS("Dragonman unknown ground damage");
      }
    }
    StartModelAnim(iAnim, 0);
    return iAnim;
  };

  // death
  INDEX AnimForDeath(void) {
    INDEX iAnim;
    if (m_bInAir) {
      iAnim = DRAGONMAN_ANIM_AIRDEATH;
    } else {
      switch (IRnd()%2) {
        case 0: iAnim = DRAGONMAN_ANIM_GROUNDDEATHBACK; break;
        case 1: iAnim = DRAGONMAN_ANIM_GROUNDDEATHFRONT; break;
        default: ASSERTALWAYS("Dragonman unknown ground death");
      }
    }
    StartModelAnim(iAnim, 0);
    return iAnim;
  };

  void DeathNotify(void) {
    ChangeCollisionBoxIndexWhenPossible(DRAGONMAN_COLLISION_BOX_DEATH);
    en_fDensity = 500.0f;
  };

  // virtual anim functions
  void StandingAnim(void) {
    if (m_bInAir) {
      StartModelAnim(DRAGONMAN_ANIM_AIRSTANDLOOP, AOF_LOOPING|AOF_NORESTART);
    } else {
      StartModelAnim(DRAGONMAN_ANIM_GROUNDSTANDLOOP, AOF_LOOPING|AOF_NORESTART);
    }
  };
  void WalkingAnim(void) {
    if (m_bInAir) {
      StartModelAnim(DRAGONMAN_ANIM_AIRFLYLOOP, AOF_LOOPING|AOF_NORESTART);
    } else {
      StartModelAnim(DRAGONMAN_ANIM_GROUNDWALK, AOF_LOOPING|AOF_NORESTART);
    }
  };
  void RunningAnim(void) {
    if (m_bInAir) {
      StartModelAnim(DRAGONMAN_ANIM_AIRFLYLOOP, AOF_LOOPING|AOF_NORESTART);
    } else {
      StartModelAnim(DRAGONMAN_ANIM_GROUNDRUN, AOF_LOOPING|AOF_NORESTART);
    }
  };
  void RotatingAnim(void) {
    if (m_bInAir) {
      StartModelAnim(DRAGONMAN_ANIM_AIRFLYLOOP, AOF_LOOPING|AOF_NORESTART);
    } else {
      StartModelAnim(DRAGONMAN_ANIM_GROUNDWALK, AOF_LOOPING|AOF_NORESTART);
    }
  };
  FLOAT AirToGroundAnim(void) {
    StartModelAnim(DRAGONMAN_ANIM_AIRTOGROUND, 0);
    return(GetModelObject()->GetAnimLength(DRAGONMAN_ANIM_AIRTOGROUND));
  };
  FLOAT GroundToAirAnim(void) {
    StartModelAnim(DRAGONMAN_ANIM_GROUNDTOAIR, 0);
    return(GetModelObject()->GetAnimLength(DRAGONMAN_ANIM_GROUNDTOAIR));
  };
  void ChangeCollisionToAir() {
    ChangeCollisionBoxIndexWhenPossible(DRAGONMAN_COLLISION_BOX_AIR);
  };
  void ChangeCollisionToGround() {
    ChangeCollisionBoxIndexWhenPossible(DRAGONMAN_COLLISION_BOX_GROUND);
  };

  // virtual sound functions
  void IdleSound(void) {
    PlaySound(m_soSound, SOUND_IDLE, SOF_3D);
  };
  void SightSound(void) {
    PlaySound(m_soSound, SOUND_SIGHT, SOF_3D);
  };
  void WoundSound(void) {
    PlaySound(m_soSound, SOUND_WOUND, SOF_3D);
  };
  void DeathSound(void) {
    PlaySound(m_soSound, SOUND_DEATH, SOF_3D);
  };

  // flame source
  void GetFlamerSourcePlacement(CPlacement3D &plFlame) {
    plFlame.pl_PositionVector = m_vFlameSource;
  };

  // fire flame
  void FireFlame(void) {
    FLOAT3D vFlamePos;
    if (m_bInAir) {
      vFlamePos = GetStretchedVector(FLAME_AIR1);
    } else {
      vFlamePos = GetStretchedVector(FLAME_GROUND1);
    }

    // create flame
    CEntityPointer penFlame = ShootProjectile(PRT_FLAME, vFlamePos, ANGLE3D(0, 0, 0));
    // link last flame with this one (if not NULL or deleted)
    if (m_penFlame!=NULL && !(m_penFlame->GetFlags()&ENF_DELETED)) {
      ((CProjectile&)*m_penFlame).m_penParticles = penFlame;
    }
    // link to player weapons
    ((CProjectile&)*penFlame).m_penParticles = this;
    // store last flame
    m_penFlame = penFlame;
    // flame source position
    m_vFlameSource = GetPlacement().pl_PositionVector + vFlamePos*GetRotationMatrix();
  };


procedures:
/************************************************************
 *                PROCEDURES WHEN HARMED                    *
 ************************************************************/
  BeWounded(EDamage eDamage) : CEnemyFly::BeWounded { 
    m_penFlame = NULL;
    jump CEnemyFly::BeWounded(eDamage);
  };



/************************************************************
 *                A T T A C K   E N E M Y                   *
 ************************************************************/
  FlyFire(EVoid) : CEnemyFly::FlyFire {
    // fire projectile
    StartModelAnim(DRAGONMAN_ANIM_AIRATTACK02, 0);
    autowait(0.4f);
    if (m_EdtType != DT_MONSTER) {
      ShootProjectile(PRT_DRAGONMAN_FIRE, GetStretchedVector(FLY_FIRE1), ANGLE3D(0, 0, 0));
    } else {
      ShootProjectile(PRT_DRAGONMAN_STRONG_FIRE, GetStretchedVector(FLY_FIRE1), ANGLE3D(0, 0, 0));
    }
    PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
    autowait(0.15f);
    if (m_EdtType != DT_MONSTER) {
      ShootProjectile(PRT_DRAGONMAN_FIRE, GetStretchedVector(FLY_FIRE1), ANGLE3D(0, 0, 0));
    } else if (m_EdtType == DT_MONSTER) {
      ShootProjectile(PRT_DRAGONMAN_STRONG_FIRE, GetStretchedVector(FLY_FIRE1), ANGLE3D(0, 0, 0));
    }
    PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
    autowait(0.85f);
/*    StandingAnim();
    autowait(FRnd() + _pTimer->TickQuantum);
    */

    return EReturn();
  };

  FlyHit(EVoid) : CEnemyFly::FlyHit {
    // fly
    if (CalcDist(m_penEnemy) <= 7.5f) {
      if (m_EdtType == DT_SOLDIER) {
        jump FlyOnEnemy();
      } else {
        jump FlyBurn();
      }
    }

    // run to enemy
    m_fShootTime = _pTimer->CurrentTick() + 0.25f;
    return EReturn();
  };

  FlyOnEnemy(EVoid) {
    StartModelAnim(DRAGONMAN_ANIM_AIRATTACKCLOSELOOP, 0);

    // jump
    FLOAT3D vDir = PlayerDestinationPos();
    vDir = (vDir - GetPlacement().pl_PositionVector).Normalize();
    vDir *= !GetRotationMatrix();
    vDir *= m_fFlyCloseRunSpeed*1.9f;
    SetDesiredTranslation(vDir);
    PlaySound(m_soSound, SOUND_KICK, SOF_3D);

    // animation - IGNORE DAMAGE WOUND -
    SpawnReminder(this, 0.9f, 0);
    m_iChargeHitAnimation = DRAGONMAN_ANIM_AIRATTACKCLOSELOOP;
    if (m_EdtType == DT_SOLDIER) {
      m_fChargeHitDamage = 25.0f;
      m_fChargeHitSpeed = 15.0f;
    } else if (m_EdtType == DT_SERGEANT) {
      m_fChargeHitDamage = 30.0f;
      m_fChargeHitSpeed = 20.0f;
    } else if (TRUE) {
      m_fChargeHitDamage = 30.0f;
      m_fChargeHitSpeed = 20.0f;
    }
    m_fChargeHitAngle = 0.0f;
    autocall CEnemyBase::ChargeHitEnemy() EReturn;

    StandingAnim();
    autowait(0.3f);
    return EReturn();
  };

  FlyBurn(EVoid) {
    StartModelAnim(DRAGONMAN_ANIM_AIRATTACK02, 0);

    // burn
    m_fFireTime = _pTimer->CurrentTick();
    FireFlame();
    m_bBurnEnemy = TRUE;
    PlaySound(m_soSound, SOUND_FIRE, SOF_3D|SOF_LOOP);
    while (m_bBurnEnemy) {
      m_fMoveFrequency = 0.1f;
      wait(m_fMoveFrequency) {
        // flame
        on (EBegin) : {
          m_vDesiredPosition = m_penEnemy->GetPlacement().pl_PositionVector;
          // rotate to enemy
          m_aRotateSpeed = 10000.0f;
          m_fMoveSpeed = 0.0f;
          // flame
          FireFlame();
          // stop
          if (_pTimer->CurrentTick()-m_fFireTime >= 1.29f) {
            m_bBurnEnemy = FALSE;
            stop;
          }
          // adjust direction and speed
          ULONG ulFlags = SetDesiredMovement(); 
          MovementAnimation(ulFlags);
          resume;
        }
        on (ETimer) : { stop; }
      }
    }
    m_soSound.Stop();

    // link last flame with nothing (if not NULL or deleted)
    if (m_penFlame!=NULL && !(m_penFlame->GetFlags()&ENF_DELETED)) {
      ((CProjectile&)*m_penFlame).m_penParticles = NULL;
      m_penFlame = NULL;
    }

    StandingAnim();
    autowait(0.3f);
    return EReturn();
  };

  Fire(EVoid) : CEnemyBase::Fire {
    // fire projectile
    StartModelAnim(DRAGONMAN_ANIM_GROUNDATTACKCLOSELOOP, 0);
    autowait(0.3f);
    if (m_EdtType != DT_MONSTER) {
      ShootProjectile(PRT_DRAGONMAN_FIRE, GetStretchedVector(GROUND_RIGHT_FIRE1), ANGLE3D(0, 0, 0));
    } else {
      ShootProjectile(PRT_DRAGONMAN_STRONG_FIRE, GetStretchedVector(GROUND_RIGHT_FIRE1), ANGLE3D(0, 0, 0));
    }
    PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
    autowait(0.8f);
    if (m_EdtType != DT_MONSTER) {
      ShootProjectile(PRT_DRAGONMAN_FIRE, GetStretchedVector(GROUND_LEFT_FIRE1), ANGLE3D(0, 0, 0));
    } else if (m_EdtType == DT_MONSTER) {
      ShootProjectile(PRT_DRAGONMAN_STRONG_FIRE, GetStretchedVector(GROUND_LEFT_FIRE1), ANGLE3D(0, 0, 0));
    }
    PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
    autowait(0.55f);
    StandingAnim();
    autowait(FRnd() + _pTimer->TickQuantum);
    return EReturn();
  };

  Hit(EVoid) : CEnemyBase::Hit {
    // burn enemy
    if (m_EdtType == DT_SERGEANT && CalcDist(m_penEnemy) <= 6.0f  ||
        m_EdtType == DT_MONSTER  && CalcDist(m_penEnemy) <= 20.0f) {
      jump BurnEnemy();
    }

    // run to enemy
    m_fShootTime = _pTimer->CurrentTick() + 0.25f;
    return EReturn();
  };

  BurnEnemy(EVoid) {
    StartModelAnim(DRAGONMAN_ANIM_GROUNDATTACKDISTANT, 0);

    // burn
    m_fFireTime = _pTimer->CurrentTick();
    FireFlame();
    m_bBurnEnemy = TRUE;
    PlaySound(m_soSound, SOUND_FIRE, SOF_3D|SOF_LOOP);
    while (m_bBurnEnemy) {
      m_fMoveFrequency = 0.1f;
      wait(m_fMoveFrequency) {
        // flame
        on (EBegin) : {
          m_vDesiredPosition = m_penEnemy->GetPlacement().pl_PositionVector;
          // rotate to enemy
          m_fMoveSpeed = 0.0f;
          m_aRotateSpeed = 10000.0f;
          // adjust direction and speed
          SetDesiredMovement(); 
          // flame
          FireFlame();
          // stop
          if (_pTimer->CurrentTick()-m_fFireTime >= 1.29f) {
            m_bBurnEnemy = FALSE;
            stop;
          }
          resume;
        }
        on (ETimer) : { stop; }
      }
    }
    m_soSound.Stop();

    // link last flame with nothing (if not NULL or deleted)
    if (m_penFlame!=NULL && !(m_penFlame->GetFlags()&ENF_DELETED)) {
      ((CProjectile&)*m_penFlame).m_penParticles = NULL;
      m_penFlame = NULL;
    }

    StandingAnim();
    autowait(0.3f);
    return EReturn();
  };



/************************************************************
 *                       M  A  I  N                         *
 ************************************************************/
  Main(EVoid) {
    // declare yourself as a model
    InitAsModel();
    SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS);
    SetCollisionFlags(ECF_MODEL);
    SetFlags(GetFlags()|ENF_ALIVE);

    if (m_EdtType == DT_SOLDIER) {
      GetModelObject()->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f));
      ModelChangeNotify();
      SetHealth(150.0f);
      m_fMaxHealth = 150.0f;
      m_fDamageWounded = 100.0f;
    } else if (m_EdtType == DT_SERGEANT) {
      GetModelObject()->StretchModel(FLOAT3D(2.0f, 2.0f, 2.0f));
      ModelChangeNotify();
      SetHealth(450.0f);
      m_fMaxHealth = 450.0f;
      m_fDamageWounded = 300.0f;
    } else if (TRUE) {
      GetModelObject()->StretchModel(FLOAT3D(4.0f, 4.0f, 4.0f));
      ModelChangeNotify();
      SetHealth(1350.0f);
      m_fMaxHealth = 1350.0f;
      m_fDamageWounded = 1000.0f;
    }
    en_tmMaxHoldBreath = 10.0f;
    en_fDensity = 2000.0f;

    // set your appearance
    SetModel(MODEL_DRAGONMAN);
    if (m_EdtType == DT_SOLDIER) {
      SetModelMainTexture(TEXTURE_DRAGONMAN1);
    } else if (m_EdtType == DT_SERGEANT) {
      SetModelMainTexture(TEXTURE_DRAGONMAN2);
    } else if (TRUE) {
      SetModelMainTexture(TEXTURE_DRAGONMAN3);
    }
    // setup moving speed
    if (m_EdtType == DT_SOLDIER) {
      m_fWalkSpeed = FRnd()*1.5f + 2.5f;
      m_aWalkRotateSpeed = FRnd()*20.0f + 50.0f;
      m_fAttackRunSpeed = FRnd()*2.0f + 11.0f;
      m_aAttackRotateSpeed = FRnd()*75 + 350.0f;
      m_fCloseRunSpeed = FRnd()*2.0f + 6.0f;
      m_aCloseRotateSpeed = FRnd()*50 + 500.0f;
    } else if (m_EdtType == DT_SERGEANT) {
      m_fWalkSpeed = (FRnd()*1.5f + 2.5f)*1.5f;
      m_aWalkRotateSpeed = FRnd()*20.0f + 50.0f;
      m_fAttackRunSpeed = (FRnd()*2.0f + 11.0f)*2;
      m_aAttackRotateSpeed = FRnd()*75 + 350.0f;
      m_fCloseRunSpeed = (FRnd()*2.0f + 6.0f)*1.5f;
      m_aCloseRotateSpeed = FRnd()*50 + 500.0f;
    } else if (TRUE) {
      m_fWalkSpeed = (FRnd()*1.5f + 2.5f)*2;
      m_aWalkRotateSpeed = FRnd()*20.0f + 50.0f;
      m_fAttackRunSpeed = (FRnd()*2.0f + 11.0f)*4;
      m_aAttackRotateSpeed = FRnd()*75 + 350.0f;
      m_fCloseRunSpeed = (FRnd()*2.0f + 6.0f)*2;
      m_aCloseRotateSpeed = FRnd()*50 + 500.0f;
    }
    // setup attack distances
    m_fAttackDistance = 100.0f;
    if (m_EdtType == DT_SOLDIER) {
      m_fCloseDistance = 0.0f;
      m_fStopDistance = 10.0f;
      m_fFlyCloseDistance = 12.5f;
      m_fFlyStopDistance = 0.0f;
      m_iScore = 1000;
    } else if (m_EdtType == DT_SERGEANT) {
      m_fCloseDistance = 20.0f;
      m_fStopDistance = 0.0f;
      m_fFlyCloseDistance = 12.5f*2;
      m_fFlyStopDistance = 0.0f;
      m_iScore = 2000;
    } else {
      m_fCloseDistance = 40.0f;
      m_fStopDistance = 0.0f;
      m_fFlyCloseDistance = 12.5f*4;
      m_fFlyStopDistance = 0.0f;
      m_iScore = 10000;
    }
    m_fAttackFireTime = 3.0f;
    m_fCloseFireTime = 2.0f;
    m_fIgnoreRange = 200.0f;
    // fly moving properties
    m_fFlyWalkSpeed = FRnd()/2 + 2.0f;
    m_aFlyWalkRotateSpeed = FRnd()*10.0f + 50.0f;
    m_fFlyAttackRunSpeed = FRnd()*2.0f + 10.0f;
    m_aFlyAttackRotateSpeed = FRnd()*75 + 350.0f;
    m_fFlyCloseRunSpeed = FRnd()*2.0f + 9.0f;
    m_aFlyCloseRotateSpeed = FRnd()*50 + 600.0f;
    // attack properties - CAN BE SET
    m_fFlyAttackDistance = 100.0f;
    m_fFlyAttackFireTime = 3.0f;
    m_fFlyCloseFireTime = 2.0f;
    m_fFlyIgnoreRange = 200.0f;
    // damage/explode properties
    m_fBlowUpAmount = 100.0f;
    m_fBodyParts = 8;
    // flame source
    m_vFlameSource = FLOAT3D(0, 0, 0);
    m_fGroundToAirSpeed = m_fFlyAttackRunSpeed;
    m_fAirToGroundSpeed = m_fFlyAttackRunSpeed*2;
    m_fAirToGroundMin = 0.1f;
    m_fAirToGroundMax = 0.1f;

    // continue behavior in base class
    jump CEnemyFly::MainLoop();
  };
};