📄 ai_shared.cpp
字号:
// ----------------------------------------------------------------------- //
//
// MODULE : AI_Shared.cpp
//
// PURPOSE : AI shared functions
//
// CREATED :
//
// ----------------------------------------------------------------------- //
#include <stdio.h>
#include "cpp_server_de.h"
//#include "Destructable.h"
#include "BaseCharacter.h"
#include "generic_msg_de.h"
#include "AI_Shared.h"
#include "ObjectUtilities.h"
#include "SoundTypes.h"
#include "PathPoint.h"
#include "gib.h"
#include <mbstring.h>
#define MAX_DISTANCE 100000.0f
void BPrint(char*);
// *************************************************************************
// *************************************************************************
// *************************************************************************
//
// Shared Functions
// All these functions are generic... they could be used by any game system
//
// *************************************************************************
// *************************************************************************
// *************************************************************************
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::AI_Shared()
//
// PURPOSE: Constructor - Initialize
//
// ----------------------------------------------------------------------- //
AI_Shared::AI_Shared()
{
m_bTurnR = DFALSE;
m_bTurnL = DFALSE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::GetEyeLevel()
//
// PURPOSE: Compute our 'eye level'
//
// ----------------------------------------------------------------------- //
DVector AI_Shared::GetEyeLevel(HOBJECT m_hObject)
{
DVector vPos, vDims;
VEC_INIT(vPos);
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject) return vPos;
pServerDE->GetObjectDims(m_hObject, &vDims);
pServerDE->GetObjectPos(m_hObject, &vPos);
vPos.y += vDims.y / 2.0f;
// vPos.y -= m_fEyeLevelOffset;
vPos.y -= 1;
return vPos;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::DistToWorld()
//
// PURPOSE: How far away is the closes object
//
// ----------------------------------------------------------------------- //
DFLOAT AI_Shared::DistToWorld(HOBJECT m_hObject, DVector vDir)
{
DVector vPos = GetEyeLevel(m_hObject);
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject) return MAX_DISTANCE;
IntersectQuery IQuery;
IntersectInfo IInfo;
VEC_COPY(IQuery.m_From, vPos);
VEC_COPY(IQuery.m_Direction, vDir);
IQuery.m_Flags = INTERSECT_OBJECTS;
IQuery.m_FilterFn = DNULL;
if (pServerDE->CastRay(&IQuery, &IInfo))
{
return VEC_DIST(vPos, IInfo.m_Point);
}
return MAX_DISTANCE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::TurnToClear()
//
// PURPOSE: To to clearest direction for traveling
//
// ----------------------------------------------------------------------- //
DBOOL AI_Shared::TurnToClear(HOBJECT hObject)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !hObject) return DFALSE;
DRotation rRot;
DVector m_vUp, m_vRight, m_vForward, vPos;
pServerDE->GetObjectRotation(hObject, &rRot);
pServerDE->GetRotationVectors(&rRot, &m_vUp, &m_vRight, &m_vForward);
pServerDE->GetObjectPos(hObject,&vPos);
IntersectQuery IQuery;
IntersectInfo IInfo;
IQuery.m_Flags = INTERSECT_OBJECTS;
IQuery.m_FilterFn = DNULL;
VEC_COPY(IQuery.m_From, vPos);
//FORWARD
VEC_COPY(IQuery.m_Direction, m_vForward);
pServerDE->CastRay(&IQuery, &IInfo);
DFLOAT fForward = VEC_DIST(vPos, IInfo.m_Point);
//RIGHT
VEC_COPY(IQuery.m_Direction, m_vRight);
pServerDE->CastRay(&IQuery, &IInfo);
DFLOAT fRight = VEC_DIST(vPos, IInfo.m_Point);
//LEFT
VEC_MULSCALAR(m_vRight,m_vRight,-1);
VEC_COPY(IQuery.m_Direction, m_vRight);
pServerDE->CastRay(&IQuery, &IInfo);
DFLOAT fLeft = VEC_DIST(vPos, IInfo.m_Point);
//Check which way we need to go
if(fForward > fRight && fForward > fLeft)
return DFALSE;
else if(fRight > fForward && fRight > fLeft)
{
pServerDE->EulerRotateY(&rRot, MATH_PI/10 * -1);
pServerDE->SetObjectRotation(hObject, &rRot);
}
else if(fLeft > fForward && fLeft > fRight)
{
pServerDE->EulerRotateY(&rRot, MATH_PI/10);
pServerDE->SetObjectRotation(hObject, &rRot);
}
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::IsLedge()
//
// PURPOSE: Check a ledge in front of you
//
// ----------------------------------------------------------------------- //
DBOOL AI_Shared::IsLedge(HOBJECT m_hObject, DFLOAT m_fDist)
{
DVector vPos, vTemp, vDir, vDims;
VEC_INIT(vPos);
VEC_INIT(vDir);
VEC_INIT(vTemp);
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject) return DFALSE;
DRotation rRot;
DVector m_vUp, m_vRight, m_vForward;
VEC_INIT(m_vUp);
VEC_INIT(m_vRight);
VEC_INIT(m_vForward);
pServerDE->GetObjectRotation(m_hObject, &rRot);
pServerDE->GetRotationVectors(&rRot, &m_vUp, &m_vRight, &m_vForward);
// m_fDist = 50;
DFLOAT m_fStepHeight = 25;
pServerDE->GetObjectDims(m_hObject, &vDims);
pServerDE->GetObjectPos(m_hObject, &vPos);
VEC_MULSCALAR(vTemp, m_vForward, m_fDist);
VEC_ADD(vPos, vPos, vTemp);
// vPos is a point in front of you.
// vDir is a point in front of you, but down
VEC_COPY(vDir, vPos);
vDir.y = (vDir.y - vDims.y) - m_fStepHeight;
IntersectQuery IQuery;
IntersectInfo IInfo;
VEC_COPY(IQuery.m_From, vPos);
VEC_COPY(IQuery.m_To, vDir);
IQuery.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID;
IQuery.m_FilterFn = NULL;
IQuery.m_pUserData = NULL;
if (pServerDE->IntersectSegment(&IQuery, &IInfo))
{
return DFALSE;
}
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::DistToWorldForward()
//
// PURPOSE: How far away is the closes object straight ahead
//
// ----------------------------------------------------------------------- //
DFLOAT AI_Shared::DistToWorldForward(HOBJECT m_hObject)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject) return DFALSE;
DRotation rRot;
DVector m_vUp, m_vRight, m_vForward;
VEC_INIT(m_vUp);
VEC_INIT(m_vRight);
VEC_INIT(m_vForward);
pServerDE->GetObjectRotation(m_hObject, &rRot);
pServerDE->GetRotationVectors(&rRot, &m_vUp, &m_vRight, &m_vForward);
return DistToWorld(m_hObject, m_vForward);
}
// ----------------------------------------------------------------------- //
// ROUTINE : AI_Shared::DistToWorldBackward
// DESCRIPTION :
// RETURN TYPE : DFLOAT
// PARAMS : HOBJECT m_hObject
// ----------------------------------------------------------------------- //
DFLOAT AI_Shared::DistToWorldBackward(HOBJECT m_hObject)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject) return DFALSE;
DRotation rRot;
DVector m_vUp, m_vRight, m_vForward;
VEC_INIT(m_vUp);
VEC_INIT(m_vRight);
VEC_INIT(m_vForward);
pServerDE->GetObjectRotation(m_hObject, &rRot);
pServerDE->GetRotationVectors(&rRot, &m_vUp, &m_vRight, &m_vForward);
DVector vDir;
VEC_COPY(vDir, m_vForward);
VEC_MULSCALAR(vDir, vDir, -1.0f); // point left
return DistToWorld(m_hObject, vDir);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::DistToWorldRight()
//
// PURPOSE: How far away is the closest object to our right
//
// ----------------------------------------------------------------------- //
DFLOAT AI_Shared::DistToWorldRight(HOBJECT m_hObject)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject) return DFALSE;
DRotation rRot;
DVector m_vUp, m_vRight, m_vForward;
VEC_INIT(m_vUp);
VEC_INIT(m_vRight);
VEC_INIT(m_vForward);
pServerDE->GetObjectRotation(m_hObject, &rRot);
pServerDE->GetRotationVectors(&rRot, &m_vUp, &m_vRight, &m_vForward);
return DistToWorld(m_hObject, m_vRight);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::DistToWorldLeft()
//
// PURPOSE: How far away is the closest object to our left
//
// ----------------------------------------------------------------------- //
DFLOAT AI_Shared::DistToWorldLeft(HOBJECT m_hObject)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject) return DFALSE;
DRotation rRot;
DVector m_vUp, m_vRight, m_vForward;
VEC_INIT(m_vUp);
VEC_INIT(m_vRight);
VEC_INIT(m_vForward);
pServerDE->GetObjectRotation(m_hObject, &rRot);
pServerDE->GetRotationVectors(&rRot, &m_vUp, &m_vRight, &m_vForward);
DVector vDir;
VEC_COPY(vDir, m_vRight);
VEC_MULSCALAR(vDir, vDir, -1.0f); // point left
return DistToWorld(m_hObject, vDir);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::IsObjectVisible()
//
// PURPOSE: Is the test object visible
//
// ----------------------------------------------------------------------- //
DBOOL AI_Shared::IsObjectVisible(HOBJECT m_hObject, HOBJECT hTestObj)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject || !hTestObj) return DFALSE;
DVector vOurPos, vTheirPos;
DVector vPos = GetEyeLevel(m_hObject);
pServerDE->GetObjectPos(m_hObject, &vOurPos);
pServerDE->GetObjectPos(hTestObj, &vTheirPos);
DVector vDir;
VEC_SUB(vDir, vTheirPos, vOurPos);
IntersectQuery IQuery;
IntersectInfo IInfo;
VEC_COPY(IQuery.m_From, vPos);
VEC_COPY(IQuery.m_Direction, vDir);
IQuery.m_Flags = INTERSECT_OBJECTS;
IQuery.m_FilterFn = DNULL;
if (pServerDE->CastRay(&IQuery, &IInfo))
{
// BUGBUG: If the object is partially occluded it might fail this test!
if (IInfo.m_hObject == hTestObj)
{
return DTRUE;
}
}
return DFALSE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::IsObjectVisibleToAI()
//
// PURPOSE: Is the test object visible to us (forward + FoV)?
//
// ----------------------------------------------------------------------- //
DBOOL AI_Shared::IsObjectVisibleToAI(HOBJECT m_hObject, HOBJECT hTestObj, DFLOAT m_fSeeingDist)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject || !hTestObj) return DFALSE;
DVector vOurPos, vTheirPos;
// Get the Rotation
DRotation rRot;
DVector m_vUp, m_vRight, m_vForward;
VEC_INIT(m_vUp);
VEC_INIT(m_vRight);
VEC_INIT(m_vForward);
pServerDE->GetObjectRotation(m_hObject, &rRot);
pServerDE->GetRotationVectors(&rRot, &m_vUp, &m_vRight, &m_vForward);
if(IsObjectVisible(m_hObject, hTestObj))
{
pServerDE->GetObjectPos(m_hObject, &vOurPos);
pServerDE->GetObjectPos(hTestObj, &vTheirPos);
DVector vDir;
VEC_SUB(vDir, vTheirPos, vOurPos);
// Now test to see if AI is facing test object...
DFLOAT fDp;
fDp = (vDir.x * m_vForward.x) + (vDir.y * m_vForward.y) + (vDir.z * m_vForward.z);
if (fDp > 0)
{
// AI is facing test object so it can 'see' it
if (VEC_MAG(vDir) < m_fSeeingDist) return DTRUE;
}
}
return DFALSE;
}
// ----------------------------------------------------------------------- //
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -