Serious-Engine/Sources/Entities/EnemyDive.es
2016-04-08 00:11:36 +02:00

251 lines
7.8 KiB
C++

313
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/EnemyBase";
uses "Entities/Debris";
uses "Entities/EnemyMarker";
enum EnemyDiveType {
0 EDT_GROUND_ONLY "Ground only", // can't dive
1 EDT_DIVE_ONLY "Dive only", // always dive can't walk
2 EDT_GROUND_DIVE "Ground and dive", // dive and walk
};
class export CEnemyDive : CEnemyBase {
name "Enemy Dive";
thumbnail "";
properties:
1 enum EnemyDiveType m_EedtType "Type" 'T' = EDT_DIVE_ONLY, // dive type
2 BOOL m_bInLiquid "In liquid" 'Q' = TRUE, // entity is in liquid
// moving/attack properties - CAN BE SET
// these following must be ordered exactly like this for GetProp() to function
10 FLOAT m_fDiveWalkSpeed = 1.0f, // dive walk speed
11 ANGLE m_aDiveWalkRotateSpeed = AngleDeg(10.0f), // dive walk rotate speed
12 FLOAT m_fDiveAttackRunSpeed = 1.0f, // dive attack run speed
13 ANGLE m_aDiveAttackRotateSpeed = AngleDeg(10.0f), // dive attack rotate speed
14 FLOAT m_fDiveCloseRunSpeed = 1.0f, // dive close run speed
15 ANGLE m_aDiveCloseRotateSpeed = AngleDeg(10.0f), // dive close rotate speed
20 FLOAT m_fDiveAttackDistance = 50.0f, // dive attack distance mode
21 FLOAT m_fDiveCloseDistance = 10.0f, // dive close distance mode
22 FLOAT m_fDiveAttackFireTime = 2.0f, // dive attack distance fire time
23 FLOAT m_fDiveCloseFireTime = 1.0f, // dive close distance fire time
24 FLOAT m_fDiveStopDistance = 0.0f, // dive stop moving toward enemy if closer than stop distance
25 FLOAT m_fDiveIgnoreRange = 200.0f, // dive cease attack if enemy farther
26 FLOAT m_fDiveLockOnEnemyTime = 0.0f, // dive time needed to fire
components:
1 class CLASS_BASE "Classes\\EnemyBase.ecl",
functions:
// overridable function for access to different properties of derived classes (flying/diving)
virtual FLOAT &GetProp(FLOAT &m_fBase)
{
if (m_bInLiquid) {
return *((&m_fBase)+(&m_fDiveWalkSpeed-&m_fWalkSpeed));
} else {
return m_fBase;
}
}
// diving enemies never use pathfinding
void StartPathFinding(void)
{
m_dtDestination=DT_PLAYERSPOTTED;
m_vPlayerSpotted = PlayerDestinationPos();
}
virtual void AdjustDifficulty(void)
{
FLOAT fMoveSpeed = GetSP()->sp_fEnemyMovementSpeed;
FLOAT fAttackSpeed = GetSP()->sp_fEnemyMovementSpeed;
// m_fDiveWalkSpeed *= fMoveSpeed;
// m_aDiveWalkRotateSpeed *= fMoveSpeed;
m_fDiveAttackRunSpeed *= fMoveSpeed;
m_aDiveAttackRotateSpeed *= fMoveSpeed;
m_fDiveCloseRunSpeed *= fMoveSpeed;
m_aDiveCloseRotateSpeed *= fMoveSpeed;
m_fDiveAttackFireTime *= 1/fAttackSpeed;
m_fDiveCloseFireTime *= 1/fAttackSpeed;
m_fDiveLockOnEnemyTime *= 1/fAttackSpeed;
CEnemyBase::AdjustDifficulty();
}
// close attack if possible
virtual BOOL CanHitEnemy(CEntity *penTarget, FLOAT fCosAngle) {
if (IsInPlaneFrustum(penTarget, fCosAngle)) {
return IsVisibleCheckAll(penTarget);
}
return FALSE;
};
/************************************************************
* POST MOVING *
************************************************************/
void PostMoving(void) {
CEnemyBase::PostMoving();
// change to liquid
if (m_EedtType!=EDT_GROUND_ONLY && !m_bInLiquid && en_fImmersionFactor>0.9f &&
(GetWorld()->wo_actContentTypes[en_iDnContent].ct_ulFlags&CTF_SWIMABLE)) {
m_bInLiquid = TRUE;
ChangeCollisionToLiquid();
SendEvent(ERestartAttack());
}
// change to ground
if (m_EedtType!=EDT_DIVE_ONLY && m_bInLiquid && (en_fImmersionFactor<0.5f || en_fImmersionFactor==1.0f) &&
en_penReference!=NULL && !(GetWorld()->wo_actContentTypes[en_iUpContent].ct_ulFlags&CTF_SWIMABLE)) {
m_bInLiquid = FALSE;
ChangeCollisionToGround();
SendEvent(ERestartAttack());
}
};
/************************************************************
* MOVING FUNCTIONS *
************************************************************/
// set desired rotation and translation to go/orient towards desired position
// and get the resulting movement type
virtual ULONG SetDesiredMovement(void)
{
// if not in air
if (!m_bInLiquid) {
// use base class
return CEnemyBase::SetDesiredMovement();
}
// get base rotation from base class
ULONG ulFlags = CEnemyBase::SetDesiredMovement();
// if we may move
if (m_fMoveSpeed>0.0f) {
// fix translation for 3d movement
FLOAT3D vTranslation = (m_vDesiredPosition - GetPlacement().pl_PositionVector) * !en_mRotation;
vTranslation(1) = 0.0f;
if (vTranslation(3)>0) {
vTranslation(3) = 0.0f;
}
vTranslation.Normalize();
vTranslation *= m_fMoveSpeed;
SetDesiredTranslation(vTranslation);
}
return ulFlags;
}
// check whether may move while attacking
BOOL MayMoveToAttack(void)
{
return WouldNotLeaveAttackRadius();
}
/************************************************************
* CLASS SUPPORT FUNCTIONS *
************************************************************/
// set entity position
void SetEntityPosition() {
switch (m_EedtType) {
case EDT_GROUND_ONLY: // can't dive
m_bInLiquid = FALSE;
break;
case EDT_DIVE_ONLY: // always dive can't walk
m_bInLiquid = TRUE;
break;
case EDT_GROUND_DIVE: // dive and walk
break;
}
// in liquid
if (m_bInLiquid) {
ChangeCollisionToLiquid();
} else {
ChangeCollisionToGround();
}
StandingAnim();
};
/************************************************************
* VIRTUAL FUNCTIONS THAT NEED OVERRIDE *
************************************************************/
virtual void ChangeCollisionToLiquid(void) {}
virtual void ChangeCollisionToGround(void) {}
procedures:
/************************************************************
* PROCEDURES WHEN NO ANY SPECIAL ACTION *
************************************************************/
/************************************************************
* ATTACK ENEMY PROCEDURES *
************************************************************/
// this is called to hit the player when near
Hit(EVoid) : CEnemyBase::Hit
{
if (m_bInLiquid) {
jump DiveHit();
} else {
jump GroundHit();
}
}
// this is called to shoot at player when far away or otherwise unreachable
Fire(EVoid) : CEnemyBase::Fire
{
if (m_bInLiquid) {
jump DiveFire();
} else {
jump GroundFire();
}
}
/************************************************************
* M A I N L O O P *
************************************************************/
// main loop
MainLoop(EVoid) : CEnemyBase::MainLoop {
SetEntityPosition();
jump CEnemyBase::MainLoop();
};
// dummy main
Main(EVoid) {
return;
};
/************************************************************
* VIRTUAL PROCEDURES THAT NEED OVERRIDE *
************************************************************/
// this is called to hit the player when near and you are on ground
GroundHit(EVoid)
{
return EReturn();
}
// this is called to shoot at player when far away or otherwise unreachable and you are on ground
GroundFire(EVoid)
{
return EReturn();
}
// this is called to hit the player when near and you are in water
DiveHit(EVoid)
{
return EReturn();
}
// this is called to shoot at player when far away or otherwise unreachable and you are in water
DiveFire(EVoid)
{
return EReturn();
}
};