// ***************************************************************************************** // ***************************************************************************************** // // 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 - <>, v + <>, 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 = <> 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, <>) 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, <>) 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, <>) 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, <>) 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, <>) 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, <>) 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, <>) 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, <>) 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