📄 ai_shared.cpp
字号:
//
// ROUTINE: AI_Shared::ListenForEnemy()
//
// PURPOSE: Look for sound objects... (will be created by Player shooting, open doors)
// sound object will remove itself after a few secs...
//
// Message from sound...
//
// ----------------------------------------------------------------------- //
//HOBJECTL AI_Shared::ListenForEnemy(HOBJECT m_hObject, DFLOAT fRange)
//{
//// Sound Messages... SOUND_NOTIFY???
// return DFALSE;
//}
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::SenseForEnemy()
//
// PURPOSE: Look for Player objects (radius)
//
// ----------------------------------------------------------------------- //
HOBJECT AI_Shared::SenseForEnemy(HOBJECT m_hObject, DFLOAT fRange)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject ) return DFALSE;
HCLASS hPlayerTest = pServerDE->GetClass("CPlayerObj");
HOBJECT hFoundObj = FindObjectInRadius(m_hObject, hPlayerTest, fRange, DFALSE, "", DTRUE);
if (hFoundObj != DNULL)
{
CBaseCharacter* pB = (CBaseCharacter*)pServerDE->HandleToObject(hFoundObj);
if( pB->IsDead() == DFALSE )
{
return hFoundObj;
}
}
return DNULL;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::SmellForEnemy()
//
// PURPOSE: Look for Player objects (radius)
//
// ----------------------------------------------------------------------- //
HOBJECT AI_Shared::SmellForEnemy(HOBJECT m_hObject, DFLOAT fRange)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject ) return DFALSE;
HCLASS hPlayerTest = pServerDE->GetClass("CPlayerObj");
HOBJECT hFoundObj = FindObjectInRadius(m_hObject, hPlayerTest, fRange, DTRUE, "", DTRUE);
if (hFoundObj != DNULL)
{
CBaseCharacter* pB = (CBaseCharacter*)pServerDE->HandleToObject(hFoundObj);
if( pB->IsDead() == DFALSE )
{
return hFoundObj;
}
}
return DNULL;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::LookForEnemy()
//
// PURPOSE: Look for Player objects (radius)
//
// ----------------------------------------------------------------------- //
HOBJECT AI_Shared::LookForEnemy(HOBJECT m_hObject, DFLOAT fRange)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject ) return DFALSE;
// 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);
HCLASS hPlayerTest = pServerDE->GetClass("CPlayerObj");
HOBJECT hFoundObj = FindObjectInRadius(m_hObject, hPlayerTest, fRange, DTRUE, "", DTRUE);
if (hFoundObj != DNULL)
{
DVector vOurPos, vTheirPos;
pServerDE->GetObjectPos(m_hObject, &vOurPos);
pServerDE->GetObjectPos(hFoundObj, &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
CBaseCharacter* pB = (CBaseCharacter*)pServerDE->HandleToObject(hFoundObj);
if( pB->IsDead() == DFALSE )
{
return hFoundObj;
}
// Already checked for range in the FindNearObjectInRadius...
//if (VEC_MAG(vDir) < fRange) return DTRUE;
}
}
return DNULL;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::FindNearObjectInRadius()
//
// RETURN: return the Ideal Object we are looking for, DNULL of nothing found
//
// PURPOSE: Look for nearest object within radius (visible or Not)
//
// ----------------------------------------------------------------------- //
HOBJECT AI_Shared::FindObjectInRadius(HOBJECT m_hObject, HCLASS hObjectTest, DFLOAT fRange, DBOOL bCheckVisible, char* sObjName, DBOOL bNear)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject ) return DNULL;
DFLOAT fObjDist, fSaveDist = 0;
DFLOAT fObjTime, fSaveTime = 0;
HOBJECT hIdealObj = DNULL;
DBOOL bVisible = DFALSE;
// Get AI's current Position
DVector vPos;
// pServerDE->GetObjectPos(m_hObject, &vPos);
DRotation rRot;
pServerDE->GetModelNodeTransform(m_hObject,szNodes[NODE_NECK-1],&vPos,&rRot);
// Create a List of objects within the Radius
ObjectList* pTargets = pServerDE->FindObjectsTouchingSphere(&vPos, fRange);
if (!pTargets || pTargets->m_nInList <= 0) return DNULL;
// Found all the Objects
ObjectLink *pLink = pTargets->m_pFirstLink;
while(pLink && pLink->m_hObject)
{
HCLASS hType = pServerDE->GetObjectClass(pLink->m_hObject);
char sTestObjectName[128];
if (_mbstrlen(sObjName) == 0)
{
_mbscpy((unsigned char*)sTestObjectName, (const unsigned char*)pServerDE->GetObjectName(pLink->m_hObject));
}
else
{
_mbscpy((unsigned char*)sTestObjectName, (const unsigned char*)sObjName);
}
// Did we find one?
if( (pServerDE->IsKindOf(hType, hObjectTest)) &&
(_mbsncmp((const unsigned char*)pServerDE->GetObjectName(pLink->m_hObject), (const unsigned char*)sTestObjectName, _mbstrlen(sTestObjectName)) == 0 ) )
{
// Check for nearest Object!
DVector vTheirPos;
pServerDE->GetObjectPos(pLink->m_hObject, &vTheirPos);
bVisible = DFALSE;
if (bCheckVisible)
{
// Cast a ray for each sholder (left and right side of dims)
IntersectQuery IQuery;
IntersectInfo IInfo;
VEC_COPY(IQuery.m_From, vPos);
VEC_COPY(IQuery.m_To, vTheirPos);
IQuery.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID;
// IQuery.m_Flags = INTERSECT_OBJECTS;
IQuery.m_FilterFn = NULL;
IQuery.m_pUserData = NULL;
if (pServerDE->IntersectSegment(&IQuery, &IInfo))
{
// BUGBUG: If the object is partially occluded it might fail this test!
if (IInfo.m_hObject == pLink->m_hObject)
{
bVisible = DTRUE;
}
}
else
{
// Line of sight to the object is clear...
bVisible = DTRUE;
}
// If only looking for Visible objects and We found one NOT visible Break to next one.
if (bVisible == DFALSE)
{
break;
}
}
fObjDist = VEC_DIST(vPos, vTheirPos);
// Smell Path Points
if ( _mbsncmp((const unsigned char*)pServerDE->GetObjectName(pLink->m_hObject), (const unsigned char*)"SMELL", _mbstrlen("SMELL") ) == 0 )
{
PathPoint *pSmell = (PathPoint*)pServerDE->HandleToObject(pLink->m_hObject);
fObjTime = pSmell->m_fStartTime;
if (fSaveTime == 0)
{
fSaveTime = fObjTime;
hIdealObj = pLink->m_hObject;
}
else
{
if (fObjTime > fSaveTime)
{
fSaveTime = fObjTime;
hIdealObj = pLink->m_hObject;
}
}
}
else
{
// NON Smell Objects
if (fSaveDist == 0)
{
fSaveDist = fObjDist;
hIdealObj = pLink->m_hObject;
}
else
{
// check to see if we are the nearest or NOT
if (bNear)
{
if (fObjDist < fSaveDist)
{
fSaveDist = fObjDist;
hIdealObj = pLink->m_hObject;
}
}
else
{
// check for far
if (fObjDist > fSaveDist)
{
fSaveDist = fObjDist;
hIdealObj = pLink->m_hObject;
}
}
}
}
}
// Next object
pLink = pLink->m_pNext;
}
// clean up
pServerDE->RelinquishList(pTargets);
// return the closest object found (DNULL of nothing found)
return hIdealObj;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::
//
// PURPOSE:
//
// ----------------------------------------------------------------------- //
DBOOL AI_Shared::CheckForProjectile(HOBJECT m_hObject)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject ) return DNULL;
HOBJECT hFoundObj = DNULL;
// Get AI's current Position
DVector vPos;
pServerDE->GetObjectPos(m_hObject, &vPos);
// Create a List of objects within the Radius
ObjectList* pTargets = pServerDE->FindObjectsTouchingSphere(&vPos, 250);
if (!pTargets || pTargets->m_nInList <= 0) return DNULL;
// Found all the Objects
ObjectLink *pLink = pTargets->m_pFirstLink;
while(pLink && pLink->m_hObject)
{
HCLASS hType = pServerDE->GetObjectClass(pLink->m_hObject);
if(pServerDE->IsKindOf(hType, pServerDE->GetClass("CGrenade")))
{
hFoundObj = pLink->m_hObject;
break;
}
// else if(pServerDE->IsKindOf(hType, pServerDE->GetClass("CMissileProjectile")))
// {
// hFoundObj = pLink->m_hObject;
// break;
// }
// else if(pServerDE->IsKindOf(hType, pServerDE->GetClass("CPulseProjectile")))
// {
// hFoundObj = pLink->m_hObject;
// break;
// }
// else if(pServerDE->IsKindOf(hType, pServerDE->GetClass("CEnergyProjectile")))
// {
// hFoundObj = pLink->m_hObject;
// break;
// }
// else if(pServerDE->IsKindOf(hType, pServerDE->GetClass("CFlareProjectile")))
// {
// hFoundObj = pLink->m_hObject;
// break;
// }
// else if(pServerDE->IsKindOf(hType, pServerDE->GetClass("CDeadlyDiscProj")))
// {
// hFoundObj = pLink->m_hObject;
// break;
// }
// Next object
pLink = pLink->m_pNext;
}
// clean up
pServerDE->RelinquishList(pTargets);
if (hFoundObj)
{
return DTRUE;
}
return DFALSE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::
//
// PURPOSE:
//
// ----------------------------------------------------------------------- //
void AI_Shared::FacePosition(HOBJECT m_hObject, DVector vTargetPos)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject) return;
DVector vDir, vPos;
// Our current position
pServerDE->GetObjectPos(m_hObject, &vPos);
VEC_SUB(vDir, vTargetPos, vPos);
VEC_NORM(vDir);
DRotation rRot;
ROT_INIT(rRot);
pServerDE->GetObjectRotation(m_hObject, &rRot);
// m_Angles.y = ATan2(vDir.x, vDir.z);
DFLOAT fAmount = (DFLOAT) atan2(vDir.x, vDir.z);
DVector vU, vR, vF;
pServerDE->GetRotationVectors(&rRot, &vU, &vR, &vF);
DFLOAT fAmount2 = (DFLOAT) atan2(vF.x, vF.z);
pServerDE->EulerRotateY(&rRot, fAmount2 - fAmount);
pServerDE->SetObjectRotation(m_hObject, &rRot);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: AI_Shared::
//
// PURPOSE:
// Aim Up/down
//
// ----------------------------------------------------------------------- //
DFLOAT AI_Shared::PitchToObject(HOBJECT m_hObject, HOBJECT hPTarget)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject || !hPTarget) return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -