mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-12-27 07:54:51 +01:00
266 lines
8.5 KiB
C++
266 lines
8.5 KiB
C++
/* Copyright (c) 2002-2012 Croteam Ltd.
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of version 2 of the GNU General Public License as published by
|
|
the Free Software Foundation
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
|
|
|
313
|
|
%{
|
|
#include "StdH.h"
|
|
%}
|
|
|
|
uses "EntitiesMP/EnemyBase";
|
|
uses "EntitiesMP/Debris";
|
|
uses "EntitiesMP/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();
|
|
}
|
|
};
|