Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
541 lines (391 sloc) 12.9 KB
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of Penumbra Overture.
*
* Penumbra Overture is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Penumbra Overture 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 Penumbra Overture. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GAME_GAME_ENEMY_H
#define GAME_GAME_ENEMY_H
#include "StdAfx.h"
#include "GameEntity.h"
#include "CharacterMove.h"
using namespace hpl;
class cGameTrigger;
class cCharacterMove;
class iGameEntity;
//-----------------------------------------
#define STATE_IDLE 0
#define STATE_HUNT 1
#define STATE_ATTACK 2
#define STATE_FLEE 3
#define STATE_KNOCKDOWN 4
#define STATE_DEAD 5
#define STATE_PATROL 6
#define STATE_INVESTIGATE 7
#define STATE_BREAKDOOR 8
#define STATE_CALLBACKUP 9
#define STATE_MOVETO 10
#define STATE_EAT 11
#define STATE_ATTENTION 12
#define STATE_NUM 13
//-----------------------------------------
enum eEnemyMoveState
{
eEnemyMoveState_Backward,
eEnemyMoveState_Stopped,
eEnemyMoveState_Walking,
eEnemyMoveState_Running,
eEnemyMoveState_LastEnum
};
//-----------------------------------------
class cEnemyPatrolNode : public iSerializable
{
kSerializableClassInit(cEnemyPatrolNode)
public:
cEnemyPatrolNode(){}
cEnemyPatrolNode(const tString &asNode, float afTime, const tString& asAnim) :
msNodeName(asNode), mfWaitTime(afTime), msAnimation(asAnim){}
tString msNodeName;
float mfWaitTime;
tString msAnimation;
};
//-----------------------------------------
class cLineOfSightRayCallback : public iPhysicsRayCallback
{
public:
void Reset();
bool OnIntersect(iPhysicsBody *pBody,cPhysicsRayParams *apParams);
bool Intersected();
private:
bool mbIntersected;
iPhysicsBody *mpGrabBody;
};
//------------------------------------------
class cEnemyFindGround : public iPhysicsRayCallback
{
public:
bool GetGround( const cVector3f &avStartPos,const cVector3f &avDir,
cVector3f *apDestPosition, cVector3f *apDestNormal,
float afMaxDistance=10);
bool OnIntersect(iPhysicsBody *pBody,cPhysicsRayParams *apParams);
private:
bool mbIntersected;
float mfMinDist;
cVector3f mvPos;
cVector3f mvNormal;
float mfMaxDistance;
};
//------------------------------------------
class cEnemyCheckForDoor : public iPhysicsRayCallback
{
public:
bool CheckDoor(const cVector3f &avStart, const cVector3f &avEnd);
bool BeforeIntersect(iPhysicsBody *pBody);
bool OnIntersect(iPhysicsBody *pBody,cPhysicsRayParams *apParams);
private:
bool mbIntersected;
};
//------------------------------------------
class iGameEnemy_SaveData : public iGameEntity_SaveData
{
kSerializableClassInit(iGameEnemy_SaveData);
public:
bool mbHasBeenActivated;
cVector3f mvCharBodyPosition;
cVector3f mvCharBodyRotation;
int mlCurrentPatrolNode;
float mfDisappearTime;
bool mbDisappearActive;
bool mbHasDisappeared;
bool mbUsesTriggers;
cVector3f mvLastPlayerPos;
tString msOnDeathCallback;
tString msOnAttackCallback;
cContainerVec<cEnemyPatrolNode> mvPatrolNodes;
iGameEntity* CreateEntity();
};
//-----------------------------------------
class iGameEnemyState
{
public:
iGameEnemyState(int alId, cInit *apInit, iGameEnemy *apEnemy);
virtual void OnEnterState(iGameEnemyState *apPrevState)=0;
virtual void OnLeaveState(iGameEnemyState *apNextState)=0;
virtual void OnUpdate(float afTimeStep)=0;
virtual void OnDraw()=0;
virtual void OnPostSceneDraw()=0;
virtual void OnSeePlayer(const cVector3f &avPosition, float afChance)=0;
virtual bool OnHearNoise(const cVector3f &avPosition, float afVolume)=0;
virtual void OnTakeHit(float afDamage)=0;
virtual void OnDeath(float afDamage)=0;
virtual void OnAnimationOver(const tString& asAnimName)=0;
virtual void OnFlashlight(const cVector3f &avPosition)=0;
void SetPreviousState(int alX){ mlPreviousState = alX;}
int GetPreviousState(){ return mlPreviousState;}
int GetId(){ return mlId;}
protected:
int mlId;
cInit *mpInit;
cPlayer *mpPlayer;
iGameEnemy *mpEnemy;
cCharacterMove *mpMover;
int mlPreviousState;
};
//-----------------------------------------
class iGameEnemy : public iGameEntity
{
#ifdef __GNUC__
typedef iGameEntity __super;
#endif
friend class cEntityLoader_GameEnemy;
public:
iGameEnemy(cInit *apInit,const tString& asName,TiXmlElement *apGameElem);
virtual ~iGameEnemy(void);
//Special
void LoadBaseProperties(TiXmlElement *apGameElem);
//Actions
void OnPlayerInteract();
void OnPlayerPick();
void Setup(cWorld3D *apWorld);
void OnWorldLoad();
void OnPostLoadScripts();
void OnWorldExit();
void OnDraw();
void OnPostSceneDraw();
virtual void ExtraPostSceneDraw(){}
void Update(float afTimeStep);
bool IsLoading(){ return mbLoading;}
void OnDamage(float afX);
void OnDeath(float afX);
void OnFlashlight(const cVector3f &avPos);
virtual void OnSetActive(bool abX);
virtual bool MoveToPos(const cVector3f& avFeetPos)=0;
virtual void ShowPlayer(const cVector3f& avPlayerFeetPos){}
virtual bool IsFighting(){ return false;}
//Physics
void SetupBody();
//Properties
cVector3f GetPosition();
void SetFOV(float afAngle){ mfFOV = afAngle;}
const tString& GetHitPS(){ return msHitPS;}
const tString& GetEnemyType(){ return msEnemyType;}
const tString& GetCloseMusic(){ return msCloseMusic;}
int GetCloseMusicPrio(){ return mlCloseMusicPrio;}
float GetCloseMusicStartDist(){ return mfCloseMusicStartDist;}
float GetCloseMusicStopDist(){ return mfCloseMusicStopDist;}
const tString& GetAttackMusic(){ return msAttackMusic;}
int GetAttackMusicPrio(){ return mlAttackMusicPrio;}
//States
void AddState(iGameEnemyState *apState);
void ChangeState(int alId);
iGameEnemyState *GetState(int alId);
int GetCurrentStateId(){ return mlCurrentState;}
//Triggers
bool HandleTrigger(cGameTrigger *apTrigger);
eGameTriggerType GetTriggerTypes(){ return mTriggerTypes;}
float GetTriggerUpdateCount() { return mfTriggerUpdateCount;}
void SetTriggerUpdateCount(float afX) { mfTriggerUpdateCount = afX; }
float GetTriggerUpdateRate() { return mfTriggerUpdateRate;}
void SetSkipSoundTriggerCount(float afX){ mfSkipSoundTriggerCount = afX;}
//Content control
void PlayAnim( const tString &asName, bool abLoop, float afFadeTime,
bool abDependsOnSpeed=false, float afSpeedMul=1.0f,
bool abSyncWithPrevFrame=false,
bool abOverideMoveState=true);
void UseMoveStateAnimations();
cAnimationState* GetCurrentAnimation(){ return mpCurrentAnimation;}
void PlaySound(const tString &asName);
//Callabcks
void SetOnDeathCallback(const tString &asFunc){ msOnDeathCallback = asFunc;}
void SetOnAttackCallback(const tString &asFunc){ msOnAttackCallback = asFunc;}
tString GetOnAttackCallback(){ return msOnAttackCallback;}
//AI
bool CanSeePlayer();
cCharacterMove* GetMover(){ return mpMover;}
cVector3f GetLastPlayerPos(){ return mvLastPlayerPos;}
void SetLastPlayerPos(const cVector3f &avPos){ mvLastPlayerPos = avPos;}
void SetTempPosition(const cVector3f &avPos) {mvTempPosition = avPos;}
cVector3f GetTempPosition() { return mvTempPosition;}
void SetTempFloat(float afX) {mfTempFloat = afX;}
float GetTempFloat() { return mfTempFloat;}
cEnemyFindGround* GetGroundFinder(){ return &mFindGround;}
cEnemyCheckForDoor* GetDoorChecker() { return &mDoorCheck;}
bool CheckForDoor();
bool CheckForTeamMate(float afMaxDist, bool abCheckIfFighting);
bool IsAttracted(){ return mbIsAttracted;}
void SetAttracted(bool abX){ mbIsAttracted = abX;}
bool GetUsesTriggers(){ return mbUsesTriggers;}
void SetUsesTriggers(bool abX){ mbUsesTriggers = abX;}
//Patrolling
void AddPatrolNode(const tString& asNode, float afTime, const tString& asAnimation);
cEnemyPatrolNode* GetPatrolNode(int alIdx){return &mvPatrolNodes[alIdx];}
int GetPatrolNodeNum(){ return (int)mvPatrolNodes.size();}
cEnemyPatrolNode* CurrentPatrolNode(){return &mvPatrolNodes[mlCurrentPatrolNode];}
void ClearPatrolNodes();
int GetCurrentPatrolNode(){ return mlCurrentPatrolNode;}
float GetWaitTime(){ return mfWaitTime;}
float GetWaitTimeCount(){ return mfWaitTimeCount;}
void SetCurrentPatrolNode(int alX){ mlCurrentPatrolNode = alX;}
void IncCurrentPatrolNode()
{
mlCurrentPatrolNode++;
if(mlCurrentPatrolNode >= (int)mvPatrolNodes.size())
mlCurrentPatrolNode =0;
}
void SetWaitTime(float afX){ mfWaitTime = afX;}
void SetWaitTimeCount(float afX){ mfWaitTimeCount = afX;}
void AddWaitTimeCount(float afX){ mfWaitTimeCount += afX;}
float GetDoorBreakCount(){ return mfDoorBreakCount;}
void SetDoorBreakCount(float afX){ mfDoorBreakCount =afX;}
void AddDoorBreakCount(float afX){ mfDoorBreakCount +=afX;}
const cVector3f& GetModelOffsetAngles(){ return mvModelOffsetAngles;}
//Virtual
virtual void OnUpdate(float afTimeStep)=0;
virtual void OnLoad()=0;
//SaveObject implementation
iGameEntity_SaveData* CreateSaveData();
void SaveToSaveData(iGameEntity_SaveData *apSaveData);
void LoadFromSaveData(iGameEntity_SaveData *apSaveData);
protected:
void UpdateEnemyPose(float afTimeStep);
void UpdateAnimations(float afTimeStep);
void UpdateCheckForPlayer(float afTimeStep);
bool HandleSoundTrigger(cGameTrigger *apTrigger);
bool LineOfSight(const cVector3f &avPos, const cVector3f &avSize);
bool mbSetFeetAtGroundOnStart;
bool mbAttachMeshToBody;
bool mbRemoveAttackerOnDisable;
tVector3fVec mvRayStartPoses;
tVector3fVec mvRayEndPoses;
cEnemyFindGround mFindGround;
eGameTriggerType mTriggerTypes;
cCharacterMove *mpMover;
tString msEnemyType;
float mfTriggerUpdateCount;
float mfTriggerUpdateRate;
float mfSkipSoundTriggerCount;
cAStarHandler* mpAStarAir;
cAStarHandler* mpAStarGround;
cAINodeContainer* mpNodeContainerAir;
cAINodeContainer* mpNodeContainerGround;
cLineOfSightRayCallback mRayCallback;
std::vector<iGameEnemyState*> mvStates;
int mlCurrentState;
cEnemyCheckForDoor mDoorCheck;
cAnimationState *mpCurrentAnimation;
bool mbAnimationIsSpeedDependant;
float mfAnimationSpeedMul;
bool mbOverideMoveState;
eEnemyMoveState mMoveState;
cVector3f mvTempPosition;
float mfTempFloat;
tStringVec mvPreloadSounds;
bool mbLoading;
bool mbAlignToGroundNormal;
cMatrixf m_mtxStartPose;
cMatrixf m_mtxGoalPose;
float mfPoseCount;
bool mbHasBeenActivated;
bool mbUsesTriggers;
///////////////////////////////
//Variable Properties
cVector3f mvLastPlayerPos;
float mfCanSeePlayerCount;
float mfCheckForPlayerCount;
float mfCheckForPlayerRate;
bool mbCanSeePlayer;
int mlPlayerInLOSCount;
int mlMaxPlayerInLOSCount;
float mfCalcPlayerHiddenPosCount;
float mfDamageSoundTimer;
tString msOnDeathCallback;
tString msOnAttackCallback;
std::vector<cEnemyPatrolNode> mvPatrolNodes;
int mlCurrentPatrolNode;
float mfWaitTime;
float mfWaitTimeCount;
float mfDoorBreakCount;
bool mbIsAttracted;
/////////////////////////////////
//Properties to be implemented
bool mbDisappear;
float mfDisappearMinTime;
float mfDisappearMaxTime;
float mfDisappearMinDistance;
tString msDisappearPS;
tString msDisappearSound;
bool mbDisappearFreezesRagdoll;
float mfDisappearTime;
bool mbDisappearActive;
bool mbHasDisappeared;
tString msCloseMusic;
int mlCloseMusicPrio;
float mfCloseMusicStartDist;
float mfCloseMusicStopDist;
tString msAttackMusic;
int mlAttackMusicPrio;
bool mbShowDebug;
tString msGroundNodeType;
cVector3f mvBodySize;
float mfBodyMass;
float mfMaxForwardSpeed;
float mfMaxBackwardSpeed;
float mfAcceleration;
float mfDeacceleration;
float mfMaxTurnSpeed;
float mfAngleDistTurnMul;
float mfMinBreakAngle;
float mfBreakAngleMul;
float mfSpeedMoveAnimMul;
float mfTurnSpeedMoveAnimMul;
cMatrixf m_mtxModelOffset;
cVector3f mvModelOffsetAngles;
float mfIdleToMoveLimit;
float mfMoveToLideLimit;
float mfMaxPushMass;
float mfPushForce;
float mfMaxSeeDist;
float mfMinAttackDist;
float mfFOV;
float mfFOVXMul;
float mfMaxHealth;
float mfStoppedToWalkSpeed;
float mfWalkToStoppedSpeed;
float mfWalkToRunSpeed;
float mfRunToWalkSpeed;
float mfMoveAnimSpeedMul;
tString msBackwardAnim;
tString msStoppedAnim;
tString msWalkAnim;
tString msRunAnim;
float mfMinStunSpeed;
float mfMinStunImpulse;
float mfObjectCollideStun;
float mfStunDamageMul;
tString msHitPS;
};
//--------------------------------------
class cEntityLoader_GameEnemy : public cEntityLoader_Object
{
public:
cEntityLoader_GameEnemy(const tString &asName, cInit *apInit);
~cEntityLoader_GameEnemy();
private:
void BeforeLoad(TiXmlElement *apRootElem, const cMatrixf &a_mtxTransform,cWorld3D *apWorld);
void AfterLoad(TiXmlElement *apRootElem, const cMatrixf &a_mtxTransform,cWorld3D *apWorld);
cInit *mpInit;
};
//--------------------------------------
#endif // GAME_GAME_ENEMY_H