mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-11-28 21:05:53 +01:00
451 lines
14 KiB
C++
451 lines
14 KiB
C++
336
|
|
|
|
%{
|
|
#include "Entities/StdH/StdH.h"
|
|
#include "Models/Enemies/Beast/Beast.h"
|
|
#include "Entities/WorldSettingsController.h"
|
|
#include "Entities/BackgroundViewer.h"
|
|
%}
|
|
|
|
uses "Entities/EnemyBase";
|
|
uses "Entities/BasicEffects";
|
|
|
|
enum BeastType {
|
|
0 BT_NORMAL "Small", // normal (fighter)
|
|
1 BT_BIG "Big", // big
|
|
};
|
|
|
|
%{
|
|
static int _tmLastStandingAnim =0;
|
|
#define BEAST_STRETCH 2.0f
|
|
#define BIG_BEAST_STRETCH 12.0f
|
|
// info structure
|
|
static EntityInfo eiBeastNormal = {
|
|
EIBT_FLESH, 1500.0f,
|
|
0.0f, 2.0f*BEAST_STRETCH, 0.0f, // source (eyes)
|
|
0.0f, 1.5f*BEAST_STRETCH, 0.0f, // target (body)
|
|
};
|
|
static EntityInfo eiBeastBig = {
|
|
EIBT_FLESH, 5000.0f,
|
|
0.0f, 2.0f*BIG_BEAST_STRETCH, 0.0f, // source (eyes)
|
|
0.0f, 1.5f*BIG_BEAST_STRETCH, 0.0f, // target (body)
|
|
};
|
|
%}
|
|
|
|
class CBeast : CEnemyBase {
|
|
name "Beast";
|
|
thumbnail "Thumbnails\\Beast.tbn";
|
|
|
|
properties:
|
|
1 enum BeastType m_bcType "Character" 'C' = BT_NORMAL,
|
|
2 INDEX m_iCounter = 0,
|
|
3 BOOL m_bBeBoss "Boss" 'B' = FALSE,
|
|
|
|
components:
|
|
0 class CLASS_BASE "Classes\\EnemyBase.ecl",
|
|
1 class CLASS_PROJECTILE "Classes\\Projectile.ecl",
|
|
|
|
10 model MODEL_BEAST "Models\\Enemies\\Beast\\Beast.mdl",
|
|
11 texture TEXTURE_BEAST_NORMAL "Models\\Enemies\\Beast\\Beast.tex",
|
|
12 texture TEXTURE_BEAST_BIG "Models\\Enemies\\Beast\\BeastBig.tex",
|
|
|
|
// ************** SOUNDS **************
|
|
50 sound SOUND_IDLE "Models\\Enemies\\Beast\\Sounds\\Idle.wav",
|
|
51 sound SOUND_SIGHT "Models\\Enemies\\Beast\\Sounds\\Sight.wav",
|
|
52 sound SOUND_WOUND "Models\\Enemies\\Beast\\Sounds\\Wound.wav",
|
|
53 sound SOUND_FIRE "Models\\Enemies\\Beast\\Sounds\\Fire.wav",
|
|
54 sound SOUND_KICK "Models\\Enemies\\Beast\\Sounds\\Kick.wav",
|
|
55 sound SOUND_DEATH "Models\\Enemies\\Beast\\Sounds\\Death.wav",
|
|
56 sound SOUND_DEATHBIG "Models\\Enemies\\Beast\\Sounds\\DeathBig.wav",
|
|
57 sound SOUND_ANGER "Models\\Enemies\\Beast\\Sounds\\Anger.wav",
|
|
|
|
functions:
|
|
// describe how this enemy killed player
|
|
virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath)
|
|
{
|
|
CTString str;
|
|
str.PrintF(TRANS("A Reptiloid killed %s"),(const char*) strPlayerName);
|
|
return str;
|
|
}
|
|
virtual const CTFileName &GetComputerMessageName(void) const {
|
|
static DECLARE_CTFILENAME(fnmNormal, "Data\\Messages\\Enemies\\BeastNormal.txt");
|
|
static DECLARE_CTFILENAME(fnmBig, "Data\\Messages\\Enemies\\BeastBig.txt");
|
|
switch(m_bcType) {
|
|
default: ASSERT(FALSE);
|
|
case BT_NORMAL: return fnmNormal;
|
|
case BT_BIG: return fnmBig;
|
|
}
|
|
};
|
|
void Precache(void) {
|
|
CEnemyBase::Precache();
|
|
PrecacheSound(SOUND_IDLE );
|
|
PrecacheSound(SOUND_SIGHT);
|
|
PrecacheSound(SOUND_WOUND);
|
|
PrecacheSound(SOUND_ANGER);
|
|
PrecacheSound(SOUND_FIRE);
|
|
PrecacheSound(SOUND_KICK);
|
|
PrecacheModel(MODEL_BEAST);
|
|
PrecacheTexture(TEXTURE_BEAST_NORMAL);
|
|
PrecacheTexture(TEXTURE_BEAST_BIG);
|
|
if (m_bcType == BT_NORMAL) {
|
|
PrecacheSound(SOUND_DEATH);
|
|
PrecacheClass(CLASS_PROJECTILE, PRT_BEAST_PROJECTILE);
|
|
} else {
|
|
PrecacheSound(SOUND_DEATHBIG);
|
|
PrecacheClass(CLASS_PROJECTILE, PRT_BEAST_BIG_PROJECTILE);
|
|
}
|
|
};
|
|
|
|
/* Entity info */
|
|
void *GetEntityInfo(void) {
|
|
if (m_bcType == BT_NORMAL) {
|
|
return &eiBeastNormal;
|
|
} else {
|
|
return &eiBeastBig;
|
|
}
|
|
};
|
|
|
|
class CWorldSettingsController *GetWSC(void)
|
|
{
|
|
CWorldSettingsController *pwsc = NULL;
|
|
// obtain bcg viewer
|
|
CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) GetWorld()->GetBackgroundViewer();
|
|
if( penBcgViewer != NULL) {
|
|
// obtain world settings controller
|
|
pwsc = (CWorldSettingsController *) &*penBcgViewer->m_penWorldSettingsController;
|
|
}
|
|
return pwsc;
|
|
}
|
|
|
|
void ShakeItBaby(FLOAT tmShaketime, FLOAT fPower)
|
|
{
|
|
CWorldSettingsController *pwsc = GetWSC();
|
|
if (pwsc!=NULL) {
|
|
pwsc->m_tmShakeStarted = tmShaketime;
|
|
pwsc->m_vShakePos = GetPlacement().pl_PositionVector;
|
|
pwsc->m_fShakeFalloff = 400.0f;
|
|
pwsc->m_fShakeFade = 3.0f;
|
|
|
|
pwsc->m_fShakeIntensityZ = 0.0f;
|
|
pwsc->m_tmShakeFrequencyZ = 5.0f;
|
|
pwsc->m_fShakeIntensityY = 0.1f*fPower;
|
|
pwsc->m_tmShakeFrequencyY = 5.0f;
|
|
pwsc->m_fShakeIntensityB = 2.5f*fPower;
|
|
pwsc->m_tmShakeFrequencyB = 7.2f;
|
|
}
|
|
}
|
|
|
|
FLOAT GetCrushHealth(void)
|
|
{
|
|
if (m_bcType == BT_BIG) {
|
|
return 100.0f;
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
/* Receive damage */
|
|
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
|
|
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
|
|
{
|
|
// can't harm own class
|
|
if (!IsOfClass(penInflictor, "Beast")) {
|
|
CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
|
|
}
|
|
};
|
|
|
|
|
|
// damage anim
|
|
INDEX AnimForDamage(FLOAT fDamage) {
|
|
INDEX iAnim;
|
|
if(m_bcType==BT_BIG && GetHealth() <= m_fMaxHealth/2) {
|
|
iAnim = BEAST_ANIM_ANGER;
|
|
} else {
|
|
iAnim = BEAST_ANIM_WOUND;
|
|
}
|
|
StartModelAnim(iAnim, 0);
|
|
return iAnim;
|
|
};
|
|
|
|
// death
|
|
INDEX AnimForDeath(void) {
|
|
INDEX iAnim;
|
|
if(m_bcType==BT_BIG) {
|
|
iAnim = BEAST_ANIM_DEATHBIG;
|
|
} else {
|
|
iAnim = BEAST_ANIM_DEATH;
|
|
}
|
|
|
|
StartModelAnim(iAnim, 0);
|
|
return iAnim;
|
|
};
|
|
|
|
void DeathNotify(void) {
|
|
ChangeCollisionBoxIndexWhenPossible(BEAST_COLLISION_BOX_DEATH);
|
|
en_fDensity = 500.0f;
|
|
};
|
|
|
|
// virtual anim functions
|
|
void StandingAnim(void) {
|
|
_tmLastStandingAnim = _pTimer->CurrentTick();
|
|
StartModelAnim(BEAST_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART);
|
|
};
|
|
|
|
void WalkingAnim(void) {
|
|
if(_pTimer->CurrentTick()>=_tmLastStandingAnim-_pTimer->TickQuantum &&
|
|
_pTimer->CurrentTick()<=_tmLastStandingAnim+_pTimer->TickQuantum)
|
|
{
|
|
BREAKPOINT;
|
|
}
|
|
|
|
if(m_bcType==BT_BIG) {
|
|
StartModelAnim(BEAST_ANIM_WALKBIG, AOF_LOOPING|AOF_NORESTART);
|
|
} else {
|
|
StartModelAnim(BEAST_ANIM_WALK, AOF_LOOPING|AOF_NORESTART);
|
|
}
|
|
};
|
|
|
|
void RunningAnim(void) {
|
|
WalkingAnim();
|
|
};
|
|
void RotatingAnim(void) {
|
|
WalkingAnim();
|
|
};
|
|
|
|
// 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) {
|
|
if(m_bcType==BT_BIG && GetHealth() <= m_fMaxHealth/2) {
|
|
PlaySound(m_soSound, SOUND_ANGER, SOF_3D);
|
|
} else {
|
|
PlaySound(m_soSound, SOUND_WOUND, SOF_3D);
|
|
}
|
|
};
|
|
void DeathSound(void) {
|
|
if (m_bcType == BT_NORMAL) {
|
|
PlaySound(m_soSound, SOUND_DEATH, SOF_3D);
|
|
} else {
|
|
PlaySound(m_soSound, SOUND_DEATHBIG, SOF_3D);
|
|
}
|
|
};
|
|
|
|
|
|
// adjust sound and watcher parameters here if needed
|
|
void EnemyPostInit(void)
|
|
{
|
|
m_soSound.Set3DParameters(160.0f, 50.0f, 2.0f, 1.0f);
|
|
};
|
|
|
|
procedures:
|
|
/************************************************************
|
|
* D E A T H *
|
|
************************************************************/
|
|
Death(EVoid) : CEnemyBase::Death {
|
|
if (m_bcType == BT_NORMAL) {
|
|
jump CEnemyBase::Death();
|
|
}
|
|
// stop moving
|
|
StopMoving();
|
|
DeathSound(); // death sound
|
|
LeaveStain(TRUE);
|
|
// set physic flags
|
|
SetPhysicsFlags(EPF_MODEL_CORPSE);
|
|
SetCollisionFlags(ECF_CORPSE);
|
|
SetFlags(GetFlags() | ENF_SEETHROUGH);
|
|
// stop making fuss
|
|
RemoveFromFuss();
|
|
// death notify (usually change collision box and change body density)
|
|
DeathNotify();
|
|
// start death anim
|
|
AnimForDeath();
|
|
autowait(1.0f);
|
|
ShakeItBaby(_pTimer->CurrentTick(), 2.0f);
|
|
autowait(2.4f-1.0f);
|
|
ShakeItBaby(_pTimer->CurrentTick(), 5.0f);
|
|
autowait(GetModelObject()->GetAnimLength(BEAST_ANIM_DEATHBIG)-3.4f);
|
|
return EEnd();
|
|
};
|
|
|
|
/************************************************************
|
|
* A T T A C K E N E M Y *
|
|
************************************************************/
|
|
Fire(EVoid) : CEnemyBase::Fire
|
|
{
|
|
// wait to finish walk and smooth change to idle
|
|
StartModelAnim(BEAST_ANIM_WALKTOIDLE, AOF_SMOOTHCHANGE);
|
|
autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn;
|
|
|
|
if( m_bcType == BT_NORMAL)
|
|
{
|
|
StartModelAnim(BEAST_ANIM_ATTACK, AOF_SMOOTHCHANGE);
|
|
autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn;
|
|
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
|
|
autowait(0.51f);
|
|
|
|
ShootProjectile(PRT_BEAST_PROJECTILE, FLOAT3D( 0.0f, 1.5f*BEAST_STRETCH, 0.0f),
|
|
ANGLE3D(AngleDeg((FRnd()-0.5)*30.0f), AngleDeg(FRnd()*10.0f), 0));
|
|
autowait(0.3f);
|
|
}
|
|
|
|
if( m_bcType == BT_BIG)
|
|
{
|
|
if( GetHealth() <= m_fMaxHealth/2)
|
|
{
|
|
m_iCounter = 0;
|
|
while ( m_iCounter<6)
|
|
{
|
|
StartModelAnim(BEAST_ANIM_ATTACKFAST, AOF_SMOOTHCHANGE);
|
|
autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn;
|
|
|
|
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
|
|
autowait(0.34f);
|
|
ShootProjectile(PRT_BEAST_BIG_PROJECTILE, FLOAT3D( 0.0f, 1.5f*BIG_BEAST_STRETCH, 0.0f),
|
|
ANGLE3D( AngleDeg(40.0f*Cos(m_iCounter*360.0/6.0f)), AngleDeg(20.0f*Sin(m_iCounter*180.0/6.0f)), 0));
|
|
//autowait(0.15f);
|
|
m_iCounter++;
|
|
}
|
|
m_fAttackFireTime = 7.0f;
|
|
}
|
|
|
|
if( GetHealth() > m_fMaxHealth/2)
|
|
{
|
|
m_iCounter = 0;
|
|
while ( m_iCounter<3)
|
|
{
|
|
StartModelAnim(BEAST_ANIM_ATTACK, AOF_SMOOTHCHANGE);
|
|
autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn;
|
|
|
|
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
|
|
autowait(0.5f);
|
|
ShootProjectile(PRT_BEAST_BIG_PROJECTILE, FLOAT3D( 0.0f, 1.5f*BIG_BEAST_STRETCH, 0.0f),
|
|
ANGLE3D( AngleDeg(20.0f*Cos(m_iCounter*360.0/3.0f)), AngleDeg(10.0f*Sin(m_iCounter*180.0/3.0f)), 0));
|
|
//autowait(0.25f);
|
|
m_iCounter++;
|
|
}
|
|
}
|
|
}
|
|
|
|
MaybeSwitchToAnotherPlayer();
|
|
|
|
autowait(FRnd()/2 + _pTimer->TickQuantum);
|
|
|
|
if( m_penEnemy != NULL)
|
|
{
|
|
FLOAT fEnemyDistance = CalcDist(m_penEnemy);
|
|
if( fEnemyDistance>m_fCloseDistance*1.25f)
|
|
{
|
|
StartModelAnim(BEAST_ANIM_IDLETOWALK, AOF_SMOOTHCHANGE);
|
|
autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn;
|
|
autowait(GetModelObject()->GetAnimLength(BEAST_ANIM_IDLETOWALK)/2.0f - _pTimer->TickQuantum);
|
|
}
|
|
}
|
|
|
|
|
|
return EReturn();
|
|
};
|
|
|
|
// hit enemy
|
|
Hit(EVoid) : CEnemyBase::Hit {
|
|
// close attack
|
|
StartModelAnim(BEAST_ANIM_KICK, 0);
|
|
autowait(0.45f);
|
|
/*
|
|
StartModelAnim(BEAST_ANIM_KICK, AOF_SMOOTHCHANGE);
|
|
autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn;
|
|
*/
|
|
PlaySound(m_soSound, SOUND_KICK, SOF_3D);
|
|
if (CalcDist(m_penEnemy) < m_fCloseDistance) {
|
|
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
|
|
vDirection.Normalize();
|
|
if (m_bcType == BT_BIG) {
|
|
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 80.0f, FLOAT3D(0, 0, 0), vDirection);
|
|
} else {
|
|
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 40.0f, FLOAT3D(0, 0, 0), vDirection);
|
|
}
|
|
}
|
|
|
|
/*
|
|
StartModelAnim(BEAST_ANIM_IDLE, AOF_SMOOTHCHANGE);
|
|
autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn;
|
|
*/
|
|
autowait(0.45f);
|
|
MaybeSwitchToAnotherPlayer();
|
|
return EReturn();
|
|
};
|
|
|
|
/************************************************************
|
|
* M A I N *
|
|
************************************************************/
|
|
Main(EVoid) {
|
|
// declare yourself as a model
|
|
InitAsModel();
|
|
SetPhysicsFlags(EPF_MODEL_WALKING);
|
|
SetCollisionFlags(ECF_MODEL);
|
|
SetFlags(GetFlags()|ENF_ALIVE);
|
|
|
|
en_fDensity = 1100.0f;
|
|
// set your appearance
|
|
SetModel(MODEL_BEAST);
|
|
StandingAnim();
|
|
// setup moving speed
|
|
m_fWalkSpeed = FRnd()*2 + 5.0f;
|
|
m_aWalkRotateSpeed = AngleDeg(FRnd()*20.0f + 50.0f);
|
|
m_fCloseRunSpeed = FRnd() + 10.0f;
|
|
m_aCloseRotateSpeed = AngleDeg(FRnd()*100 + 900.0f);
|
|
// setup attack distances
|
|
m_fAttackDistance = 500.0f;
|
|
m_fCloseDistance = 0.0f;
|
|
m_fStopDistance = 0.0f;
|
|
m_fCloseFireTime = 1.0f;
|
|
m_fIgnoreRange = 750.0f;
|
|
m_bBoss = m_bBeBoss;
|
|
m_fStopDistance = 5.0f;
|
|
m_fCloseDistance = 7.0f;
|
|
m_tmGiveUp = Max(m_tmGiveUp, 10.0f);
|
|
|
|
// damage/explode properties
|
|
if( m_bcType == BT_NORMAL)
|
|
{
|
|
m_fAttackRunSpeed = 6.0f;//6
|
|
m_aAttackRotateSpeed = AngleDeg(3600.0f);
|
|
SetHealth(400.0f);
|
|
SetModelMainTexture(TEXTURE_BEAST_NORMAL);
|
|
m_fBlowUpAmount = 10000.0f;
|
|
m_fBodyParts = 4;
|
|
m_fDamageWounded = 250.0f;
|
|
m_iScore = 5000;//500
|
|
// set stretch factor
|
|
GetModelObject()->StretchModel(FLOAT3D(BEAST_STRETCH, BEAST_STRETCH, BEAST_STRETCH));
|
|
ModelChangeNotify();
|
|
m_sptType = SPT_SLIME;
|
|
m_fAttackFireTime = 3.0f;
|
|
}
|
|
else
|
|
{
|
|
m_fAttackRunSpeed = 8.0f;//8
|
|
m_aAttackRotateSpeed = AngleDeg(600.0f);
|
|
SetHealth(2000.0f);//500
|
|
SetModelMainTexture(TEXTURE_BEAST_BIG);
|
|
m_fBlowUpAmount = 10000.0f;//500
|
|
m_fBodyParts = 6;
|
|
m_fDamageWounded = 650.0f;//500
|
|
m_iScore = 25000; //1000
|
|
m_fStopDistance = 15;
|
|
m_fCloseDistance = 20;
|
|
// set stretch factor
|
|
GetModelObject()->StretchModel(FLOAT3D(BIG_BEAST_STRETCH, BIG_BEAST_STRETCH, BIG_BEAST_STRETCH));
|
|
ModelChangeNotify();
|
|
m_sptType = SPT_BLOOD;
|
|
m_fAttackFireTime = 5.0f;
|
|
}
|
|
m_fMaxHealth = GetHealth();
|
|
|
|
// continue behavior in base class
|
|
jump CEnemyBase::MainLoop();
|
|
};
|
|
};
|