398 lines
12 KiB
Scheme
Executable File
398 lines
12 KiB
Scheme
Executable File
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
//
|
|
// FILE NAME : rc_threat_special_public.sch
|
|
// AUTHOR : Andy Mingella / Aaron Gandaa
|
|
// DESCRIPTION : Functions used in RC's to handle threats
|
|
//
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
|
|
//----------------------
|
|
// INCLUDES
|
|
//----------------------
|
|
USING "rage_builtins.sch"
|
|
USING "globals.sch"
|
|
USING "RC_Helper_Functions.sch"
|
|
USING "commands_shapetest.sch"
|
|
|
|
//----------------------
|
|
// ENUMS
|
|
//----------------------
|
|
ENUM SIGHTTEST_STATUS
|
|
SIGHTTEST_READY,
|
|
SIGHTTEST_ABORTED,
|
|
SIGHTTEST_PENDING,
|
|
SIGHTTEST_COMPLETE
|
|
ENDENUM
|
|
|
|
//----------------------
|
|
// STRUCTS
|
|
//----------------------
|
|
STRUCT PEDSIGHT_TEST
|
|
BOOL bIsFree = TRUE
|
|
PED_INDEX viewerPedID // the ped who is looking
|
|
PED_INDEX targetPedID // the ped we are looking at
|
|
FLOAT fViewCone = 170.0 // the field of view cone of the looking ped
|
|
INT iLastSightTime = 0
|
|
|
|
SHAPETEST_INDEX mShapeTest = NULL // index of the shape test we are using
|
|
BOOL bSeenOnLastCheck = FALSE
|
|
VECTOR vCheckPoint
|
|
|
|
// if we have seen him we wait a few frames before trying this again
|
|
// we randomize this so that everyone doesn't do shape test at once
|
|
INT iNextCheckTime
|
|
SIGHTTEST_STATUS mSightStatus
|
|
INT iIndex = -1
|
|
ENDSTRUCT
|
|
|
|
//----------------------
|
|
// CONSTANTS
|
|
//----------------------
|
|
CONST_INT MAXIMUM_SIGHTTESTS 10
|
|
|
|
//----------------------
|
|
// VARAIBLES
|
|
//----------------------
|
|
PEDSIGHT_TEST mSightTestArray[MAXIMUM_SIGHTTESTS]
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
BOOL bDumpSightTestTTY = FALSE
|
|
#ENDIF
|
|
|
|
//----------------------
|
|
// FUNCTIONS
|
|
//----------------------
|
|
|
|
/// PURPOSE:
|
|
/// Finds a gap in the threat shape test array
|
|
/// RETURNS:
|
|
/// Returns the array number of a space for a new threat sighttest or -1 if array is full
|
|
FUNC INT GET_FREE_SIGHTTEST_INDEX()
|
|
INT i
|
|
REPEAT COUNT_OF(mSightTestArray) i
|
|
IF (mSightTestArray[i].bIsFree = TRUE)
|
|
RETURN i
|
|
ENDIF
|
|
ENDREPEAT
|
|
RETURN -1
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Registers a new Ped Sight Test
|
|
/// PARAMS:
|
|
/// viewPed - The Ped who is doing the looking
|
|
/// targetPed - The ped we are looking for
|
|
/// viewCone - Field of View (For People in Aircraft set this to 0.0)
|
|
/// RETURNS:
|
|
/// Index to the sight test Array or -1 if it can't register one
|
|
FUNC INT REGISTER_PEDSIGHT_TEST(PED_INDEX viewPed, PED_INDEX tgtPed, FLOAT viewCone = 170.0)
|
|
INT i
|
|
|
|
// check to see if these peds are already registered
|
|
REPEAT COUNT_OF(mSightTestArray) i
|
|
IF ((mSightTestArray[i].viewerPedID = viewPed) AND (mSightTestArray[i].targetPedID = tgtPed))
|
|
mSightTestArray[i].fViewCone = viewCone
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
IF (bDumpSightTestTTY = TRUE)
|
|
CPRINTLN(DEBUG_MISSION, "Sight Test Already Registered:", i)
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
RETURN i
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
// else try and find empty sighttest
|
|
i = GET_FREE_SIGHTTEST_INDEX()
|
|
IF (i = -1)
|
|
#IF IS_DEBUG_BUILD
|
|
IF (bDumpSightTestTTY = TRUE)
|
|
CPRINTLN(DEBUG_MISSION, "Sight Test Register Failed")
|
|
ENDIF
|
|
#ENDIF
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
IF (bDumpSightTestTTY = TRUE)
|
|
CPRINTLN(DEBUG_MISSION, "Sight Test Registered:", i)
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
mSightTestArray[i].bIsFree = FALSE
|
|
mSightTestArray[i].viewerPedID = viewPed
|
|
mSightTestArray[i].targetPedID = tgtPed
|
|
mSightTestArray[i].iLastSightTime = 0
|
|
mSightTestArray[i].fViewCone = viewCone
|
|
mSightTestArray[i].mShapeTest = NULL
|
|
mSightTestArray[i].iIndex = i
|
|
|
|
RETURN i
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Deregisters a new Ped Sight Test
|
|
/// Remove All Sights tests involving this ped
|
|
/// PARAMS:
|
|
/// viewPed - The Ped who is doing the looking
|
|
PROC DEREGISTER_PEDSIGHT_TEST(PEDSIGHT_TEST &sightTest)
|
|
IF (sightTest.bIsFree = FALSE)
|
|
sightTest.bIsFree = FALSE
|
|
sightTest.viewerPedID = NULL
|
|
sightTest.targetPedID = NULL
|
|
sightTest.iLastSightTime = 0
|
|
sightTest.iNextCheckTime = 0
|
|
sightTest.mSightStatus = SIGHTTEST_ABORTED
|
|
sightTest.mShapeTest = NULL
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Deregisters a new Ped Sight Test
|
|
/// Remove All Sights tests involving this ped
|
|
/// PARAMS:
|
|
/// viewPed - The Ped who is doing the looking
|
|
PROC DEREGISTER_PEDSIGHT_TESTS(PED_INDEX viewPed)
|
|
INT i
|
|
REPEAT COUNT_OF(mSightTestArray) i
|
|
IF (mSightTestArray[i].bIsFree = FALSE)
|
|
IF ((mSightTestArray[i].viewerPedID = viewPed) OR (mSightTestArray[i].targetPedID = viewPed))
|
|
DEREGISTER_PEDSIGHT_TEST(mSightTestArray[i])
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Updates all Ped Sight Test
|
|
/// Call this every frame before using can ped see ped
|
|
FUNC SIGHTTEST_STATUS UPDATE_PEDSIGHT_TEST(PEDSIGHT_TEST &sightTest)
|
|
|
|
VECTOR vTemp
|
|
INT iNHits = 0
|
|
VECTOR vHitPos, vNormal
|
|
ENTITY_INDEX hitEntity
|
|
SHAPETEST_STATUS shapeStatus
|
|
|
|
// moved them inside here to so it doesn't clash with rc_threat
|
|
CONST_FLOAT SPROBE_DIST_TO_HIT 0.5 // how far away from the player the probe can be for us say he can be seen
|
|
CONST_FLOAT SPROBE_DIST_TO_HIT_CAR 2.5 // how far away from the player's car the probe can be for us say he can be seen
|
|
CONST_FLOAT SPROBE_DIST_TO_HIT_AIRCRAFT 5.0 // how far away from the player's car the probe can be for us say he can be seen
|
|
CONST_FLOAT SPROBE_DIST_TO_HIT_PED_IN_COVER 0.310
|
|
CONST_FLOAT SPROBE_DIST_TO_HIT_PED_RUNNING 0.8
|
|
|
|
// do alive checks - should do stuff to bail out here
|
|
IF (sightTest.bIsFree = TRUE)
|
|
RETURN SIGHTTEST_ABORTED
|
|
ENDIF
|
|
|
|
IF (NOT IS_ENTITY_ALIVE(sightTest.viewerPedID)) OR (NOT IS_ENTITY_ALIVE(sightTest.targetPedID))
|
|
// just grab the shape test so we can flush it
|
|
IF (sightTest.mShapeTest <> NULL)
|
|
shapeStatus = GET_SHAPE_TEST_RESULT(sightTest.mShapeTest, iNHits, vHitPos, vNormal, hitEntity)
|
|
sightTest.mShapeTest = NULL
|
|
ENDIF
|
|
|
|
IF NOT IS_ENTITY_ALIVE(sightTest.viewerPedID)
|
|
DEREGISTER_PEDSIGHT_TESTS(sightTest.viewerPedID)
|
|
ENDIF
|
|
|
|
IF NOT IS_ENTITY_ALIVE(sightTest.targetPedID)
|
|
DEREGISTER_PEDSIGHT_TESTS(sightTest.targetPedID)
|
|
ENDIF
|
|
|
|
RETURN SIGHTTEST_ABORTED
|
|
ENDIF
|
|
|
|
// check to see if target is outside of view ped's viewcont - if so bail out
|
|
FLOAT fViewLimit = sightTest.fViewCone / 2.0
|
|
VECTOR vPedPos = GET_ENTITY_COORDS(sightTest.viewerPedID)
|
|
VECTOR vPedLookForPos = GET_ENTITY_COORDS(sightTest.targetPedID)
|
|
|
|
IF (sightTest.fViewCone > 0.0)
|
|
VECTOR vNormalisedVec = NORMALISE_VECTOR(vPedLookForPos - vPedPos)
|
|
FLOAT fViewAngle = DOT_PRODUCT(GET_ENTITY_FORWARD_VECTOR(sightTest.viewerPedID), vNormalisedVec)
|
|
IF fViewAngle <= COS(fViewLimit)
|
|
|
|
// just grab the shape test so we can flush it
|
|
IF (sightTest.mShapeTest <> NULL)
|
|
shapeStatus = GET_SHAPE_TEST_RESULT(sightTest.mShapeTest, iNHits, vHitPos, vNormal, hitEntity)
|
|
sightTest.mShapeTest = NULL
|
|
ENDIF
|
|
|
|
RETURN SIGHTTEST_ABORTED // target is behind the ped and can't be seen
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// grab a shape test
|
|
IF (sightTest.mShapeTest = NULL)
|
|
vPedPos = GET_PED_BONE_COORDS(sightTest.viewerPedID, BONETAG_HEAD, <<0.0, 0.6, 0.0>>)
|
|
|
|
// we need to work out how far the person will be ahead of time
|
|
sightTest.vCheckPoint = vPedLookForPos + (GET_ENTITY_VELOCITY(sightTest.targetPedID) * GET_FRAME_TIME())
|
|
vTemp = ((sightTest.vCheckPoint - vPedPos) * 1.25) + vPedPos
|
|
sightTest.mShapeTest = START_SHAPE_TEST_LOS_PROBE(vPedPos, vTemp, SCRIPT_INCLUDE_ALL)
|
|
RETURN SIGHTTEST_PENDING
|
|
ENDIF
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
IF (bDumpSightTestTTY = TRUE)
|
|
DRAW_DEBUG_LINE(vPedPos, vPedLookForPos)
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
// we have a shape test
|
|
FLOAT fDist
|
|
BOOL tgtSeen = FALSE
|
|
|
|
shapeStatus = GET_SHAPE_TEST_RESULT(sightTest.mShapeTest, iNHits, vHitPos, vNormal, hitEntity)
|
|
IF (shapeStatus = SHAPETEST_STATUS_NONEXISTENT)
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
IF (bDumpSightTestTTY = TRUE)
|
|
CPRINTLN(DEBUG_MISSION, "Shape Test Non-Existant for Sight Test:", sightTest.iIndex)
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
sightTest.mShapeTest = NULL
|
|
RETURN SIGHTTEST_ABORTED
|
|
ELIF (shapeStatus = SHAPETEST_STATUS_RESULTS_NOTREADY)
|
|
#IF IS_DEBUG_BUILD
|
|
IF (bDumpSightTestTTY = TRUE)
|
|
CPRINTLN(DEBUG_MISSION, "Shape Test Results Not Ready for Sight Test:", sightTest.iIndex)
|
|
ENDIF
|
|
#ENDIF
|
|
RETURN SIGHTTEST_PENDING
|
|
ENDIF
|
|
|
|
// process the results
|
|
IF (iNHits = 0) // we have a clear line of sight
|
|
sightTest.iLastSightTime = GET_GAME_TIMER()
|
|
#IF IS_DEBUG_BUILD
|
|
IF (bDumpSightTestTTY = TRUE)
|
|
CPRINTLN(DEBUG_MISSION, "Sight Test:", sightTest.iIndex, " Complete - Clear Line Of Sight - Time:", sightTest.iLastSightTime)
|
|
ENDIF
|
|
#ENDIF
|
|
ELSE
|
|
|
|
// check our distance between hit point and object in 2D
|
|
FLOAT spdshift = ABSF (GET_ENTITY_SPEED(sightTest.viewerPedID) * GET_FRAME_TIME())
|
|
|
|
spdshift = 0
|
|
fDist = GET_DISTANCE_BETWEEN_COORDS(sightTest.vCheckPoint, vHitPos, FALSE)// + (GET_ENTITY_SPEED(sightTest.viewerPedID) * GET_FRAME_TIME())
|
|
IF IS_PED_IN_ANY_HELI(sightTest.viewerPedID)
|
|
tgtSeen = (fDist <= (SPROBE_DIST_TO_HIT_AIRCRAFT + spdshift))
|
|
ELIF IS_PED_IN_ANY_VEHICLE(sightTest.targetPedID)
|
|
tgtSeen = (fDist <= (SPROBE_DIST_TO_HIT_CAR + spdshift))
|
|
ELIF IS_PED_RUNNING(sightTest.targetPedID)
|
|
tgtSeen = (fDist <= (SPROBE_DIST_TO_HIT_PED_RUNNING + spdshift))
|
|
ELIF IS_PED_IN_COVER(sightTest.targetPedID)
|
|
tgtSeen = (fDist <= (SPROBE_DIST_TO_HIT_PED_IN_COVER + spdshift))
|
|
ELSE
|
|
tgtSeen = (fDist <= (SPROBE_DIST_TO_HIT + spdshift))
|
|
ENDIF
|
|
|
|
// then check to see we are within height difference (+ or - 1 meter)
|
|
IF (tgtSeen) AND (ABSF(sightTest.vCheckPoint.z - vHitPos.z) > 1.0)
|
|
tgtSeen = FALSE
|
|
ENDIF
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
IF (bDumpSightTestTTY = TRUE)
|
|
CPRINTLN(DEBUG_MISSION, "Sight Test:", sightTest.iIndex, " Complete - Hits:", iNHits, " Target Seen:", tgtSeen)
|
|
ENDIF
|
|
#ENDIF
|
|
sightTest.bSeenOnLastCheck = tgtSeen
|
|
|
|
// record this sight time
|
|
IF (tgtSeen)
|
|
sightTest.iLastSightTime = GET_GAME_TIMER()
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
IF (bDumpSightTestTTY = TRUE)
|
|
DRAW_DEBUG_SPHERE(vHitPos, 0.0625, 255, 0, 0, 255)
|
|
ENDIF
|
|
#ENDIF
|
|
ENDIF
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
IF (bDumpSightTestTTY = TRUE) AND (tgtSeen = FALSE)
|
|
DRAW_DEBUG_SPHERE(vHitPos, 0.0625)
|
|
ENDIF
|
|
#ENDIF
|
|
ENDIF
|
|
|
|
// reset safe check
|
|
sightTest.iNextCheckTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(64, 256)
|
|
sightTest.mShapeTest = NULL
|
|
RETURN SIGHTTEST_COMPLETE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Updates all Ped Sight Test
|
|
/// Call this every frame before using can ped see ped
|
|
PROC UPDATE_PEDSIGHT_TESTS()
|
|
INT i
|
|
|
|
REPEAT COUNT_OF(mSightTestArray) i
|
|
IF NOT ((mSightTestArray[i].mSightStatus = SIGHTTEST_COMPLETE) AND (GET_GAME_TIMER() < mSightTestArray[i].iNextCheckTime))
|
|
mSightTestArray[i].mSightStatus = UPDATE_PEDSIGHT_TEST(mSightTestArray[i])
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Use this to see if the sight test worked (person saw person)
|
|
/// PARAMS:
|
|
/// i - the sight test index you'll recieve this when you register the sight ped
|
|
/// iGraceTime - If we've seen the person within this amount of time it still counts
|
|
/// RETURNS:
|
|
/// True on Success
|
|
FUNC BOOL DID_SIGHTTEST_PASS(INT i, INT iGraceTime = 250)
|
|
|
|
IF (i = -1)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF (i >= COUNT_OF(mSightTestArray))
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// we don't care if the sight test in not used or he hasn't been seen yet
|
|
IF (mSightTestArray[i].bIsFree = TRUE) OR (mSightTestArray[i].iLastSightTime = 0)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN ((GET_GAME_TIMER() - mSightTestArray[i].iLastSightTime) < iGraceTime)
|
|
ENDFUNC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Shows sight times for all sight tests (debug only)
|
|
PROC DRAW_DEBUG_SIGHT_TIMES()
|
|
INT i
|
|
INT cnt
|
|
|
|
// draw how many tests have passed
|
|
cnt = 0
|
|
i = 0
|
|
REPEAT COUNT_OF(mSightTestArray) i
|
|
IF DID_SIGHTTEST_PASS(i)
|
|
cnt ++
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
SET_TEXT_SCALE(0.5, 0.5)
|
|
DISPLAY_TEXT_WITH_NUMBER(0.5, 0.1, "NUMBER", cnt)
|
|
|
|
// draw sight times
|
|
i = 0
|
|
REPEAT COUNT_OF(mSightTestArray) i
|
|
SET_TEXT_SCALE(0.25, 0.25)
|
|
DISPLAY_TEXT_WITH_NUMBER(0.1, 0.2 + (TO_FLOAT(i) * 0.025), "NUMBER", mSightTestArray[i].iLastSightTime)
|
|
ENDREPEAT
|
|
ENDPROC
|