Files
gtav-src/script/dev_ng/singleplayer/include/private/friendUtil_private.sch
T
2025-09-29 00:52:08 +02:00

522 lines
17 KiB
Scheme
Executable File

//- commands headers -//
//- script headers -//
//- public headers -//
USING "friends_public.sch"
//- private headers -//
USING "friendUtil_dialogue_private.sch"
USING "friendUtil_location_private.sch"
#IF IS_DEBUG_BUILD
//- debug headers -//
#ENDIF
///private header for friend utils - including this file will include all utils
/// sam.hackett@rockstarnorth.com
///
CONST_FLOAT CONST_fApproachAmbientPlayerDistOn 10.5//12.5//15.0//15.0//20.0//15.0//20.0
CONST_FLOAT CONST_fApproachAmbientPlayerDistOff 12.0//15.0//17.0//20.0//25.0//30.0//40.0
CONST_INT CONST_iFriendAdhocChance 15
// *******************************************************************************************
// DEBUG OUTPUT UTILS
// *******************************************************************************************
#IF IS_DEBUG_BUILD
USING "script_debug.sch"
USING "shared_debug.sch"
// USING "hud_creator_tool.sch"
// Draw background box (should probably be a function in FriendUtil_private.sch)
FUNC BOOL DrawFriendBox(FLOAT fCentreX, FLOAT fCentreY, FLOAT fWidth, FLOAT fHeight, INT R, INT G, INT B, INT A)
IF g_flowUnsaved.bShowMissionFlowDebugScreen
IF (g_iDebugSelectedFriendConnDisplay > 0)
DRAW_RECT(fCentreX, fCentreY, fWidth, fHeight, R, G, B, A)
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL DrawFriendLiteralString(STRING sLiteral, INT iColumn, HUD_COLOURS eColour = HUD_COLOUR_PURE_WHITE)
IF g_flowUnsaved.bShowMissionFlowDebugScreen
IF (g_iDebugSelectedFriendConnDisplay > 0)
CONST_FLOAT fDebugRow_one 0.5//0.320 //(12.0*0.0305)
CONST_FLOAT fDebugRow_two 0.075 //(4.0*0.0305)
CONST_FLOAT fDebugRow_three 0.023
FLOAT fDebugRow = 0.0
IF (g_iDebugSelectedFriendConnDisplay = 1)
fDebugRow = fDebugRow_one
ELIF (g_iDebugSelectedFriendConnDisplay = 2)
fDebugRow = fDebugRow_two
ENDIF
INT red, green, blue, iAlpha
GET_HUD_COLOUR(eColour, red, green, blue, iAlpha)
SET_TEXT_SCALE(0.35, 0.30)
SET_TEXT_COLOUR(red, green, blue, iAlpha)
DISPLAY_TEXT_WITH_LITERAL_STRING(0.7795, fDebugRow+(fDebugRow_three*TO_FLOAT(iColumn)), "STRING", sLiteral)
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL DrawFriendLiteralStringInt(STRING sLiteral, INT sInt, INT iColumn, HUD_COLOURS eColour = HUD_COLOUR_PURE_WHITE)
TEXT_LABEL_63 sNewLiteral = sLiteral
sNewLiteral += sInt
RETURN DrawFriendLiteralString(sNewLiteral, iColumn, eColour)
ENDFUNC
FUNC BOOL DrawFriendLiteralStringFloat(STRING sLiteral, FLOAT sFloat, INT iColumn, HUD_COLOURS eColour = HUD_COLOUR_PURE_WHITE)
TEXT_LABEL_63 sNewLiteral = sLiteral
sNewLiteral += GET_STRING_FROM_FLOAT(sFloat)
RETURN DrawFriendLiteralString(sNewLiteral, iColumn, eColour)
ENDFUNC
FUNC BOOL DrawFriendLiteralStringFriend(STRING sLiteral, enumFriend friendID, INT iColumn, HUD_COLOURS eColour = HUD_COLOUR_PURE_WHITE)
TEXT_LABEL_63 sNewLiteral = GetLabel_enumFriend(friendID)
sNewLiteral += " "
sNewLiteral += sLiteral
RETURN DrawFriendLiteralString(sNewLiteral, iColumn, eColour)
ENDFUNC
FUNC BOOL DrawFriendTimerBar(structTimer sTimer, FLOAT fHoursMax, INT iColumn, HUD_COLOURS eColour = HUD_COLOUR_PURE_WHITE)
IF g_flowUnsaved.bShowMissionFlowDebugScreen
IF (g_iDebugSelectedFriendConnDisplay > 0)
CONST_FLOAT fTopX 0.7770 //= 0.7795 + (0.7770-0.7795)
CONST_FLOAT fWidth 0.1500
CONST_FLOAT fHeight 0.0200
CONST_FLOAT fDebugRow_one 0.320 //(12.0*0.0305)
CONST_FLOAT fDebugRow_two 0.075 //(4.0*0.0305)
CONST_FLOAT fDebugRow_three 0.023
FLOAT fDebugRow = 0.0
IF (g_iDebugSelectedFriendConnDisplay = 1)
fDebugRow = fDebugRow_one
ELIF (g_iDebugSelectedFriendConnDisplay = 2)
fDebugRow = fDebugRow_two
ENDIF
FLOAT fTopY = fDebugRow+(fDebugRow_three*TO_FLOAT(iColumn))
FLOAT fTimerInSeconds = GET_TIMER_IN_SECONDS(sTimer)
FLOAT fHoursSeconds = fHoursMax*60*60
FLOAT fWidthMult =1-(fTimerInSeconds/fHoursSeconds)
INT theR, theG, theB, theA
GET_HUD_COLOUR(eColour, theR, theG, theB, theA)
theR = ROUND(1.0-TO_FLOAT(theR))
theG = ROUND(1.0-TO_FLOAT(theG))
theB = ROUND(1.0-TO_FLOAT(theB))
theA = ROUND((TO_FLOAT(theA))*0.75)
DRAW_RECT_FROM_CORNER(fTopX, fTopY, fWidth*fWidthMult, fHeight, theR, theG, theB, theA)
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
#ENDIF
//---------------------------------------------------------------------------------------------------
//-- Range functions
//---------------------------------------------------------------------------------------------------
FUNC BOOL Util_IsPedInsideRange( ENTITY_INDEX hPed, VECTOR vCentre, FLOAT fRange )
VECTOR vPed = GET_ENTITY_COORDS(hPed)
vPed.x -= vCentre.x
vPed.y -= vCentre.y
vPed.z -= vCentre.z
RETURN (((vPed.x*vPed.x)+(vPed.y*vPed.y)+(vPed.z*vPed.z)) <= fRange*fRange)
ENDFUNC
FUNC BOOL Util_IsPedOutsideRange( ENTITY_INDEX hPed, VECTOR vCentre, FLOAT fRange )
VECTOR vPed = GET_ENTITY_COORDS(hPed)
vPed.x -= vCentre.x
vPed.y -= vCentre.y
vPed.z -= vCentre.z
RETURN (((vPed.x*vPed.x)+(vPed.y*vPed.y)+(vPed.z*vPed.z)) > fRange*fRange)
ENDFUNC
FUNC BOOL Util_IsVecInsideRange( VECTOR vPoint, VECTOR vCentre, FLOAT fRange )
vPoint.x -= vCentre.x
vPoint.y -= vCentre.y
vPoint.z -= vCentre.z
RETURN (((vPoint.x*vPoint.x)+(vPoint.y*vPoint.y)+(vPoint.z*vPoint.z)) <= fRange*fRange)
ENDFUNC
FUNC BOOL Util_IsVecOutsideRange( VECTOR vPoint, VECTOR vCentre, FLOAT fRange )
vPoint.x -= vCentre.x
vPoint.y -= vCentre.y
vPoint.z -= vCentre.z
RETURN (((vPoint.x*vPoint.x)+(vPoint.y*vPoint.y)+(vPoint.z*vPoint.z)) > fRange*fRange)
ENDFUNC
FUNC BOOL Util_IsPedInsideRangePed( ENTITY_INDEX hPed1, ENTITY_INDEX hPed2, FLOAT fRange )
VECTOR vPed1 = GET_ENTITY_COORDS(hPed1)
VECTOR vPed2 = GET_ENTITY_COORDS(hPed2)
vPed1.x -= vPed2.x
vPed1.y -= vPed2.y
vPed1.z -= vPed2.z
RETURN (((vPed1.x*vPed1.x)+(vPed1.y*vPed1.y)+(vPed1.z*vPed1.z)) <= fRange*fRange)
ENDFUNC
FUNC BOOL Util_IsPedOutsideRangePed( ENTITY_INDEX hPed1, ENTITY_INDEX hPed2, FLOAT fRange )
VECTOR vPed1 = GET_ENTITY_COORDS(hPed1)
VECTOR vPed2 = GET_ENTITY_COORDS(hPed2)
vPed1.x -= vPed2.x
vPed1.y -= vPed2.y
vPed1.z -= vPed2.z
RETURN (((vPed1.x*vPed1.x)+(vPed1.y*vPed1.y)+(vPed1.z*vPed1.z)) > fRange*fRange)
ENDFUNC
FUNC BOOL Private_IsPointInArea2D(VECTOR vPoint, VECTOR vMin, VECTOR vMax)
IF vMin.x <= vPoint.x AND vPoint.x <= vMax.x
AND vMin.y <= vPoint.y AND vPoint.y <= vMax.y
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
//---------------------------------------------------------------------------------------------------
//-- Hospital charges
//---------------------------------------------------------------------------------------------------
FUNC CC_CodeID Private_GetHospitalChargeCID(PED_INDEX hPed)
IF DOES_ENTITY_EXIST(hPed)
VECTOR vPos = GET_ENTITY_COORDS(hPed, FALSE)
IF NOT DOES_ENTITY_EXIST(PLAYER_PED_ID()) OR HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(hPed, PLAYER_PED_ID())
SWITCH GET_CLOSEST_HOSPITAL(vPos, TRUE)
CASE HOSPITAL_RH RETURN CID_HOSPITAL_CHARGE_RH BREAK
CASE HOSPITAL_SC RETURN CID_HOSPITAL_CHARGE_SC BREAK
CASE HOSPITAL_DT RETURN CID_HOSPITAL_CHARGE_DT BREAK
CASE HOSPITAL_SS RETURN CID_HOSPITAL_CHARGE_SS BREAK
CASE HOSPITAL_PB RETURN CID_HOSPITAL_CHARGE_PB BREAK
ENDSWITCH
RETURN CID_HOSPITAL_CHARGE_RH
ENDIF
ENDIF
RETURN CID_BLANK
ENDFUNC
//---------------------------------------------------------------------------------------------------
//-- Connection played query functions
//---------------------------------------------------------------------------------------------------
FUNC BOOL HAS_CONNECTION_BEEN_PLAYED(enumFriendConnection eConnection)
IF eConnection < MAX_FRIEND_CONNECTIONS
RETURN IS_BIT_SET(g_SavedGlobals.sFriendsData.g_FriendConnectData[eConnection].flags, ENUM_TO_INT(FC_FLAG_DoneCompletionPercent))
ELSE
SCRIPT_ASSERT("HAS_CONNECTION_BEEN_PLAYED() - Invalid connection")
RETURN FALSE
ENDIF
ENDFUNC
PROC SET_CONNECTION_PLAYED(enumFriendConnection eConnection)
IF eConnection < MAX_FRIEND_CONNECTIONS
IF NOT IS_BIT_SET(g_SavedGlobals.sFriendsData.g_FriendConnectData[eConnection].flags, ENUM_TO_INT(FC_FLAG_DoneCompletionPercent))
CPRINTLN(DEBUG_FRIENDS, "SET_CONNECTION_PLAYED(", GetLabel_enumFriendConnection(eConnection), ")")
SET_BIT(g_SavedGlobals.sFriendsData.g_FriendConnectData[eConnection].flags, ENUM_TO_INT(FC_FLAG_DoneCompletionPercent))
ENDIF
ELSE
SCRIPT_ASSERT("SET_CONNECTION_PLAYED() - Invalid connection")
ENDIF
ENDPROC
//---------------------------------------------------------------------------------------------------
//-- Placement functions
//---------------------------------------------------------------------------------------------------
/// PURPOSE:
/// Set's an entity either to the given heading, or it's opposite, whichever is nearest
/// PARAMS:
/// hEntity - entity to rotate
/// fHeading - entity will be set to this direction, or the opposite direction
/// RETURNS:
/// Returns true if used given heading, false if used reverse heading
FUNC BOOL SET_ENTITY_PARALLEL_TO_HEADING(ENTITY_INDEX hEntity, FLOAT fHeading)
VECTOR vEntityForward = GET_ENTITY_FORWARD_VECTOR(hEntity)
VECTOR vHeadingForward = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<0.0,0.0,0.0>>, fHeading, <<0.0,1.0,0.0>>)
IF DOT_PRODUCT_XY(vEntityForward, vHeadingForward) >= 0
SET_ENTITY_HEADING(hEntity, fHeading)
RETURN TRUE
ELSE
SET_ENTITY_HEADING(hEntity, fHeading+180.0)
RETURN FALSE
ENDIF
ENDFUNC
/// PURPOSE:
/// Gets the heading an entity would need to have to point at a given coord
/// PARAMS:
/// hEntity - the entity to be rotated
/// vLookAt - the point the entity wants to face
FUNC FLOAT GET_FACING_HEADING(VECTOR vEntityPos, vector vLookAt)
RETURN GET_HEADING_FROM_VECTOR_2D(vLookAt.x - vEntityPos.x, vLookAt.y - vEntityPos.y)
ENDFUNC
FUNC BOOL IS_ENTITY_FACING_HEADING(PED_INDEX hPed, FLOAT fHeading, FLOAT fMaxAngle = 30.0)
VECTOR vForward = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<0.0, 0.0, 0.0>>, fHeading, <<0.0, 1.0, 0.0>>)
VECTOR vFacing = GET_ENTITY_FORWARD_VECTOR(hPed)
IF vFacing.x < 0.001 AND vFacing.y < 0.001
RETURN TRUE
ENDIF
vFacing.z = 0.0
vFacing = NORMALISE_VECTOR(vFacing)
// Is entity facing to left?
IF DOT_PRODUCT(vForward, vFacing) > COS(fMaxAngle)
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL IS_ENTITY_FACING_COORD(ENTITY_INDEX hEntity, VECTOR vCoord)
VECTOR vToCoord = vCoord - GET_ENTITY_COORDS(hEntity)
VECTOR vFacing = GET_ENTITY_FORWARD_VECTOR(hEntity)
IF DOT_PRODUCT_XY(vToCoord, vFacing) > 0
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
//FUNC BOOL IS_HEADING_FACING_COORD(VECTOR vOrigin, FLOAT fHeading, VECTOR vCoord)
//
// VECTOR vForward = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<0.0, 0.0, 0.0>>, fHeading, <<0.0, 1.0, 0.0>>)
// vCoord -= vOrigin
//
// IF vCoord.x < 0.001 AND vCoord.y < 0.001
// RETURN TRUE
// ENDIF
// vCoord.z = 0.0
//
// IF DOT_PRODUCT_XY(vForward, vCoord) > 0.0
// RETURN TRUE
// ENDIF
//
// RETURN FALSE
//
//ENDFUNC
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
PROC Private_EnableFamilyScenes(enumCharacterList eChar, BOOL bEnable)
IF bEnable = FALSE
SWITCH eChar
CASE CHAR_MICHAEL
g_eCurrentFamilyEvent[FM_TREVOR_0_MICHAEL] = FAMILY_MEMBER_BUSY
BREAK
CASE CHAR_FRANKLIN
//
BREAK
CASE CHAR_TREVOR
g_eCurrentFamilyEvent[FM_TREVOR_0_TREVOR] = FAMILY_MEMBER_BUSY
BREAK
CASE CHAR_LAMAR
g_eCurrentFamilyEvent[FM_FRANKLIN_LAMAR] = FAMILY_MEMBER_BUSY
BREAK
CASE CHAR_JIMMY
g_eCurrentFamilyEvent[FM_MICHAEL_SON] = FAMILY_MEMBER_BUSY
BREAK
CASE CHAR_AMANDA
g_eCurrentFamilyEvent[FM_MICHAEL_WIFE] = FAMILY_MEMBER_BUSY
BREAK
DEFAULT
CPRINTLN(DEBUG_FRIENDS, "Private_EnableFamilyScenes(", GetLabel_enumCharacterList(eChar), ", FALSE) - This char not supported")
SCRIPT_ASSERT("Private_EnableFamilyScenes() - This char not supported")
BREAK
ENDSWITCH
ELSE
SWITCH eChar
CASE CHAR_MICHAEL
IF g_eCurrentFamilyEvent[FM_TREVOR_0_MICHAEL] = FAMILY_MEMBER_BUSY
g_eCurrentFamilyEvent[FM_TREVOR_0_MICHAEL] = NO_FAMILY_EVENTS
ENDIF
BREAK
CASE CHAR_FRANKLIN
//
BREAK
CASE CHAR_TREVOR
IF g_eCurrentFamilyEvent[FM_TREVOR_0_TREVOR] = FAMILY_MEMBER_BUSY
g_eCurrentFamilyEvent[FM_TREVOR_0_TREVOR] = NO_FAMILY_EVENTS
ENDIF
BREAK
CASE CHAR_LAMAR
IF g_eCurrentFamilyEvent[FM_FRANKLIN_LAMAR] = FAMILY_MEMBER_BUSY
g_eCurrentFamilyEvent[FM_FRANKLIN_LAMAR] = NO_FAMILY_EVENTS
ENDIF
BREAK
CASE CHAR_JIMMY
IF g_eCurrentFamilyEvent[FM_MICHAEL_SON] = FAMILY_MEMBER_BUSY
g_eCurrentFamilyEvent[FM_MICHAEL_SON] = NO_FAMILY_EVENTS
ENDIF
BREAK
CASE CHAR_AMANDA
IF g_eCurrentFamilyEvent[FM_MICHAEL_WIFE] = FAMILY_MEMBER_BUSY
g_eCurrentFamilyEvent[FM_MICHAEL_WIFE] = NO_FAMILY_EVENTS
ENDIF
BREAK
DEFAULT
CPRINTLN(DEBUG_FRIENDS, "Private_EnableFamilyScenes(", GetLabel_enumCharacterList(eChar), ", TRUE) - This char not supported")
SCRIPT_ASSERT("Private_EnableFamilyScenes() - This char not supported")
BREAK
ENDSWITCH
ENDIF
ENDPROC
FUNC BOOL Private_IsFamilySceneCharActive(enumCharacterList eChar)
SWITCH eChar
CASE CHAR_MICHAEL
IF g_eCurrentFamilyEvent[FM_TREVOR_0_MICHAEL] < MAX_FAMILY_EVENTS
RETURN TRUE
ENDIF
BREAK
CASE CHAR_FRANKLIN
//
BREAK
CASE CHAR_TREVOR
IF g_eCurrentFamilyEvent[FM_TREVOR_0_TREVOR] < MAX_FAMILY_EVENTS
RETURN TRUE
ENDIF
BREAK
CASE CHAR_LAMAR
IF g_eCurrentFamilyEvent[FM_FRANKLIN_LAMAR] < MAX_FAMILY_EVENTS
RETURN TRUE
ENDIF
BREAK
CASE CHAR_JIMMY
IF g_eCurrentFamilyEvent[FM_MICHAEL_SON] < MAX_FAMILY_EVENTS
RETURN TRUE
ENDIF
BREAK
CASE CHAR_AMANDA
IF g_eCurrentFamilyEvent[FM_MICHAEL_WIFE] < MAX_FAMILY_EVENTS
RETURN TRUE
ENDIF
BREAK
DEFAULT
CPRINTLN(DEBUG_FRIENDS, "Private_IsFamilySceneCharActive(", GetLabel_enumCharacterList(eChar), ", FALSE) - This char not supported")
SCRIPT_ASSERT("Private_IsFamilySceneCharActive() - This char not supported")
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC
//----------------------------------------------------------------------------------
FUNC BOOL CREATE_STORED_VEHICLE(VEHICLE_INDEX &ReturnVeh, enumCharacterList ePed, VECTOR vCoords, FLOAT fHeading, BOOL bCleanupModel, PED_VEH_DATA_STRUCT& sVehData)
IF sVehData.model = DUMMY_MODEL_FOR_SCRIPT
// Bail out so we don't get stuck.
// Scripts should be checking if the vehicle is driveable anyway.
RETURN TRUE
ENDIF
IF DOES_ENTITY_EXIST(ReturnVeh)
IF GET_ENTITY_MODEL(ReturnVeh) != sVehData.model
#IF IS_DEBUG_BUILD
SCRIPT_ASSERT("CREATE_STORED_VEHICLE - Vehicle ID already exists with different model")
#ENDIF
ENDIF
RETURN TRUE
ENDIF
REQUEST_MODEL(sVehData.model)
IF HAS_MODEL_LOADED(sVehData.model)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": CREATE_STORED_VEHICLE() Using stored data")
ReturnVeh = CREATE_VEHICLE(sVehData.model, vCoords, fHeading)
SET_VEHICLE_ON_GROUND_PROPERLY(ReturnVeh)
SET_VEHICLE_NOT_STEALABLE_AMBIENTLY(ReturnVeh, FALSE)
SET_VEHICLE_CAN_SAVE_IN_GARAGE(ReturnVeh, FALSE)
SET_VEHICLE_HAS_STRONG_AXLES(ReturnVeh, TRUE)
SET_VEH_DATA_FROM_STRUCT(ReturnVeh, sVehData)
IF sVehData.bIsPlayerVehicle
// Attach Mr Raspberry Jam to Trevors truck
IF ePed = CHAR_TREVOR
IF GET_ENTITY_MODEL(ReturnVeh) = BODHI2
TURN_ON_MR_RASPBERRY_JAM(ReturnVeh)
ENDIF
ENDIF
STORE_TEMP_PLAYER_VEHICLE_ID(ReturnVeh, ePed)
ENDIF
IF bCleanupModel
SET_MODEL_AS_NO_LONGER_NEEDED(sVehData.model)
ENDIF
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
FUNC BOOL Private_IsEntityOwnedBy(ENTITY_INDEX hEntity, STRING sCheckScript)
STRING sOwnerScript = ""
INT hOwnerScript = 0
sOwnerScript = GET_ENTITY_SCRIPT(hEntity, hOwnerScript)
IF NOT IS_STRING_NULL_OR_EMPTY(sOwnerScript)
AND NOT IS_STRING_NULL_OR_EMPTY(sCheckScript)
IF ARE_STRINGS_EQUAL(sOwnerScript, sCheckScript)
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC