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

449 lines
16 KiB
Scheme
Executable File

// *****************************************************************************************
// *****************************************************************************************
//
// FILE NAME : RC_Rent_A_Rucus.sch
// AUTHOR : Aaron Gandaa
// DESCRIPTION : Creates a Simple Rucus with 2 teams
//
// *****************************************************************************************
// *****************************************************************************************
//----------------------
// INCLUDES
//----------------------
USING "rage_builtins.sch"
USING "globals.sch"
USING "RC_Helper_Functions.sch"
USING "rgeneral_include.sch"
//----------------------
// ENUM
//----------------------
ENUM FIGHT_SIDE
SIDE_FRIENDLY,
SIDE_FOE
ENDENUM
//----------------------
// CONSTANTS
//----------------------
CONST_INT MAX_RUCUS_PEDS 10
//----------------------
// STRUCTS
//----------------------
STRUCT FIGHT_PED
PED_INDEX pedID
BLIP_INDEX blipID
BOOL bIsFriendly = FALSE
INT iRecheckTimer = 0
ENDSTRUCT
STRUCT FIGHT_GROUP
BOOL bIsFriendly = FALSE
MODEL_NAMES pedModel
REL_GROUP_HASH relGroup
INT iAliveCounter
INT iCreateCounter
WEAPON_TYPE weapon[2]
VECTOR vCenter
FLOAT fRadius
FIGHT_PED attackPed[MAX_RUCUS_PEDS]
COMBAT_PARAMETERS combatParam
BOOL bUseCombatParams = FALSE
INT iMaxActivePeds
ENDSTRUCT
//----------------------
// VARIABLES
//----------------------
FIGHT_GROUP fightGroup[2]
ANGLED_AREA fightNoSpawnArea[8]
INT iFightSpawnAreas = 0
//----------------------
// INTERNAL FUNCTIONS
//----------------------
//------------------------------------------------------------------------------
// FUNCTION: GENERATE_PED_SPAWN_POINT_IN_DISC()
// PURPOSE: CALCULATES A SPAWN POINT GIVEN CENTER AND RADIUS
//------------------------------------------------------------------------------
FUNC BOOL GENERATE_PED_SPAWN_POINT_IN_DISC(VECTOR center, FLOAT radius, VECTOR &out)
FLOAT z
INT i
VECTOR pos = center
pos.x += GET_RANDOM_FLOAT_IN_RANGE(-radius, radius)
pos.y += GET_RANDOM_FLOAT_IN_RANGE(-radius, radius)
out = pos
/*
IF NOT GET_SAFE_COORD_FOR_PED(pos, FALSE, out)
PRINTSTRING(" COULD NOT GENERATE SAFE POINT\n")
RETURN FALSE
ENDIF
*/
// do get ground pos in point 10 meters above this one
out.z += 15
IF NOT GET_GROUND_Z_FOR_3D_COORD(out, z)
//PRINTSTRING(" COULD NOT GENERATE GROUND POINT\n")
RETURN FALSE
ENDIF
out.z = z
// check point isn't in a no spawn area
IF (iFightSpawnAreas > 0)
REPEAT iFightSpawnAreas i
IF IS_POINT_IN_ANGLED_AREA(out, fightNoSpawnArea[i].vPosition[0], fightNoSpawnArea[i].vPosition[1], fightNoSpawnArea[i].fWidth)
RETURN FALSE
ENDIF
ENDREPEAT
ENDIF
IF IS_SPHERE_VISIBLE(out, 0.5)
//IF NOT WOULD_ENTITY_BE_OCCLUDED(GET_PLAYER_MODEL(), out)
RETURN FALSE
//ENDIF
ENDIF
//PRINTSTRING(" COULD NOT GENERATE POINT\n")
RETURN TRUE
ENDFUNC
//------------------------------------------------------------------------------
// FUNCTION: REPEAT_GENERATE_PED_SPAWN_POINT_IN_DISC()
// PURPOSE: TRIES MULTIPLE TIMES TO GENERATE A SPAWN POINT
//------------------------------------------------------------------------------
FUNC BOOL REPEAT_GENERATE_PED_SPAWN_POINT_IN_DISC(VECTOR center, FLOAT radius, VECTOR &out, INT tries = 5)
INT i
REPEAT tries i
IF GENERATE_PED_SPAWN_POINT_IN_DISC(center, radius, out)
RETURN TRUE
ENDIF
ENDREPEAT
//PRINTSTRING(" COULD NOT GENERATE REPEAT POINT\n")
RETURN FALSE
ENDFUNC
//------------------------------------------------------------------------------
// FUNCTION: GET_FREE_FIGHT_PED_INDEX()
// PURPOSE: GETS INDEX TO FREE PED IN A FIGHT PED ARRAY
// NOTES: USED INTERNALLY
//------------------------------------------------------------------------------
FUNC BOOL GET_FREE_FIGHT_PED_INDEX(FIGHT_PED &array[], INT &out)
INT i
REPEAT COUNT_OF(array) i
IF NOT DOES_ENTITY_EXIST(array[i].pedID)
out = i
RETURN TRUE
ENDIF
ENDREPEAT
//PRINTSTRING(" COULD NOT GET FREE PED\n")
RETURN FALSE
ENDFUNC
//------------------------------------------------------------------------------
// FUNCTION: UPDATE_ALIVE_FIGHT_PED_COUNTER()
// PURPOSE: UPDATES NUMBER OF ALIVE PEDS IN A FIGHT PED ARRAY
// NOTES: USED INTERNALLY
//------------------------------------------------------------------------------
FUNC INT UPDATE_ALIVE_FIGHT_PED_COUNTER(FIGHT_GROUP &fg)
INT i
fg.iAliveCounter = 0
REPEAT COUNT_OF(fg.attackPed) i
IF IS_ENTITY_ALIVE(fg.attackPed[i].pedID)
fg.iAliveCounter ++
IF GET_SCRIPT_TASK_STATUS(fg.attackPed[i].pedID,SCRIPT_TASK_COMBAT_HATED_TARGETS_AROUND_PED) <> PERFORMING_TASK
REGISTER_HATED_TARGETS_AROUND_PED(fg.attackPed[i].pedID, 200.0)
fg.attackPed[i].iRecheckTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(30000, 60000)
TASK_COMBAT_HATED_TARGETS_AROUND_PED(fg.attackPed[i].pedID, 200.0)
ENDIF
ENDIF
ENDREPEAT
RETURN fg.iAliveCounter
ENDFUNC
//------------------------------------------------------------------------------
// FUNCTION: SETUP_FIGHT_GROUP()
// PURPOSE: SETS UP A FIGHT TO GROUP TO CONTAIN A NUMBER OF PEDS
// NOTES: USED INTERNALLY
//------------------------------------------------------------------------------
PROC SETUP_FIGHT_GROUP(FIGHT_GROUP &fg, INT count, BOOL neverdie = FALSE)
INT i
INT ind
VECTOR out
FLOAT rand
IF (fg.fRadius < 5.0)
fg.fRadius = 5.0
ENDIF
REPEAT count i
IF NOT GET_FREE_FIGHT_PED_INDEX(fg.attackPed, ind)
EXIT
ENDIF
IF REPEAT_GENERATE_PED_SPAWN_POINT_IN_DISC(fg.vCenter, GET_RANDOM_FLOAT_IN_RANGE(fg.fRadius - 5.0, fg.fRadius + 5.0), out)
fg.attackPed[ind].pedID = CREATE_PED(PEDTYPE_MISSION, fg.pedModel, out)
IF IS_ENTITY_ALIVE(fg.attackPed[ind].pedID)
fg.attackPed[ind].blipID = CREATE_PED_BLIP(fg.attackPed[ind].pedID, TRUE, fg.bIsFriendly)
fg.attackPed[ind].bIsFriendly = fg.bIsFriendly
SET_PED_RELATIONSHIP_GROUP_HASH(fg.attackPed[ind].pedID, fg.relGroup)
SET_PED_RANDOM_COMPONENT_VARIATION(fg.attackPed[ind].pedID)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(fg.attackPed[ind].pedID, FALSE)
SET_PED_INFINITE_AMMO(fg.attackPed[ind].pedID, TRUE)
SET_PED_COMBAT_ATTRIBUTES(fg.attackPed[ind].pedID, CA_USE_COVER, TRUE)
SET_PED_FLEE_ATTRIBUTES(fg.attackPed[ind].pedID, FA_USE_COVER, TRUE)
SET_PED_INFINITE_AMMO(fg.attackPed[ind].pedID, TRUE)
IF NOT (fg.bIsFriendly)
SET_PED_DEFENSIVE_SPHERE_ATTACHED_TO_PED(fg.attackPed[ind].pedID, player_ped_id(), <<0, 0, 0>>, 60.0, TRUE)
ENDIF
// setup combat movement
IF GET_RANDOM_FLOAT_IN_RANGE() <= 0.5
SET_PED_SPHERE_DEFENSIVE_AREA(fg.attackPed[ind].pedID, fg.vCenter, fg.fRadius)
SET_PED_COMBAT_MOVEMENT(fg.attackPed[ind].pedID, CM_DEFENSIVE )
ELSE
SET_PED_COMBAT_MOVEMENT(fg.attackPed[ind].pedID, CM_WILLADVANCE )
ENDIF
// setup combat range
rand = GET_RANDOM_FLOAT_IN_RANGE()
IF (rand < 0.33)
SET_PED_COMBAT_RANGE(fg.attackPed[ind].pedID, CR_NEAR)
ELIF (rand < 0.66)
SET_PED_COMBAT_RANGE(fg.attackPed[ind].pedID, CR_MEDIUM)
ELSE
SET_PED_COMBAT_RANGE(fg.attackPed[ind].pedID, CR_FAR)
ENDIF
IF (fg.bIsFriendly)
SET_PED_DEFENSIVE_SPHERE_ATTACHED_TO_PED(fg.attackPed[ind].pedID, PLAYER_PED_ID(), <<0, 0, 0>>, 30.0)
ENDIF
IF GET_RANDOM_FLOAT_IN_RANGE() <= 0.5
GIVE_WEAPON_TO_PED(fg.attackPed[ind].pedID, fg.weapon[0], INFINITE_AMMO, TRUE, TRUE)
ELSE
GIVE_WEAPON_TO_PED(fg.attackPed[ind].pedID, fg.weapon[1], INFINITE_AMMO, TRUE, TRUE)
ENDIF
IF (neverdie)
SET_ENTITY_ONLY_DAMAGED_BY_PLAYER(fg.attackPed[ind].pedID, TRUE)
ENDIF
IF (fg.bUseCombatParams)
APPLY_COMBAT_PARAMETERS_TO_PED(fg.attackPed[ind].pedID, fg.combatParam)
ENDIF
REGISTER_HATED_TARGETS_AROUND_PED(fg.attackPed[ind].pedID, 200.0)
fg.attackPed[ind].iRecheckTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(30000, 60000)
fg.iCreateCounter --
TASK_COMBAT_HATED_TARGETS_AROUND_PED(fg.attackPed[ind].pedID, 200.0)
ENDIF
ENDIF
ENDREPEAT
ENDPROC
//------------------------------------------------------------------------------
// FUNCTION: INIT_FIGHT_GROUP()
// PURPOSE: THIS INITIALIZE A FIGHT TO GROUP TO CONTAIN A NUMBER OF PEDS
// NOTES: USED INTERNALLY
//------------------------------------------------------------------------------
PROC INIT_FIGHT_GROUP(FIGHT_GROUP &fg, REL_GROUP_HASH groupHash, VECTOR center, FLOAT radius, MODEL_NAMES mdl, INT iCnt, BOOL friendly = FALSE, WEAPON_TYPE wpn1 = WEAPONTYPE_PISTOL, WEAPON_TYPE wpn2 = WEAPONTYPE_PISTOL, BOOL bUseCombatParam = FALSE)
SECURE_REQUEST_AND_LOAD_MODEL(mdl)
fg.relGroup = groupHash
fg.iCreateCounter = iCnt
fg.pedModel = mdl
fg.vCenter = center
fg.fRadius = radius
fg.weapon[0] = wpn1
fg.weapon[1] = wpn2
fg.bIsFriendly = friendly
fg.iMaxActivePeds = iCnt
fg.bUseCombatParams = bUseCombatParam
ENDPROC
//------------------------------------------------------------------------------
// FUNCTION: UPDATE_FIGHT_GROUP()
// PURPOSE: THIS UPDATES THE FIGHT GROUP AND MAINTAINS COUNTER
// NOTES: USED INTERNALLY
//------------------------------------------------------------------------------
PROC UPDATE_FIGHT_GROUP(FIGHT_GROUP &fg)
INT i
INT ac
REPEAT COUNT_OF(fg.attackPed) i
IF DOES_ENTITY_EXIST(fg.attackPed[i].pedID)
IF NOT IS_ENTITY_ALIVE(fg.attackPed[i].pedID)
SAFE_REMOVE_BLIP(fg.attackPed[i].blipID)
SAFE_RELEASE_PED(fg.attackPed[i].pedID)
ENDIF
ENDIF
ENDREPEAT
ac = UPDATE_ALIVE_FIGHT_PED_COUNTER(fg)
IF (fg.iCreateCounter > 0) AND (ac < fg.iMaxActivePeds)
SETUP_FIGHT_GROUP(fg, 1)
ENDIF
ENDPROC
//------------------------------------------------------------------------------
// FUNCTION: CLEANUP_FIGHT_GROUP()
// PURPOSE: THIS CLEANSUP THE FIGHT GROUP AND MAINTAINS COUNTER
// NOTES: USED INTERNALLY
//------------------------------------------------------------------------------
PROC CLEANUP_FIGHT_GROUP(FIGHT_GROUP &fg)
INT i
REPEAT COUNT_OF(fg.attackPed) i
SAFE_REMOVE_BLIP(fg.attackPed[i].blipID)
SAFE_RELEASE_PED(fg.attackPed[i].pedID)
ENDREPEAT
IF (fg.pedModel <> DUMMY_MODEL_FOR_SCRIPT)
SET_MODEL_AS_NO_LONGER_NEEDED(fg.pedModel)
fg.pedModel = DUMMY_MODEL_FOR_SCRIPT
ENDIF
ENDPROC
//------------------------------------------------------------------------------
// FUNCTION: CLEANUP_FIGHT_GROUP()
// PURPOSE: THIS CLEANSUP THE FIGHT GROUP AND MAINTAINS COUNTER
// NOTES: USED INTERNALLY
//------------------------------------------------------------------------------
PROC DELETE_FIGHT_GROUP(FIGHT_GROUP &fg)
INT i
REPEAT COUNT_OF(fg.attackPed) i
SAFE_REMOVE_BLIP(fg.attackPed[i].blipID)
SAFE_DELETE_PED(fg.attackPed[i].pedID)
ENDREPEAT
ENDPROC
//----------------------
// EXTERNAL FUNCTIONS
//----------------------
//------------------------------------------------------------------------------
// FUNCTION: ADD_FIGHT_NOSPAWN_AREA()
// PURPOSE: ADD AN ANGLED AREA IN WHICH PEOPLE CAN'T SPAWN IN
//------------------------------------------------------------------------------
PROC ADD_FIGHT_NOSPAWN_AREA(VECTOR p1, VECTOR p2, FLOAT w)
IF (iFightSpawnAreas >= COUNT_OF(fightNoSpawnArea))
SCRIPT_ASSERT("YOU'VE USED MORE THAN MAX AMOUNT OF NO SPAWN AREAS - GET AARON TO INCREASE THE AMOUNT OR USE LESS!")
ENDIF
fightNoSpawnArea[iFightSpawnAreas].vPosition[0] = p1
fightNoSpawnArea[iFightSpawnAreas].vPosition[1] = p2
fightNoSpawnArea[iFightSpawnAreas].fWidth = w
iFightSpawnAreas ++
ENDPROC
//------------------------------------------------------------------------------
// FUNCTION: SET_SIDE_MAX_ACTIVE_PEDS()
// PURPOSE: SETS THE MAX NUMBER OF PEDS ACTIVE IN A SIDE
//------------------------------------------------------------------------------
PROC SET_SIDE_MAX_ACTIVE_PEDS(FIGHT_SIDE side, INT i)
fightGroup[ENUM_TO_INT(side)].iMaxActivePeds = i
ENDPROC
//------------------------------------------------------------------------------
// FUNCTION: SET_SIDE_WEAPONS()
// PURPOSE: SETS WEAPONS FOR A SIDE
//------------------------------------------------------------------------------
PROC SET_SIDE_WEAPONS(FIGHT_SIDE side, WEAPON_TYPE wpn1, WEAPON_TYPE wpn2 = WEAPONTYPE_INVALID)
fightGroup[ENUM_TO_INT(side)].weapon[0] = wpn1
IF NOT (wpn2 <> WEAPONTYPE_INVALID)
fightGroup[ENUM_TO_INT(side)].weapon[0] = wpn2
ENDIF
ENDPROC
//------------------------------------------------------------------------------
// FUNCTION: GET_SIDE_ALIVE_COUNT()
// PURPOSE: RETURNS HOW MANY ARE LEFT ON A SIDE
//------------------------------------------------------------------------------
FUNC INT GET_SIDE_ALIVE_COUNT(FIGHT_SIDE side)
RETURN fightGroup[ENUM_TO_INT(side)].iAliveCounter
ENDFUNC
//------------------------------------------------------------------------------
// FUNCTION: GET_GOOD_GROUP_ALIVE_COUNT()
// PURPOSE: RETURNS HOW MANY ARE LEFT IN GOOD GROUP
//------------------------------------------------------------------------------
FUNC INT GET_GOOD_GROUP_ALIVE_COUNT()
RETURN fightGroup[0].iAliveCounter
ENDFUNC
//------------------------------------------------------------------------------
// FUNCTION: GET_EVIL_GROUP_ALIVE_COUNT()
// PURPOSE: RETURNS HOW MANY ARE LEFT IN EVIL GROUP
//------------------------------------------------------------------------------
FUNC INT GET_EVIL_GROUP_ALIVE_COUNT()
RETURN fightGroup[1].iAliveCounter
ENDFUNC
//------------------------------------------------------------------------------
// FUNCTION: INIT_GOOD_FIGHT_GROUP()
// PURPOSE: SETS UPS GOOD FIGHT GROUP
// NOTES: ONLY CALL THIS ONCE
//------------------------------------------------------------------------------
PROC INIT_GOOD_FIGHT_GROUP(REL_GROUP_HASH groupHash, VECTOR center, FLOAT radius, MODEL_NAMES mdl, INT iCnt, BOOL friendly = FALSE, WEAPON_TYPE wpn1 = WEAPONTYPE_PISTOL, WEAPON_TYPE wpn2 = WEAPONTYPE_PISTOL, BOOL bUseCombatParam = FALSE)
INIT_FIGHT_GROUP(fightGroup[0], groupHash, center, radius, mdl, iCnt, friendly, wpn1, wpn2, bUseCombatParam)
ENDPROC
//------------------------------------------------------------------------------
// FUNCTION: INIT_EVIL_FIGHT_GROUP()
// PURPOSE: SETS UPS EVIL FIGHT GROUP
// NOTES: ONLY CALL THIS ONCE
//------------------------------------------------------------------------------
PROC INIT_EVIL_FIGHT_GROUP(REL_GROUP_HASH groupHash, VECTOR center, FLOAT radius, MODEL_NAMES mdl, INT iCnt, BOOL friendly = FALSE, WEAPON_TYPE wpn1 = WEAPONTYPE_PISTOL, WEAPON_TYPE wpn2 = WEAPONTYPE_PISTOL, BOOL bUseCombatParam = FALSE)
INIT_FIGHT_GROUP(fightGroup[1], groupHash, center, radius, mdl, iCnt, friendly, wpn1, wpn2, bUseCombatParam)
ENDPROC
//------------------------------------------------------------------------------
// FUNCTION: UPDATE_FIGHT_GROUPS()
// PURPOSE: UPDATES FIGHT GROUPS
//------------------------------------------------------------------------------
PROC UPDATE_FIGHT_GROUPS()
UPDATE_FIGHT_GROUP(fightGroup[0])
UPDATE_FIGHT_GROUP(fightGroup[1])
ENDPROC
//------------------------------------------------------------------------------
// FUNCTION: CLEANUP_FIGHT_GROUPS()
// PURPOSE: UPDATES FIGHT GROUPS
//------------------------------------------------------------------------------
PROC CLEANUP_FIGHT_GROUPS()
CLEANUP_FIGHT_GROUP(fightGroup[0])
CLEANUP_FIGHT_GROUP(fightGroup[1])
ENDPROC
//------------------------------------------------------------------------------
// FUNCTION: DELETE_FIGHT_GROUPS()
// PURPOSE: DELETES FIGHT GROUPS
//------------------------------------------------------------------------------
PROC DELETE_FIGHT_GROUPS()
DELETE_FIGHT_GROUP(fightGroup[0])
DELETE_FIGHT_GROUP(fightGroup[1])
ENDPROC