2016-03-11 14:57:17 +01:00
|
|
|
/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */
|
|
|
|
|
|
|
|
323
|
|
|
|
%{
|
2016-04-01 20:04:24 +02:00
|
|
|
#include "EntitiesMP/StdH/StdH.h"
|
2016-03-11 14:57:17 +01:00
|
|
|
#include "Models/Enemies/Eyeman/Eyeman.h"
|
|
|
|
%}
|
|
|
|
|
|
|
|
uses "EntitiesMP/EnemyFly";
|
|
|
|
|
|
|
|
enum EyemanChar {
|
|
|
|
0 EYC_SOLDIER "Soldier", // soldier
|
|
|
|
1 EYC_SERGEANT "Sergeant", // sergeant
|
|
|
|
};
|
|
|
|
|
|
|
|
enum EyemanEnv {
|
|
|
|
0 EYE_NORMAL "Normal",
|
|
|
|
1 EYE_LAVA "Lava",
|
|
|
|
};
|
|
|
|
|
|
|
|
%{
|
|
|
|
// info structure
|
|
|
|
static EntityInfo eiEyemanBig = {
|
|
|
|
EIBT_FLESH, 140.0f,
|
|
|
|
0.0f, 1.4f, 0.0f,
|
|
|
|
0.0f, 1.0f, 0.0f,
|
|
|
|
};
|
|
|
|
static EntityInfo eiEyemanSmall = {
|
|
|
|
EIBT_FLESH, 120.0f,
|
|
|
|
0.0f, 1.4f, 0.0f,
|
|
|
|
0.0f, 1.0f, 0.0f,
|
|
|
|
};
|
|
|
|
|
|
|
|
#define BITE_AIR 3.0f
|
|
|
|
#define HIT_GROUND 2.0f
|
|
|
|
#define FIRE_GROUND FLOAT3D(0.75f, 1.5f, -1.25f)
|
|
|
|
%}
|
|
|
|
|
|
|
|
|
|
|
|
class CEyeman : CEnemyFly {
|
|
|
|
name "Eyeman";
|
|
|
|
thumbnail "Thumbnails\\Eyeman.tbn";
|
|
|
|
|
|
|
|
properties:
|
|
|
|
1 enum EyemanChar m_EecChar "Character" 'C' = EYC_SOLDIER, // character
|
|
|
|
2 BOOL m_bInvisible "Invisible" 'I'=FALSE,
|
|
|
|
3 enum EyemanEnv m_eeEnv "Environment" 'E' = EYE_NORMAL,
|
|
|
|
4 BOOL m_bMumbleSoundPlaying = FALSE,
|
|
|
|
5 CSoundObject m_soMumble,
|
|
|
|
|
|
|
|
components:
|
|
|
|
0 class CLASS_BASE "Classes\\EnemyFly.ecl",
|
|
|
|
1 model MODEL_EYEMAN "Models\\Enemies\\Eyeman\\Eyeman.mdl",
|
|
|
|
2 texture TEXTURE_EYEMAN_SOLDIER "Models\\Enemies\\Eyeman\\Eyeman4.tex",
|
|
|
|
3 texture TEXTURE_EYEMAN_SERGEANT "Models\\Enemies\\Eyeman\\Eyeman5.tex",
|
|
|
|
5 texture TEXTURE_EYEMAN_LAVA "Models\\Enemies\\Eyeman\\Eyeman6.tex",
|
|
|
|
4 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
|
|
|
|
|
|
|
|
// ************** SOUNDS **************
|
|
|
|
50 sound SOUND_IDLE "Models\\Enemies\\Eyeman\\Sounds\\Idle.wav",
|
|
|
|
51 sound SOUND_SIGHT "Models\\Enemies\\Eyeman\\Sounds\\Sight.wav",
|
|
|
|
52 sound SOUND_WOUND "Models\\Enemies\\Eyeman\\Sounds\\Wound.wav",
|
|
|
|
53 sound SOUND_BITE "Models\\Enemies\\Eyeman\\Sounds\\Bite.wav",
|
|
|
|
54 sound SOUND_PUNCH "Models\\Enemies\\Eyeman\\Sounds\\Punch.wav",
|
|
|
|
55 sound SOUND_DEATH "Models\\Enemies\\Eyeman\\Sounds\\Death.wav",
|
|
|
|
56 sound SOUND_MUMBLE "Models\\Enemies\\Eyeman\\Sounds\\Mumble.wav",
|
|
|
|
|
|
|
|
/*
|
|
|
|
60 model MODEL_EYEMAN_BODY "Models\\Enemies\\Eyeman\\Debris\\Torso.mdl",
|
|
|
|
61 model MODEL_EYEMAN_HAND "Models\\Enemies\\Eyeman\\Debris\\Arm.mdl",
|
|
|
|
62 model MODEL_EYEMAN_LEGS "Models\\Enemies\\Eyeman\\Debris\\Leg.mdl",
|
|
|
|
*/
|
|
|
|
|
|
|
|
functions:
|
|
|
|
// describe how this enemy killed player
|
|
|
|
virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath)
|
|
|
|
{
|
|
|
|
CTString str;
|
|
|
|
if (m_bInAir) {
|
2016-03-29 05:21:44 +02:00
|
|
|
str.PrintF(TRANSV("A Gnaar bit %s to death"), (const char *) strPlayerName);
|
2016-03-11 14:57:17 +01:00
|
|
|
} else {
|
2016-03-29 05:21:44 +02:00
|
|
|
str.PrintF(TRANSV("%s was beaten up by a Gnaar"), (const char *) strPlayerName);
|
2016-03-11 14:57:17 +01:00
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
void Precache(void) {
|
|
|
|
CEnemyBase::Precache();
|
|
|
|
PrecacheSound(SOUND_IDLE );
|
|
|
|
PrecacheSound(SOUND_SIGHT);
|
|
|
|
PrecacheSound(SOUND_WOUND);
|
|
|
|
PrecacheSound(SOUND_BITE );
|
|
|
|
PrecacheSound(SOUND_PUNCH);
|
|
|
|
PrecacheSound(SOUND_DEATH);
|
|
|
|
PrecacheSound(SOUND_MUMBLE);
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Entity info */
|
|
|
|
void *GetEntityInfo(void) {
|
|
|
|
if (m_EecChar==EYC_SERGEANT) {
|
|
|
|
return &eiEyemanBig;
|
|
|
|
} else {
|
|
|
|
return &eiEyemanSmall;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Receive damage */
|
|
|
|
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
|
|
|
|
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
|
|
|
|
{
|
|
|
|
// eyeman can't harm eyeman
|
|
|
|
if (!IsOfClass(penInflictor, "Eyeman")) {
|
|
|
|
CEnemyFly::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
|
|
|
|
// if died of chainsaw
|
|
|
|
if (dmtType==DMT_CHAINSAW && GetHealth()<=0) {
|
|
|
|
// must always blowup
|
|
|
|
m_fBlowUpAmount = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Fill in entity statistics - for AI purposes only */
|
|
|
|
BOOL FillEntityStatistics(EntityStats *pes)
|
|
|
|
{
|
|
|
|
CEnemyBase::FillEntityStatistics(pes);
|
|
|
|
switch(m_EecChar) {
|
|
|
|
case EYC_SERGEANT: { pes->es_strName+=" Sergeant"; } break;
|
|
|
|
case EYC_SOLDIER : { pes->es_strName+=" Soldier"; } break;
|
|
|
|
}
|
|
|
|
if (m_bInvisible) {
|
|
|
|
pes->es_strName+=" Invisible";
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual const CTFileName &GetComputerMessageName(void) const {
|
|
|
|
static DECLARE_CTFILENAME(fnmSergeant, "Data\\Messages\\Enemies\\EyemanGreen.txt");
|
|
|
|
static DECLARE_CTFILENAME(fnmSoldier , "Data\\Messages\\Enemies\\EyemanPurple.txt");
|
|
|
|
switch(m_EecChar) {
|
|
|
|
default: ASSERT(FALSE);
|
|
|
|
case EYC_SERGEANT: return fnmSergeant;
|
|
|
|
case EYC_SOLDIER : return fnmSoldier;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
/* Adjust model shading parameters if needed. */
|
|
|
|
BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient)
|
|
|
|
{
|
|
|
|
// no shadows for invisibles
|
|
|
|
if (m_bInvisible) {
|
|
|
|
colAmbient = C_WHITE;
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
return CEnemyBase::AdjustShadingParameters(vLightDirection, colLight, colAmbient);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// damage anim
|
|
|
|
INDEX AnimForDamage(FLOAT fDamage) {
|
|
|
|
DeactivateMumblingSound();
|
|
|
|
INDEX iAnim;
|
|
|
|
if (m_bInAir) {
|
|
|
|
switch (IRnd()%2) {
|
|
|
|
case 0: iAnim = EYEMAN_ANIM_MORPHWOUND01; break;
|
|
|
|
case 1: iAnim = EYEMAN_ANIM_MORPHWOUND02; break;
|
|
|
|
default: ASSERTALWAYS("Eyeman unknown fly damage");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
FLOAT3D vFront;
|
|
|
|
GetHeadingDirection(0, vFront);
|
|
|
|
FLOAT fDamageDir = m_vDamage%vFront;
|
|
|
|
if (Abs(fDamageDir)<=10) {
|
|
|
|
switch (IRnd()%3) {
|
|
|
|
case 0: iAnim = EYEMAN_ANIM_WOUND03; break;
|
|
|
|
case 1: iAnim = EYEMAN_ANIM_WOUND06; break;
|
|
|
|
case 2: iAnim = EYEMAN_ANIM_WOUND07; break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (fDamageDir<0) {
|
|
|
|
iAnim = EYEMAN_ANIM_FALL01;
|
|
|
|
} else {
|
|
|
|
iAnim = EYEMAN_ANIM_FALL02;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
StartModelAnim(iAnim, 0);
|
|
|
|
return iAnim;
|
|
|
|
};
|
|
|
|
|
|
|
|
// death
|
|
|
|
INDEX AnimForDeath(void) {
|
|
|
|
DeactivateMumblingSound();
|
|
|
|
INDEX iAnim;
|
|
|
|
if (m_bInAir) {
|
|
|
|
iAnim = EYEMAN_ANIM_MORPHDEATH;
|
|
|
|
} else {
|
|
|
|
FLOAT3D vFront;
|
|
|
|
GetHeadingDirection(0, vFront);
|
|
|
|
FLOAT fDamageDir = m_vDamage%vFront;
|
|
|
|
if (fDamageDir<0) {
|
|
|
|
iAnim = EYEMAN_ANIM_DEATH02;
|
|
|
|
} else {
|
|
|
|
iAnim = EYEMAN_ANIM_DEATH01;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
StartModelAnim(iAnim, 0);
|
|
|
|
return iAnim;
|
|
|
|
};
|
|
|
|
|
|
|
|
FLOAT WaitForDust(FLOAT3D &vStretch) {
|
|
|
|
if(GetModelObject()->GetAnim()==EYEMAN_ANIM_DEATH01)
|
|
|
|
{
|
|
|
|
vStretch=FLOAT3D(1,1,1)*0.75f;
|
|
|
|
return 0.5f;
|
|
|
|
}
|
|
|
|
else if(GetModelObject()->GetAnim()==EYEMAN_ANIM_DEATH02)
|
|
|
|
{
|
|
|
|
vStretch=FLOAT3D(1,1,1)*0.75f;
|
|
|
|
return 0.5f;
|
|
|
|
}
|
|
|
|
else if(GetModelObject()->GetAnim()==EYEMAN_ANIM_MORPHDEATH)
|
|
|
|
{
|
|
|
|
vStretch=FLOAT3D(1,1,1)*1.0f;
|
|
|
|
return 0.5f;
|
|
|
|
}
|
|
|
|
return -1.0f;
|
|
|
|
};
|
|
|
|
|
|
|
|
void DeathNotify(void) {
|
|
|
|
ChangeCollisionBoxIndexWhenPossible(EYEMAN_COLLISION_BOX_DEATH);
|
|
|
|
en_fDensity = 500.0f;
|
|
|
|
};
|
|
|
|
|
|
|
|
// mumbling sounds
|
|
|
|
void ActivateMumblingSound(void)
|
|
|
|
{
|
|
|
|
if (!m_bMumbleSoundPlaying) {
|
|
|
|
PlaySound(m_soMumble, SOUND_MUMBLE, SOF_3D|SOF_LOOP);
|
|
|
|
m_bMumbleSoundPlaying = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void DeactivateMumblingSound(void)
|
|
|
|
{
|
|
|
|
m_soMumble.Stop();
|
|
|
|
m_bMumbleSoundPlaying = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// virtual anim functions
|
|
|
|
void StandingAnim(void) {
|
|
|
|
DeactivateMumblingSound();
|
|
|
|
if (m_bInAir) {
|
|
|
|
StartModelAnim(EYEMAN_ANIM_MORPHATTACKFLY, AOF_LOOPING|AOF_NORESTART);
|
|
|
|
} else {
|
|
|
|
StartModelAnim(EYEMAN_ANIM_STAND, AOF_LOOPING|AOF_NORESTART);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
void WalkingAnim(void) {
|
|
|
|
ActivateMumblingSound();
|
|
|
|
if (m_bInAir) {
|
|
|
|
StartModelAnim(EYEMAN_ANIM_MORPHATTACKFLY, AOF_LOOPING|AOF_NORESTART);
|
|
|
|
} else {
|
|
|
|
StartModelAnim(EYEMAN_ANIM_WALK, AOF_LOOPING|AOF_NORESTART);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
void RunningAnim(void) {
|
|
|
|
ActivateMumblingSound();
|
|
|
|
if (m_bInAir) {
|
|
|
|
StartModelAnim(EYEMAN_ANIM_MORPHATTACKFLY, AOF_LOOPING|AOF_NORESTART);
|
|
|
|
} else {
|
|
|
|
StartModelAnim(EYEMAN_ANIM_RUN, AOF_LOOPING|AOF_NORESTART);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
void RotatingAnim(void) {
|
|
|
|
if (m_bInAir) {
|
|
|
|
StartModelAnim(EYEMAN_ANIM_MORPHATTACKFLY, AOF_LOOPING|AOF_NORESTART);
|
|
|
|
} else {
|
|
|
|
StartModelAnim(EYEMAN_ANIM_RUN, AOF_LOOPING|AOF_NORESTART);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
FLOAT AirToGroundAnim(void) {
|
|
|
|
StartModelAnim(EYEMAN_ANIM_MORPHUP, 0);
|
|
|
|
return(GetModelObject()->GetAnimLength(EYEMAN_ANIM_MORPHUP));
|
|
|
|
};
|
|
|
|
FLOAT GroundToAirAnim(void) {
|
|
|
|
StartModelAnim(EYEMAN_ANIM_MORPHDOWN, 0);
|
|
|
|
return(GetModelObject()->GetAnimLength(EYEMAN_ANIM_MORPHDOWN));
|
|
|
|
};
|
|
|
|
void ChangeCollisionToAir() {
|
|
|
|
ChangeCollisionBoxIndexWhenPossible(EYEMAN_COLLISION_BOX_AIR);
|
|
|
|
};
|
|
|
|
void ChangeCollisionToGround() {
|
|
|
|
ChangeCollisionBoxIndexWhenPossible(EYEMAN_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);
|
|
|
|
};
|
|
|
|
|
|
|
|
/************************************************************
|
|
|
|
* BLOW UP FUNCTIONS *
|
|
|
|
************************************************************/
|
|
|
|
// spawn body parts
|
|
|
|
/*void BlowUp(void)
|
|
|
|
{
|
|
|
|
// get your size
|
|
|
|
FLOATaabbox3D box;
|
|
|
|
GetBoundingBox(box);
|
|
|
|
FLOAT fEntitySize = box.Size().MaxNorm();
|
|
|
|
|
|
|
|
FLOAT3D vNormalizedDamage = m_vDamage-m_vDamage*(m_fBlowUpAmount/m_vDamage.Length());
|
|
|
|
vNormalizedDamage /= Sqrt(vNormalizedDamage.Length());
|
|
|
|
|
|
|
|
vNormalizedDamage *= 0.75f;
|
|
|
|
|
|
|
|
FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute-en_vGravityDir*(en_vGravityDir%en_vCurrentTranslationAbsolute);
|
|
|
|
|
|
|
|
// spawn debris
|
|
|
|
Debris_Begin(EIBT_FLESH, DPT_BLOODTRAIL, BET_BLOODSTAIN, fEntitySize, vNormalizedDamage, vBodySpeed, 1.0f, 0.0f);
|
|
|
|
|
|
|
|
INDEX iTextureID = TEXTURE_EYEMAN_SOLDIER;
|
|
|
|
if (m_EecChar==EYC_SERGEANT)
|
|
|
|
{
|
|
|
|
iTextureID = TEXTURE_EYEMAN_SERGEANT;
|
|
|
|
}
|
|
|
|
|
|
|
|
Debris_Spawn(this, this, MODEL_EYEMAN_BODY, iTextureID, 0, 0, 0, 0, 0.0f,
|
|
|
|
FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
|
|
|
|
Debris_Spawn(this, this, MODEL_EYEMAN_HAND, iTextureID, 0, 0, 0, 0, 0.0f,
|
|
|
|
FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
|
|
|
|
Debris_Spawn(this, this, MODEL_EYEMAN_HAND, iTextureID, 0, 0, 0, 0, 0.0f,
|
|
|
|
FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
|
|
|
|
Debris_Spawn(this, this, MODEL_EYEMAN_LEGS, iTextureID, 0, 0, 0, 0, 0.0f,
|
|
|
|
FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
|
|
|
|
|
|
|
|
// hide yourself (must do this after spawning debris)
|
|
|
|
SwitchToEditorModel();
|
|
|
|
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
|
|
|
|
SetCollisionFlags(ECF_IMMATERIAL);
|
|
|
|
};*/
|
|
|
|
|
|
|
|
/************************************************************
|
|
|
|
* MOVING FUNCTIONS *
|
|
|
|
************************************************************/
|
|
|
|
// check whether may move while attacking
|
|
|
|
BOOL MayMoveToAttack(void)
|
|
|
|
{
|
|
|
|
if (m_bInAir) {
|
|
|
|
return WouldNotLeaveAttackRadius();
|
|
|
|
} else {
|
|
|
|
return CEnemyBase::MayMoveToAttack();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// must be more relaxed about hitting then usual enemies
|
|
|
|
BOOL CanHitEnemy(CEntity *penTarget, FLOAT fCosAngle) {
|
|
|
|
if (IsInPlaneFrustum(penTarget, fCosAngle)) {
|
|
|
|
return IsVisibleCheckAll(penTarget);
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
};
|
|
|
|
procedures:
|
|
|
|
/************************************************************
|
|
|
|
* A T T A C K E N E M Y *
|
|
|
|
************************************************************/
|
|
|
|
|
|
|
|
FlyHit(EVoid) : CEnemyFly::FlyHit {
|
|
|
|
if (CalcDist(m_penEnemy) > BITE_AIR) {
|
|
|
|
m_fShootTime = _pTimer->CurrentTick() + 0.25f;
|
|
|
|
return EReturn();
|
|
|
|
}
|
|
|
|
StartModelAnim(EYEMAN_ANIM_MORPHATTACK, 0);
|
|
|
|
StopMoving();
|
|
|
|
PlaySound(m_soSound, SOUND_BITE, SOF_3D);
|
|
|
|
// damage enemy
|
|
|
|
autowait(0.4f);
|
|
|
|
// damage enemy
|
|
|
|
if (CalcDist(m_penEnemy) < BITE_AIR) {
|
|
|
|
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
|
|
|
|
vDirection.SafeNormalize();
|
|
|
|
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 3.5f, FLOAT3D(0, 0, 0), vDirection);
|
|
|
|
// spawn blood cloud
|
|
|
|
ESpawnEffect eSpawnEffect;
|
|
|
|
eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE;
|
|
|
|
eSpawnEffect.betType = BET_BLOODEXPLODE;
|
|
|
|
eSpawnEffect.vStretch = FLOAT3D(1,1,1);
|
|
|
|
CPlacement3D plOne = GetPlacement();
|
|
|
|
GetEntityPointRatio(
|
|
|
|
FLOAT3D(Lerp(-0.2f, +0.2f, FRnd()), Lerp(-0.2f, +0.2f, FRnd()), -1.0f),
|
|
|
|
plOne.pl_PositionVector);
|
|
|
|
CEntityPointer penBloodCloud = CreateEntity( plOne, CLASS_BASIC_EFFECT);
|
|
|
|
penBloodCloud->Initialize( eSpawnEffect);
|
|
|
|
}
|
|
|
|
autowait(0.24f);
|
|
|
|
|
|
|
|
StandingAnim();
|
|
|
|
return EReturn();
|
|
|
|
};
|
|
|
|
|
|
|
|
GroundHit(EVoid) : CEnemyFly::GroundHit {
|
|
|
|
if (CalcDist(m_penEnemy) > HIT_GROUND) {
|
|
|
|
m_fShootTime = _pTimer->CurrentTick() + 0.25f;
|
|
|
|
return EReturn();
|
|
|
|
}
|
|
|
|
StartModelAnim(EYEMAN_ANIM_ATTACK02, 0);
|
|
|
|
StopMoving();
|
|
|
|
// damage enemy
|
|
|
|
autowait(0.2f);
|
|
|
|
// damage enemy
|
|
|
|
if (CalcDist(m_penEnemy) < HIT_GROUND) {
|
|
|
|
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
|
|
|
|
vDirection.SafeNormalize();
|
|
|
|
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 3.5f, FLOAT3D(0, 0, 0), vDirection);
|
|
|
|
PlaySound(m_soSound, SOUND_PUNCH, SOF_3D);
|
|
|
|
}
|
|
|
|
autowait(0.3f);
|
|
|
|
// damage enemy
|
|
|
|
if (CalcDist(m_penEnemy) < HIT_GROUND) {
|
|
|
|
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
|
|
|
|
vDirection.SafeNormalize();
|
|
|
|
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 3.5f, FLOAT3D(0, 0, 0), vDirection);
|
|
|
|
PlaySound(m_soSound, SOUND_PUNCH, SOF_3D);
|
|
|
|
}
|
|
|
|
autowait(0.4f);
|
|
|
|
|
|
|
|
StandingAnim();
|
|
|
|
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_EecChar==EYC_SERGEANT) {
|
|
|
|
SetHealth(90.0f);
|
|
|
|
m_fMaxHealth = 90.0f;
|
|
|
|
// damage/explode properties
|
|
|
|
m_fBlowUpAmount = 130.0f;
|
|
|
|
m_fBodyParts = 5;
|
|
|
|
m_fBlowUpSize = 2.5f;
|
|
|
|
m_fDamageWounded = 40.0f;
|
|
|
|
} else {
|
|
|
|
SetHealth(60.0f);
|
|
|
|
m_fMaxHealth = 60.0f;
|
|
|
|
// damage/explode properties
|
|
|
|
m_fBlowUpAmount = 100.0f;
|
|
|
|
m_fBodyParts = 5;
|
|
|
|
m_fBlowUpSize = 2.0f;
|
|
|
|
m_fDamageWounded = 25.0f;
|
|
|
|
}
|
|
|
|
en_fDensity = 2000.0f;
|
|
|
|
if (m_EeftType == EFT_GROUND_ONLY) {
|
|
|
|
en_tmMaxHoldBreath = 5.0f;
|
|
|
|
} else {
|
|
|
|
en_tmMaxHoldBreath = 30.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set your appearance
|
|
|
|
SetModel(MODEL_EYEMAN);
|
|
|
|
if (m_EecChar==EYC_SERGEANT) {
|
|
|
|
SetModelMainTexture(TEXTURE_EYEMAN_SERGEANT);
|
|
|
|
GetModelObject()->StretchModel(FLOAT3D(1.3f, 1.3f, 1.3f));
|
|
|
|
ModelChangeNotify();
|
|
|
|
m_iScore = 1000;
|
|
|
|
} else {
|
|
|
|
m_iScore = 500;
|
|
|
|
if (m_eeEnv == EYE_LAVA) {
|
|
|
|
SetModelMainTexture(TEXTURE_EYEMAN_LAVA);
|
|
|
|
} else {
|
|
|
|
SetModelMainTexture(TEXTURE_EYEMAN_SOLDIER);
|
|
|
|
}
|
|
|
|
GetModelObject()->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f));
|
|
|
|
ModelChangeNotify();
|
|
|
|
}
|
|
|
|
if (m_bInvisible) {
|
|
|
|
GetModelObject()->mo_colBlendColor = C_WHITE|0x25;
|
|
|
|
m_iScore*=2;
|
|
|
|
}
|
|
|
|
// setup moving speed
|
|
|
|
m_fWalkSpeed = FRnd() + 1.5f;
|
|
|
|
m_aWalkRotateSpeed = FRnd()*10.0f + 500.0f;
|
|
|
|
if (m_EecChar==EYC_SERGEANT) {
|
|
|
|
m_fAttackRunSpeed = FRnd()*2.0f + 10.0f;
|
|
|
|
m_aAttackRotateSpeed = AngleDeg(FRnd()*100 + 600.0f);
|
|
|
|
m_fCloseRunSpeed = FRnd()*2.0f + 10.0f;
|
|
|
|
m_aCloseRotateSpeed = AngleDeg(FRnd()*100 + 600.0f);
|
|
|
|
} else {
|
|
|
|
m_fAttackRunSpeed = FRnd()*2.0f + 9.0f;
|
|
|
|
m_aAttackRotateSpeed = AngleDeg(FRnd()*100 + 600.0f);
|
|
|
|
m_fCloseRunSpeed = FRnd()*2.0f + 9.0f;
|
|
|
|
m_aCloseRotateSpeed = AngleDeg(FRnd()*100 + 600.0f);
|
|
|
|
}
|
|
|
|
// setup attack distances
|
|
|
|
m_fAttackDistance = 100.0f;
|
|
|
|
m_fCloseDistance = 3.5f;
|
|
|
|
m_fStopDistance = 1.5f;
|
|
|
|
m_fAttackFireTime = 2.0f;
|
|
|
|
m_fCloseFireTime = 0.5f;
|
|
|
|
m_fIgnoreRange = 200.0f;
|
|
|
|
// fly moving properties
|
|
|
|
m_fFlyWalkSpeed = FRnd()*2.0f + 3.0f;
|
|
|
|
m_aFlyWalkRotateSpeed = FRnd()*20.0f + 600.0f;
|
|
|
|
if (m_EecChar==EYC_SERGEANT) {
|
|
|
|
m_fFlyAttackRunSpeed = FRnd()*2.0f + 9.5f;
|
|
|
|
m_aFlyAttackRotateSpeed = FRnd()*25 + 350.0f;
|
|
|
|
m_fFlyCloseRunSpeed = FRnd()*2.0f + 9.5f;
|
|
|
|
m_aFlyCloseRotateSpeed = FRnd()*50 + 400.0f;
|
|
|
|
} else {
|
|
|
|
m_fFlyAttackRunSpeed = FRnd()*2.0f + 9.5f;
|
|
|
|
m_aFlyAttackRotateSpeed = FRnd()*25 + 300.0f;
|
|
|
|
m_fFlyCloseRunSpeed = FRnd()*2.0f + 9.5f;
|
|
|
|
m_aFlyCloseRotateSpeed = FRnd()*50 + 300.0f;
|
|
|
|
}
|
|
|
|
m_fGroundToAirSpeed = 2.5f;
|
|
|
|
m_fAirToGroundSpeed = 2.5f;
|
|
|
|
m_fAirToGroundMin = 0.1f;
|
|
|
|
m_fAirToGroundMax = 0.1f;
|
|
|
|
m_fFlyHeight = 1.0f;
|
|
|
|
// attack properties - CAN BE SET
|
|
|
|
m_fFlyAttackDistance = 100.0f;
|
|
|
|
m_fFlyCloseDistance = 10.0f;
|
|
|
|
m_fFlyStopDistance = 1.5f;
|
|
|
|
m_fFlyAttackFireTime = 2.0f;
|
|
|
|
m_fFlyCloseFireTime = 0.5f;
|
|
|
|
m_fFlyIgnoreRange = 200.0f;
|
|
|
|
m_soMumble.Set3DParameters(25.0f, 0.0f, 1.0f, 1.0f);
|
|
|
|
|
|
|
|
// continue behavior in base class
|
|
|
|
jump CEnemyFly::MainLoop();
|
|
|
|
};
|
|
|
|
};
|