mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-12-01 22:25:53 +01:00
351 lines
11 KiB
C++
351 lines
11 KiB
C++
|
328
|
||
|
%{
|
||
|
#include "Entities/StdH/StdH.h"
|
||
|
#include "Models/Enemies/Fishman/fishman.h"
|
||
|
%}
|
||
|
|
||
|
uses "Entities/EnemyDive";
|
||
|
|
||
|
%{
|
||
|
static EntityInfo eiFishmanGround = {
|
||
|
EIBT_FLESH, 100.0f,
|
||
|
0.0f, 1.4f, 0.0f,
|
||
|
0.0f, 1.0f, 0.0f,
|
||
|
};
|
||
|
static EntityInfo eiFishmanLiquid = {
|
||
|
EIBT_FLESH, 33.3f,
|
||
|
0.0f, 0.0f, 0.0f,
|
||
|
0.0f, 0.0f, 0.0f,
|
||
|
};
|
||
|
|
||
|
#define FIRE_WATER FLOAT3D(0.0f, 0.3f, -1.1f)
|
||
|
#define FIRE_GROUND FLOAT3D(0.0f, 0.8f, -1.25f)
|
||
|
#define SPEAR_HIT 1.75f
|
||
|
%}
|
||
|
|
||
|
|
||
|
class CFishman : CEnemyDive {
|
||
|
name "Fishman";
|
||
|
thumbnail "Thumbnails\\Fishman.tbn";
|
||
|
|
||
|
properties:
|
||
|
components:
|
||
|
0 class CLASS_BASE "Classes\\EnemyDive.ecl",
|
||
|
1 model MODEL_FISHMAN "Models\\Enemies\\Fishman\\Fishman.mdl",
|
||
|
2 texture TEXTURE_FISHMAN "Models\\Enemies\\Fishman\\Fishman.tex",
|
||
|
|
||
|
// ************** SOUNDS **************
|
||
|
50 sound SOUND_IDLE_WATER "Models\\Enemies\\Fishman\\Sounds\\IdleWater.wav",
|
||
|
51 sound SOUND_IDLE_GROUND "Models\\Enemies\\Fishman\\Sounds\\IdleGround.wav",
|
||
|
52 sound SOUND_SIGHT_WATER "Models\\Enemies\\Fishman\\Sounds\\SightWater.wav",
|
||
|
53 sound SOUND_SIGHT_GROUND "Models\\Enemies\\Fishman\\Sounds\\SightGround.wav",
|
||
|
54 sound SOUND_WOUND_WATER "Models\\Enemies\\Fishman\\Sounds\\WoundWater.wav",
|
||
|
55 sound SOUND_WOUND_GROUND "Models\\Enemies\\Fishman\\Sounds\\WoundGround.wav",
|
||
|
56 sound SOUND_DEATH_WATER "Models\\Enemies\\Fishman\\Sounds\\DeathWater.wav",
|
||
|
57 sound SOUND_DEATH_GROUND "Models\\Enemies\\Fishman\\Sounds\\DeathGround.wav",
|
||
|
58 sound SOUND_FIRE "Models\\Enemies\\Fishman\\Sounds\\Fire.wav",
|
||
|
59 sound SOUND_KICK "Models\\Enemies\\Fishman\\Sounds\\Kick.wav",
|
||
|
|
||
|
functions:
|
||
|
/* Entity info */
|
||
|
void *GetEntityInfo(void) {
|
||
|
if (m_bInLiquid) {
|
||
|
return &eiFishmanLiquid;
|
||
|
} else {
|
||
|
return &eiFishmanGround;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/* Receive damage */
|
||
|
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
|
||
|
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
|
||
|
{
|
||
|
// fishman can't harm fishman
|
||
|
if (!IsOfClass(penInflictor, "Fishman")) {
|
||
|
CEnemyDive::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
// damage anim
|
||
|
INDEX AnimForDamage(FLOAT fDamage) {
|
||
|
INDEX iAnim;
|
||
|
if (m_bInLiquid) {
|
||
|
switch (IRnd()%2) {
|
||
|
case 0: iAnim = FISHMAN_ANIM_WATERWOUND01; break;
|
||
|
case 1: iAnim = FISHMAN_ANIM_WATERWOUND02; break;
|
||
|
default: ASSERTALWAYS("Fishman unknown liquid damage");
|
||
|
}
|
||
|
} else {
|
||
|
switch (IRnd()%3) {
|
||
|
case 0: iAnim = FISHMAN_ANIM_GROUNDWOUND03; break;
|
||
|
case 1: iAnim = FISHMAN_ANIM_GROUNDWOUND04; break;
|
||
|
case 2: iAnim = FISHMAN_ANIM_GROUNDWOUND05; break;
|
||
|
default: ASSERTALWAYS("Fishman unknown ground damage");
|
||
|
}
|
||
|
}
|
||
|
StartModelAnim(iAnim, 0);
|
||
|
return iAnim;
|
||
|
};
|
||
|
|
||
|
// death
|
||
|
INDEX AnimForDeath(void) {
|
||
|
INDEX iAnim;
|
||
|
if (m_bInLiquid) {
|
||
|
iAnim = FISHMAN_ANIM_WATERDEATH;
|
||
|
} else {
|
||
|
iAnim = FISHMAN_ANIM_GROUNDDEATH;
|
||
|
}
|
||
|
StartModelAnim(iAnim, 0);
|
||
|
return iAnim;
|
||
|
};
|
||
|
|
||
|
void DeathNotify(void) {
|
||
|
if (m_bInLiquid) {
|
||
|
ChangeCollisionBoxIndexWhenPossible(FISHMAN_COLLISION_BOX_DEATH_WATER);
|
||
|
} else {
|
||
|
ChangeCollisionBoxIndexWhenPossible(FISHMAN_COLLISION_BOX_DEATH_GROUND);
|
||
|
}
|
||
|
en_fDensity = 500.0f;
|
||
|
};
|
||
|
|
||
|
// virtual anim functions
|
||
|
void StandingAnim(void) {
|
||
|
if (m_bInLiquid) {
|
||
|
StartModelAnim(FISHMAN_ANIM_WATERSTAND, AOF_LOOPING|AOF_NORESTART);
|
||
|
} else {
|
||
|
StartModelAnim(FISHMAN_ANIM_GROUNDSTAND, AOF_LOOPING|AOF_NORESTART);
|
||
|
}
|
||
|
};
|
||
|
void WalkingAnim(void) {
|
||
|
if (m_bInLiquid) {
|
||
|
StartModelAnim(FISHMAN_ANIM_WATERSWIM02, AOF_LOOPING|AOF_NORESTART);
|
||
|
} else {
|
||
|
StartModelAnim(FISHMAN_ANIM_GROUNDWALK, AOF_LOOPING|AOF_NORESTART);
|
||
|
}
|
||
|
};
|
||
|
void RunningAnim(void) {
|
||
|
if (m_bInLiquid) {
|
||
|
StartModelAnim(FISHMAN_ANIM_WATERSWIM01, AOF_LOOPING|AOF_NORESTART);
|
||
|
} else {
|
||
|
StartModelAnim(FISHMAN_ANIM_GROUNDRUN, AOF_LOOPING|AOF_NORESTART);
|
||
|
}
|
||
|
};
|
||
|
void RotatingAnim(void) {
|
||
|
if (m_bInLiquid) {
|
||
|
StartModelAnim(FISHMAN_ANIM_WATERSWIM02, AOF_LOOPING|AOF_NORESTART);
|
||
|
} else {
|
||
|
StartModelAnim(FISHMAN_ANIM_GROUNDWALK, AOF_LOOPING|AOF_NORESTART);
|
||
|
}
|
||
|
};
|
||
|
void ChangeCollisionToLiquid() {
|
||
|
ChangeCollisionBoxIndexWhenPossible(FISHMAN_COLLISION_BOX_WATER);
|
||
|
};
|
||
|
void ChangeCollisionToGround() {
|
||
|
ChangeCollisionBoxIndexWhenPossible(FISHMAN_COLLISION_BOX_GROUND);
|
||
|
};
|
||
|
|
||
|
// virtual sound functions
|
||
|
void IdleSound(void) {
|
||
|
if (m_bInLiquid) {
|
||
|
PlaySound(m_soSound, SOUND_IDLE_WATER , SOF_3D);
|
||
|
} else {
|
||
|
PlaySound(m_soSound, SOUND_IDLE_GROUND, SOF_3D);
|
||
|
}
|
||
|
};
|
||
|
void SightSound(void) {
|
||
|
if (m_bInLiquid) {
|
||
|
PlaySound(m_soSound, SOUND_SIGHT_WATER , SOF_3D);
|
||
|
} else {
|
||
|
PlaySound(m_soSound, SOUND_SIGHT_GROUND, SOF_3D);
|
||
|
}
|
||
|
};
|
||
|
void WoundSound(void) {
|
||
|
if (m_bInLiquid) {
|
||
|
PlaySound(m_soSound, SOUND_WOUND_WATER , SOF_3D);
|
||
|
} else {
|
||
|
PlaySound(m_soSound, SOUND_WOUND_GROUND, SOF_3D);
|
||
|
}
|
||
|
};
|
||
|
void DeathSound(void) {
|
||
|
if (m_bInLiquid) {
|
||
|
PlaySound(m_soSound, SOUND_DEATH_WATER , SOF_3D);
|
||
|
} else {
|
||
|
PlaySound(m_soSound, SOUND_DEATH_GROUND, SOF_3D);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
procedures:
|
||
|
/************************************************************
|
||
|
* A T T A C K E N E M Y *
|
||
|
************************************************************/
|
||
|
DiveFire(EVoid) : CEnemyDive::DiveFire {
|
||
|
// fire projectile
|
||
|
StartModelAnim(FISHMAN_ANIM_WATERATTACK02, 0);
|
||
|
autowait(0.4f);
|
||
|
ShootProjectile(PRT_FISHMAN_FIRE, FIRE_WATER, ANGLE3D(0, 0, 0));
|
||
|
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
|
||
|
autowait(0.95f);
|
||
|
StandingAnim();
|
||
|
autowait(FRnd()/3 + _pTimer->TickQuantum);
|
||
|
|
||
|
return EReturn();
|
||
|
};
|
||
|
|
||
|
DiveHit(EVoid) : CEnemyDive::DiveHit {
|
||
|
if (CalcDist(m_penEnemy) > SPEAR_HIT) {
|
||
|
// run to enemy
|
||
|
m_fShootTime = _pTimer->CurrentTick() + 0.25f;
|
||
|
return EReturn();
|
||
|
}
|
||
|
|
||
|
// attack with spear
|
||
|
StartModelAnim(FISHMAN_ANIM_WATERATTACK01, 0);
|
||
|
|
||
|
// to left hit
|
||
|
autowait(0.5f);
|
||
|
PlaySound(m_soSound, SOUND_KICK, SOF_3D);
|
||
|
if (CalcDist(m_penEnemy)<SPEAR_HIT) {
|
||
|
// damage enemy
|
||
|
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
|
||
|
vDirection.Normalize();
|
||
|
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 5.0f, FLOAT3D(0, 0, 0), vDirection);
|
||
|
// push target away
|
||
|
FLOAT3D vSpeed;
|
||
|
GetHeadingDirection(0.0f, vSpeed);
|
||
|
vSpeed = vSpeed * 5.0f;
|
||
|
KickEntity(m_penEnemy, vSpeed);
|
||
|
}
|
||
|
autowait(0.5f);
|
||
|
|
||
|
StandingAnim();
|
||
|
autowait(0.2f + FRnd()/3);
|
||
|
return EReturn();
|
||
|
};
|
||
|
|
||
|
Fire(EVoid) : CEnemyBase::Fire {
|
||
|
// wait anim end
|
||
|
if (!GetModelObject()->IsAnimFinished()) {
|
||
|
autowait(GetModelObject()->GetCurrentAnimLength() - GetModelObject()->GetPassedTime());
|
||
|
}
|
||
|
|
||
|
// fire projectile
|
||
|
StartModelAnim(FISHMAN_ANIM_GROUNDATTACK02, 0);
|
||
|
autowait(0.3f);
|
||
|
ShootProjectile(PRT_FISHMAN_FIRE, FIRE_GROUND, ANGLE3D(0, 0, 0));
|
||
|
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
|
||
|
autowait(0.4f);
|
||
|
StandingAnim();
|
||
|
autowait(FRnd()/3 + _pTimer->TickQuantum);
|
||
|
|
||
|
return EReturn();
|
||
|
};
|
||
|
|
||
|
Hit(EVoid) : CEnemyBase::Hit {
|
||
|
if (CalcDist(m_penEnemy) > SPEAR_HIT) {
|
||
|
// run to enemy
|
||
|
m_fShootTime = _pTimer->CurrentTick() + 0.25f;
|
||
|
return EReturn();
|
||
|
}
|
||
|
|
||
|
// wait anim end
|
||
|
if (!GetModelObject()->IsAnimFinished()) {
|
||
|
autowait(GetModelObject()->GetCurrentAnimLength() - GetModelObject()->GetPassedTime());
|
||
|
}
|
||
|
|
||
|
// attack with spear
|
||
|
StartModelAnim(FISHMAN_ANIM_GROUNDATTACKLOOP, 0);
|
||
|
|
||
|
// to left hit
|
||
|
autowait(0.5f);
|
||
|
PlaySound(m_soSound, SOUND_KICK, SOF_3D);
|
||
|
if (CalcDist(m_penEnemy)<SPEAR_HIT) {
|
||
|
// damage enemy
|
||
|
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
|
||
|
vDirection.Normalize();
|
||
|
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 2.5f, FLOAT3D(0, 0, 0), vDirection);
|
||
|
// push target left
|
||
|
FLOAT3D vSpeed;
|
||
|
GetHeadingDirection(90.0f, vSpeed);
|
||
|
vSpeed = vSpeed * 5.0f;
|
||
|
KickEntity(m_penEnemy, vSpeed);
|
||
|
}
|
||
|
autowait(0.5f);
|
||
|
PlaySound(m_soSound, SOUND_KICK, SOF_3D);
|
||
|
if (CalcDist(m_penEnemy)<SPEAR_HIT) {
|
||
|
// damage enemy
|
||
|
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
|
||
|
vDirection.Normalize();
|
||
|
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 2.5f, FLOAT3D(0, 0, 0), vDirection);
|
||
|
// push target right
|
||
|
FLOAT3D vSpeed;
|
||
|
GetHeadingDirection(-90.0f, vSpeed);
|
||
|
vSpeed = vSpeed * 5.0f;
|
||
|
KickEntity(m_penEnemy, vSpeed);
|
||
|
}
|
||
|
autowait(0.6f);
|
||
|
|
||
|
StandingAnim();
|
||
|
autowait(0.2f + FRnd()/3);
|
||
|
return EReturn();
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
/************************************************************
|
||
|
* M A I N *
|
||
|
************************************************************/
|
||
|
Main(EVoid) {
|
||
|
// declare yourself as a model
|
||
|
InitAsModel();
|
||
|
SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS|EPF_HASGILLS);
|
||
|
SetCollisionFlags(ECF_MODEL);
|
||
|
SetFlags(GetFlags()|ENF_ALIVE);
|
||
|
SetHealth(30.0f);
|
||
|
m_fMaxHealth = 30.0f;
|
||
|
en_tmMaxHoldBreath = 5.0f;
|
||
|
en_fDensity = 1000.0f;
|
||
|
|
||
|
// set your appearance
|
||
|
SetModel(MODEL_FISHMAN);
|
||
|
SetModelMainTexture(TEXTURE_FISHMAN);
|
||
|
// setup moving speed
|
||
|
m_fWalkSpeed = FRnd() + 1.5f;
|
||
|
m_aWalkRotateSpeed = FRnd()*10.0f + 500.0f;
|
||
|
m_fAttackRunSpeed = FRnd()*0.5f + 5.0f;
|
||
|
m_aAttackRotateSpeed = FRnd()*50 + 245.0f;
|
||
|
m_fCloseRunSpeed = FRnd()*0.5f + 5.0f;
|
||
|
m_aCloseRotateSpeed = FRnd()*50 + 245.0f;
|
||
|
// setup attack distances
|
||
|
m_fAttackDistance = 50.0f;
|
||
|
m_fCloseDistance = 5.0f;
|
||
|
m_fStopDistance = 0.0f;
|
||
|
m_fAttackFireTime = 3.0f;
|
||
|
m_fCloseFireTime = 2.0f;
|
||
|
m_fIgnoreRange = 200.0f;
|
||
|
// fly moving properties
|
||
|
m_fDiveWalkSpeed = FRnd() + 3.0f;
|
||
|
m_aDiveWalkRotateSpeed = FRnd()*10.0f + 500.0f;
|
||
|
m_fDiveAttackRunSpeed = FRnd()*4.0f + 14.0f;
|
||
|
m_aDiveAttackRotateSpeed = FRnd()*25 + 500.0f;
|
||
|
m_fDiveCloseRunSpeed = FRnd()*2.0f + 8.0f;
|
||
|
m_aDiveCloseRotateSpeed = FRnd()*50 + 800.0f;
|
||
|
// attack properties
|
||
|
m_fDiveAttackDistance = 50.0f;
|
||
|
m_fDiveCloseDistance = 3.0f;
|
||
|
m_fDiveStopDistance = 0.0f;
|
||
|
m_fDiveAttackFireTime = 3.0f;
|
||
|
m_fDiveCloseFireTime = 2.0f;
|
||
|
m_fDiveIgnoreRange = 200.0f;
|
||
|
// damage/explode properties
|
||
|
m_fBlowUpAmount = 60.0f;
|
||
|
m_fBodyParts = 4;
|
||
|
m_fDamageWounded = 15.0f;
|
||
|
m_iScore = 500;
|
||
|
|
||
|
// continue behavior in base class
|
||
|
jump CEnemyDive::MainLoop();
|
||
|
};
|
||
|
};
|