/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */

340
%{
#include "StdH.h"
#include "ModelsMP/Enemies/Mental/Mental.h"
%}

uses "EntitiesMP/EnemyBase";
uses "EntitiesMP/BasicEffects";

enum BigHeadType {
  0 BHT_NORMAL  "Normal",
  1 BHT_ZOMBIE  "Zombie",
  2 BHT_SAINT   "Saint",
};

%{
// info structure
static EntityInfo eiMental = {
  EIBT_FLESH, 200.0f,
  0.0f, 1.5f, 0.0f,     // source (eyes)
  0.0f, 1.0f, 0.0f,     // target (body)
};

#define GREET_SENSE_RANGE 10.0f
#define GREET_SENSE_DELAY 30.0f

%}

class CBigHead: CEnemyBase {
name      "BigHead";
thumbnail "Thumbnails\\Mental.tbn";

properties:
  // class internal
  1 CTFileName m_fnmHeadTex "Head texture" 'H' = CTString(""),
  2 CTFileName m_fnmNameSnd "Name sound" 'S' = CTString(""),
  3 FLOAT m_tmLastGreetTime = -100.0f,
  4 enum BigHeadType m_bhtType  "Type" 'Y'= BHT_NORMAL,
  5 BOOL m_bIgnorePlayer "Ignore player" 'I' = FALSE,
  6 BOOL m_bPlayingWalkSound = FALSE,
  7 BOOL m_bSleeping "Sleeping" 'S' = FALSE,  // set to make it sleep initally
  8 FLOAT m_tmLastWalkingSoundTime = -100.0f,
  9 FLOAT m_tmWalkingSound "Walk sound frequency" = 5.0f,
  
  {
    CAutoPrecacheSound m_aps;
    CAutoPrecacheTexture m_apt;
  }

components:
  1 class   CLASS_BASE            "Classes\\EnemyBase.ecl",
  2 class   CLASS_BLOOD_SPRAY     "Classes\\BloodSpray.ecl",
  3 class   CLASS_BASIC_EFFECT    "Classes\\BasicEffect.ecl",

// ************** DATA **************
 10 model   MODEL_MENTAL          "ModelsMP\\Enemies\\Mental\\Mental.mdl",
 11 texture TEXTURE_MENTAL        "ModelsMP\\Enemies\\Mental\\Mental.tex",
 12 model   MODEL_HEAD            "ModelsMP\\Enemies\\Mental\\Head.mdl",
 13 model   MODEL_HORNS           "ModelsMP\\Enemies\\Mental\\Horns.mdl",
 14 texture TEXTURE_HORNS         "ModelsMP\\Enemies\\Mental\\Horns.tex",
 15 model   MODEL_AURA            "ModelsMP\\Enemies\\Mental\\Aura.mdl",
 16 texture TEXTURE_AURA          "ModelsMP\\Enemies\\Mental\\Aura.tex",
 
 50 sound   SOUND_IDLE            "Models\\Enemies\\Mental\\Sounds\\Idle.wav",
 51 sound   SOUND_SIGHT           "Models\\Enemies\\Mental\\Sounds\\Sight.wav",
 52 sound   SOUND_WOUND           "Models\\Enemies\\Mental\\Sounds\\Wound.wav",
 53 sound   SOUND_DEATH           "Models\\Enemies\\Mental\\Sounds\\Death.wav",
 54 sound   SOUND_WALKZOMBIE      "ModelsMP\\Enemies\\Mental\\Sounds\\ComeToDaddy.wav",
 55 sound   SOUND_WALKSAINT       "ModelsMP\\Enemies\\Mental\\Sounds\\PeaceWithYou.wav",

functions:
  BOOL HandleEvent(const CEntityEvent &ee)
  {
    if (m_bIgnorePlayer) {
      if (ee.ee_slEvent==EVENTCODE_ETouch) {
        ETouch &et = (ETouch &)ee;
        if (IsOfClass(et.penOther, "Player")) {
          return TRUE;
        }
      }
    }
    return CEnemyBase::HandleEvent(ee);
  }

  /* Entity info */
  void *GetEntityInfo(void)
  {
    return &eiMental;
  };

