3168 lines
88 KiB
Scheme
Executable File
3168 lines
88 KiB
Scheme
Executable File
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
//
|
|
// FILE NAME : rgeneral_include.sch
|
|
// AUTHOR : Aaron Gandaa
|
|
// DESCRIPTION : Handy functions for spawn points and stuff
|
|
//
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
|
|
//----------------------
|
|
// INCLUDES
|
|
//----------------------
|
|
USING "rage_builtins.sch"
|
|
USING "globals.sch"
|
|
USING "commands_script.sch"
|
|
USING "commands_entity.sch"
|
|
USING "commands_object.sch"
|
|
USING "commands_hud.sch"
|
|
USING "commands_misc.sch"
|
|
USING "script_maths.sch"
|
|
USING "script_ped.sch"
|
|
USING "shared_hud_displays.sch"
|
|
|
|
//----------------------
|
|
// ENUMS
|
|
//----------------------
|
|
ENUM STAGE_PROGRESS
|
|
SP_LOADING,
|
|
SP_SETUP,
|
|
SP_RUNNING,
|
|
SP_CSKIPPED,
|
|
SP_CLEANUP
|
|
ENDENUM
|
|
|
|
ENUM RAND_GENTYPE
|
|
RAND_STICK,
|
|
RAND_LIM,
|
|
RAND_GERHARD,
|
|
RAND_BILL
|
|
ENDENUM
|
|
|
|
ENUM PLANE_SIDE
|
|
INFRONT_PLANE = 1,
|
|
BEHIND_PLANE = -1,
|
|
ON_PLANE = 0
|
|
ENDENUM
|
|
|
|
STRUCT COMBAT_PARAMETERS
|
|
FIRING_PATTERN_HASH hFiringPattern = FIRING_PATTERN_DELAY_FIRE_BY_ONE_SEC
|
|
|
|
FLOAT fPlayerWeaponDamageModifier = 1.0 // set this to increase or decrease damage dealt out by player
|
|
FLOAT fPlayerWeaponDefenseModifier = 1.0 // set this to increase or decrease damage taken by player
|
|
FLOAT fPlayerMeleeWeaponDefenseModifier = 1.0 // set this to increase or decrease melee damage taken by player
|
|
|
|
FLOAT fWeaponAccuracy1 = 0.075
|
|
FLOAT fWeaponAccuracy2 = 0.075
|
|
|
|
FLOAT fNearBlankChance = 0.0 // default in code
|
|
FLOAT fFarBlankChance = 0.5 // default in code
|
|
FLOAT fFlankChance = 0.2
|
|
FLOAT fCoverOnlyChance = 0.0
|
|
|
|
FLOAT fMinTimeBetweenPeeks = 10.0 // default in code
|
|
FLOAT fMaxTimeBetweenPeeks = 11.0
|
|
|
|
FLOAT fMinTimeBetweenCoverBurst = 1.25 // default in code
|
|
FLOAT fMaxTimeBetweenCoverBurst = 2.25
|
|
|
|
FLOAT fMinBurstDurationTime = 2.0 // default in code
|
|
FLOAT fMaxBurstDurationTime = 2.5
|
|
|
|
INT iMinShootRate = 99
|
|
INT iMaxShootRate = 100
|
|
|
|
INT iForcedCombatLevel = -1 // -1 - pick a random level, 0 - poor, 1 - average, 2 - pro
|
|
INT iForcedCombatRange = -1 // -1 - pick a random range, 0 - near, 1 - medium, 2 - far
|
|
|
|
FLOAT fAgressionChance = 0.5
|
|
ENDSTRUCT
|
|
|
|
//----------------------
|
|
// STRUCT
|
|
//----------------------
|
|
STRUCT COLOR_STRUCT
|
|
INT r
|
|
INT g
|
|
INT b
|
|
INT a
|
|
ENDSTRUCT
|
|
|
|
STRUCT ANGLED_AREA
|
|
VECTOR vPosition[2]
|
|
FLOAT fWidth
|
|
ENDSTRUCT
|
|
|
|
//----------------------
|
|
// CONST
|
|
//----------------------
|
|
CONST_INT ONE_MINUTE 60000
|
|
CONST_INT REQUEST_TIMEOUT 7500
|
|
CONST_INT MAX_PASSENGERS_IN_VEHICLE 16 // MAX_VEHICLE_SEATS=16 in VehicleDefines.h
|
|
|
|
//----------------------
|
|
// VARIABLES
|
|
//----------------------
|
|
INT iMissionDebugTime
|
|
BOOL bShowDebugMissionTime
|
|
INT iCurrentGameTime
|
|
|
|
//----------------------
|
|
// INTERP FUNCS
|
|
//-----------------------
|
|
|
|
/// PURPOSE:
|
|
/// Oscillates a Value using a sine wave
|
|
/// PARAMS:
|
|
/// ang - this is the value we use as the oscilator
|
|
/// t - the period of the oscilation
|
|
/// RETURNS:
|
|
/// Oscilated value
|
|
FUNC FLOAT SINE_OSCILLATOR(FLOAT &ang, FLOAT t)
|
|
ang += ((360.0 * GET_FRAME_TIME()) / t)
|
|
IF (ang > 360.0)
|
|
ang -= 360.0
|
|
ENDIF
|
|
RETURN SIN(ang)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Oscillates a Value using a sine wave
|
|
/// PARAMS:
|
|
/// ang - this is the value we use as the oscilator
|
|
/// t - the period of the oscilation
|
|
/// RETURNS:
|
|
/// Oscilated value
|
|
FUNC FLOAT COSINE_OSCILLATOR(FLOAT &ang, FLOAT t)
|
|
ang += ((360.0 * GET_FRAME_TIME()) / t)
|
|
IF (ang > 360.0)
|
|
ang -= 360.0
|
|
ENDIF
|
|
RETURN COS(ang)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// To Linearly Interpolate 2 Ints
|
|
/// PARAM
|
|
/// i1 - Source Int
|
|
/// i2 - Target Int
|
|
/// t - how far you want to interpolate (0 = i1, 1 = t2)
|
|
/// RETURNS:
|
|
/// An int with the interpolated value
|
|
FUNC INT INTERPOLATE_INT(INT i1, INT i2, FLOAT t)
|
|
INT out
|
|
FLOAT f = TO_FLOAT(i1) + ((TO_FLOAT(i2 - i1)) * t)
|
|
|
|
out = CEIL(f)
|
|
IF (out < i1)
|
|
out = i1
|
|
ENDIF
|
|
|
|
IF (out > i2)
|
|
out = i2
|
|
ENDIF
|
|
|
|
RETURN out
|
|
ENDFUNC
|
|
|
|
FUNC FLOAT INTERPOLATE_FLOAT(FLOAT f1, FLOAT f2, FLOAT t, BOOL bClamp = TRUE)
|
|
IF (bClamp)
|
|
t = CLAMP(t, 0, 1)
|
|
ENDIF
|
|
|
|
RETURN f1 + (t * (f2 - f1))
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// To Linearly Interpolate 2 Vectors
|
|
/// PARAM
|
|
/// i1 - Source Vector
|
|
/// i2 - Target Vector
|
|
/// t - how far you want to interpolate (0 = i1, 1 = t2)
|
|
/// RETURNS:
|
|
/// A vector with the interpolated value
|
|
FUNC VECTOR INTERPOLATE_VECTOR(VECTOR v1, VECTOR v2, FLOAT t, BOOL bClamp = TRUE)
|
|
IF (bClamp)
|
|
t = CLAMP(t, 0, 1)
|
|
ENDIF
|
|
|
|
RETURN v1 + (t * (v2 - v1))
|
|
ENDFUNC
|
|
|
|
FUNC INT FSGN(FLOAT f)
|
|
IF (f < 0.0)
|
|
RETURN -1
|
|
ELSE
|
|
RETURN 1
|
|
ENDIF
|
|
ENDFUNC
|
|
|
|
//----------------------
|
|
// AREA FUNCS
|
|
//-----------------------
|
|
|
|
/// PURPOSE:
|
|
/// Sets up an Angled Area Struct
|
|
/// PARAM
|
|
/// a - Area Reference
|
|
/// v1 - Area Point 1
|
|
/// v2 - Area Point 2
|
|
/// w - Width of the area
|
|
PROC SET_ANGLED_AREA(ANGLED_AREA &a, VECTOR v1, VECTOR v2, FLOAT w)
|
|
a.vPosition[0] = v1
|
|
a.vPosition[1] = v2
|
|
a.fWidth = w
|
|
ENDPROC
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
/// PURPOSE:
|
|
/// Creates and Angled Area Debug Widget
|
|
PROC SETUP_ANGLED_AREA_DEBUG_WIDGET(ANGLED_AREA &area, STRING nme, INT idx = -1)
|
|
TEXT_LABEL sLabel = nme
|
|
|
|
IF (idx >= 0)
|
|
sLabel += idx
|
|
ENDIF
|
|
|
|
START_WIDGET_GROUP(sLabel)
|
|
ADD_WIDGET_VECTOR_SLIDER("Point 1", area.vPosition[0], -5000.0, 5000.0, 10.0)
|
|
ADD_WIDGET_VECTOR_SLIDER("Point 2", area.vPosition[1], -5000.0, 5000.0, 10.0)
|
|
ADD_WIDGET_FLOAT_SLIDER("Width", area.fWidth, 0.0, 200.0, 0.1)
|
|
STOP_WIDGET_GROUP()
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
///
|
|
/// PARAMS:
|
|
/// model_name -
|
|
/// AUTHOR: alwyn.roberts@rockstarnorth.com
|
|
/// COMMENTS:
|
|
PROC ADD_WIDGET_READ_ONLY_VECTOR(STRING name, VECTOR &pos_to_change)
|
|
TEXT_LABEL_63 slider_name = name
|
|
slider_name += " x"
|
|
ADD_WIDGET_FLOAT_READ_ONLY(slider_name, pos_to_change.x)
|
|
slider_name = name
|
|
slider_name += " y"
|
|
ADD_WIDGET_FLOAT_READ_ONLY(slider_name, pos_to_change.y)
|
|
slider_name = name
|
|
slider_name += " z"
|
|
ADD_WIDGET_FLOAT_READ_ONLY(slider_name, pos_to_change.z)
|
|
ENDPROC
|
|
|
|
#ENDIF
|
|
|
|
//----------------------
|
|
// COLOR FUNCS
|
|
//-----------------------
|
|
|
|
/// PURPOSE:
|
|
/// Populates a color struct
|
|
/// PARAMS:
|
|
/// col - color struct reference
|
|
/// r - red component (0 - 255)
|
|
/// g - green component (0 - 255)
|
|
/// b - blue component (0 - 255)
|
|
/// a - alpha component (0 - 255)
|
|
PROC SET_COLOR_STRUCT(COLOR_STRUCT &col, INT r, INT g, INT b, INT a)
|
|
col.r = r
|
|
col.g = g
|
|
col.b = b
|
|
col.a = a
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// To Linearly Interpolate 2 Color
|
|
/// PARAM
|
|
/// i1 - Source Color
|
|
/// i2 - Target Color
|
|
/// t - how far you want to interpolate (0 = i1, 1 = t2)
|
|
/// RETURNS:
|
|
/// A Color Struct with the interpolated value
|
|
FUNC COLOR_STRUCT INTERPOLATE_COLOR_STRUCT(COLOR_STRUCT src, COLOR_STRUCT des, FLOAT t)
|
|
COLOR_STRUCT out
|
|
|
|
out.r = INTERPOLATE_INT(src.r, des.r, t)
|
|
out.g = INTERPOLATE_INT(src.g, des.g, t)
|
|
out.b = INTERPOLATE_INT(src.b, des.b, t)
|
|
out.a = INTERPOLATE_INT(src.a, des.a, t)
|
|
|
|
RETURN out
|
|
ENDFUNC
|
|
|
|
//----------------------
|
|
// ENTITY FUNCS
|
|
//-----------------------
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Sets the alpha on a ped
|
|
/// PARAMS:
|
|
/// ind - ped index
|
|
/// val - value for 0 to 255
|
|
/// ac - alpha counter if this gets over 8 - it won't set alpha
|
|
PROC SET_PED_ALPHA(PED_INDEX ind, INT val, INT &ac)
|
|
IF (ac >= 8)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SET_ENTITY_ALPHA(ind, val, FALSE)
|
|
ac ++
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Sets the alpha on a ped
|
|
/// PARAMS:
|
|
/// ind - ped index
|
|
/// val - value for 0 to 255
|
|
/// ac - alpha counter if this gets over 8 - it won't set alpha
|
|
PROC SET_VEHICLE_ALPHA(VEHICLE_INDEX ind, INT val, INT &ac)
|
|
IF (ac >= 8)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SET_ENTITY_ALPHA(ind, val, FALSE)
|
|
ac ++
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Check if an entity exists and is alive
|
|
FUNC BOOL IS_ENTITY_OK(ENTITY_INDEX ent)
|
|
IF NOT DOES_ENTITY_EXIST(ent)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN NOT IS_ENTITY_DEAD(ent)
|
|
ENDFUNC
|
|
|
|
|
|
FUNC BOOL IS_PLAYER_UPRIGHT()
|
|
// check vehicle is upright
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
VEHICLE_INDEX veh = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
|
|
RETURN IS_ENTITY_UPRIGHT(veh)
|
|
ENDIF
|
|
|
|
RETURN IS_ENTITY_UPRIGHT(PLAYER_PED_ID())
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets Ratio Of Ped Health
|
|
/// PARAMS:
|
|
/// ped -
|
|
/// RETURNS:
|
|
/// 1.0 if at full hp
|
|
FUNC FLOAT GET_PED_HEALTH_RATIO(PED_INDEX ped)
|
|
IF NOT IS_ENTITY_OK(ped)
|
|
RETURN 0.0
|
|
ENDIF
|
|
|
|
RETURN TO_FLOAT(GET_ENTITY_HEALTH(ped)) / TO_FLOAT(GET_PED_MAX_HEALTH(ped))
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Creates a fake weapon for the player to drop
|
|
/// Be aware calling this will remove all the player's actual weapons
|
|
/// PARAMS:
|
|
/// wpn - the weapontype of the weapon to drop
|
|
/// bLeftHand - set this to true to put weapon in left hand
|
|
/// RETURNS:
|
|
/// Object Index of the fake weapon - you need to call DETACH_ENTITY on this object 1 frame later to drop it
|
|
FUNC OBJECT_INDEX CREATE_FAKE_WEAPON_FOR_PLAYER(WEAPON_TYPE wpn, BOOL bLeftHand = FALSE)
|
|
OBJECT_INDEX obj
|
|
PED_BONETAG bonehand = BONETAG_PH_R_HAND
|
|
|
|
// if the player is dead - bail and return nothing
|
|
IF NOT IS_ENTITY_OK(PLAYER_PED_ID())
|
|
RETURN NULL
|
|
ENDIF
|
|
|
|
// sanity check to make sure people aren't trying to create stupid things
|
|
IF (wpn = WEAPONTYPE_INVALID) OR (wpn = WEAPONTYPE_UNARMED)
|
|
RETURN NULL
|
|
ENDIF
|
|
|
|
// just incase we want the left hand (why as left handed people are evil...)
|
|
IF (bLeftHand = TRUE)
|
|
bonehand = BONETAG_PH_L_HAND
|
|
ENDIF
|
|
|
|
// remove and create weapon
|
|
REMOVE_ALL_PED_WEAPONS(PLAYER_PED_ID())
|
|
obj = CREATE_OBJECT_NO_OFFSET(GET_WEAPONTYPE_MODEL(wpn), GET_PED_BONE_COORDS(PLAYER_PED_ID(), bonehand, <<0, 0, 0>>))
|
|
IF NOT DOES_ENTITY_EXIST(obj)
|
|
RETURN NULL
|
|
ENDIF
|
|
|
|
// attach weapon and finalize
|
|
ATTACH_ENTITY_TO_ENTITY(obj, PLAYER_PED_ID(), GET_PED_BONE_INDEX(PLAYER_PED_ID(), bonehand), <<0, 0, 0>>, <<0, 0, 0>>)
|
|
RETURN obj
|
|
ENDFUNC
|
|
|
|
PROC SAFE_REMOVE_PARTICLE_FX(PTFX_ID &id)
|
|
IF (id <> NULL)
|
|
|
|
// also stop it if it is looped
|
|
IF DOES_PARTICLE_FX_LOOPED_EXIST(id)
|
|
STOP_PARTICLE_FX_LOOPED(id)
|
|
ELSE
|
|
REMOVE_PARTICLE_FX(id)
|
|
ENDIF
|
|
id = NULL
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
//----------------------
|
|
// LINE FUNCS
|
|
//-----------------------
|
|
|
|
|
|
FUNC BOOL IS_DIRECTION_WITHIN_DEGRESS_OF_DESIRED_DIRECTION(VECTOR fwd, VECTOR ddir, FLOAT angle)
|
|
RETURN ACOS(ABSF(DOT_PRODUCT(ddir, fwd))) <= angle
|
|
ENDFUNC
|
|
|
|
FUNC BOOL IS_DIRECTION_WITHIN_DEGRESS_OF_DESIRED_DIRECTION_2D(VECTOR fwd, VECTOR ddir, FLOAT angle)
|
|
RETURN ACOS(ABSF(DOT_PRODUCT(ddir, fwd))) <= angle
|
|
ENDFUNC
|
|
|
|
FUNC BOOL IS_DIRECTION_WITHIN_DEGRESS_OF_DESIRED_DIRECTION_SIGNED(VECTOR fwd, VECTOR ddir, FLOAT angle)
|
|
RETURN ACOS(DOT_PRODUCT(ddir, fwd)) <= angle
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Check if an entity is range m from a position in 2d
|
|
/// PARAMS:
|
|
/// ent - Entity
|
|
/// pos - Position
|
|
/// range - distance we want to check
|
|
FUNC BOOL IS_ENTITY_IN_RANGE_COORDS_2D(ENTITY_INDEX ent, VECTOR pos, FLOAT range)
|
|
VECTOR ve = GET_ENTITY_COORDS(ent)
|
|
VECTOR v = pos - ve
|
|
RETURN ((v.x * v.x) + (v.y * v.y)) <= (range * range)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Calculates the length a line between 2 points
|
|
/// PARAMS:
|
|
/// stt - Line Start
|
|
/// end - Line End
|
|
/// RETURNS:
|
|
/// Length of Line
|
|
FUNC FLOAT GET_LINE_MAGNITUDE(VECTOR stt, VECTOR end)
|
|
VECTOR v = end - stt
|
|
RETURN SQRT(v.x * v.x + v.y * v.y + v.z * v.z)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Calculates the Squared length a line between 2 points
|
|
/// PARAMS:
|
|
/// stt - Line Start
|
|
/// end - Line End
|
|
/// RETURNS:
|
|
/// Squared Length of Line
|
|
FUNC FLOAT GET_LINE_MAGNITUDE_SQUARED(VECTOR stt, VECTOR end)
|
|
VECTOR v = end - stt
|
|
RETURN (v.x * v.x + v.y * v.y + v.z * v.z)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets the closest point on a line and the interpolate value
|
|
/// PARAMS:
|
|
/// p - point we want to check how close to the line it is
|
|
/// vStart - line Start
|
|
/// vEnd - line End
|
|
/// bClamp - do we clamp this to the end points
|
|
/// RETURNS:
|
|
/// Returns the closest point
|
|
//FUNC VECTOR GET_CLOSEST_POINT_ON_LINE(VECTOR p, VECTOR vStart, VECTOR vEnd, BOOL bClamp = TRUE)
|
|
// VECTOR diff = (vEnd - vStart)
|
|
// FLOAT u = GET_RATIO_OF_CLOSEST_POINT_ON_LINE(p, vStart, vEnd, bClamp)
|
|
// RETURN vStart + (u * diff)
|
|
//ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets the closest point on a plane to a position
|
|
/// PARAMS:
|
|
/// in - point we want to check how close to the plane
|
|
/// pNorm - plane normal
|
|
/// pOrg - plane origin
|
|
/// RETURNS:
|
|
/// Returns the closest point on plane
|
|
FUNC VECTOR GET_CLOSEST_POINT_ON_PLANE(VECTOR in, VECTOR pNorm, VECTOR pOrg)
|
|
FLOAT D = DOT_PRODUCT(pNorm, pOrg)
|
|
FLOAT t = DOT_PRODUCT(pNorm, in) - D
|
|
RETURN in - (t * pNorm)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets the distance from an infinite plane to a point
|
|
/// PARAMS:
|
|
/// in - point we want to check how close to the plane
|
|
/// pNorm - plane normal
|
|
/// pOrg - plane origin
|
|
/// RETURNS:
|
|
/// Returns the distance to closest point on plane
|
|
FUNC FLOAT GET_DISTANCE_TO_PLANE(VECTOR in, VECTOR pNorm, VECTOR pOrg)
|
|
FLOAT D = DOT_PRODUCT(pNorm, pOrg)
|
|
FLOAT t = DOT_PRODUCT(pNorm, in) - D
|
|
RETURN t / DOT_PRODUCT(pNorm, pNorm)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Tells what side of a plane a point is on
|
|
/// PARAMS:
|
|
/// pNorm - plane normal
|
|
/// pOrg - plane origin
|
|
/// v - point we want to check
|
|
/// RETURNS:
|
|
/// Returns -1 if behind plane, +1 if in front and 0 if on plane
|
|
FUNC PLANE_SIDE GET_PLANE_SIDE(VECTOR pNorm, VECTOR pOrg, VECTOR v)
|
|
FLOAT dot = DOT_PRODUCT(v - pOrg, pNorm)
|
|
IF (dot < 0)
|
|
RETURN BEHIND_PLANE
|
|
ELIF (dot > 0)
|
|
RETURN INFRONT_PLANE
|
|
ENDIF
|
|
|
|
RETURN ON_PLANE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Tells where on an infinite plane a given line will intersect
|
|
/// PARAMS:
|
|
/// out - position where line will intersect (this is overwritten)
|
|
/// p1 - line start
|
|
/// p2 - lien end
|
|
/// pNorm - plane normal
|
|
/// pOrg - plane origin
|
|
/// RETURNS:
|
|
/// If this returns false the line will never touch the plane
|
|
FUNC BOOL GET_LINE_PLANE_INTERSECT(VECTOR &out, VECTOR p1, VECTOR p2, VECTOR pNorm, VECTOR pOrg)
|
|
VECTOR u = p2 - p1
|
|
VECTOR w = p1 - pOrg
|
|
|
|
FLOAT D = DOT_PRODUCT(pNorm, u)
|
|
FLOAT N = -DOT_PRODUCT(pNorm, w)
|
|
FLOAT SI
|
|
|
|
// line is either parallel or doesn't intersect
|
|
IF (ABSF(D) < 0.00000001)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
SI = N / D
|
|
out = p1 + (SI * u)
|
|
|
|
// no intersection
|
|
IF (SI < 0) OR (SI > 1)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Tells whether a line and sphere will intersect
|
|
/// PARAMS:
|
|
/// p1 - line start
|
|
/// p2 - lien end
|
|
/// sc - sphere center
|
|
/// r - sphere radius
|
|
/// RETURNS:
|
|
/// If this returns false the line will never touch the sphere
|
|
FUNC BOOL DOES_LINE_SPHERE_INTERSECT(VECTOR p1, VECTOR p2, VECTOR sc, FLOAT r)
|
|
|
|
FLOAT a,b,c
|
|
FLOAT bb4ac
|
|
VECTOR dp
|
|
|
|
// horrible vector stuff - i didn't quite understand at school
|
|
// i'll simplfy and comment this properly later
|
|
dp = p2 - p1
|
|
a = dp.x * dp.x + dp.y * dp.y + dp.z * dp.z
|
|
|
|
b = 2 * (dp.x * (p1.x - sc.x) + dp.y * (p1.y - sc.y) + dp.z * (p1.z - sc.z))
|
|
|
|
c = sc.x * sc.x + sc.y * sc.y + sc.z * sc.z
|
|
c += p1.x * p1.x + p1.y * p1.y + p1.z * p1.z
|
|
c -= 2 * (sc.x * p1.x + sc.y * p1.y + sc.z * p1.z)
|
|
c -= r * r
|
|
|
|
bb4ac = b * b - 4 * a * c
|
|
IF (ABSF(a) < 0.00001) OR (bb4ac <= 0.0)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets Heading given 2 coords
|
|
/// PARAMS:
|
|
/// oldCoords - source point
|
|
/// newCoords - target point
|
|
/// invert - this is true (just keep it as true)
|
|
/// RETURNS:
|
|
/// Heading
|
|
FUNC FLOAT GET_HEADING_FROM_COORDS(vector oldCoords,vector newCoords, bool invert=true)
|
|
float heading
|
|
float dX = newCoords.x - oldCoords.x
|
|
float dY = newCoords.y - oldCoords.y
|
|
if dY != 0
|
|
heading = ATAN2(dX,dY)
|
|
ELSE
|
|
if dX < 0
|
|
heading = -90
|
|
ELSE
|
|
heading = 90
|
|
ENDIF
|
|
ENDIF
|
|
|
|
//flip because for some odd reason the coders think west is a heading of 90 degrees, so this'll match the output of commands such as GET_ENTITY_HEADING()
|
|
IF invert = TRUE
|
|
heading *= -1.0
|
|
//below not necessary but helps for debugging
|
|
IF heading < 0
|
|
heading += 360.0
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN heading
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets Heading from 1 entity to another
|
|
/// PARAMS:
|
|
/// oldEnd - source entity
|
|
/// newEnd - target entity
|
|
/// invert - this is true (just keep it as true)
|
|
/// RETURNS:
|
|
/// Heading
|
|
FUNC FLOAT GET_HEADING_FROM_ENTITIES(entity_index oldEnd, entity_index newEnt, bool invert=true)
|
|
vector v1,v2
|
|
v1 = GET_ENTITY_COORDS(oldEnd,FALSE)
|
|
v2 = GET_ENTITY_COORDS(newEnt,FALSE)
|
|
RETURN GET_HEADING_FROM_COORDS(v1,v2, invert)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets Pitch and Heading from a direction vector
|
|
/// PARAMS:
|
|
/// dir - direction vector
|
|
/// pitch - returned pitch
|
|
/// head - returned heading
|
|
/// invert - this is true (just keep it as true)
|
|
PROC GET_PITCH_AND_HEADING_FROM_DIRECTION_VECTOR(VECTOR dir, FLOAT &pitch, FLOAT &head, bool invert=true)
|
|
|
|
float sq
|
|
|
|
if dir.y != 0
|
|
head = ATAN2(dir.x, dir.y)
|
|
ELSE
|
|
if dir.x < 0
|
|
head = -90
|
|
ELSE
|
|
head = 90
|
|
ENDIF
|
|
ENDIF
|
|
|
|
//flip because for some odd reason the coders think west is a heading of 90 degrees, so this'll match the output of commands such as GET_ENTITY_HEADING()
|
|
IF invert = TRUE
|
|
head *= -1.0
|
|
//below not necessary but helps for debugging
|
|
IF head < 0
|
|
head += 360.0
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// now do pitch
|
|
sq = SQRT((dir.x * dir.x) + (dir.y * dir.y))
|
|
IF (sq != 0)
|
|
pitch = ATAN2(dir.z, sq)
|
|
ELSE
|
|
IF (dir.z < 0)
|
|
pitch = -90
|
|
ELSE
|
|
pitch = 90
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Gets Pitch and Heading from 1 entity to another
|
|
/// PARAMS:
|
|
/// oldCoords - source point
|
|
/// newCoords - target point
|
|
/// pitch - returned pitch
|
|
/// head - returned heading
|
|
/// invert - this is true (just keep it as true)
|
|
PROC GET_PITCH_AND_HEADING_FROM_COORDS(VECTOR oldCoords, VECTOR newCoords, FLOAT &pitch, FLOAT &head, bool invert=true)
|
|
VECTOR diff = newCoords - oldCoords
|
|
GET_PITCH_AND_HEADING_FROM_DIRECTION_VECTOR(diff, pitch, head, invert)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Gets Pitch given 2 coords
|
|
/// PARAMS:
|
|
/// oldCoords - source point
|
|
/// newCoords - target point
|
|
/// RETURNS:
|
|
/// Pitch
|
|
FUNC FLOAT GET_PITCH_FROM_COORDS(vector oldCoords,vector newCoords)
|
|
float pitch
|
|
float dX = newCoords.z - oldCoords.z
|
|
float dY = newCoords.y - oldCoords.y
|
|
float dZ = newCoords.z - oldCoords.z
|
|
float sq
|
|
|
|
// now do pitch
|
|
sq = SQRT((dx * dx) + (dy * dy))
|
|
IF (sq != 0)
|
|
pitch = ATAN2(dZ, sq)
|
|
ELSE
|
|
IF (dZ < 0)
|
|
pitch = -90
|
|
ELSE
|
|
pitch = 90
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN pitch
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Is Sphere Occupied - Just an override for IS_AREA_OCCUPIED that takes into account spheres
|
|
/// PARAMS:
|
|
/// v - sphere center
|
|
/// r - sphere radius
|
|
/// RETURNS:
|
|
FUNC BOOL IS_SPHERE_OCCUPIED(VECTOR v, FLOAT r, BOOL bBuildingFlag, BOOL bVehicleFlag, BOOL bPedFlag, BOOL bObjectFlag, BOOL bDummyFlag, ENTITY_INDEX ExcludeEntityIndex = NULL, BOOL bCheckAlive = FALSE)
|
|
//RETURN IS_AREA_OCCUPIED(v - <<r, r, r>>, v + <<r, r, r>>, bBuildingFlag, bVehicleFlag, bPedFlag, bObjectFlag, bDummyFlag, ExcludeEntityIndex, bCheckAlive)
|
|
RETURN IS_POSITION_OCCUPIED(v, r, bBuildingFlag, bVehicleFlag, bPedFlag, bObjectFlag, bDummyFlag, ExcludeEntityIndex, bCheckAlive)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Just an override for IS_AREA_OCCUPIED that takes into account spheres and only checks for peds
|
|
/// PARAMS:
|
|
/// v - sphere center
|
|
/// r - sphere radius
|
|
FUNC BOOL IS_ANY_PED_IN_SPHERE(VECTOR v, FLOAT r, ENTITY_INDEX ExcludeEntityIndex = NULL, BOOL bCheckAlive = TRUE)
|
|
RETURN IS_POSITION_OCCUPIED(v, r, FALSE, FALSE, TRUE, FALSE, FALSE, ExcludeEntityIndex, bCheckAlive)
|
|
ENDFUNC
|
|
|
|
//----------------------
|
|
// MISC FUNCS
|
|
//-----------------------
|
|
|
|
/// PURPOSE:
|
|
/// Enables or Disables all Dispatch Services
|
|
/// PARAMS:
|
|
/// ok - set true to turn them on
|
|
PROC ENABLE_ALL_DISPATCH_SERVICES(BOOL ok = TRUE)
|
|
ENABLE_DISPATCH_SERVICE(DT_POLICE_HELICOPTER, ok)
|
|
ENABLE_DISPATCH_SERVICE(DT_FIRE_DEPARTMENT, ok)
|
|
ENABLE_DISPATCH_SERVICE(DT_SWAT_AUTOMOBILE, ok)
|
|
ENABLE_DISPATCH_SERVICE(DT_AMBULANCE_DEPARTMENT, ok)
|
|
ENABLE_DISPATCH_SERVICE(DT_POLICE_RIDERS, ok)
|
|
ENABLE_DISPATCH_SERVICE(DT_POLICE_VEHICLE_REQUEST, ok)
|
|
ENABLE_DISPATCH_SERVICE(DT_POLICE_ROAD_BLOCK, ok)
|
|
ENABLE_DISPATCH_SERVICE(DT_POLICE_AUTOMOBILE_WAIT_PULLED_OVER, ok)
|
|
ENABLE_DISPATCH_SERVICE(DT_POLICE_AUTOMOBILE_WAIT_CRUISING, ok)
|
|
ENABLE_DISPATCH_SERVICE(DT_GANGS, ok)
|
|
ENABLE_DISPATCH_SERVICE(DT_SWAT_HELICOPTER, ok)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Enables or Disables all Ambient Cars and Peds
|
|
/// PARAMS:
|
|
/// pedok - set true to turn peds on
|
|
/// carok - set true to turn cars on
|
|
PROC ENABLE_AMBIENT_PEDS_AND_VEHICLES(BOOL pedok = TRUE, BOOL carok = TRUE, BOOL clearpeds = FALSE, BOOL clearcars = FALSE)
|
|
|
|
IF (pedok = TRUE)
|
|
SET_PED_POPULATION_BUDGET(1)
|
|
SET_PED_DENSITY_MULTIPLIER_THIS_FRAME(1)
|
|
SET_SCENARIO_PED_DENSITY_MULTIPLIER_THIS_FRAME(1, 1)
|
|
ELSE
|
|
SET_PED_POPULATION_BUDGET(0)
|
|
SET_PED_DENSITY_MULTIPLIER_THIS_FRAME(0)
|
|
SET_SCENARIO_PED_DENSITY_MULTIPLIER_THIS_FRAME(0, 0)
|
|
ENDIF
|
|
|
|
IF (carok = TRUE)
|
|
SET_VEHICLE_POPULATION_BUDGET(1)
|
|
SET_RANDOM_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(1)
|
|
SET_PARKED_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(1)
|
|
ELSE
|
|
SET_VEHICLE_POPULATION_BUDGET(0)
|
|
SET_RANDOM_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(0)
|
|
SET_PARKED_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(0)
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_OK(PLAYER_PED_ID())
|
|
IF clearpeds = TRUE
|
|
CLEAR_AREA_OF_PEDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), 100.0)
|
|
ENDIF
|
|
IF clearcars = TRUE
|
|
CLEAR_AREA_OF_VEHICLES(GET_ENTITY_COORDS(PLAYER_PED_ID()), 100.0)
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Draw a circle in debug mode
|
|
/// PARAMS:
|
|
/// center - circle center
|
|
/// radius - circle radius
|
|
/// r, g, b, a - red/green/blue/alpha components
|
|
/// sides - how smooth the circle is
|
|
PROC DRAW_DEBUG_CIRCLE(VECTOR center, FLOAT radius, INT r = 0, INT g = 0, INT b = 255, INT a = 255, INT sides = 32)
|
|
INT i
|
|
FLOAT ainc = 360.0 / TO_FLOAT(sides)
|
|
VECTOR lastpos = center
|
|
VECTOR nextpos = center
|
|
FLOAT angle = 0
|
|
|
|
lastpos = center
|
|
lastpos.x += (SIN(angle - ainc) * radius)
|
|
lastpos.y += (COS(angle - ainc) * radius)
|
|
|
|
FOR i = 0 TO sides
|
|
nextpos = center
|
|
nextpos.x += (SIN(angle) * radius)
|
|
nextpos.y += (COS(angle) * radius)
|
|
|
|
DRAW_DEBUG_LINE(lastpos, nextpos, r, g, b, a)
|
|
lastpos = nextpos
|
|
angle += ainc
|
|
ENDFOR
|
|
ENDPROC
|
|
|
|
PROC DRAW_DEBUG_CYLINDER(VECTOR center, FLOAT radius, FLOAT height, INT r = 0, INT g = 0, INT b = 255, INT a = 255, INT sides = 32)
|
|
INT i
|
|
FLOAT ainc = 360.0 / TO_FLOAT(sides)
|
|
VECTOR lastpos = center
|
|
VECTOR nextpos = center
|
|
FLOAT angle = 0
|
|
|
|
lastpos = center
|
|
lastpos.x += (SIN(angle - ainc) * radius)
|
|
lastpos.y += (COS(angle - ainc) * radius)
|
|
|
|
FOR i = 0 TO sides
|
|
nextpos = center
|
|
nextpos.x += (SIN(angle) * radius)
|
|
nextpos.y += (COS(angle) * radius)
|
|
|
|
DRAW_DEBUG_LINE(lastpos, nextpos, r, g, b, a)
|
|
DRAW_DEBUG_LINE(lastpos + <<0, 0, height>>, nextpos + <<0, 0, height>>, r, g, b, a)
|
|
DRAW_DEBUG_LINE(lastpos + <<0, 0, height / 2.0>>, nextpos + <<0, 0, height / 2.0>>, r, g, b, a)
|
|
DRAW_DEBUG_LINE(nextpos, nextpos + <<0, 0, height>>, r, g, b, a)
|
|
lastpos = nextpos
|
|
angle += ainc
|
|
ENDFOR
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Draw a circle in debug mode but on the XZ plane (vertically)
|
|
/// PARAMS:
|
|
/// center - circle center
|
|
/// radius - circle radius
|
|
/// r, g, b, a - red/green/blue/alpha components
|
|
/// sides - how smooth the circle is
|
|
PROC DRAW_DEBUG_CIRCLE_VERTICAL(VECTOR center, FLOAT radius, INT r = 0, INT g = 0, INT b = 255, INT a = 255, INT sides = 16)
|
|
INT i
|
|
FLOAT ainc = 360.0 / TO_FLOAT(sides)
|
|
VECTOR lastpos = center
|
|
VECTOR nextpos = center
|
|
FLOAT angle = 0
|
|
|
|
lastpos = center
|
|
lastpos.x += (SIN(angle - ainc) * radius)
|
|
lastpos.z += (COS(angle - ainc) * radius)
|
|
|
|
FOR i = 0 TO sides
|
|
nextpos = center
|
|
nextpos.x += (SIN(angle) * radius)
|
|
nextpos.z += (COS(angle) * radius)
|
|
|
|
DRAW_DEBUG_LINE(lastpos, nextpos, r, g, b, a)
|
|
lastpos = nextpos
|
|
angle += ainc
|
|
ENDFOR
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Draw an area in debug mode
|
|
/// PARAMS:
|
|
/// p1 - area point 1
|
|
/// p2 - area point 2
|
|
/// width - area width
|
|
/// r, g, b, a - red/green/blue/alpha components
|
|
PROC DRAW_DEBUG_AREA(VECTOR p1, VECTOR p2, FLOAT width, INT r = 0, INT g = 0, INT b = 255, INT a = 255)
|
|
IF (width = 0)
|
|
EXIT
|
|
ENDIF
|
|
|
|
VECTOR fwd = NORMALISE_VECTOR(p2 - p1)
|
|
VECTOR rt = CROSS_PRODUCT(fwd, <<0, 0, 1>>)
|
|
FLOAT w = width / 2.0
|
|
VECTOR pa, pb
|
|
VECTOR p[8]
|
|
INT i
|
|
pa = p1
|
|
pb = p2
|
|
pb.z = p1.z
|
|
|
|
// draw base
|
|
p[0] = pa - (rt * w)
|
|
p[1] = pa + (rt * w)
|
|
p[2] = pb + (rt * w)
|
|
p[3] = pb - (rt * w)
|
|
|
|
DRAW_DEBUG_LINE(p[0], p[1], r, g, b, a)
|
|
DRAW_DEBUG_LINE(p[1], p[2], r, g, b, a)
|
|
DRAW_DEBUG_LINE(p[2], p[3], r, g, b, a)
|
|
DRAW_DEBUG_LINE(p[3], p[0], r, g, b, a)
|
|
|
|
// draw top
|
|
FOR i = 0 TO 3
|
|
p[4 + i] = p[i]
|
|
p[4 + i].z = p2.z
|
|
ENDFOR
|
|
|
|
DRAW_DEBUG_LINE(p[4], p[5], r, g, b, a)
|
|
DRAW_DEBUG_LINE(p[5], p[6], r, g, b, a)
|
|
DRAW_DEBUG_LINE(p[6], p[7], r, g, b, a)
|
|
DRAW_DEBUG_LINE(p[7], p[4], r, g, b, a)
|
|
|
|
// draw connecting bits
|
|
DRAW_DEBUG_LINE(p[0], p[4], r, g, b, a)
|
|
DRAW_DEBUG_LINE(p[1], p[5], r, g, b, a)
|
|
DRAW_DEBUG_LINE(p[2], p[6], r, g, b, a)
|
|
DRAW_DEBUG_LINE(p[3], p[7], r, g, b, a)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Draw an area in debug mode
|
|
/// PARAMS:
|
|
/// area - angled area
|
|
/// r, g, b, a - red/green/blue/alpha components
|
|
PROC DEBUG_DRAW_ANGLED_AREA_EX(ANGLED_AREA &area, INT r = 0, INT g = 0, INT b = 255, INT a = 255)
|
|
DRAW_DEBUG_AREA(area.vPosition[0], area.vPosition[1], area.fWidth, r, g, b, a)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Draw lines in vector array from one vector to another
|
|
/// PARAMS:
|
|
/// area - angled area
|
|
/// r, g, b, a - red/green/blue/alpha components
|
|
PROC DRAW_DEBUG_VECTOR_ARRAY(VECTOR &array[], INT nPoints, INT r = 0, INT g = 0, INT b = 255, INT a = 255)
|
|
INT i
|
|
|
|
IF (nPoints > COUNT_OF(array))
|
|
nPoints = COUNT_OF(array)
|
|
ENDIF
|
|
|
|
REPEAT nPoints i
|
|
IF (i > 0)
|
|
DRAW_DEBUG_LINE(array[i], array[i - 1], r, g, b, a)
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Works out minimum and maximum given a point and an axis aligned box size
|
|
/// PARAMS:
|
|
/// center - box center
|
|
/// size - box 3size
|
|
/// min - returned minimum point
|
|
/// max - returned maximum point
|
|
PROC CALCULATE_MIN_MAX_FROM_POSITION_AND_DIMENSIONS(VECTOR center, VECTOR size, VECTOR &min, VECTOR &max)
|
|
VECTOR halfsize = size / 2.0
|
|
min = center - halfsize
|
|
max = center + halfsize
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Works out minimum and maximum given a point and radius
|
|
/// PARAMS:
|
|
/// center - sphere center
|
|
/// radius - sphere radius
|
|
/// min - returned minimum point
|
|
/// max - returned maximum point
|
|
PROC CALCULATE_MIN_MAX_FROM_POSITION_AND_RADIUS(VECTOR center, FLOAT radius, VECTOR &min, VECTOR &max)
|
|
VECTOR halfsize = <<radius, radius, radius>>
|
|
min = center - halfsize
|
|
max = center + halfsize
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Expands an angled area by an amount and returns the expanded version
|
|
/// PARAMS:
|
|
/// a - area to expand
|
|
/// exp - expand amount
|
|
FUNC ANGLED_AREA EXPAND_ANGLED_AREA(ANGLED_AREA a, FLOAT exp = 1.0)
|
|
ANGLED_AREA aOut
|
|
|
|
VECTOR vNormal = NORMALISE_VECTOR(a.vPosition[1] - a.vPosition[0]) * exp
|
|
aOut.vPosition[0] = a.vPosition[0] - vNormal
|
|
aOut.vPosition[1] = a.vPosition[1] + vNormal
|
|
aOut.fWidth = a.fWidth + (exp * 2.0)
|
|
|
|
RETURN aOut
|
|
ENDFUNC
|
|
|
|
FUNC VECTOR GET_ANGLED_AREA_CENTER(ANGLED_AREA a)
|
|
RETURN INTERPOLATE_VECTOR(a.vPosition[0], a.vPosition[1], 0.5)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// IS_ENTITY_IN_ANGLED_AREA only checks if the point is the area this checks the extents
|
|
/// RETURNS:
|
|
///
|
|
FUNC BOOL IS_ENTITY_IN_ANGLED_AREA_COMPLEX(ENTITY_INDEX ent, VECTOR v1, VECTOR v2, FLOAT w)
|
|
VECTOR v
|
|
VECTOR vmin, vmax
|
|
|
|
IF IS_ENTITY_IN_ANGLED_AREA(ent, v1, v2, w)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_A_PED(ent)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// only do this over the top check for not peds
|
|
GET_MODEL_DIMENSIONS(GET_ENTITY_MODEL(ent), vmin, vmax)
|
|
|
|
// check front left
|
|
v = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(ent, <<vmin.x, vmax.y, 0.0>>)
|
|
IF IS_POINT_IN_ANGLED_AREA(v, v1, v2, w)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
// check front
|
|
v = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(ent, <<0, vmax.y, 0.0>>)
|
|
IF IS_POINT_IN_ANGLED_AREA(v, v1, v2, w)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
// check front right
|
|
v = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(ent, <<vmax.x, vmax.y, 0.0>>)
|
|
IF IS_POINT_IN_ANGLED_AREA(v, v1, v2, w)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
// check back left
|
|
v = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(ent, <<vmin.x, vmin.y, 0.0>>)
|
|
IF IS_POINT_IN_ANGLED_AREA(v, v1, v2, w)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
// check back
|
|
v = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(ent, <<0, vmin.y, 0.0>>)
|
|
IF IS_POINT_IN_ANGLED_AREA(v, v1, v2, w)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
// check back right
|
|
v = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(ent, <<vmax.x, vmin.y, 0.0>>)
|
|
IF IS_POINT_IN_ANGLED_AREA(v, v1, v2, w)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Converts Milliseconds into minutes, seconds and tenths
|
|
/// PARAMS:
|
|
/// iTotal - time to convert
|
|
/// mins - returned minutes
|
|
/// secs - returned secs
|
|
/// ths - returned tenths of secs
|
|
PROC CONVERT_INT_TO_TIME(INT iTotal, INT& mins, INT &secs, INT &ths)
|
|
iTotal = ABSI(iTotal)
|
|
|
|
// this looks broken to me... look at this later
|
|
mins = (iTotal - (iTotal % ONE_MINUTE)) / ONE_MINUTE
|
|
secs = (iTotal % ONE_MINUTE) / 1000
|
|
ths = (iTotal % 1000) / 100
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "Time Convereted:", iTotal, " = ", mins, ":", secs, ".", ths)
|
|
#ENDIF
|
|
|
|
/*
|
|
mins = (iTotal / 1000) / 60
|
|
secs = (iTotal - (mins * 60 * 1000)) / 1000
|
|
ths = (iTotal - ((secs + (mins * 60)) * 1000))
|
|
ths /= 100
|
|
IF (ths > 9)
|
|
ths = 9
|
|
ENDIF
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "Time Convereted:", iTotal, " = ", mins, ":", secs, ".", ths)
|
|
#ENDIF
|
|
*/
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Releases a sound safely and zeros it's reference
|
|
/// PARAMS:
|
|
/// snd - sound index reference
|
|
PROC SAFE_STOP_AND_RELEASE_SOUND_ID(INT &snd)
|
|
IF (snd <> -1)
|
|
STOP_SOUND(snd)
|
|
RELEASE_SOUND_ID(snd)
|
|
snd = -1
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Places an entity on the floor
|
|
/// PARAMS:
|
|
/// pos - new position
|
|
/// RETURNS:
|
|
/// new grounded position
|
|
FUNC VECTOR SET_ENTITY_COORDS_GROUNDED(ENTITY_INDEX ent, VECTOR pos)
|
|
FLOAT z
|
|
pos.z += 0.15
|
|
IF GET_GROUND_Z_FOR_3D_COORD(pos, z)
|
|
pos.z = z
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_OK(ent)
|
|
SET_ENTITY_COORDS(ent, pos)
|
|
ENDIF
|
|
RETURN pos
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets heading entity needs to face the player
|
|
/// PARAMS:
|
|
/// ent - entity to turn
|
|
/// RETURNS:
|
|
/// new heading
|
|
FUNC FLOAT GET_ENTITY_HEADING_FACE_PLAYER(ENTITY_INDEX ent)
|
|
RETURN GET_HEADING_FROM_COORDS(GET_ENTITY_COORDS(ent), GET_ENTITY_COORDS(PLAYER_PED_ID()), TRUE)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Sets entity to face the player
|
|
/// PARAMS:
|
|
/// ent - entity to turn
|
|
PROC SET_ENTITY_HEADING_FACE_PLAYER(ENTITY_INDEX ent)
|
|
FLOAT head = GET_HEADING_FROM_COORDS(GET_ENTITY_COORDS(ent), GET_ENTITY_COORDS(PLAYER_PED_ID()), TRUE)
|
|
SET_ENTITY_HEADING(ent, head)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Sets entity to face a coordinate
|
|
/// PARAMS:
|
|
/// ent - entity to turn
|
|
/// pos - position to face
|
|
PROC SET_ENTITY_HEADING_FACE_COORDS(ENTITY_INDEX ent, VECTOR pos)
|
|
FLOAT head = GET_HEADING_FROM_COORDS(GET_ENTITY_COORDS(ent), pos, TRUE)
|
|
SET_ENTITY_HEADING(ent, head)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Sets entity to face an entity
|
|
/// PARAMS:
|
|
/// ent - entity to turn
|
|
/// targent - entity to face
|
|
PROC SET_ENTITY_HEADING_FACE_ENTITY(ENTITY_INDEX ent, ENTITY_INDEX targent)
|
|
FLOAT head = GET_HEADING_FROM_COORDS(GET_ENTITY_COORDS(ent), GET_ENTITY_COORDS(targent), TRUE)
|
|
SET_ENTITY_HEADING(ent, head)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Sets entity rotation to face an entity
|
|
/// PARAMS:
|
|
/// ent - entity to turn
|
|
/// target - entity to face
|
|
PROC SET_ENTITY_ROTATION_FACE_ENTITY(ENTITY_INDEX ent, ENTITY_INDEX target)
|
|
FLOAT pitch
|
|
FLOAT head
|
|
GET_PITCH_AND_HEADING_FROM_COORDS(GET_ENTITY_COORDS(ent), GET_ENTITY_COORDS(target), pitch, head, true)
|
|
SET_ENTITY_ROTATION(ent, <<pitch, 0, head>>)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Sets entity rotation to face an coordinate
|
|
/// PARAMS:
|
|
/// ent - entity to turn
|
|
/// target - position to face
|
|
PROC SET_ENTITY_ROTATION_FACE_COORDS(ENTITY_INDEX ent, VECTOR target)
|
|
FLOAT pitch
|
|
FLOAT head
|
|
GET_PITCH_AND_HEADING_FROM_COORDS(GET_ENTITY_COORDS(ent), target, pitch, head, true)
|
|
SET_ENTITY_ROTATION(ent, <<pitch, 0, head>>)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Tells us if a waypoint index is on screen or not
|
|
/// PARAMS:
|
|
/// wayname - waypoint recording name
|
|
/// ind - point index in waypoint recording
|
|
/// rad - tolerance
|
|
FUNC BOOL IS_WAYPOINT_INDEX_POINT_VISIBLE(STRING wayname, INT ind = 0, FLOAT rad = 2.0)
|
|
VECTOR pos
|
|
|
|
// get first and second points so we can point vehicle in right direction
|
|
IF NOT WAYPOINT_RECORDING_GET_COORD(wayname, ind, pos)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN IS_SPHERE_VISIBLE(pos, rad)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Tells us if a vehicle is ruined
|
|
/// PARAMS:
|
|
/// vehicleID - vehicle
|
|
/// chkfire - set this if we include it being on fire
|
|
FUNC BOOL IS_VEHICLE_BRUCK_UP(VEHICLE_INDEX VehicleID, BOOL chkfire = TRUE)
|
|
|
|
IF NOT IS_ENTITY_OK(VehicleID)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (GET_ENTITY_HEALTH(VehicleID) = 0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF NOT IS_VEHICLE_DRIVEABLE(VehicleID)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (chkfire)
|
|
IF IS_ENTITY_ON_FIRE(VehicleID)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
|
|
|
|
//----------------------
|
|
// COMBAT PARAM FUNCS
|
|
//-----------------------
|
|
|
|
/// PURPOSE:
|
|
/// Applies combat parameters to ped
|
|
/// PARAMS:
|
|
/// ped - ped index
|
|
/// cpm - combat param reference
|
|
/// bUseAcc2 - set this to true to use accuracy #2
|
|
PROC APPLY_COMBAT_PARAMETERS_TO_PED(PED_INDEX ped, COMBAT_PARAMETERS &cpm, BOOL bUseAcc2 = FALSE)
|
|
INT iRnd
|
|
SET_PED_CHANCE_OF_FIRING_BLANKS(ped, cpm.fNearBlankChance, cpm.fFarBlankChance)
|
|
SET_PED_SHOOT_RATE(ped, GET_RANDOM_INT_IN_RANGE(cpm.iMinShootRate, cpm.iMaxShootRate))
|
|
SET_PED_FIRING_PATTERN(ped, cpm.hFiringPattern)
|
|
|
|
SET_COMBAT_FLOAT(ped, CCF_TIME_BETWEEN_BURSTS_IN_COVER, GET_RANDOM_FLOAT_IN_RANGE(cpm.fMinTimeBetweenCoverBurst, cpm.fMaxTimeBetweenCoverBurst))
|
|
SET_COMBAT_FLOAT(ped, CCF_TIME_BETWEEN_PEEKS, GET_RANDOM_FLOAT_IN_RANGE(cpm.fMinTimeBetweenPeeks, cpm.fMaxTimeBetweenPeeks))
|
|
SET_COMBAT_FLOAT(ped, CCF_BURST_DURATION_IN_COVER, GET_RANDOM_FLOAT_IN_RANGE(cpm.fMinBurstDurationTime, cpm.fMaxBurstDurationTime))
|
|
//SET_PED_TARGET_LOSS_RESPONSE(ped, TLR_NEVER_LOSE_TARGET)
|
|
|
|
IF (bUseAcc2)
|
|
SET_COMBAT_FLOAT(ped, CCF_WEAPON_ACCURACY, cpm.fWeaponAccuracy2)
|
|
ELSE
|
|
SET_COMBAT_FLOAT(ped, CCF_WEAPON_ACCURACY, cpm.fWeaponAccuracy1)
|
|
ENDIF
|
|
|
|
SET_PLAYER_WEAPON_DAMAGE_MODIFIER(PLAYER_ID(), cpm.fPlayerWeaponDamageModifier)
|
|
SET_PLAYER_WEAPON_DEFENSE_MODIFIER(PLAYER_ID(), cpm.fPlayerWeaponDefenseModifier)
|
|
SET_PLAYER_MELEE_WEAPON_DEFENSE_MODIFIER(PLAYER_ID(), cpm.fPlayerMeleeWeaponDefenseModifier)
|
|
SET_PED_COMBAT_ATTRIBUTES(ped, CA_AGGRESSIVE, GET_RANDOM_FLOAT_IN_RANGE() < cpm.fAgressionChance)
|
|
|
|
SET_PED_COMBAT_ATTRIBUTES(ped, CA_CAN_FLANK, GET_RANDOM_FLOAT_IN_RANGE() < cpm.fFlankChance)
|
|
SET_PED_COMBAT_ATTRIBUTES(ped, CA_JUST_SEEK_COVER, GET_RANDOM_FLOAT_IN_RANGE() < cpm.fCoverOnlyChance)
|
|
|
|
// combat range
|
|
IF (cpm.iForcedCombatRange <> -1)
|
|
iRnd = cpm.iForcedCombatRange
|
|
ELSE
|
|
iRnd = GET_RANDOM_INT_IN_RANGE(0, 3)
|
|
ENDIF
|
|
|
|
SWITCH (iRnd)
|
|
CASE 0
|
|
SET_PED_COMBAT_RANGE(ped, CR_NEAR) // Seeks a defensive position.
|
|
BREAK
|
|
CASE 1
|
|
SET_PED_COMBAT_RANGE(ped, CR_MEDIUM) // Will advance forward in combat
|
|
BREAK
|
|
CASE 2
|
|
SET_PED_COMBAT_RANGE(ped, CR_FAR) // Will retreat if the enemy gets too close
|
|
BREAK
|
|
DEFAULT
|
|
SET_PED_COMBAT_RANGE(ped, CR_MEDIUM) // Will advance forward in combat
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
// combat range
|
|
IF (cpm.iForcedCombatLevel <> -1)
|
|
iRnd = cpm.iForcedCombatLevel
|
|
ELSE
|
|
iRnd = GET_RANDOM_INT_IN_RANGE(0, 3)
|
|
ENDIF
|
|
|
|
SWITCH (iRnd)
|
|
CASE 0
|
|
SET_PED_COMBAT_ABILITY(ped, CAL_POOR)
|
|
BREAK
|
|
CASE 1
|
|
SET_PED_COMBAT_ABILITY(ped, CAL_AVERAGE)
|
|
BREAK
|
|
CASE 2
|
|
SET_PED_COMBAT_ABILITY(ped, CAL_PROFESSIONAL)
|
|
BREAK
|
|
DEFAULT
|
|
SET_PED_COMBAT_ABILITY(ped, CAL_AVERAGE)
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Reset combat parameters
|
|
/// PARAMS:
|
|
/// cpm - combat param reference
|
|
PROC RESET_COMBAT_PARAMETERS(COMBAT_PARAMETERS &cpm)
|
|
cpm.hFiringPattern = FIRING_PATTERN_DELAY_FIRE_BY_ONE_SEC
|
|
|
|
cpm.fWeaponAccuracy1 = 0.0325
|
|
cpm.fWeaponAccuracy2 = 0.0325
|
|
|
|
cpm.fNearBlankChance = 0.36 // default in code
|
|
cpm.fFarBlankChance = 0.60 // default in code
|
|
cpm.fFlankChance = 0.20
|
|
cpm.fCoverOnlyChance = 0.0
|
|
|
|
cpm.fMinTimeBetweenPeeks = 10.0 // default in code
|
|
cpm.fMaxTimeBetweenPeeks = 11.0
|
|
|
|
cpm.fMinTimeBetweenCoverBurst = 1.25 // default in code
|
|
cpm.fMaxTimeBetweenCoverBurst = 2.25
|
|
|
|
cpm.fMinBurstDurationTime = 2.0 // default in code
|
|
cpm.fMaxBurstDurationTime = 2.5
|
|
|
|
cpm.iMinShootRate = 20
|
|
cpm.iMaxShootRate = 50
|
|
|
|
cpm.iForcedCombatLevel = 0
|
|
cpm.iForcedCombatRange = -1
|
|
|
|
cpm.fPlayerWeaponDamageModifier = 1.0
|
|
cpm.fPlayerWeaponDefenseModifier = 1.0
|
|
cpm.fPlayerMeleeWeaponDefenseModifier = 1.0
|
|
cpm.fAgressionChance = 0.5
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Reset combat parameters
|
|
/// PARAMS:
|
|
/// cpm - combat param reference
|
|
/// nme - display name
|
|
#IF IS_DEBUG_BUILD
|
|
PROC SETUP_COMBAT_PARAMETERS_WIDGET(COMBAT_PARAMETERS &cpm, STRING nme)
|
|
START_WIDGET_GROUP(nme)
|
|
ADD_WIDGET_FLOAT_SLIDER("Ped Accuracy Weapon 1", cpm.fWeaponAccuracy1, 0.0, 1.0, 0.001)
|
|
ADD_WIDGET_FLOAT_SLIDER("Ped Accuracy Weapon 2", cpm.fWeaponAccuracy2, 0.0, 1.0, 0.001)
|
|
|
|
ADD_WIDGET_FLOAT_SLIDER("Player Weapon Damage Modifier", cpm.fPlayerWeaponDamageModifier, 0.0, 5.0, 0.001)
|
|
ADD_WIDGET_FLOAT_SLIDER("Player Weapon Defense Modifier", cpm.fPlayerWeaponDefenseModifier, 0.0, 5.0, 0.001)
|
|
ADD_WIDGET_FLOAT_SLIDER("Player Melee Weapon Defense Modifier", cpm.fPlayerMeleeWeaponDefenseModifier, 0.0, 5.0, 0.001)
|
|
|
|
START_WIDGET_GROUP("Chance")
|
|
ADD_WIDGET_FLOAT_SLIDER("Agression Chance", cpm.fAgressionChance, 0.0, 1.0, 0.05)
|
|
ADD_WIDGET_FLOAT_SLIDER("Near Blank Chance", cpm.fNearBlankChance, 0.0, 1.0, 0.01)
|
|
ADD_WIDGET_FLOAT_SLIDER("Far Blank Chance", cpm.fFarBlankChance, 0.0, 1.0, 0.01)
|
|
ADD_WIDGET_FLOAT_SLIDER("Flank Chance", cpm.fFlankChance, 0.0, 1.0, 0.01)
|
|
ADD_WIDGET_FLOAT_SLIDER("Cover Only Chance", cpm.fCoverOnlyChance, 0.0, 1.0, 0.01)
|
|
ADD_WIDGET_INT_SLIDER("Forced Combat Range", cpm.iForcedCombatRange, -1, 2, 1)
|
|
ADD_WIDGET_INT_SLIDER("Forced Combat Level", cpm.iForcedCombatLevel, -1, 2, 1)
|
|
STOP_WIDGET_GROUP()
|
|
|
|
START_WIDGET_GROUP("Rate")
|
|
ADD_WIDGET_INT_SLIDER("Min Shoot Rate", cpm.iMinShootRate, 0, 100, 1)
|
|
ADD_WIDGET_INT_SLIDER("Max Shoot Rate", cpm.iMaxShootRate, 1, 100, 1)
|
|
ADD_WIDGET_FLOAT_SLIDER("Min Time Between Peeks", cpm.fMinTimeBetweenPeeks, 0.0, 60.0, 0.01)
|
|
ADD_WIDGET_FLOAT_SLIDER("Max Time Between Peeks", cpm.fMaxTimeBetweenPeeks, 0.0, 60.0, 0.01)
|
|
ADD_WIDGET_FLOAT_SLIDER("Min Time Between Cover Burst", cpm.fMinTimeBetweenCoverBurst, 0.0, 60.0, 0.01)
|
|
ADD_WIDGET_FLOAT_SLIDER("Max Time Between Cover Burst", cpm.fMaxTimeBetweenCoverBurst, 0.0, 60.0, 0.01)
|
|
ADD_WIDGET_FLOAT_SLIDER("Min Burst Duration Time", cpm.fMinBurstDurationTime, 0.0, 60.0, 0.01)
|
|
ADD_WIDGET_FLOAT_SLIDER("Max Burst Duration Time", cpm.fMaxBurstDurationTime, 0.0, 60.0, 0.01)
|
|
STOP_WIDGET_GROUP()
|
|
STOP_WIDGET_GROUP()
|
|
ENDPROC
|
|
#ENDIF
|
|
|
|
//----------------------
|
|
// TIMER FUNCS
|
|
//-----------------------
|
|
|
|
/// PURPOSE:
|
|
/// Starts my mission debug timer
|
|
PROC START_MISSION_DEBUG_TIMER()
|
|
iMissionDebugTime = GET_GAME_TIMER()
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Toggles display of mission debug timer
|
|
PROC SHOW_MISSION_DEBUG_TIMER(BOOL ok = FALSE)
|
|
bShowDebugMissionTime = ok
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Updates display of mission debug timer
|
|
PROC UPDATE_MISSION_DEBUG_TIMER()
|
|
iCurrentGameTime = GET_GAME_TIMER()
|
|
IF (bShowDebugMissionTime = TRUE)
|
|
DRAW_GENERIC_TIMER(iCurrentGameTime - iMissionDebugTime, "TIMER_TIME", 0, TIMER_STYLE_USEMILLISECONDS, -1, PODIUMPOS_NONE, HUDORDER_BOTTOM)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
//----------------------
|
|
// SAFE LOADING FUNCS
|
|
//-----------------------
|
|
|
|
/// PURPOSE:
|
|
/// Safely loads additional text
|
|
/// PARAMS:
|
|
/// nme - text block name
|
|
/// slot - text block slot
|
|
/// loadwait - set this to pause script until loading is complete
|
|
/// forceloading - set this force load the text block
|
|
/// RETURNS:
|
|
/// true if loaded successfully or if is requested
|
|
FUNC BOOL SECURE_REQUEST_AND_LOAD_ADDITIONAL_TEXT(STRING nme, TEXT_BLOCK_SLOTS slot, BOOL loadwait = TRUE, BOOL forceloading = FALSE)
|
|
INT gt = GET_GAME_TIMER() + REQUEST_TIMEOUT
|
|
|
|
//CLEAR_ADDITIONAL_TEXT(slot, FALSE)
|
|
REQUEST_ADDITIONAL_TEXT(nme, slot)
|
|
|
|
IF HAS_ADDITIONAL_TEXT_LOADED(slot) AND NOT forceloading
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS] - Additional Text:", nme, " in slot:", ENUM_TO_INT(slot)," has already been loaded")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (loadwait = FALSE)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD PENDING] - Additional Text:", nme, " in slot:", ENUM_TO_INT(slot)," has been requested")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
WHILE NOT HAS_ADDITIONAL_TEXT_LOADED(slot)
|
|
WAIT(0)
|
|
IF (GET_GAME_TIMER() > gt) AND NOT HAS_ADDITIONAL_TEXT_LOADED(slot)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD FAILURE] - Additional Text:", nme, " in slot:", ENUM_TO_INT(slot)," has failed to load - Time out")
|
|
#ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDWHILE
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS] - Additional Text:", nme, " in slot:", ENUM_TO_INT(slot)," has loaded")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Safely loads animation dictionaries
|
|
/// PARAMS:
|
|
/// nme - anim dict name
|
|
/// loadwait - set this to pause script until loading is complete
|
|
/// RETURNS:
|
|
/// true if loaded successfully or if is requested
|
|
FUNC BOOL SECURE_REQUEST_AND_LOAD_ANIM_DICT(STRING mdl, BOOL loadwait = TRUE)
|
|
INT gt = GET_GAME_TIMER() + REQUEST_TIMEOUT
|
|
|
|
REQUEST_ANIM_DICT(mdl)
|
|
|
|
IF HAS_ANIM_DICT_LOADED(mdl)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS] - Anim Dict:", mdl, " has already been loaded")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (loadwait = FALSE)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD PENDING] - Anim Dict:", mdl, " has been requested")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
WHILE NOT HAS_ANIM_DICT_LOADED(mdl)
|
|
WAIT(0)
|
|
IF (GET_GAME_TIMER() > gt) AND NOT HAS_ANIM_DICT_LOADED(mdl)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD FAILURE]: Anim Dict:", mdl, " has failed to load - Time out")
|
|
#ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDWHILE
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Anim Dict:", mdl, " has loaded")
|
|
#ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Safely loads audio bank
|
|
/// PARAMS:
|
|
/// nme - audio bank name
|
|
/// loadwait - set this to pause script until loading is complete
|
|
/// RETURNS:
|
|
/// true if loaded successfully or if is requested
|
|
FUNC BOOL SECURE_REQUEST_AND_LOAD_AUDIO_BANK(STRING mdl, BOOL loadwait = TRUE)
|
|
INT gt = GET_GAME_TIMER() + REQUEST_TIMEOUT
|
|
|
|
IF REQUEST_SCRIPT_AUDIO_BANK(mdl)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Audio Bank:", mdl, " has already been loaded")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (loadwait = FALSE)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD ALERT]: Audio Bank:", mdl, " has been requested")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
WHILE NOT REQUEST_SCRIPT_AUDIO_BANK(mdl)
|
|
WAIT(0)
|
|
|
|
IF (GET_GAME_TIMER() > gt) AND NOT REQUEST_SCRIPT_AUDIO_BANK(mdl)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD FAILURE]: Audio Bank:", mdl, " has failed to load - Time out")
|
|
#ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDWHILE
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Audio Bank:", mdl, " has loaded")
|
|
#ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Safely loads audio stream
|
|
/// PARAMS:
|
|
/// nme - audio stream name
|
|
/// loadwait - set this to pause script until loading is complete
|
|
/// RETURNS:
|
|
/// true if loaded successfully or if is requested
|
|
FUNC BOOL SECURE_REQUEST_AND_LOAD_AUDIO_STREAM(STRING mdl, BOOL loadwait = TRUE)
|
|
BOOL ok
|
|
INT gt = GET_GAME_TIMER() + REQUEST_TIMEOUT
|
|
|
|
ok = LOAD_STREAM(mdl)
|
|
|
|
IF (ok)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Audio Stream:", mdl, " has already been loaded")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (loadwait = FALSE)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD ALERT]: Audio Stream:", mdl, " has been requested")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD ALERT]: Audio Stream:", mdl, " is loading")
|
|
#ENDIF
|
|
|
|
WHILE NOT LOAD_STREAM(mdl)
|
|
WAIT(0)
|
|
|
|
IF (GET_GAME_TIMER() > gt) AND NOT LOAD_STREAM(mdl)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD FAILURE]: Audio Stream:", mdl, " failed to load - Time Out")
|
|
#ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDWHILE
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Audio Stream:", mdl, " loaded")
|
|
#ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Safely loads audio stream
|
|
/// PARAMS:
|
|
/// nme - audio stream name
|
|
/// loadwait - set this to pause script until loading is complete
|
|
/// RETURNS:
|
|
/// true if loaded successfully or if is requested
|
|
FUNC BOOL SECURE_REQUEST_AND_LOAD_AUDIO_STREAM_WITH_SOUNDSET(STRING mdl, STRING setname, BOOL loadwait = TRUE)
|
|
BOOL ok
|
|
INT gt = GET_GAME_TIMER() + REQUEST_TIMEOUT
|
|
|
|
ok = LOAD_STREAM(mdl, setname)
|
|
|
|
IF (ok)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Audio Stream:", mdl, " has already been loaded")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (loadwait = FALSE)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD ALERT]: Audio Stream:", mdl, " has been requested")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD ALERT]: Audio Stream:", mdl, " is loading")
|
|
#ENDIF
|
|
|
|
WHILE NOT LOAD_STREAM(mdl, setname)
|
|
WAIT(0)
|
|
|
|
IF (GET_GAME_TIMER() > gt) AND NOT LOAD_STREAM(mdl, setname)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD FAILURE]: Audio Stream:", mdl, " failed to load - Time Out")
|
|
#ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDWHILE
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Audio Stream:", mdl, " loaded")
|
|
#ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Safely loads model
|
|
/// PARAMS:
|
|
/// mdl - model name
|
|
/// loadwait - set this to pause script until loading is complete
|
|
/// RETURNS:
|
|
/// true if loaded successfully or if is requested
|
|
FUNC BOOL SECURE_REQUEST_AND_LOAD_MODEL(MODEL_NAMES mdl, BOOL loadwait = TRUE)
|
|
|
|
INT gt = GET_GAME_TIMER() + REQUEST_TIMEOUT
|
|
|
|
IF (mdl = DUMMY_MODEL_FOR_SCRIPT)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
REQUEST_MODEL (mdl)
|
|
|
|
IF HAS_MODEL_LOADED(mdl)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Model:", GET_MODEL_NAME_FOR_DEBUG(mdl), " has already been loaded")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (loadwait = FALSE)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD ALERT]: Model:", GET_MODEL_NAME_FOR_DEBUG(mdl), " has been requested")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
WHILE NOT HAS_MODEL_LOADED(mdl)
|
|
WAIT(0)
|
|
IF (GET_GAME_TIMER() > gt) AND NOT HAS_MODEL_LOADED(mdl)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD ALERT]: Model:", GET_MODEL_NAME_FOR_DEBUG(mdl), " has failed to load - Time Out")
|
|
#ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDWHILE
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Model:", GET_MODEL_NAME_FOR_DEBUG(mdl), " has loaded")
|
|
#ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Safely loads PTFX asset
|
|
/// PARAMS:
|
|
/// nme - asset name
|
|
/// loadwait - set this to pause script until loading is complete
|
|
/// RETURNS:
|
|
/// true if loaded successfully or if is requested
|
|
FUNC BOOL SECURE_REQUEST_AND_LOAD_PTFX(STRING nme, BOOL loadwait = TRUE)
|
|
INT gt = GET_GAME_TIMER() + REQUEST_TIMEOUT
|
|
|
|
REQUEST_PTFX_ASSET()
|
|
|
|
IS_STRING_NULL(nme) // release build is crying
|
|
|
|
IF HAS_PTFX_ASSET_LOADED()
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS] - PTFX Asset:", nme, " has loaded")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (loadwait = FALSE)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD PENDING] - PTFX Asset:", nme, " has been requested")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
WHILE NOT HAS_PTFX_ASSET_LOADED()
|
|
WAIT(0)
|
|
|
|
IF (GET_GAME_TIMER() > gt) AND NOT HAS_PTFX_ASSET_LOADED()
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD FAILURE]: PTFX Asset:", nme, " has failed to load - Time out")
|
|
#ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDWHILE
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: PTFX Asset:", nme, " has loaded")
|
|
#ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Safely loads texture dictionary
|
|
/// PARAMS:
|
|
/// mdl - text dictionary name
|
|
/// priority - load this as priorty
|
|
/// loadwait - set this to pause script until loading is complete
|
|
/// RETURNS:
|
|
/// true if loaded successfully or if is requested
|
|
FUNC BOOL SECURE_REQUEST_AND_LOAD_TEXTURE_DICT(STRING mdl, BOOL prority = FALSE, BOOL loadwait = TRUE)
|
|
INT gt = GET_GAME_TIMER() + REQUEST_TIMEOUT
|
|
|
|
REQUEST_STREAMED_TEXTURE_DICT(mdl, prority)
|
|
|
|
IF HAS_STREAMED_TEXTURE_DICT_LOADED(mdl)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Texture Dictionary:", mdl, " has loaded")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (loadwait = FALSE)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD ALERT]: Texture Dictionary:", mdl, " has been requested")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
WHILE NOT HAS_STREAMED_TEXTURE_DICT_LOADED(mdl)
|
|
WAIT(0)
|
|
IF (GET_GAME_TIMER() > gt)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD ALERT]: Texture Dictionary:", mdl, " has failed to load - Time out")
|
|
#ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDWHILE
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Texture Dictionary:", mdl, " has loaded")
|
|
#ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC SECURE_UNLOAD_TEXTURE_DICT(STRING nme)
|
|
IF HAS_STREAMED_TEXTURE_DICT_LOADED(nme)
|
|
SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED(nme)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Safely loads weapon asset
|
|
/// PARAMS:
|
|
/// nme - asset name
|
|
/// loadwait - set this to pause script until loading is complete
|
|
/// RETURNS:
|
|
/// true if loaded successfully or if is requested
|
|
FUNC BOOL SECURE_REQUEST_AND_LOAD_WEAPON_ASSET(WEAPON_TYPE nme, BOOL loadwait = TRUE)
|
|
INT gt = GET_GAME_TIMER() + REQUEST_TIMEOUT
|
|
|
|
REQUEST_WEAPON_ASSET(nme)
|
|
|
|
IF HAS_WEAPON_ASSET_LOADED(nme)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Weapon Asset:", GET_WEAPON_NAME(nme), " has loaded")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (loadwait = FALSE)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD ALERT]: Weapon Asset:", GET_WEAPON_NAME(nme), " has been requested")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
WHILE NOT HAS_WEAPON_ASSET_LOADED(nme)
|
|
WAIT(0)
|
|
IF (GET_GAME_TIMER() > gt) AND NOT HAS_WEAPON_ASSET_LOADED(nme)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD ALERT]: Weapon Asset:", GET_WEAPON_NAME(nme), " has failed to load - Time out")
|
|
#ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDWHILE
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Weapon Asset:", GET_WEAPON_NAME(nme), " has loaded")
|
|
#ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Safely loads vehicle recording
|
|
/// PARAMS:
|
|
/// num - vehicle recording number
|
|
/// nme - vehicle recording name
|
|
/// loadwait - set this to pause script until loading is complete
|
|
/// RETURNS:
|
|
/// true if loaded successfully or if is requested
|
|
FUNC BOOL SECURE_REQUEST_AND_LOAD_VEHICLE_REC(INT num, STRING nme, BOOL loadwait = TRUE)
|
|
INT gt = GET_GAME_TIMER() + REQUEST_TIMEOUT
|
|
|
|
REQUEST_VEHICLE_RECORDING(num, nme)
|
|
|
|
IF HAS_VEHICLE_RECORDING_BEEN_LOADED(num, nme)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Car Recording:", nme, " ", num, " has already been loaded")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (loadwait = FALSE)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD ALERT]: Car Recording:", nme, " ", num, " has been requested")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
WHILE NOT HAS_VEHICLE_RECORDING_BEEN_LOADED(num, nme)
|
|
WAIT(0)
|
|
IF (GET_GAME_TIMER() > gt) AND NOT HAS_VEHICLE_RECORDING_BEEN_LOADED(num, nme)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD FAILED]: Car Recording:", nme, " ", num, " loading has timed out")
|
|
#ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDWHILE
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Car Recording:", nme, " ", num, " has loaded")
|
|
#ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Safely loads waypoint recording
|
|
/// PARAMS:
|
|
/// nme - waypoint recording name
|
|
/// loadwait - set this to pause script until loading is complete
|
|
/// RETURNS:
|
|
/// true if loaded successfully or if is requested
|
|
FUNC BOOL SECURE_REQUEST_AND_LOAD_WAYPOINT_REC(STRING nme, BOOL loadwait = TRUE)
|
|
INT gt = GET_GAME_TIMER() + REQUEST_TIMEOUT
|
|
|
|
REQUEST_WAYPOINT_RECORDING(nme)
|
|
IF GET_IS_WAYPOINT_RECORDING_LOADED(nme)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Waypoint Recording:", nme, " has already been loaded")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (loadwait = FALSE)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD ALERT]: Waypoint Recording:", nme, " has been requested")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
WHILE NOT GET_IS_WAYPOINT_RECORDING_LOADED(nme)
|
|
WAIT(0)
|
|
IF (GET_GAME_TIMER() > gt)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD FAILED]: Waypoint Recording:", nme, " loading has timed out")
|
|
#ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDWHILE
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Waypoint Recording:", nme, " has loaded")
|
|
#ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC SECURE_UNLOAD_WAYPOINT_REC(STRING nme)
|
|
IF GET_IS_WAYPOINT_RECORDING_LOADED(nme)
|
|
REMOVE_WAYPOINT_RECORDING(nme)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Safely loads scaleform
|
|
/// PARAMS:
|
|
/// mdl - waypoint recording name
|
|
/// si - scaleform index - this is written to by function
|
|
/// loadwait - set this to pause script until loading is complete
|
|
/// RETURNS:
|
|
/// true if loaded successfully or if is requested
|
|
FUNC BOOL SECURE_REQUEST_AND_LOAD_SCALEFORM(STRING mdl, SCALEFORM_INDEX &si, BOOL loadwait = TRUE)
|
|
INT gt = GET_GAME_TIMER() + REQUEST_TIMEOUT
|
|
|
|
IF (si = NULL)
|
|
si = REQUEST_SCALEFORM_MOVIE(mdl)
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD ALERT]:Scaleform Movie", mdl, "has been requested")
|
|
ENDIF
|
|
|
|
IF HAS_SCALEFORM_MOVIE_LOADED(si)
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Scaleform Movie:", mdl, "has already been loaded")
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (loadwait = FALSE)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
WHILE NOT HAS_SCALEFORM_MOVIE_LOADED(si)
|
|
WAIT(0)
|
|
|
|
IF (GET_GAME_TIMER() > gt) AND NOT HAS_SCALEFORM_MOVIE_LOADED(si)
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD FAILURE]: Scaleform Movie:", mdl, " has failed to load - Time out")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDWHILE
|
|
|
|
CPRINTLN(DEBUG_MISSION, "[LOAD SUCCESS]: Scaleform Movie:", mdl, " has loaded")
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Safely unloads vehicle reocrding
|
|
/// PARAMS:
|
|
/// num - vehicle recording number
|
|
/// nme - vehicle recording name
|
|
PROC SECURE_UNLOAD_VEHICLE_REC(INT num, STRING nme)
|
|
// commented out for B*663880
|
|
//IF HAS_VEHICLE_RECORDING_BEEN_LOADED(num, nme)
|
|
REMOVE_VEHICLE_RECORDING(num, nme)
|
|
//ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Safely unloads model
|
|
/// PARAMS:
|
|
/// mdl - model name
|
|
PROC SECURE_UNLOAD_MODEL(MODEL_NAMES mdl)
|
|
IF (mdl <> DUMMY_MODEL_FOR_SCRIPT)
|
|
SET_MODEL_AS_NO_LONGER_NEEDED(mdl)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Safely unloads animation dictionaries
|
|
/// PARAMS:
|
|
/// mdl - anim dict name
|
|
PROC SECURE_UNLOAD_ANIM_DICT(STRING mdl)
|
|
REMOVE_ANIM_DICT (mdl)
|
|
ENDPROC
|
|
|
|
//----------------------
|
|
// SPAWNPT FUNCTIONS
|
|
//----------------------
|
|
|
|
/// PURPOSE:
|
|
/// Generates a random bool
|
|
/// RETURNS:
|
|
/// True or False
|
|
FUNC BOOL GENERATE_RANDOM_BOOL()
|
|
IF GET_RANDOM_INT_IN_RANGE(0, 1999) / 1000 = 1
|
|
RETURN TRUE
|
|
ELSE
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Get the closest offscreen point to a given position
|
|
/// PARAMS:
|
|
/// in - position
|
|
/// out - new offscreen position
|
|
/// debug - draw debug stuff
|
|
/// RETURNS:
|
|
/// true if we were successful
|
|
FUNC BOOL GET_CLOSEST_OFFSCREEN_POINT(VECTOR in, VECTOR &out, BOOL debug = FALSE)
|
|
VECTOR lend
|
|
VECTOR intersect
|
|
VECTOR lstart = GET_GAMEPLAY_CAM_COORD()
|
|
VECTOR plyrPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
|
|
|
|
FLOAT oplength
|
|
FLOAT adjlength
|
|
FLOAT zvalue = GET_GAMEPLAY_CAM_RELATIVE_HEADING() + GET_ENTITY_HEADING(PLAYER_PED_ID())
|
|
|
|
// if point is off screen just return point
|
|
IF NOT IS_SPHERE_VISIBLE(in, 0.25)
|
|
out = in
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
// work out start and end of line (get point miles in front of camera)
|
|
lstart.z = plyrPos.z
|
|
lend = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(lstart, zvalue, <<0, 300.0, 0>>)
|
|
IF (debug = TRUE)
|
|
DRAW_DEBUG_LINE_WITH_TWO_COLOURS(lstart, lend)
|
|
ENDIF
|
|
|
|
IF (debug = TRUE)
|
|
DRAW_DEBUG_LINE_WITH_TWO_COLOURS(lstart, in)
|
|
DRAW_DEBUG_SPHERE(in, 0.5, 0, 255, 0, 64)
|
|
ENDIF
|
|
|
|
// calculate nearest point on line to point
|
|
intersect = GET_CLOSEST_POINT_ON_LINE(in, lstart, lend)
|
|
|
|
IF (debug = TRUE)
|
|
DRAW_DEBUG_SPHERE(intersect, 0.5, 0, 255, 0, 64)
|
|
ENDIF
|
|
|
|
adjlength = GET_DISTANCE_BETWEEN_COORDS(lstart, intersect)
|
|
oplength = adjlength * TAN(GET_GAMEPLAY_CAM_FOV())
|
|
|
|
// check side
|
|
VECTOR v1 = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(lstart, zvalue, <<oplength, adjlength, 0>>)
|
|
VECTOR v2 = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(lstart, zvalue, <<-oplength, adjlength, 0>>)
|
|
|
|
out = v1
|
|
IF GET_LINE_MAGNITUDE_SQUARED(v2, in) < GET_LINE_MAGNITUDE_SQUARED(v1, in)
|
|
out = v2
|
|
ENDIF
|
|
|
|
IF (debug = TRUE)
|
|
DRAW_DEBUG_SPHERE(out, 0.5, 0, 255, 0, 64)
|
|
DRAW_DEBUG_LINE_WITH_TWO_COLOURS(intersect, out)
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
///------------------------------------------------------------------------------
|
|
/// FUNCTION: GET_CLOSEST_OFFSCREEN_PED_SPAWNPOINT()
|
|
/// PURPOSE: GETS CLOSEST OFFSCREEN POINT TO A POSITION
|
|
///------------------------------------------------------------------------------
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Gets the closest off screen ped spawn point to a position
|
|
/// PARAMS:
|
|
/// in - position
|
|
/// out - new offscreen position
|
|
/// safecheck - use safe spawn point check
|
|
/// pavecheck - use pavement check
|
|
/// RETURNS:
|
|
/// true if we were successful
|
|
FUNC BOOL GET_CLOSEST_OFFSCREEN_PED_SPAWNPOINT(VECTOR in, VECTOR &out, BOOL safecheck = TRUE, BOOL pavecheck = FALSE)
|
|
VECTOR tmp
|
|
FLOAT z
|
|
|
|
IF NOT GET_CLOSEST_OFFSCREEN_POINT(in, out, FALSE)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF (safecheck)
|
|
IF NOT GET_SAFE_COORD_FOR_PED(out, pavecheck, tmp)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
out = tmp
|
|
RETURN NOT IS_SPHERE_VISIBLE(out, 0.25)
|
|
ENDIF
|
|
|
|
IF NOT GET_GROUND_Z_FOR_3D_COORD(out, z)
|
|
RETURN FALSE
|
|
ENDIF
|
|
out.z = z
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets the closest off screen car spawn point
|
|
/// PARAMS:
|
|
/// in - desired position
|
|
/// out - new spawn point position (overwritten)
|
|
/// head - new heading
|
|
/// heightTol - if the position is less than x meters from out - fail
|
|
/// debug - draw debug stuff
|
|
/// RETURNS:
|
|
/// true on success
|
|
FUNC BOOL GET_CLOSEST_OFFSCREEN_CAR_SPAWNPOINT(VECTOR in, VECTOR &out, FLOAT &head, FLOAT heightTol = 15.0, BOOL debug = FALSE)
|
|
VECTOR tmp
|
|
INT iNodeAddr
|
|
|
|
IF NOT GET_CLOSEST_OFFSCREEN_POINT(in, out, debug)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
tmp = out
|
|
IF NOT GET_RANDOM_VEHICLE_NODE( tmp, 20.0, 1, FALSE, FALSE, out, iNodeAddr)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
GET_SPAWN_COORDS_FOR_VEHICLE_NODE( iNodeAddr, GET_ENTITY_COORDS(PLAYER_PED_ID()), out, head)
|
|
|
|
IF IS_SPHERE_VISIBLE(out, 0.125)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
tmp = GET_ENTITY_COORDS(PLAYER_PED_ID())
|
|
IF (ABSF(tmp.z - out.z) > heightTol)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Generates a spawn point around position
|
|
/// PARAMS:
|
|
/// in - desired position
|
|
/// out - new position
|
|
/// range - minimum range of spawn point
|
|
/// safecheck - use safe spawn point check
|
|
/// pavecheck - use pavement check
|
|
/// RETURNS:
|
|
/// true on success
|
|
FUNC BOOL GENERATE_SPAWN_POINT_AROUND_POSITION(VECTOR in, VECTOR &out, FLOAT range, BOOL safechk = FALSE, BOOL pavecheck = FALSE)
|
|
FLOAT zrot
|
|
VECTOR pos
|
|
|
|
pos = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(in, GET_RANDOM_FLOAT_IN_RANGE(0.0, 360.0), <<0, range, 0>>)
|
|
|
|
IF GET_GROUND_Z_FOR_3D_COORD(pos, zrot)
|
|
pos.z = zrot
|
|
ENDIF
|
|
|
|
out = pos
|
|
IF (safechk = FALSE)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN GET_SAFE_COORD_FOR_PED(pos, pavecheck, out)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Generates a ped spawn point within an axial aligned box
|
|
/// PARAMS:
|
|
/// min - min corner of area box
|
|
/// max - max corner of area box
|
|
/// out - new position
|
|
/// safecheck - use safe spawn point check
|
|
/// pavecheck - use pavement check
|
|
/// RETURNS:
|
|
/// true on success
|
|
FUNC BOOL GENERATE_SPAWN_POINT_IN_AREA(VECTOR min, VECTOR max, VECTOR &out, BOOL safechk = FALSE, BOOL pavecheck = FALSE)
|
|
FLOAT zrot
|
|
VECTOR pos
|
|
VECTOR diff
|
|
|
|
diff = max - min
|
|
pos = min
|
|
|
|
IF (diff.x > 0)
|
|
pos.x += GET_RANDOM_FLOAT_IN_RANGE(0, diff.x)
|
|
ENDIF
|
|
|
|
IF (diff.y > 0)
|
|
pos.y += GET_RANDOM_FLOAT_IN_RANGE(0, diff.y)
|
|
ENDIF
|
|
|
|
IF (diff.z > 0)
|
|
pos.z += GET_RANDOM_FLOAT_IN_RANGE(0, diff.z)
|
|
ENDIF
|
|
|
|
IF GET_GROUND_Z_FOR_3D_COORD(pos, zrot)
|
|
pos.z = zrot
|
|
ENDIF
|
|
|
|
out = pos
|
|
IF (safechk = FALSE)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN GET_SAFE_COORD_FOR_PED(pos, pavecheck, out)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Generates a ped spawn point in range of player
|
|
/// PARAMS:
|
|
/// out - new position
|
|
/// range - desired ranged
|
|
/// safechk - use safe coord check
|
|
/// pavecheck - use pavement check (if safechk is off this is ignored)
|
|
/// RETURNS:
|
|
/// True on success
|
|
FUNC BOOL GENERATE_SPAWN_POINT_AROUND_PLAYER(VECTOR &out, FLOAT range, BOOL safechk = FALSE, BOOL pavecheck = FALSE)
|
|
FLOAT zrot
|
|
VECTOR pos
|
|
|
|
pos = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_RANDOM_FLOAT_IN_RANGE(0.0, 360.0), <<0, range, 0>>)
|
|
|
|
IF GET_GROUND_Z_FOR_3D_COORD(pos, zrot)
|
|
pos.z = zrot
|
|
ENDIF
|
|
|
|
out = pos
|
|
IF (safechk = FALSE)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN GET_SAFE_COORD_FOR_PED(pos, pavecheck, out)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Generates a ped spawn point in range of player but in front of player
|
|
/// PARAMS:
|
|
/// out - new position
|
|
/// range - desired ranged
|
|
/// safechk - use safe coord check
|
|
/// pavecheck - use pavement check (if safechk is off this is ignored)
|
|
/// RETURNS:
|
|
/// True on success
|
|
FUNC BOOL GENERATE_SPAWN_POINT_IN_FRONT_OF_PLAYER(VECTOR &out, FLOAT range, BOOL safechk = FALSE, BOOL pavecheck = FALSE)
|
|
FLOAT angle
|
|
FLOAT zrot
|
|
VECTOR pos
|
|
VECTOR camPos
|
|
|
|
camPos = GET_GAMEPLAY_CAM_COORD()
|
|
zrot = GET_GAMEPLAY_CAM_RELATIVE_HEADING() + GET_ENTITY_HEADING(PLAYER_PED_ID())
|
|
|
|
angle = (GET_GAMEPLAY_CAM_FOV() / 2.0) + GET_RANDOM_FLOAT_IN_RANGE(0.0, 8.0)
|
|
|
|
pos = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(campos, GET_RANDOM_FLOAT_IN_RANGE(zrot - angle, zrot + angle), <<0, range, 0>>)
|
|
|
|
IF GET_GROUND_Z_FOR_3D_COORD(pos, zrot)
|
|
pos.z = zrot
|
|
ENDIF
|
|
|
|
out = pos
|
|
IF (safechk = FALSE)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN GET_SAFE_COORD_FOR_PED(pos, pavecheck, out)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Generates a ped spawn point in range of player but in front of player within a cone
|
|
/// PARAMS:
|
|
/// out - new position
|
|
/// range - desired ranged
|
|
/// angle - angle of cone
|
|
/// safechk - use safe coord check
|
|
/// pavecheck - use pavement check (if safechk is off this is ignored)
|
|
/// RETURNS:
|
|
/// True on success
|
|
FUNC BOOL GENERATE_SPAWN_POINT_IN_FRONT_OF_PLAYER_CONE(VECTOR &out, FLOAT range, FLOAT angle, BOOL safechk = FALSE, BOOL pavecheck = FALSE)
|
|
FLOAT zrot
|
|
VECTOR pos
|
|
VECTOR camPos
|
|
|
|
camPos = GET_GAMEPLAY_CAM_COORD()
|
|
zrot = GET_GAMEPLAY_CAM_RELATIVE_HEADING() + GET_ENTITY_HEADING(PLAYER_PED_ID())
|
|
|
|
angle /= 2.0
|
|
|
|
pos = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(campos, GET_RANDOM_FLOAT_IN_RANGE(zrot - angle, zrot + angle), <<0, range, 0>>)
|
|
|
|
IF GET_GROUND_Z_FOR_3D_COORD(pos, zrot)
|
|
pos.z = zrot
|
|
ENDIF
|
|
|
|
out = pos
|
|
IF (safechk = FALSE)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN GET_SAFE_COORD_FOR_PED(pos, pavecheck, out)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Generate a ped spawm point in front of player but off screen
|
|
/// PARAMS:
|
|
/// out - new position
|
|
/// range - distance away from player
|
|
/// right - pick the left or right side of screen
|
|
/// pavecheck - use the pavement check
|
|
/// RETURNS:
|
|
/// True on Success
|
|
FUNC BOOL GENERATE_SPAWN_POINT_IN_FRONT_OF_PLAYER_OFF_VIEWCONE(VECTOR &out, FLOAT range, BOOL right = TRUE, BOOL pavecheck = FALSE)
|
|
FLOAT zvalue
|
|
FLOAT oplength
|
|
VECTOR camPos
|
|
VECTOR tmp
|
|
INT i = 0
|
|
|
|
camPos = GET_GAMEPLAY_CAM_COORD()
|
|
zvalue = GET_GAMEPLAY_CAM_RELATIVE_HEADING() + GET_ENTITY_HEADING(PLAYER_PED_ID())
|
|
|
|
// this is the offscreen position [on camera plane]
|
|
oplength = (range * TAN(GET_GAMEPLAY_CAM_FOV() / 2.0)) + 1
|
|
|
|
// now check along the edge in 2.5 meter increments to get a point properly off screen
|
|
FOR i = 0 TO 4
|
|
IF (right = TRUE)
|
|
tmp = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(campos, zvalue, <<oplength, range, 0>>)
|
|
ELSE
|
|
tmp = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(campos, zvalue, <<-oplength, range, 0>>)
|
|
ENDIF
|
|
|
|
IF GET_SAFE_COORD_FOR_PED(tmp, pavecheck, out)
|
|
IF NOT IS_SPHERE_VISIBLE(out, 0.125)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
oplength += 2.5
|
|
ENDFOR
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Generate a cae spawm point in front of player but off screen
|
|
/// PARAMS:
|
|
/// out - new position
|
|
/// head - new heading
|
|
/// range - distance away from player
|
|
/// right - pick the left or right side of screen
|
|
/// RETURNS:
|
|
/// True on Success
|
|
FUNC BOOL GENERATE_CAR_SPAWN_POINT_IN_FRONT_OF_PLAYER_OFF_VIEWCONE(VECTOR &out, FLOAT &head, FLOAT range, BOOL right = TRUE)
|
|
VECTOR tmp
|
|
INT i
|
|
|
|
IF NOT GENERATE_SPAWN_POINT_IN_FRONT_OF_PLAYER_OFF_VIEWCONE(tmp, range, right)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF GET_CLOSEST_VEHICLE_NODE_WITH_HEADING(GET_ENTITY_COORDS(PLAYER_PED_ID()), out, head)
|
|
IF NOT IS_SPHERE_VISIBLE(out, 1.0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
FOR i = 1 TO 6
|
|
IF GET_NTH_CLOSEST_VEHICLE_NODE_FAVOUR_DIRECTION(tmp, GET_ENTITY_COORDS(PLAYER_PED_ID()), i, out, head)
|
|
IF NOT IS_SPHERE_VISIBLE(out, 1.0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDFOR
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Given 2 points works out which point I am more facing
|
|
/// PARAMS:
|
|
/// ent - entity
|
|
/// pt1 - point 1
|
|
/// pt2 - point 2
|
|
/// RETURNS:
|
|
/// closest point i am facing
|
|
FUNC VECTOR GET_ENTITY_FACING_POINT(ENTITY_INDEX ent, VECTOR pt1, VECTOR pt2)
|
|
VECTOR pt1toent
|
|
VECTOR pt2toent
|
|
VECTOR entfwd
|
|
FLOAT angle1
|
|
FLOAT angle2
|
|
|
|
entfwd = GET_ENTITY_FORWARD_VECTOR(ent)
|
|
pt1toent = NORMALISE_VECTOR(pt1 - GET_ENTITY_COORDS(ent))
|
|
pt2toent = NORMALISE_VECTOR(pt2 - GET_ENTITY_COORDS(ent))
|
|
|
|
angle1 = ABSF(GET_ANGLE_BETWEEN_2D_VECTORS(pt1toent.x, pt1toent.y, entfwd.x, entfwd.y))
|
|
angle2 = ABSF(GET_ANGLE_BETWEEN_2D_VECTORS(pt2toent.x, pt2toent.y, entfwd.x, entfwd.y))
|
|
|
|
IF (angle2 < angle1)
|
|
RETURN pt2
|
|
ENDIF
|
|
|
|
RETURN pt1
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Works if distance between 2 points is less then range
|
|
/// PARAMS:
|
|
/// stt - point 1
|
|
/// end - point 2
|
|
/// range - distance
|
|
/// RETURNS:
|
|
/// true or false
|
|
FUNC BOOL IS_IN_RANGE_QUICK(VECTOR stt, VECTOR end, FLOAT range)
|
|
VECTOR v = end - stt
|
|
RETURN (v.x * v.x + v.y * v.y + v.z * v.z) <= (range * range)
|
|
ENDFUNC
|
|
|
|
//----------------------
|
|
// GENERAL FUNCTIONS
|
|
//----------------------
|
|
|
|
/// PURPOSE:
|
|
/// Tells if a ped has been killed by a head shot
|
|
/// PARAMS:
|
|
/// pedID - ped ID
|
|
/// RETURNS:
|
|
/// True or False
|
|
FUNC BOOL CHECK_HEADSHOT(PED_INDEX pedID)
|
|
IF NOT DOES_ENTITY_EXIST(pedID)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
PED_BONETAG ePedBonetag = BONETAG_NULL
|
|
|
|
IF IS_ENTITY_DEAD(pedID) OR IS_PED_INJURED(pedID)
|
|
IF NOT GET_PED_LAST_DAMAGE_BONE(pedID, ePedBonetag)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN ePedBonetag = BONETAG_HEAD OR ePedBonetag = BONETAG_NECK
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Tells if a ped has been crippled (shot in the legs)
|
|
/// PARAMS:
|
|
/// pedID - ped ID
|
|
/// RETURNS:
|
|
/// True or False
|
|
FUNC BOOL CHECK_CRIPPLED(PED_INDEX pedID)
|
|
IF NOT DOES_ENTITY_EXIST(pedID)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
PED_BONETAG ePedBonetag = BONETAG_NULL
|
|
|
|
IF IS_ENTITY_DEAD(pedID) OR IS_PED_INJURED(pedID)
|
|
IF NOT GET_PED_LAST_DAMAGE_BONE(pedID, ePedBonetag)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN (ePedBonetag = BONETAG_L_CALF) OR (ePedBonetag = BONETAG_R_CALF) OR (ePedBonetag = BONETAG_R_THIGH) OR (ePedBonetag = BONETAG_L_THIGH)
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Tells if a ped has been executed (died while trying to get up)
|
|
/// PARAMS:
|
|
/// pedID - ped ID
|
|
/// RETURNS:
|
|
/// True or False
|
|
FUNC BOOL CHECK_EXECUTION(PED_INDEX pedID)
|
|
IF NOT DOES_ENTITY_EXIST(pedID)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN IS_PED_GETTING_UP(pedID)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets a list of peds using the ped scanner
|
|
/// PARAMS:
|
|
/// ped - ped to check
|
|
/// array - array to write list of peds to
|
|
/// range - distance to check
|
|
/// vRoadRange - ignored peds who are further away from road than this
|
|
/// vRoadZDist - ignore peds who's z dist is this diffrent from the road
|
|
/// misped - include mission peds
|
|
/// incar - include peds in cars
|
|
/// RETURNS:
|
|
/// # of peds found
|
|
FUNC INT GET_PEDS_NEAR_PED(PED_INDEX ped, PED_INDEX& array[], FLOAT range = 60.0, FLOAT vRoadRange = 0.0, FLOAT vRoadZDist = 5.0, BOOL misped = FALSE, BOOL incar = FALSE)
|
|
|
|
INT i
|
|
INT cnt
|
|
INT ind = 0
|
|
VECTOR tmp
|
|
VECTOR pedpos
|
|
|
|
PED_INDEX tmpArray[25]
|
|
|
|
IF NOT IS_ENTITY_OK(ped)
|
|
RETURN 0
|
|
ENDIF
|
|
|
|
range = range
|
|
cnt = GET_PED_NEARBY_PEDS(ped, tmpArray)
|
|
IF (cnt > COUNT_OF(tmpArray))
|
|
SCRIPT_ASSERT("[WARNING]:GET_PEDS_NEAR_PED - There are more in range than in the temp array")
|
|
ENDIF
|
|
|
|
IF (vRoadRange = 0.0)
|
|
|
|
i = 0
|
|
WHILE (i < cnt)
|
|
IF IS_ENTITY_OK(tmpArray[i])
|
|
|
|
IF (misped = FALSE) AND NOT IS_ENTITY_A_MISSION_ENTITY(tmpArray[i])
|
|
IF (incar = FALSE) AND NOT IS_PED_IN_ANY_VEHICLE(tmpArray[i])
|
|
IF NOT IS_PED_USING_ANY_SCENARIO(tmpArray[i])
|
|
array[ind] = tmpArray[i]
|
|
ind ++
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
i ++
|
|
ENDWHILE
|
|
|
|
ELSE
|
|
|
|
i = 0
|
|
WHILE (i < cnt)
|
|
IF IS_ENTITY_OK(tmpArray[i])
|
|
|
|
IF (misped = FALSE) AND NOT IS_ENTITY_A_MISSION_ENTITY(tmpArray[i])
|
|
IF (incar = FALSE) AND NOT IS_PED_IN_ANY_VEHICLE(tmpArray[i])
|
|
IF NOT IS_PED_USING_ANY_SCENARIO(tmpArray[i])
|
|
pedpos = GET_ENTITY_COORDS(tmpArray[i])
|
|
IF NOT GET_CLOSEST_VEHICLE_NODE(pedpos, tmp)
|
|
array[ind] = tmpArray[i]
|
|
ind ++
|
|
ELIF GET_DISTANCE_BETWEEN_COORDS(pedpos, tmp) < vRoadRange
|
|
IF (ABSF(pedpos.z - tmp.z) <= vRoadZDist)
|
|
array[ind] = tmpArray[i]
|
|
ind ++
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
i ++
|
|
ENDWHILE
|
|
|
|
ENDIF
|
|
|
|
RETURN ind
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Returns an array of everyone in the vehicle
|
|
/// PARAMS:
|
|
/// vehicle -
|
|
/// pedArray - array of ped indexs in vehicles. MAX_VEHICLE_SEATS=16 in VehicleDefines.h
|
|
/// numPeds - number of peds found and written to pedArray
|
|
/// RETURNS: true if any peds where found
|
|
///
|
|
FUNC BOOL TRY_GET_PEDS_IN_VEHICLE(VEHICLE_INDEX vehicle, PED_INDEX& pedArray[MAX_PASSENGERS_IN_VEHICLE], INT& numPeds)
|
|
|
|
numPeds = 0
|
|
|
|
INT iMaxSeats = (GET_VEHICLE_MAX_NUMBER_OF_PASSENGERS(vehicle) + 1) //Add 1 for the driver
|
|
|
|
IF iMaxSeats > MAX_PASSENGERS_IN_VEHICLE
|
|
CASSERTLN(DEBUG_SYSTEM, "Number of seats in vehicle exceeds", MAX_PASSENGERS_IN_VEHICLE, ". This is not supported.")
|
|
iMaxSeats = MAX_PASSENGERS_IN_VEHICLE
|
|
ENDIF
|
|
|
|
INT i
|
|
PED_INDEX VehPed
|
|
REPEAT iMaxSeats i
|
|
VehPed = GET_PED_IN_VEHICLE_SEAT(vehicle, INT_TO_ENUM(VEHICLE_SEAT, i-1))
|
|
IF IS_ENTITY_OK(VehPed)
|
|
pedArray[numPeds] = VehPed
|
|
numPeds++
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN numPeds > 0
|
|
ENDFUNC
|
|
|
|
FUNC BOOL IS_PED_PLAYER_OR_PLAYERS_MATE(PED_INDEX ped)
|
|
IF (ped = PLAYER_PED_ID())
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF IS_PED_IN_GROUP(ped)
|
|
IF GET_PED_GROUP_INDEX(ped) = GET_PLAYER_GROUP(PLAYER_ID())
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Forces all peds in cars near the ped to run away
|
|
/// PARAMS:
|
|
/// ped - ped we are running away from
|
|
/// radius - distance to check
|
|
/// checkDir - if we do this then check direction
|
|
/// angle -
|
|
PROC FORCE_VEHICLE_OCCUPANTS_NEAR_PED_FLEE(PED_INDEX ped, FLOAT radius = 10.0, BOOL checkDir = FALSE, FLOAT angle = 20.0)
|
|
INT cnt
|
|
INT i, n
|
|
INT totalseats
|
|
VECTOR dirToPed
|
|
PED_INDEX fleePed
|
|
SEQUENCE_INDEX seqTask
|
|
VEHICLE_INDEX tmpArray[32]
|
|
BOOL ok
|
|
|
|
// scan for vehicles near player
|
|
cnt = GET_PED_NEARBY_VEHICLES(ped, tmpArray)
|
|
IF (cnt = 0)
|
|
EXIT
|
|
ENDIF
|
|
|
|
// loop through vehicles if they are in radius tell occupants to run away
|
|
REPEAT cnt i
|
|
IF IS_ENTITY_OK(tmpArray[i])
|
|
IF NOT IS_THIS_MODEL_A_HELI(GET_ENTITY_MODEL(tmpArray[i]))
|
|
|
|
IF VDIST2(GET_ENTITY_COORDS(tmpArray[i]), GET_ENTITY_COORDS(ped)) <= (radius * radius)
|
|
|
|
ok = TRUE
|
|
|
|
IF (checkDir)
|
|
dirToPed = NORMALISE_VECTOR(GET_ENTITY_COORDS(ped) - GET_ENTITY_COORDS(tmpArray[i]))
|
|
ok = (DOT_PRODUCT(dirToPed, GET_ENTITY_FORWARD_VECTOR(tmpArray[i])) < COS(angle))
|
|
ENDIF
|
|
|
|
IF (ok)
|
|
// driver
|
|
fleePed = GET_PED_IN_VEHICLE_SEAT(tmpArray[i])
|
|
IF IS_ENTITY_OK(fleePed)
|
|
IF NOT IS_PED_PLAYER_OR_PLAYERS_MATE(fleePed)
|
|
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(fleePed, TRUE)
|
|
OPEN_SEQUENCE_TASK(seqTask)
|
|
TASK_LEAVE_ANY_VEHICLE(NULL)
|
|
TASK_SMART_FLEE_PED(NULL, ped, 300.0, -1, FALSE)
|
|
CLOSE_SEQUENCE_TASK(seqTask)
|
|
TASK_PERFORM_SEQUENCE(fleePed, seqTask)
|
|
CLEAR_SEQUENCE_TASK(seqTask)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// passengers
|
|
n = 0
|
|
totalseats = GET_VEHICLE_MAX_NUMBER_OF_PASSENGERS(tmpArray[i])
|
|
|
|
REPEAT totalseats n
|
|
fleePed = GET_PED_IN_VEHICLE_SEAT(tmpArray[i], INT_TO_ENUM(VEHICLE_SEAT, n))
|
|
|
|
IF IS_ENTITY_OK(fleePed)
|
|
IF NOT IS_PED_PLAYER_OR_PLAYERS_MATE(fleePed)
|
|
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(fleePed, TRUE)
|
|
OPEN_SEQUENCE_TASK(seqTask)
|
|
TASK_LEAVE_ANY_VEHICLE(NULL)
|
|
TASK_SMART_FLEE_PED(NULL, ped, 300.0, -1, FALSE)
|
|
CLOSE_SEQUENCE_TASK(seqTask)
|
|
TASK_PERFORM_SEQUENCE(fleePed, seqTask)
|
|
CLEAR_SEQUENCE_TASK(seqTask)
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Tells us if a vehicle has free seats
|
|
/// PARAMS:
|
|
/// vehicle - vehicle index
|
|
/// seat - seat enum (the first free seat, this is overwritten)
|
|
/// numFreeSeats - # of seats free (the first free seat, this is overwritten)
|
|
/// driverAlso - do we include the driver
|
|
/// stopCheck - if a vehicle is moving and this is set, this function will fail
|
|
/// RETURNS:
|
|
/// True if a seat is remaninig
|
|
FUNC BOOL GET_VEHICLE_HAS_FREE_SEATS(VEHICLE_INDEX vehicle, VEHICLE_SEAT& seat, INT& numFreeSeats, BOOL driverAlso = TRUE, BOOL stopCheck = TRUE)
|
|
|
|
BOOL ret = FALSE
|
|
|
|
numFreeSeats = GET_VEHICLE_MAX_NUMBER_OF_PASSENGERS(vehicle) - GET_VEHICLE_NUMBER_OF_PASSENGERS(vehicle)
|
|
|
|
IF NOT IS_ENTITY_DEAD(vehicle)
|
|
|
|
IF (stopCheck) AND NOT IS_VEHICLE_STOPPED(vehicle)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF driverAlso AND IS_VEHICLE_SEAT_FREE(vehicle, VS_DRIVER)
|
|
seat = VS_DRIVER
|
|
ret = TRUE
|
|
ELSE
|
|
INT i
|
|
REPEAT GET_VEHICLE_MAX_NUMBER_OF_PASSENGERS(vehicle) i
|
|
|
|
IF IS_VEHICLE_SEAT_FREE(vehicle, INT_TO_ENUM(VEHICLE_SEAT, i))
|
|
seat = INT_TO_ENUM(VEHICLE_SEAT, i)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
ENDREPEAT
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
RETURN ret
|
|
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Creates a ped in a vehicle and automatically gives them a chair
|
|
/// PARAMS:
|
|
/// pedModel - ped model
|
|
/// veh - vehicle to put them in
|
|
/// wpn - a weapon to give them
|
|
/// hatePlayer - set this to set peds relationship hash to RELGROUPHASH_HATES_PLAYER
|
|
/// blockTemp - set this turn off temporary events
|
|
/// pedType - ped type
|
|
/// RETURNS:
|
|
/// the ped index of the new ped or null if there are no chairs
|
|
FUNC PED_INDEX CREATE_PED_INSIDE_VEHICLE_AUTO_SEAT(MODEL_NAMES pedModel, VEHICLE_INDEX veh, WEAPON_TYPE wpn = WEAPONTYPE_INVALID, BOOL hatePlayer = FALSE, BOOL blockTemp = FALSE, PED_TYPE pedType = PEDTYPE_MISSION)
|
|
INT num
|
|
PED_INDEX ped
|
|
VEHICLE_SEAT seat
|
|
|
|
IF NOT GET_VEHICLE_HAS_FREE_SEATS(veh, seat, num)
|
|
RETURN NULL
|
|
ENDIF
|
|
|
|
ped = CREATE_PED_INSIDE_VEHICLE(veh, pedType, pedModel, seat)
|
|
IF NOT DOES_ENTITY_EXIST(ped)
|
|
RETURN NULL
|
|
ENDIF
|
|
|
|
IF (wpn <> WEAPONTYPE_INVALID) AND (wpn <> WEAPONTYPE_UNARMED)
|
|
GIVE_WEAPON_TO_PED(ped, wpn, INFINITE_AMMO, TRUE)
|
|
ENDIF
|
|
|
|
IF (hatePlayer)
|
|
SET_PED_RELATIONSHIP_GROUP_HASH(ped, RELGROUPHASH_HATES_PLAYER)
|
|
ENDIF
|
|
|
|
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(ped, blockTemp)
|
|
RETURN ped
|
|
ENDFUNC
|
|
|
|
PROC NET_SET_ENTITY_INVINCIBLE(ENTITY_INDEX ent, BOOL bOk = TRUE)
|
|
IF IS_ENTITY_OK(ent)
|
|
IF (g_bInMultiplayer)
|
|
IF NETWORK_HAS_CONTROL_OF_ENTITY(ent)
|
|
SET_ENTITY_INVINCIBLE(ent, bOK)
|
|
ENDIF
|
|
ELSE
|
|
SET_ENTITY_INVINCIBLE(ent, bOK)
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC SET_VEHICLE_AND_OCCUPANTS_INVINCIBLE(VEHICLE_INDEX veh, BOOL bOK = TRUE)
|
|
NET_SET_ENTITY_INVINCIBLE(veh, bOK)
|
|
NET_SET_ENTITY_INVINCIBLE(GET_PED_IN_VEHICLE_SEAT(veh, VS_DRIVER), bOK)
|
|
NET_SET_ENTITY_INVINCIBLE(GET_PED_IN_VEHICLE_SEAT(veh, VS_FRONT_RIGHT), bOK)
|
|
NET_SET_ENTITY_INVINCIBLE(GET_PED_IN_VEHICLE_SEAT(veh, VS_BACK_LEFT), bOK)
|
|
NET_SET_ENTITY_INVINCIBLE(GET_PED_IN_VEHICLE_SEAT(veh, VS_BACK_RIGHT), bOK)
|
|
NET_SET_ENTITY_INVINCIBLE(GET_PED_IN_VEHICLE_SEAT(veh, VS_EXTRA_LEFT_1), bOK)
|
|
NET_SET_ENTITY_INVINCIBLE(GET_PED_IN_VEHICLE_SEAT(veh, VS_EXTRA_RIGHT_1), bOK)
|
|
NET_SET_ENTITY_INVINCIBLE(GET_PED_IN_VEHICLE_SEAT(veh, VS_EXTRA_LEFT_2), bOK)
|
|
NET_SET_ENTITY_INVINCIBLE(GET_PED_IN_VEHICLE_SEAT(veh, VS_EXTRA_RIGHT_2), bOK)
|
|
NET_SET_ENTITY_INVINCIBLE(GET_PED_IN_VEHICLE_SEAT(veh, VS_EXTRA_LEFT_3), bOK)
|
|
NET_SET_ENTITY_INVINCIBLE(GET_PED_IN_VEHICLE_SEAT(veh, VS_EXTRA_RIGHT_3), bOK)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Does a shifting ground z check
|
|
/// PARAMS:
|
|
/// pos - position
|
|
/// outz - new z
|
|
/// it - number of times to try shifting
|
|
/// RETURNS:
|
|
/// true if ground z is found
|
|
FUNC BOOL REPEAT_GET_GROUND_Z(VECTOR pos, FLOAT &outz, INT it = 1)
|
|
INT I
|
|
|
|
FOR I = 0 TO it
|
|
IF GET_GROUND_Z_FOR_3D_COORD(pos, outz)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
pos.z += 0.5
|
|
ENDFOR
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL DOES_PLAYER_HAVE_THIS_MONEY(INT iCash)
|
|
IF NETWORK_IS_GAME_IN_PROGRESS()
|
|
RETURN GET_PLAYER_CASH(PLAYER_ID()) >= iCash
|
|
ENDIF
|
|
|
|
SWITCH (GET_CURRENT_PLAYER_PED_ENUM())
|
|
CASE CHAR_TREVOR
|
|
RETURN GET_ACCOUNT_BALANCE(BANK_ACCOUNT_TREVOR) >= iCash
|
|
|
|
CASE CHAR_MICHAEL
|
|
RETURN GET_ACCOUNT_BALANCE(BANK_ACCOUNT_MICHAEL) >= iCash
|
|
|
|
CASE CHAR_FRANKLIN
|
|
RETURN GET_ACCOUNT_BALANCE(BANK_ACCOUNT_FRANKLIN) >= iCash
|
|
ENDSWITCH
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets bank balance of current player
|
|
/// RETURNS:
|
|
///
|
|
FUNC INT GET_CURRENT_PLAYER_PED_ACCOUNT_BALANCE()
|
|
|
|
IF NETWORK_IS_GAME_IN_PROGRESS()
|
|
RETURN GET_PLAYER_CASH(PLAYER_ID())
|
|
ENDIF
|
|
|
|
SWITCH (GET_CURRENT_PLAYER_PED_ENUM())
|
|
CASE CHAR_TREVOR
|
|
RETURN GET_ACCOUNT_BALANCE(BANK_ACCOUNT_TREVOR)
|
|
|
|
CASE CHAR_MICHAEL
|
|
RETURN GET_ACCOUNT_BALANCE(BANK_ACCOUNT_MICHAEL)
|
|
|
|
CASE CHAR_FRANKLIN
|
|
RETURN GET_ACCOUNT_BALANCE(BANK_ACCOUNT_FRANKLIN)
|
|
ENDSWITCH
|
|
|
|
RETURN 0
|
|
ENDFUNC
|
|
|
|
PROC CHARGE_CURRENT_PLAYER_PED_ACCOUNT_BALANCE(INT amnt, BANK_ACCOUNT_ACTION_SOURCE_BAAC bac = BAAC_UNLOGGED_SMALL_ACTION)
|
|
INT cash
|
|
IF NETWORK_IS_GAME_IN_PROGRESS()
|
|
cash = GET_PLAYER_CASH(PLAYER_ID())
|
|
IF (cash > 0)
|
|
IF (cash >= amnt)
|
|
GIVE_LOCAL_PLAYER_FM_CASH(-amnt)
|
|
ELSE
|
|
GIVE_LOCAL_PLAYER_FM_CASH(-cash)
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
DEBIT_BANK_ACCOUNT(GET_CURRENT_PLAYER_PED_ENUM(), bac, amnt)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC CHARGE_PLAYER_PED_ACCOUNT_BALANCE(PED_INDEX hPed, INT amnt, BANK_ACCOUNT_ACTION_SOURCE_BAAC bac = BAAC_UNLOGGED_SMALL_ACTION)
|
|
|
|
IF NOT IS_ENTITY_OK(hPed)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF NETWORK_IS_GAME_IN_PROGRESS()
|
|
EXIT
|
|
ELSE
|
|
enumCharacterList eChar = GET_PLAYER_PED_ENUM(hPed)
|
|
IF eChar = NO_CHARACTER
|
|
eChar = GET_NPC_PED_ENUM(hPed)
|
|
ENDIF
|
|
DEBIT_BANK_ACCOUNT(eChar, bac, amnt)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Clears a cylinder of stuff
|
|
/// PARAMS:
|
|
/// v1 - position 1
|
|
/// v2 - position 2
|
|
/// rad - radius
|
|
/// ped - clear peds
|
|
/// car - clear cars
|
|
/// obj - clear objects
|
|
PROC CLEAR_CYLINDER_OF_FIRE(VECTOR v1, VECTOR v2, FLOAT rad, BOOL bClearProj = TRUE)
|
|
FLOAT dist = GET_DISTANCE_BETWEEN_COORDS(v1, v2)
|
|
VECTOR v = v1
|
|
VECTOR norm = NORMALISE_VECTOR(v2 - v1)
|
|
FLOAT f
|
|
|
|
WHILE f < dist
|
|
STOP_FIRE_IN_RANGE(v, rad)
|
|
IF (bClearProj)
|
|
CLEAR_AREA_OF_PROJECTILES(v, rad)
|
|
ENDIF
|
|
v += norm * (rad / 2.0)
|
|
f += (rad / 2.0)
|
|
ENDWHILE
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Clears a cylinder of stuff
|
|
/// PARAMS:
|
|
/// v1 - position 1
|
|
/// v2 - position 2
|
|
/// rad - radius
|
|
/// ped - clear peds
|
|
/// car - clear cars
|
|
/// obj - clear objects
|
|
PROC CLEAR_CYLINDER_OF_ENTITIES(VECTOR v1, VECTOR v2, FLOAT rad, BOOL ped = FALSE, BOOL car = FALSE, BOOL obj = FALSE, BOOL fire = FALSE, BOOL prj = TRUE)
|
|
FLOAT dist = GET_DISTANCE_BETWEEN_COORDS(v1, v2)
|
|
FLOAT f
|
|
VECTOR v = v1
|
|
VECTOR norm = NORMALISE_VECTOR(v2 - v1)
|
|
|
|
WHILE f < dist
|
|
IF (ped)
|
|
CLEAR_AREA_OF_PEDS(v, rad)
|
|
ENDIF
|
|
IF (obj)
|
|
CLEAR_AREA_OF_OBJECTS(v, rad)
|
|
ENDIF
|
|
IF (car)
|
|
CLEAR_AREA_OF_VEHICLES(v, rad)
|
|
ENDIF
|
|
IF (fire)
|
|
STOP_FIRE_IN_RANGE(v, rad)
|
|
ENDIF
|
|
IF (prj)
|
|
CLEAR_AREA_OF_PROJECTILES(v, rad)
|
|
ENDIF
|
|
v += norm * (rad / 2.0)
|
|
f += (rad / 2.0)
|
|
ENDWHILE
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Block Scenaios and Ambient
|
|
/// PARAMS:
|
|
/// sb - reference to block index - keep this index you need to call it with UNBLOCK_SCENARIOS_AND_AMBIENT to rese tit
|
|
PROC BLOCK_SCENARIOS_AND_AMBIENT(SCENARIO_BLOCKING_INDEX &sb, BOOL bClearPeds = FALSE)
|
|
// Disable all peds...
|
|
SET_PED_POPULATION_BUDGET(0)
|
|
SET_REDUCE_PED_MODEL_BUDGET(TRUE)
|
|
|
|
// Traffic and cops
|
|
SET_VEHICLE_POPULATION_BUDGET(0)
|
|
SET_REDUCE_VEHICLE_MODEL_BUDGET(TRUE)
|
|
SET_DISPATCH_COPS_FOR_PLAYER(PLAYER_ID(), FALSE)
|
|
SET_CREATE_RANDOM_COPS(FALSE)
|
|
|
|
// Turn on the slipstream effect
|
|
SET_ENABLE_VEHICLE_SLIPSTREAMING(TRUE)
|
|
|
|
// Block all scenarios
|
|
sb = ADD_SCENARIO_BLOCKING_AREA(<<-7000.0, -7000.0, -100.0>>, <<7000.0, 7000.0, 315.0>>)
|
|
|
|
// Needed to disable scenarios at docks
|
|
SET_SCENARIO_TYPE_ENABLED("DRIVE", FALSE)
|
|
|
|
// Remove vehicle gens
|
|
SET_ALL_VEHICLE_GENERATORS_ACTIVE_IN_AREA(<<-7000.0, -7000.0, -100.0>>, <<7000.0, 7000.0, 315.0>>, FALSE)
|
|
REMOVE_VEHICLES_FROM_GENERATORS_IN_AREA(<<-7000.0, -7000.0, -100.0>>, <<7000.0, 7000.0, 315.0>>)
|
|
|
|
IF IS_ENTITY_OK(PLAYER_PED_ID()) AND (bClearPeds = TRUE)
|
|
CLEAR_AREA_OF_PEDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), 500) // B*930668 - make sure there are no ambient peds still mooching around
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Unblock Scenaios and Ambient
|
|
/// PARAMS:
|
|
/// sb - reference to block index
|
|
PROC UNBLOCK_SCENARIOS_AND_AMBIENT(SCENARIO_BLOCKING_INDEX sb)
|
|
// Restore peds
|
|
SET_REDUCE_PED_MODEL_BUDGET(FALSE)
|
|
SET_PED_POPULATION_BUDGET(3)
|
|
|
|
// Traffic and cops
|
|
SET_REDUCE_VEHICLE_MODEL_BUDGET(FALSE)
|
|
SET_VEHICLE_POPULATION_BUDGET(3)
|
|
SET_DISPATCH_COPS_FOR_PLAYER(PLAYER_ID(), TRUE)
|
|
SET_CREATE_RANDOM_COPS(TRUE)
|
|
|
|
// Turn on the slipstream effect
|
|
SET_ENABLE_VEHICLE_SLIPSTREAMING(FALSE)
|
|
|
|
// Restore scenarios and vehicle gens
|
|
REMOVE_SCENARIO_BLOCKING_AREA(sb)
|
|
SET_SCENARIO_TYPE_ENABLED("DRIVE", TRUE)
|
|
SET_ALL_VEHICLE_GENERATORS_ACTIVE_IN_AREA(<<-7000.0, -7000.0, -100.0>>, <<7000.0, 7000.0, 315.0>>, TRUE)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Turns off ambient peds and vehicles scenarios everything - call this every frame
|
|
PROC NO_AMBIENT_MALARKY_THIS_FRAME()
|
|
SET_PED_DENSITY_MULTIPLIER_THIS_FRAME(0)
|
|
SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(0)
|
|
SET_SCENARIO_PED_DENSITY_MULTIPLIER_THIS_FRAME(0, 0)
|
|
SET_RANDOM_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(0)
|
|
SET_PARKED_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(0)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Given an array of vectors get the closest index to v
|
|
/// PARAMS:
|
|
/// v - point to test
|
|
/// array - vector array
|
|
/// RETURNS:
|
|
/// index of closest vector
|
|
FUNC INT GET_CLOSEST_INDEX_TO_POINT_IN_VECTOR_ARRRY(VECTOR v, VECTOR& array[])
|
|
INT i, ind = 0
|
|
FLOAT dist, mindist = -1.0
|
|
|
|
REPEAT COUNT_OF(array) i
|
|
dist = GET_DISTANCE_BETWEEN_COORDS(v, array[i])
|
|
IF (dist < mindist) OR (mindist = -1.0)
|
|
ind = i
|
|
mindist = dist
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN ind
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Returns a position from a static blip
|
|
/// PARAMS:
|
|
/// blip - blip enum
|
|
/// RETURNS:
|
|
/// Vector
|
|
FUNC VECTOR GET_POSITION_FROM_STATIC_BLIP(STATIC_BLIP_NAME_ENUM blip)
|
|
INT iIndex = ENUM_TO_INT(blip)
|
|
RETURN g_GameBlips[iIndex].vCoords[0]
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Catmull Rom Evaulation given 4 points - give us a spline point beteen p1 and p2
|
|
/// PARAMS:
|
|
/// p0 -
|
|
/// p1 -
|
|
/// p2 -
|
|
/// p3 -
|
|
/// t -
|
|
/// RETURNS:
|
|
///
|
|
FUNC VECTOR CALCULATE_SPLINE_POINT(VECTOR& p0, VECTOR& p1, VECTOR& p2, VECTOR& p3, FLOAT t)
|
|
VECTOR ret
|
|
FLOAT t2 = t * t
|
|
FLOAT t3 = t2 * t
|
|
|
|
//CPRINTLN(DEBUG_AMBIENT, "CALCULATE_SPLINE_POINT - START")
|
|
|
|
ret.x = 0.5 * ((2.0 * p1.x) +
|
|
(-p0.x + p2.x) * t +
|
|
(2.0 * p0.x - 5.0 * p1.x + 4 * p2.x - p3.x) * t2 +
|
|
(-p0.x + 3.0 * p1.x - 3.0 * p2.x + p3.x) * t3)
|
|
//CPRINTLN(DEBUG_AMBIENT, " RET X", ret.x)
|
|
|
|
ret.y = 0.5 * ((2.0 * p1.y) +
|
|
(-p0.y + p2.y) * t +
|
|
(2.0 * p0.y - 5.0 * p1.y + 4 * p2.y - p3.y) * t2 +
|
|
(-p0.y + 3.0 * p1.y - 3.0 * p2.y + p3.y) * t3)
|
|
//CPRINTLN(DEBUG_AMBIENT, " RET Y", ret.y)
|
|
|
|
ret.z = 0.5 * ((2.0 * p1.z) +
|
|
(-p0.z + p2.z) * t +
|
|
(2.0 * p0.z - 5.0 * p1.z + 4 * p2.z - p3.z) * t2 +
|
|
(-p0.z + 3.0 * p1.z - 3.0 * p2.z + p3.z) * t3)
|
|
//CPRINTLN(DEBUG_AMBIENT, " RET Z", ret.z)
|
|
//CPRINTLN(DEBUG_AMBIENT, "CALCULATE_SPLINE_POINT - END")
|
|
|
|
RETURN ret
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets the position from a static blip
|
|
/// PARAMS:
|
|
/// blip - blip enum
|
|
/// RETURNS:
|
|
/// Positon as Vector
|
|
FUNC VECTOR GET_STATIC_BLIP_COORDS(STATIC_BLIP_NAME_ENUM blip)
|
|
INT ind = ENUM_TO_INT(blip)
|
|
RETURN g_GameBlips[ind].vCoords[0]
|
|
ENDFUNC
|
|
|
|
PROC CHECK_AND_CLEAR_HELP()
|
|
IF IS_HELP_MESSAGE_BEING_DISPLAYED()
|
|
CLEAR_HELP()
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
FUNC BOOL IS_ENTITY_SMALLER_THAN_MODEL(ENTITY_INDEX veh, MODEL_NAMES mdl)
|
|
VECTOR vmin, vmax
|
|
VECTOR mmin, mmax
|
|
|
|
GET_MODEL_DIMENSIONS(GET_ENTITY_MODEL(veh), vmin, vmax)
|
|
GET_MODEL_DIMENSIONS(mdl, mmin, mmax)
|
|
|
|
IF ABSF(vmax.x - vmin.x) > ABSF(mmax.x - mmin.x)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF ABSF(vmax.y - vmin.y) > ABSF(mmax.y - mmin.y)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
|