void Prophet::AI_STATE_AttackFar() { DFLOAT fHeight = (DFLOAT)fabs(m_vTargetPos.y - m_MoveObj.GetPos().y); //SCHLEGZ 4/22/98 4:51:21 PM: sanity check if(m_hTarget == DNULL) { if(fHeight <= m_vDims.y) SetNewState(STATE_SearchVisualTarget); else ComputeState(); return; } m_fStimuli[SIGHT] = VEC_DIST(m_MoveObj.GetPos(),m_vTargetPos); DBOOL bAbove = (m_vTargetPos.y - m_MoveObj.GetPos().y) > 0; switch(Metacmd) { case 1: MC_FaceTarget(); break; case 2: MC_BestWeapon(); break; case 3: if(m_fStimuli[SIGHT] <= (m_fSeeingDist * 0.75) || m_nCurMetacmd == MC_FIRE_STAND || m_nCurMetacmd == MC_FIRE_CROUCH || fHeight > m_vDims.y) { if((fHeight > m_vDims.y && !bAbove) || m_nCurMetacmd == MC_FIRE_CROUCH || m_fStimuli[HEALTH] < 0.5f) { MC_Fire_Crouch(); } else { MC_Fire_Stand(); } } else Metacmd++; break; case 4: if(m_fStimuli[SIGHT] > (m_fSeeingDist * 0.75)) { MC_FaceTarget(); Metacmd--; if(!IsLedge(m_MoveObj.GetForwardVector()) && fHeight <= m_vDims.y && m_nCurMetacmd != MC_FIRE_CROUCH) { if(m_nInjuredLeg) MC_Walk(); else MC_Fire_Run(); } else { MC_Fire_Crouch(); } } else Metacmd++; break; case 5: ComputeState(); break; } return; }
void OpheliaAI::AI_STATE_AttackClose() { DFLOAT fHeight = (DFLOAT)fabs(m_vTargetPos.y - m_MoveObj.GetPos().y); //SCHLEGZ 4/22/98 4:51:21 PM: sanity check if(m_hTarget == DNULL && m_nCurMetacmd != MC_FIRE_STAND) { if(fHeight <= m_vDims.y) SetNewState(STATE_SearchVisualTarget); else ComputeState(); return; } m_fStimuli[SIGHT] = VEC_DIST(m_MoveObj.GetPos(),m_vTargetPos); DBOOL bAbove = (m_vTargetPos.y - m_MoveObj.GetPos().y) > 0; CWeapon* pW = m_InventoryMgr.GetCurrentWeapon(); if(pW == DNULL) { SetNewState(STATE_Idle); return; } switch(Metacmd) { case 1: MC_FaceTarget(); break; case 2: MC_BestWeapon(); break; case 3: if(m_fStimuli[SIGHT] <= (m_fSeeingDist * 0.33) || m_nCurMetacmd == MC_FIRE_STAND || m_nCurMetacmd == MC_FIRE_CROUCH) { if(m_nDodgeFlags & FORWARD || m_nDodgeFlags & BACKWARD || m_fStimuli[HEALTH] < 0.5f || m_nCurMetacmd == MC_FIRE_CROUCH || (fHeight > m_vDims.y && !bAbove) || pW->GetType() == WEAP_SNIPERRIFLE) { MC_Fire_Crouch(); } else { MC_Fire_Stand(); } } else Metacmd++; break; case 4: if(m_fStimuli[SIGHT] > (m_fSeeingDist * 0.33) && m_fStimuli[SIGHT] < (m_fSeeingDist * 0.5)) { MC_FaceTarget(); Metacmd--; if(!IsLedge(m_MoveObj.GetForwardVector()) && fHeight <= m_vDims.y && m_nCurMetacmd != MC_FIRE_CROUCH && pW->GetType() != WEAP_SNIPERRIFLE) { if(m_nInjuredLeg) MC_Walk(); else { if(m_nDodgeFlags & FORWARD || m_nDodgeFlags & BACKWARD || m_fStimuli[HEALTH] < 0.5f) MC_Fire_Crawl(); else MC_Fire_Run(); } } else { MC_Fire_Crouch(); } } else Metacmd++; break; case 5: ComputeState(); break; } return; }
int CDestructable::CalculateHitLimb(DVector vDir, DVector vPos, DFLOAT fDamage) { CServerDE* pServerDE = BaseClass::GetServerDE(); if (!pServerDE || !m_hObject || !m_pInventoryMgr || !m_pAnim_Sound) return -1; int nNode = -1; DFLOAT fNodeDist = 0.0f, fDist = 999.0f, fTemp = 0.0f; DVector vShot, vNewShot, vTemp, vObjDims, vNodePos, vZ; DFLOAT fX, fY, ft; DBOOL bStatus = DFALSE; DRotation rRot; if(pServerDE->GetModelAnimUserDims(m_hObject, &vObjDims, pServerDE->GetModelAnimation(m_hObject)) == DE_INVALIDPARAMS) pServerDE->DebugOut("CalculateHitLimb() f****d up\r\n"); vTemp.x = (float)fabs(vDir.x); vTemp.y = (float)fabs(vDir.y); vTemp.z = (float)fabs(vDir.z); if(vTemp.x > vTemp.y && vTemp.x > vTemp.z) { fTemp = vObjDims.x / vTemp.x; } else if(vTemp.y > vTemp.x && vTemp.y > vTemp.z) { fTemp = vObjDims.y / vTemp.y; } else if(vTemp.z > vTemp.x && vTemp.z > vTemp.y) { fTemp = vObjDims.z / vTemp.z; } VEC_MULSCALAR(vNewShot,vDir,fTemp); VEC_ADD(vShot,vPos,vNewShot); DVector vC; VEC_SUB(vC,vShot,vPos); fX = 1 / VEC_DOT(vC,vC); fY = fX * -(VEC_DOT(vC,vPos)); for(int i = 0; i < NUM_STD_NODES; i++) { pServerDE->GetModelNodeHideStatus(m_hObject, szNodes[i], &bStatus); if(!bStatus) { DBOOL bRet = pServerDE->GetModelNodeTransform(m_hObject, szNodes[i], &vNodePos, &rRot); ft = VEC_DOT(vC,vNodePos) * fX + fY; if(ft >= 0.0f && ft <= 1.0f) { VEC_ADDSCALED(vZ,vPos,vC, ft); fNodeDist = VEC_DIST(vNodePos, vZ); if(fNodeDist < fDist && fNodeDist <= m_pAnim_Sound->m_fHitSpheres[i]) { fDist = fNodeDist; nNode = i; } } } } /* //Do we leave a pass through mark behind us? if(nNode != -1) { CWeapon *pW = m_pInventoryMgr->GetCurrentWeapon(); if(pW) { VEC_MULSCALAR(vTemp,vDir,-1.0f); // TODO: combine sparks with weaponFX GK 8/27 // pW->AddSparks(vPos, vTemp, fDamage * 2.0f, m_hObject, SURFTYPE_FLESH); // pW->AddBloodSpurt(vPos, vTemp, fDamage * 2.0f, m_hObject, SURFTYPE_FLESH); // Took this out - more efficient to send one message. GK 8/27 // vTemp.x *= -1.0f; // vTemp.z *= -1.0f; // pW->AddBloodSpurt(vPos, vTemp, fDamage * 2.0f, m_hObject, SURFTYPE_FLESH); IntersectQuery iq; IntersectInfo ii; // Set the intersection query values iq.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID; iq.m_FilterFn = DNULL; iq.m_pUserData = DNULL; VEC_COPY(iq.m_From, vPos); VEC_ADDSCALED(iq.m_To, vPos, vDir, 75.0f); // Apply a blood splat to the wall if(pServerDE->IntersectSegment(&iq, &ii) && (ii.m_hObject == pServerDE->GetWorldObject())) { // pW->AddImpact(WFX_BLOODSPLAT, ii.m_Point, vDir, ii.m_Plane.m_Normal, fDamage * 2.0f, // ii.m_hObject, SURFTYPE_FLESH); // pW->AddSparks(ii.m_Point, ii.m_Plane.m_Normal, fDamage * 2.0f, ii.m_hObject, SURFTYPE_FLESH); } } } */ return nNode; }
LTBOOL CAISenseHearEnemyWeaponImpact::Update(HOBJECT hStimulus, LTFLOAT fTimeDelta) { if ( !IsCharacter(hStimulus) ) return LTFALSE; CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(hStimulus); CharFireInfo info; pChar->GetLastFireInfo(info); // Make sure this is a recent firing of the weapon... if (info.fTime + 1.0 < g_pLTServer->GetTime() || info.nWeaponId == WMGR_INVALID_ID) return LTFALSE; AMMO* pAmmo = g_pWeaponMgr->GetAmmo(info.nAmmoId); if (!pAmmo || !pAmmo->pImpactFX) return LTFALSE; // Get the Distance that the impact noise carries LTFLOAT fWeaponImpactNoiseDistance = (LTFLOAT) pAmmo->pImpactFX->nAISoundRadius; // Scale based on surface types SURFACE* pSurf = g_pSurfaceMgr->GetSurface(info.eSurface); _ASSERT(pSurf); if ( pSurf && !pAmmo->pImpactFX->bAIIgnoreSurface ) { fWeaponImpactNoiseDistance *= pSurf->fImpactNoiseModifier; } // Get the distance from the impact LTFLOAT fDistance = VEC_DIST(info.vImpactPos, m_pAI->GetPosition()); // Are we close enough to hear? (or did it hit us?) if ( (fDistance < (m_fDistance + fWeaponImpactNoiseDistance)) || (info.hObject == GetAI()->GetObject()) ) { React(); // Record the Timestamp m_fTimestamp = info.fTime; return LTTRUE; } else { // If it hit a character (forget if we like him or not), and we can see that character, react. if ( info.hObject && IsCharacter(info.hObject) && (fDistance < (500.0f)) ) { LTVector vPosition; g_pLTServer->GetObjectPos(info.hObject, &vPosition); LTBOOL bVisible = LTFALSE; if ( m_pAI->CanSeeThrough() ) { bVisible = m_pAI->IsObjectPositionVisibleFromEye(CAI::SeeThroughFilterFn, CAI::SeeThroughPolyFilterFn, info.hObject, vPosition, (250000.0f), LTTRUE); } else { bVisible = m_pAI->IsObjectPositionVisibleFromEye(CAI::DefaultFilterFn, NULL, info.hObject, vPosition, (250000.0f), LTTRUE); } if ( bVisible ) { React(); // Record the Timestamp m_fTimestamp = info.fTime; return LTTRUE; } } } return LTFALSE; }
void CultistAI::AI_STATE_Escape_RunAway() { if(Metacmd > 1) { int nStimType = ComputeStimuli(); if(nStimType > 0) { ComputeState(nStimType); return; } } DFLOAT fDim = (DFLOAT)sqrt((m_vDims.x * m_vDims.x) + (m_vDims.z * m_vDims.z)) + 0.1f; switch(Metacmd) { case 1: m_hTrackObject = FindObjectInRadius(m_pServerDE->GetClass("ExitHint"), m_fSeeingDist, FIND_VISIBLE | FIND_AVOID_TARGET); if(m_hTrackObject) { m_pServerDE->GetObjectPos(m_hTrackObject,&m_vTrackObjPos); MC_FacePos(m_vTrackObjPos); if(!m_MoveObj.CalculatePath(m_vTrackObjPos)) SetNewState(STATE_Escape_Hide); } else SetNewState(STATE_AttackFar); break; case 2: { DVector* pvPos = m_MoveObj.GetNextPathPoint(); if(pvPos) MC_FacePos(*pvPos); else SetNewState(STATE_Escape_Hide); break; } case 3: { DVector vPoint = *m_MoveObj.GetNextPathPoint(); vPoint.y = m_MoveObj.GetPos().y; if(VEC_DIST(vPoint, m_MoveObj.GetPos()) <= fDim/2) { if(!m_MoveObj.MoveToNextPathPoint()) { MC_FacePos(m_vTargetPos); } else { Metacmd = 2; } } else MC_Run(); break; } case 4: ComputeState(); break; } return; }
void CivilianAI::AI_STATE_Escape_RunAway() { DVector vDims; m_pServerDE->GetObjectDims(m_hObject,&vDims); DFLOAT fDim = (DFLOAT)sqrt((vDims.x * vDims.x) + (vDims.z * vDims.z)) + 0.1f; switch(Metacmd) { case 1: { m_hTrackObject = FindObjectInRadius(m_pServerDE->GetClass("ExitHint"), m_fSeeingDist, FIND_VISIBLE); if(m_hTrackObject) { m_pServerDE->GetObjectPos(m_hTrackObject,&m_vTrackObjPos); DFLOAT fDist = VEC_DIST(m_vTrackObjPos, m_MoveObj.GetPos()); if(fDist <= fDim/2) { SetNewState(STATE_Escape_Hide); break; } MC_FacePos(m_vTrackObjPos); DRotation rRot; DVector vU, vR, vF, vMyF; m_pServerDE->GetObjectRotation(m_hTrackObject, &rRot); m_pServerDE->GetRotationVectors(&rRot, &vU, &vR, &vF); VEC_COPY(vMyF, m_MoveObj.GetForwardVector()); DFLOAT fHintDp = (vMyF.x * vF.x) + (vMyF.y * vF.y) + (vMyF.z * vF.z); if(fHintDp > 0) { if(!m_MoveObj.CalculatePath(m_vTrackObjPos)) SetNewState(STATE_Escape_Hide); } else SetNewState(STATE_Escape_Hide); } else SetNewState(STATE_Escape_Hide); break; } case 2: { DVector* pvPos = m_MoveObj.GetNextPathPoint(); if(pvPos) MC_FacePos(*pvPos); else SetNewState(STATE_Escape_RunAway); break; } case 3: { DVector vPoint = *m_MoveObj.GetNextPathPoint(); vPoint.y = m_MoveObj.GetPos().y; if(VEC_DIST(vPoint, m_MoveObj.GetPos()) <= fDim/2) { if(!m_MoveObj.MoveToNextPathPoint()) { MC_FacePos(m_vTargetPos); } else { Metacmd = 2; } } else MC_Run(); break; } case 4: ComputeState(); break; } return; }
DVector CMovement::FindShortestTurn(DVector vStart, DRotation* prRot, DFLOAT fMoveLen) { CServerDE* pServerDE = BaseClass::GetServerDE(); if (!pServerDE) return vStart; DVector vDir, vEnd, vCurPos; DVector vUp,vRight,vForward,vLeft; VEC_COPY(vCurPos, vStart); IntersectQuery IQuery; IntersectInfo ii; DFLOAT fLeftDist = 0.0f, fRightDist = 0.0f, fMaxDist = 0.0f; pServerDE->GetRotationVectors(prRot,&vUp,&vRight,&vForward); VEC_MULSCALAR(vLeft,vRight,-1.0f); //create the left rotation vector IQuery.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID; IQuery.m_FilterFn = DNULL; //get the farthest left we could travel VEC_COPY(IQuery.m_From,vCurPos); VEC_COPY(IQuery.m_Direction,vLeft); if(pServerDE->CastRay(&IQuery,&ii)) { fMaxDist = fLeftDist = VEC_DIST(vCurPos,ii.m_Point); } //now get the farthest right VEC_COPY(IQuery.m_Direction,vRight); if(pServerDE->CastRay(&IQuery,&ii)) { fRightDist = VEC_DIST(vCurPos,ii.m_Point); if(fRightDist > fMaxDist) fMaxDist = fRightDist; } //travel the obstacle in both directions looking for a clearing VEC_INIT(vDir); VEC_MULSCALAR(vEnd,vForward,fMoveLen + 5.0f); for(float fWidth = fMoveLen; !(fWidth >= fRightDist && fWidth >= fLeftDist); fWidth += fMoveLen) { //Check the right side if(fWidth < fRightDist) { VEC_ADDSCALED(IQuery.m_From,vCurPos,vRight,fWidth); VEC_ADD(IQuery.m_To,IQuery.m_From,vEnd); if(!pServerDE->IntersectSegment(&IQuery,&ii)) { VEC_ADDSCALED(IQuery.m_From,IQuery.m_From,vRight,fWidth/2); pServerDE->AlignRotation(prRot, &vLeft, &m_vUp); return IQuery.m_From; } } //Check the left side if(fWidth < fLeftDist) { VEC_ADDSCALED(IQuery.m_From,vCurPos,vLeft,fWidth); VEC_ADD(IQuery.m_To,IQuery.m_From,vEnd); if(!pServerDE->IntersectSegment(&IQuery,&ii)) { VEC_ADDSCALED(IQuery.m_From,IQuery.m_From,vLeft,fWidth/2); pServerDE->AlignRotation(prRot, &vRight, &m_vUp); return IQuery.m_From; } } } return vStart; }
DBOOL CMovement::CalculatePath(DVector vDestPos) { CServerDE* pServerDE = BaseClass::GetServerDE(); if (!pServerDE) return DFALSE; DVector vDims, vTest; DRotation rRot; //sanity check to make sure vDestPos is valid VEC_INIT(vTest); if(VEC_DIST(vTest, vDestPos) <= 0) return DFALSE; IntersectQuery IQuery; IntersectInfo IInfo; IQuery.m_Flags = INTERSECT_OBJECTS; IQuery.m_FilterFn = DNULL; // LARGE_INTEGER start; // QueryPerformanceCounter(&start); //clear the path list out Term(); //get the parent's dims pServerDE->GetObjectDims(m_hObject,&vDims); DFLOAT fDim = (DFLOAT)sqrt((vDims.x * vDims.x) + (vDims.z * vDims.z)) + 0.1f; if(!ClearToPoint(m_vPos, vDestPos,vDims, &IInfo)) { VEC_ADDSCALED(IInfo.m_Point,IInfo.m_Point, IInfo.m_Plane.m_Normal, fDim - 0.1f) AddPosToPathList(IInfo.m_Point); //align a test rotation to the obstacles normal and retrieve the rotation vectors VEC_MULSCALAR(IInfo.m_Plane.m_Normal, IInfo.m_Plane.m_Normal, -1.0f); pServerDE->AlignRotation(&rRot, &(IInfo.m_Plane.m_Normal), &m_vUp); DVector vTurnPoint = FindShortestTurn(IInfo.m_Point, &rRot, fDim); if(VEC_DIST(vTurnPoint, IInfo.m_Point) <= 0.0f) return DFALSE; AddPosToPathList(vTurnPoint); DVector vU,vR,vF; pServerDE->GetRotationVectors(&rRot,&vU,&vR,&vF); vTurnPoint = FindTurn(vTurnPoint, vF, IInfo.m_Plane.m_Normal, fDim, fDim); if(VEC_DIST(vTurnPoint, vDestPos) <= 0.0f) return DFALSE; if(ClearToPoint(vTurnPoint, vDestPos, vDims, &IInfo)) { AddPosToPathList(vTurnPoint); AddPosToPathList(vDestPos); // ConsolidatePath(); } else return DFALSE; } else AddPosToPathList(vDestPos); /* LARGE_INTEGER end; QueryPerformanceCounter(&end); pServerDE->DebugOut("Shortest Path Computed: %u ticks\r\n", (unsigned long)(end.QuadPart - start.QuadPart)); */ return DTRUE; }
void GremlinAI::AI_STATE_AttackFar() { //SCHLEGZ 4/22/98 4:51:21 PM: sanity check if(m_hTarget == DNULL) { ComputeState(); return; } DFLOAT fHeight = (DFLOAT)fabs(m_vTargetPos.y - m_MoveObj.GetPos().y); m_fStimuli[SIGHT] = VEC_DIST(m_MoveObj.GetPos(),m_vTargetPos); DBOOL bAbove = (m_vTargetPos.y - m_MoveObj.GetPos().y) > 0; MC_FaceTarget(); Metacmd--; switch(Metacmd) { case 1: { if (m_nCurMetacmd != MC_TAUNT_BOLD) { if (IsRandomChance(40)) { MC_Taunt_Bold(); Metacmd--; } else Metacmd++; } else { if(m_pServerDE->GetModelPlaybackState(m_hObject) & MS_PLAYDONE) Metacmd++; } break; } case 2: if(m_fStimuli[SIGHT] <= (m_fSeeingDist * 0.75) || m_nCurMetacmd == MC_FIRE_STAND || (bAbove && fHeight > m_vDims.y)) { MC_Fire_Stand(); } else { if(m_fStimuli[SIGHT] < (m_fSeeingDist * 0.33)) ComputeState(); else MC_Walk(); } break; case 3: if((m_fStimuli[SIGHT] < (m_fSeeingDist * 0.33)) && m_nCurMetacmd != MC_JUMP) { ComputeState(); } else if(m_fStimuli[SIGHT] < (m_fSeeingDist * 0.4) || m_nCurMetacmd == MC_JUMP || IsLedge(m_MoveObj.GetForwardVector())) { MC_Jump(); } else Metacmd++; break; default: ComputeState(); break; } return; }