  void Precache(void)
  {
    CEnemyBase::Precache();
    PrecacheSound(SOUND_SIGHT);
    PrecacheSound(SOUND_IDLE);
    PrecacheSound(SOUND_WOUND);
    PrecacheSound(SOUND_DEATH);
    PrecacheSound(SOUND_WALKZOMBIE);
    PrecacheSound(SOUND_WALKSAINT);
    m_aps.Precache(m_fnmNameSnd);
    m_apt.Precache(m_fnmHeadTex);
  };

  INDEX GetWalkAnim(void)
  {
    if (m_bhtType==BHT_ZOMBIE) {
      return MENTAL_ANIM_WALKZOMBIE;
    } else if (m_bhtType==BHT_SAINT) {
      return MENTAL_ANIM_WALKANGEL;
    } else {
      return MENTAL_ANIM_RUN;
    }
  }

  // damage anim
  INDEX AnimForDamage(FLOAT fDamage) {
    INDEX iAnim;
    iAnim = MENTAL_ANIM_PANIC;
    StartModelAnim(iAnim, 0);
    return iAnim;
  };

  // death
  INDEX AnimForDeath(void) {
    INDEX iAnim;
    iAnim = MENTAL_ANIM_DEATH;
    StartModelAnim(iAnim, 0);
    return iAnim;
  };

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

  // virtual anim functions
  void StandingAnim(void) {
    StartModelAnim(MENTAL_ANIM_GROUNDREST, AOF_LOOPING|AOF_NORESTART);
  };
  void WalkingAnim(void) {
    PlayWalkSound();
    StartModelAnim(GetWalkAnim(), AOF_LOOPING|AOF_NORESTART);

    if (!m_bIgnorePlayer && _pTimer->CurrentTick()>m_tmLastGreetTime+GREET_SENSE_DELAY) {
      m_fSenseRange = GREET_SENSE_RANGE;
      m_bDeaf = FALSE;
    }
  };
  void RunningAnim(void)
  {
    PlayWalkSound();
    StartModelAnim(GetWalkAnim(), AOF_LOOPING|AOF_NORESTART);
  };
  void RotatingAnim(void) {
    RunningAnim();
  };

  void PlayWalkSound(void)
  {
    INDEX iSound = SOUND_WALKZOMBIE;
    if (m_bhtType==BHT_ZOMBIE) {
      iSound = SOUND_WALKZOMBIE;
    } else if (m_bhtType==BHT_SAINT) {
      iSound = SOUND_WALKSAINT;
    } else {
      return;
    }
    if (!m_bPlayingWalkSound || _pTimer->CurrentTick()-m_tmLastWalkingSoundTime>m_tmWalkingSound) {
      m_bPlayingWalkSound = TRUE;
      m_tmLastWalkingSoundTime = _pTimer->CurrentTick();
      PlaySound(m_soSound, iSound, SOF_3D);
    }
  }

  // virtual sound functions
  void IdleSound(void) {
    if (m_bIgnorePlayer) {
      return;
    }
    PlaySound(m_soSound, SOUND_IDLE, SOF_3D);
    m_bPlayingWalkSound = FALSE;
  };

  void SightSound(void) {
    PlaySound(m_soSound, SOUND_SIGHT, SOF_3D);
    m_bPlayingWalkSound = FALSE;
  };
  void WoundSound(void) {
    PlaySound(m_soSound, SOUND_WOUND, SOF_3D);
    m_bPlayingWalkSound = FALSE;
  };
  void DeathSound(void) {
    PlaySound(m_soSound, SOUND_DEATH, SOF_3D);
    m_bPlayingWalkSound = FALSE;
  };

procedures:
  Fire(EVoid) : CEnemyBase::Fire {
    // hit
    if (CalcDist(m_penEnemy) <= m_fStopDistance*1.1f) {
      if (m_fnmNameSnd!="") {
        PlaySound(m_soSound, m_fnmNameSnd, SOF_3D);
        m_bPlayingWalkSound = FALSE;
      }
      m_bBlind = TRUE;
      m_bDeaf = TRUE;
      m_fSenseRange = 0.0f;
      m_tmLastGreetTime = _pTimer->CurrentTick();
      SetTargetNone();
      StartModelAnim(MENTAL_ANIM_GREET, 0);
      autowait(GetModelObject()->GetCurrentAnimLength());
      StandingAnim();
      return EReconsiderBehavior();
    }
    return EReturn();
  }

