// ***************************************************************************************** // ***************************************************************************************** // // 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