  Sleep(EVoid)
  {
    // start sleeping anim
    StartModelAnim(MENTAL_ANIM_SNORE, AOF_LOOPING);
    // repeat
    wait() {
      // if triggered
      on(ETrigger eTrigger) : {
//        // remember enemy
//        SetTargetSoft(eTrigger.penCaused);
        // wake up
        jump WakeUp();
      }
/*      // if damaged
      on(EDamage eDamage) : {
        // wake up
        jump WakeUp();
      }
      */
      otherwise() : {
        resume;
      }
    }
  }

  WakeUp(EVoid)
  {
    // wakeup anim
    SightSound();
    StartModelAnim(MENTAL_ANIM_GETUP, 0);
    autowait(GetModelObject()->GetCurrentAnimLength());

    // trigger your target
//    SendToTarget(m_penDeathTarget, m_eetDeathType);
    // proceed with normal functioning
    return EReturn();
  }

  // overridable called before main enemy loop actually begins
  PreMainLoop(EVoid) : CEnemyBase::PreMainLoop
  {
    // if sleeping
    if (m_bSleeping) {
      m_bSleeping = FALSE;
      // go to sleep until waken up
      wait() {
        on (EBegin) : {
          call Sleep();
        }
        on (EReturn) : {
          stop;
        };
        // if dead
        on(EDeath eDeath) : {
          // die
          jump CEnemyBase::Die(eDeath);
        }
      }
    }
    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);
    SetHealth(20.0f);
    m_fMaxHealth = 20.0f;
    en_tmMaxHoldBreath = 5.0f;
    en_fDensity = 2000.0f;
    m_fBlowUpSize = 2.0f;

    // set your appearance
    SetModel(MODEL_MENTAL);
    SetModelMainTexture(TEXTURE_MENTAL);
    AddAttachment(0, MODEL_HEAD, TEXTURE_MENTAL);
    if (m_fnmHeadTex!="") {
      // try to
      try {
        CAttachmentModelObject *pamoHead = GetModelObject()->GetAttachmentModel(0);
        if (pamoHead!=NULL) {
          pamoHead->amo_moModelObject.mo_toTexture.SetData_t(m_fnmHeadTex);
        }
      // if anything failed
      } catch (char *strError) {
        // report error
        CPrintF("%s\n", strError);
        AddAttachment(0, MODEL_HEAD, TEXTURE_MENTAL);
      }
    }
    if (m_bhtType==BHT_ZOMBIE) {
      AddAttachment(MENTAL_ATTACHMENT_HORNS, MODEL_HORNS, TEXTURE_HORNS);
    } else if (m_bhtType==BHT_SAINT) {
      AddAttachment(MENTAL_ATTACHMENT_AURA, MODEL_AURA, TEXTURE_AURA);
    }

    // setup moving speed
    m_fWalkSpeed = FRnd() + 1.5f;
    m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f);
    m_fAttackRunSpeed = FRnd()*2.0f + 6.0f;
    m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f);
    m_fCloseRunSpeed = FRnd()*2.0f + 6.0f;
    m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f);
    // setup attack distances
    m_fAttackDistance = 50.0f;
    m_fCloseDistance = 0.0f;
    m_fStopDistance = 5.0f; // greeting distance
    m_fAttackFireTime = 0.1f;
    m_fCloseFireTime = 0.1f;
    m_fIgnoreRange = 200.0f;
    // damage/explode properties
    m_fBlowUpAmount = 65.0f;
    m_fBodyParts = 4;
    m_fDamageWounded = 1.0f;
    m_iScore = 0;
    if (m_bIgnorePlayer) {
      m_bBlind = TRUE;
      m_bDeaf = TRUE;
      m_fSenseRange = 0;
    } else {
      m_bBlind = TRUE;
      m_fSenseRange = GREET_SENSE_RANGE;
    }

    // set stretch factors for height and width
    const FLOAT fSize = 0.6f;
    GetModelObject()->StretchModel(FLOAT3D(fSize, fSize, fSize));
    ModelChangeNotify();
    StandingAnim();

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