Files
2025-09-29 00:52:08 +02:00

876 lines
38 KiB
XML
Executable File

// script_DEBUG.sch
//
// Common procedures/functions used for debug in the game.
USING "globals.sch"
#IF IS_DEBUG_BUILD
USING "shared_debug.sch"
#ENDIF
USING "types.sch"
USING "script_MISC.sch"
USING "script_player.sch"
USING "commands_entity.sch"
USING "commands_object.sch"
USING "commands_vehicle.sch"
USING "commands_camera.sch"
//// *******************************************************************************************
//// TO STRING FUNCTIONS AND PROCEDURES
//// *******************************************************************************************
/// PURPOSE: a string of the time in miliseconds (in the format 11:11:1111)
/// PARAMS:
/// ms - Time in ms
/// RETURNS: a string of the time in miliseconds (in the format 11:11:1111
/// AUTHOR: alwyn.roberts@rockstarnorth.com
#IF IS_DEBUG_BUILD
FUNC STRING GET_STRING_FROM_MILISECONDS(INT ms)
INT iHours = ((ms/1000)/(60*60))
INT iMinutes = (((ms/1000)/60)-iHours*60) //(ms/1000)/60
INT iSeconds = ((ms-(((iMinutes+(iHours*60))*60)*1000))/1000) //(ms-(iMinutes*60*1000))/1000
INT iMiliseconds = ms-((iSeconds+((iMinutes+(iHours*60))*60))*1000) //ms-((iSeconds+(iMinutes*60))*1000)
TEXT_LABEL_63 tl
IF iHours > 0
tl += iHours
tl += ":"
IF iMinutes < 10
tl += "0"
IF iMinutes < 0
tl += iMinutes
tl += ":"
IF iSeconds < 10
tl += "0"
ENDIF
ENDIF
ENDIF
ENDIF
IF iMinutes > 0
tl += iMinutes
tl += ":"
IF iSeconds < 10
tl += "0"
ENDIF
ENDIF
tl += iSeconds
tl += "."
IF iMiliseconds >= 0
tl += iMiliseconds
ELSE
tl += (iMiliseconds*-1)
ENDIF
IF iMiliseconds < 10
tl += "00"
ELIF iMiliseconds < 100
tl += "0"
ENDIF
RETURN GET_FIRST_N_CHARACTERS_OF_LITERAL_STRING(tl, GET_LENGTH_OF_LITERAL_STRING(tl))
ENDFUNC
#ENDIF // IS_DEBUG_BUILD
// PURPOSE: Convert a time in msec to a format of: 0h 0m 0s
#IF IS_DEBUG_BUILD
FUNC STRING Convert_Msec_To_HMS_String(INT ms)
INT iHours = ((ms/1000)/(60*60))
INT iMinutes = (((ms/1000)/60)-iHours*60) //(ms/1000)/60
INT iSeconds = ((ms-(((iMinutes+(iHours*60))*60)*1000))/1000) //(ms-(iMinutes*60*1000))/1000
TEXT_LABEL_15 tl15 = ""
BOOL stringStarted = FALSE
IF (iHours > 0)
tl15 += iHours
tl15 += "h "
stringStarted = TRUE
ENDIF
IF NOT (stringStarted)
IF (iMinutes > 0)
stringStarted = TRUE
ENDIF
ENDIF
IF (stringStarted)
tl15 += iMinutes
tl15 += "m "
ENDIF
tl15 += iSeconds
tl15 += "s"
RETURN (GET_FIRST_N_CHARACTERS_OF_LITERAL_STRING(tl15, GET_LENGTH_OF_LITERAL_STRING(tl15)))
ENDFUNC
#ENDIF
/// PURPOSE: Returns the float passed as a string to 4 decimal places.
/// PARAMS:
/// f - A float, +ve or -ve.
/// RETURNS: a string of the float passed.
/// AUTHOR: alwyn.roberts@rockstarnorth.com
#IF IS_DEBUG_BUILD
FUNC STRING GET_STRING_FROM_FLOAT(FLOAT f, INT decimal_places = 4)
TEXT_LABEL float_text_label
INT string_length
// Handle -ve values.
IF f < 0
INT iCeil_f = CEIL(f)
IF iCeil_f = 0
float_text_label = "-"
ENDIF
float_text_label += iCeil_f
ELSE
float_text_label += FLOOR(f)
ENDIF
float_text_label += "."
string_length = GET_LENGTH_OF_LITERAL_STRING(float_text_label)
FLOAT fFloat_remainder_a = f%1.0
FLOAT fFloat_remainder_b = (fFloat_remainder_a)*10000.0
INT iFloat_remainder_c = ROUND((fFloat_remainder_b))
INT iAddedZeros = 0
IF absi(iFloat_remainder_c) < 10
float_text_label += "000"
iAddedZeros = 3
ELIF absi(iFloat_remainder_c) < 100
float_text_label += "00"
iAddedZeros = 2
ELIF absi(iFloat_remainder_c) < 1000
float_text_label += "0"
iAddedZeros = 1
ENDIF
INT iFloat_remainder_d = ABSI(iFloat_remainder_c)
float_text_label += iFloat_remainder_d
INT iToAddZeros = 0
IF iFloat_remainder_d < 10
iToAddZeros = 3
ELIF iFloat_remainder_d < 100
iToAddZeros = 2
ELIF iFloat_remainder_d < 1000
iToAddZeros = 1
ENDIF
IF iToAddZeros > iAddedZeros
//might need to add zeros to end of text label...
ENDIF
RETURN GET_FIRST_N_CHARACTERS_OF_LITERAL_STRING(float_text_label, string_length + decimal_places)
ENDFUNC
/// PURPOSE:
/// Returns an integer bitfield as a string.
/// PARAMS:
/// iBitfield - INT you want printed as a bitfield
/// RETURNS:
/// A string of this format...
/// "BIT0 0000 0000 0000 0000 0000 0000 0000 0000 BIT31"
FUNC STRING GET_STRING_FROM_BITFIELD( INT iBinaryField )
TEXT_LABEL_63 tBuffer = "BIT0 "
INT iIndex = 0
FOR iIndex = 1 TO 32
IF IS_BIT_SET( iBinaryField, 0 )
tBuffer += 1
ELSE
tBuffer += 0
ENDIF
IF iIndex % 4 = 0
tBuffer += " "
ENDIF
iBinaryField = SHIFT_RIGHT(iBinaryField, 1)
ENDFOR
tBuffer += "BIT31"
RETURN GET_FIRST_N_CHARACTERS_OF_LITERAL_STRING(tBuffer, GET_LENGTH_OF_LITERAL_STRING(tBuffer))
ENDFUNC
/// PURPOSE:
/// Returns a bool as a string (TRUE/FALSE).
/// PARAMS:
/// bBool -
/// RETURNS:
///
FUNC STRING GET_STRING_FROM_BOOL(BOOL bBool)
IF bBool = TRUE
RETURN("TRUE")
ELSE
RETURN("FALSE")
ENDIF
ENDFUNC
#ENDIF // IS_DEBUG_BUILD
int i_sd_time_to_break_out, i_sd_time_started
// PURPOSE : temp stuff until the mocap rolls in
PROC DISPLAY_PLACEHOLDER_TEXT(STRING strText, BOOL b_fade_in_after = TRUE)
//------| If screen is faded out - We then instantly fade in then draw the rectangle.
//------| If screen is faded in - We then want the screen to fade out nicely then to instantly fade in for the rect stuff.
BOOL b_skip_timer= FALSE
INT i_duration = 11000
INT i_sd_current_time = GET_GAME_TIMER()
i_sd_time_started = i_sd_current_time
i_sd_time_to_break_out = i_sd_current_time + i_duration
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
WHILE NOT (i_sd_current_time >= i_sd_time_to_break_out)
AND NOT b_skip_timer
IF IS_CUTSCENE_SKIP_BUTTON_PRESSED()
AND ((i_sd_current_time - i_sd_time_started) > 1000)
b_skip_timer = TRUE
ENDIF
//Steve T
HIDE_HUD_AND_RADAR_THIS_FRAME ()
DRAW_RECT(0.5, 0.5, 1.0, 1.0, 0, 0, 0, 255)
SET_TEXT_CENTRE(TRUE)
SET_TEXT_COLOUR(255, 255, 255, 255)
SET_TEXT_SCALE(0.3, 0.5)
SET_SCRIPT_GFX_DRAW_ORDER(GFX_ORDER_AFTER_FADE)
DISPLAY_TEXT(0.5, 0.5, strText)
i_sd_current_time = GET_GAME_TIMER()
WAIT(0)
ENDWHILE
//Steve T
//DO_SCREEN_FADE_OUT(0)
IF b_fade_in_after
//SCRIPT_ASSERT()
// DO_SCREEN_FADE_IN(1000)
ELSE
// FADE_OUT_AND_WAIT(0)
ENDIF
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
ENDPROC
#IF IS_DEBUG_BUILD
/// PURPOSE:
/// Converts the current position and rotation of the debug cam into an attach and point offset relative to a given vehicle.
/// This is useful for quickly creating cameras that will be attached to/pointed at vehicles.
/// PARAMS:
/// veh - The vehicle to attach to and point at. If NULL, the nearest vehicle will be used
PROC OUTPUT_DEBUG_CAM_RELATIVE_TO_VEHICLE(VEHICLE_INDEX veh = NULL)
CAMERA_INDEX cam = GET_DEBUG_CAM()
IF DOES_CAM_EXIST(cam)
IF NOT DOES_ENTITY_EXIST(veh)
INT i_search_flags = VEHICLE_SEARCH_FLAG_RETURN_MISSION_VEHICLES
i_search_flags |= VEHICLE_SEARCH_FLAG_RETURN_VEHICLES_CONTAINING_A_PLAYER
i_search_flags |= VEHICLE_SEARCH_FLAG_RETURN_RANDOM_VEHICLES
i_search_flags |= VEHICLE_SEARCH_FLAG_RETURN_LAW_ENFORCER_VEHICLES
i_search_flags |= VEHICLE_SEARCH_FLAG_RETURN_VEHICLES_CONTAINING_A_DEAD_OR_DYING_PED
i_search_flags |= VEHICLE_SEARCH_FLAG_RETURN_VEHICLES_CONTAINING_GROUP_MEMBERS
i_search_flags |= VEHICLE_SEARCH_FLAG_ALLOW_VEHICLE_OCCUPANTS_TO_BE_PERFORMING_A_SCRIPTED_TASK
veh = GET_CLOSEST_VEHICLE(GET_CAM_COORD(cam), 500.0, DUMMY_MODEL_FOR_SCRIPT, i_search_flags)
ENDIF
IF IS_VEHICLE_DRIVEABLE(veh)
VECTOR v_cam_pos = GET_CAM_COORD(cam)
VECTOR v_cam_rot = GET_CAM_ROT(cam)
VECTOR v_veh_rot = GET_ENTITY_ROTATION(veh)
IF v_veh_rot.z > 180.0
v_veh_rot.z = -180.0 -(180.0 - v_veh_rot.z)
ENDIF
VECTOR v_cam_dir = <<-SIN(v_cam_rot.z) * COS(v_cam_rot.x), COS(v_cam_rot.z) * COS(v_cam_rot.x), SIN(v_cam_rot.x)>>
VECTOR v_cam_front_pos = v_cam_pos + (v_cam_dir * 3.0)
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE("ATTACH_CAM_TO_ENTITY(cam, veh, ")
SAVE_VECTOR_TO_DEBUG_FILE(GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(veh, v_cam_pos))
SAVE_STRING_TO_DEBUG_FILE(")")
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE("POINT_CAM_AT_ENTITY(cam, veh, ")
SAVE_VECTOR_TO_DEBUG_FILE(GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(veh, v_cam_front_pos))
SAVE_STRING_TO_DEBUG_FILE(")")
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE("SET_CAM_FOV(cam, ")
SAVE_FLOAT_TO_DEBUG_FILE(GET_CAM_FOV(cam))
SAVE_STRING_TO_DEBUG_FILE(")")
SAVE_NEWLINE_TO_DEBUG_FILE()
//Source data
VECTOR v_veh_pos = GET_ENTITY_COORDS(veh)
SAVE_STRING_TO_DEBUG_FILE("Camera world coords: ")
SAVE_VECTOR_TO_DEBUG_FILE(v_cam_pos)
SAVE_STRING_TO_DEBUG_FILE(" Camera rotation: ")
SAVE_VECTOR_TO_DEBUG_FILE(v_cam_rot)
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE("Vehicle world coords: ")
SAVE_VECTOR_TO_DEBUG_FILE(v_veh_pos)
SAVE_STRING_TO_DEBUG_FILE(" Vehicle rotation: ")
SAVE_VECTOR_TO_DEBUG_FILE(v_veh_rot)
SAVE_NEWLINE_TO_DEBUG_FILE()
ENDIF
ENDIF
ENDPROC
#ENDIF
#IF IS_DEBUG_BUILD
/// PURPOSE:
/// Converts the current position and rotation of the debug cam into an attach and point offset relative to a given entity.
/// This is useful for quickly creating cameras that will be attached to/pointed at entities.
/// PARAMS:
/// entity - The entity to attach to and point at.
PROC OUTPUT_DEBUG_CAM_RELATIVE_TO_ENTITY(ENTITY_INDEX entity)
CAMERA_INDEX cam = GET_DEBUG_CAM()
IF DOES_CAM_EXIST(cam)
IF NOT IS_ENTITY_DEAD(entity)
VECTOR v_cam_pos = GET_CAM_COORD(cam)
VECTOR v_cam_rot = GET_CAM_ROT(cam)
VECTOR v_entity_rot = GET_ENTITY_ROTATION(entity)
IF v_entity_rot.z > 180.0
v_entity_rot.z = -180.0 -(180.0 - v_entity_rot.z)
ENDIF
VECTOR v_cam_dir = <<-SIN(v_cam_rot.z) * COS(v_cam_rot.x), COS(v_cam_rot.z) * COS(v_cam_rot.x), SIN(v_cam_rot.x)>>
VECTOR v_cam_front_pos = v_cam_pos + (v_cam_dir * 3.0)
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE("ATTACH_CAM_TO_ENTITY(cam, entity, ")
SAVE_VECTOR_TO_DEBUG_FILE(GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(entity, v_cam_pos))
SAVE_STRING_TO_DEBUG_FILE(")")
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE("POINT_CAM_AT_ENTITY(cam, entity, ")
SAVE_VECTOR_TO_DEBUG_FILE(GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(entity, v_cam_front_pos))
SAVE_STRING_TO_DEBUG_FILE(")")
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE("SET_CAM_FOV(cam, ")
SAVE_FLOAT_TO_DEBUG_FILE(GET_CAM_FOV(cam))
SAVE_STRING_TO_DEBUG_FILE(")")
SAVE_NEWLINE_TO_DEBUG_FILE()
//Source data
VECTOR v_entity_pos = GET_ENTITY_COORDS(entity)
SAVE_STRING_TO_DEBUG_FILE("Camera world coords: ")
SAVE_VECTOR_TO_DEBUG_FILE(v_cam_pos)
SAVE_STRING_TO_DEBUG_FILE(" Camera rotation: ")
SAVE_VECTOR_TO_DEBUG_FILE(v_cam_rot)
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE("Entity world coords: ")
SAVE_VECTOR_TO_DEBUG_FILE(v_entity_pos)
SAVE_STRING_TO_DEBUG_FILE(" Entity rotation: ")
SAVE_VECTOR_TO_DEBUG_FILE(v_entity_rot)
SAVE_NEWLINE_TO_DEBUG_FILE()
ENDIF
ENDIF
ENDPROC
#ENDIF
// PURPOSE : References a string to fool the compiler
PROC DUMMY_REFERENCE_STRING(STRING dummyText)
IF ARE_STRINGS_EQUAL(dummyText, dummyText)
ENDIF
ENDPROC
// PURPOSE : References a bool to fool the compiler
PROC DUMMY_REFERENCE_BOOL(BOOL dummyBOOL)
IF dummyBOOL
ENDIF
ENDPROC
// PURPOSE : References an integer to fool the compiler
PROC DUMMY_REFERENCE_INT(INT dummyINT)
IF dummyINT > 0
ENDIF
ENDPROC
// PURPOSE : References a float to fool the compiler
PROC DUMMY_REFERENCE_FLOAT(FLOAT dummyFLOAT)
IF dummyFLOAT <> 0
ENDIF
ENDPROC
// PURPOSE : References a vector to fool the compiler
PROC DUMMY_REFERENCE_VECTOR(VECTOR dummyVECTOR)
IF VDIST(dummyVECTOR, dummyVECTOR) > 1
ENDIF
ENDPROC
//Steve T doctored this hack.. HAS_PICKUP was removed by John G.
//PURPOSE : References a pickup to fool the compiler
PROC DUMMY_REFERENCE_PICKUP(PICKUP_INDEX dummyPICKUP)
IF dummyPICKUP = dummyPICKUP
ENDIF
//IF HAS_PICKUP_BEEN_COLLECTED(dummyPICKUP)
//ENDIF
ENDPROC
/// PURPOSE:
/// Can pass vectors straight into command, unlike GET_HEADING_FROM_VECTOR_2D
/// PARAMS:
/// VECTOR V1, VECTOR V2
FUNC FLOAT GET_HEADING_BETWEEN_VECTORS_2D(VECTOR V1, VECTOR V2)
RETURN GET_HEADING_FROM_VECTOR_2D(V2.x-V1.x,V2.y-V1.y)
ENDFUNC
#IF IS_DEBUG_BUILD
/// PURPOSE:
/// Draws debug text in position above the specified position with Z coordinate offset.
/// PARAMS:
/// vPosition - Position to draw the debug text above.
/// sText - String to draw on screen.
/// fZOffset - Z coordinate offset to apply to draw position.
/// iRed - Red component of RGB for the debug text.
/// iGreen - Green component of RGB for the debug text.
/// iBlue - Blue component of RGB for the debug text.
/// iAlpha - Alpha for the debug text.
PROC DRAW_DEBUG_TEXT_ABOVE_COORDS(VECTOR vPosition, STRING sText, FLOAT fZOffset, INT iRed = 255, INT iGreen = 0, INT iBlue = 0, INT iAlpha = 255)
VECTOR vNewPosition = vPosition
vNewPosition.Z = vPosition.Z + fZOffset
DRAW_DEBUG_TEXT(sText, vNewPosition, iRed, iGreen, iBlue, iAlpha)
ENDPROC
/// PURPOSE:
/// Draws debug text in position above the specified entity with Z coordinate offset.
/// PARAMS:
/// EntityIndex - Entity to draw debug text above.
/// sText - String to draw on screen.
/// fZOffset - Z coordinate offset to apply to draw position.
/// iRed - Red component of RGB for the debug text.
/// iGreen - Green component of RGB for the debug text.
/// iBlue - Blue component of RGB for the debug text.
/// iAlpha - Alpha for the debug text.
PROC DRAW_DEBUG_TEXT_ABOVE_ENTITY(ENTITY_INDEX EntityIndex, STRING sText, FLOAT fZOffset, INT iRed = 255, INT iGreen = 0, INT iBlue = 0, INT iAlpha = 255)
IF DOES_ENTITY_EXIST(EntityIndex)
IF NOT IS_ENTITY_DEAD(EntityIndex)
VECTOR vPosition = GET_ENTITY_COORDS(EntityIndex)
vPosition.Z = vPosition.Z + fZOffset
DRAW_DEBUG_TEXT(sText, vPosition, iRed, iGreen, iBlue, iAlpha)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Draws debug vehicle recording name, number and playback time in position above the specified vehcile with Z coordinate offset.
/// PARAMS:
/// VehicleIndex - Vehicle index to check for vehicle recording name, number and playback time.
/// fZOffset - Z coordinate offset to apply to draw position.
/// iRed - Red component of RGB for the debug text.
/// iGreen - Green component of RGB for the debug text.
/// iBlue - Blue component of RGB for the debug text.
/// iAlpha - Alpha for the debug text.
PROC DRAW_DEBUG_VEHICLE_RECORDING_INFO(VEHICLE_INDEX VehicleIndex, FLOAT fZOffset, INT iRed = 255, INT iGreen = 0, INT iBlue = 0, INT iAlpha = 255)
IF DOES_ENTITY_EXIST(VehicleIndex)
IF NOT IS_ENTITY_DEAD(VehicleIndex)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(VehicleIndex)
TEXT_LABEL_63 sRecordingName
RECORDING_ID iRecordingID = GET_CURRENT_PLAYBACK_FOR_VEHICLE(VehicleIndex)
INT iRecordingPlaybackTime = FLOOR(GET_TIME_POSITION_IN_RECORDING(VehicleIndex))
sRecordingName = GET_VEHICLE_RECORDING_NAME(iRecordingID)
sRecordingName += ": "
sRecordingName += iRecordingPlaybackTime
DRAW_DEBUG_TEXT_ABOVE_ENTITY(VehicleIndex, sRecordingName, fZOffset, iRed, iGreen, iBlue, iAlpha)
ENDIF
ENDIF
ENDIF
ENDPROC
///PURPOSE:
/// Draws a solid angled area to help distinguish it from other angled areas. (Remember SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE)
PROC DRAW_DEBUG_POLY_ANGLED_AREA(VECTOR vCoord1, VECTOR vCoord2, FLOAT fWidth, INT iRed = 255, INT iGreen = 0, INT iBlue = 0, INT iAlpha = 128, BOOL bDebugLines = TRUE, BOOL bDebugSolid = TRUE)
IF bDebugSolid
//Bottom
DRAW_DEBUG_POLY(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue, iAlpha)
DRAW_DEBUG_POLY(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue, iAlpha)
//Top
DRAW_DEBUG_POLY(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue, iAlpha)
DRAW_DEBUG_POLY(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue, iAlpha)
//Left
DRAW_DEBUG_POLY(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue, iAlpha)
DRAW_DEBUG_POLY(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue, iAlpha)
//Right
DRAW_DEBUG_POLY(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue, iAlpha)
DRAW_DEBUG_POLY(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue, iAlpha)
//Front
DRAW_DEBUG_POLY(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue, iAlpha)
DRAW_DEBUG_POLY(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue, iAlpha)
//Back
DRAW_DEBUG_POLY(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue, iAlpha)
DRAW_DEBUG_POLY(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>, <<vCoord2.X, vCoord2.Y, vCoord2.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue, iAlpha)
ENDIF
IF bDebugLines
OR bDebugSolid = FALSE
//Bottom
DRAW_DEBUG_LINE(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue)
DRAW_DEBUG_LINE(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue)
DRAW_DEBUG_LINE(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue)
DRAW_DEBUG_LINE(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue)
//Top
DRAW_DEBUG_LINE(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue)
DRAW_DEBUG_LINE(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue)
DRAW_DEBUG_LINE(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue)
DRAW_DEBUG_LINE(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue)
//Edges
DRAW_DEBUG_LINE(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue)
DRAW_DEBUG_LINE(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord1.X, vCoord1.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue)
DRAW_DEBUG_LINE(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue)
DRAW_DEBUG_LINE(GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord1.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(<<vCoord2.X, vCoord2.Y, vCoord2.Z>>,
GET_HEADING_BETWEEN_VECTORS_2D(<<vCoord1.X, vCoord1.Y, vCoord1.Z>>, <<vCoord2.X, vCoord2.Y, vCoord1.Z>>),
<<-(fWidth / 2), 0.0, 0.0>>),
iRed, iGreen, iBlue)
ENDIF
ENDPROC
FUNC BOOL GET_DRAW_DEBUG_COMMANDLINE_PARAM_EXISTS(STRING sParam = NULL, BOOL bBypassAllFlag = FALSE)
IF GET_COMMANDLINE_PARAM_EXISTS("sc_DrawDebugStuff")
STRING sArgs = GET_COMMANDLINE_PARAM("sc_DrawDebugStuff")
IF IS_STRING_NULL_OR_EMPTY(sParam)
sParam = GET_THIS_SCRIPT_NAME()
ENDIF
//First, check string is not null.
IF IS_STRING_NULL_OR_EMPTY(sArgs)
ASSERTLN("GET_DRAW_DEBUG_COMMANDLINE_PARAM_EXISTS: The character string was null.")
RETURN FALSE
ENDIF
IF ARE_STRINGS_EQUAL("all", sArgs)
AND NOT bBypassAllFlag
RETURN TRUE
ENDIF
// Get string length.
INT stringLength = GET_LENGTH_OF_LITERAL_STRING(sArgs)
//Use this int to store the character indexes at which the string is split.
//There are a maxumum of 2 breaks as there is a maximum of 3 playable characters.
INT iBreakIndex[2]
INT iNumBreaksFound = 0
//Step through the string and record break indexes.
INT iStringIndex
REPEAT (stringLength-1) iStringIndex
IF ARE_STRINGS_EQUAL(GET_STRING_FROM_STRING(sArgs, iStringIndex, iStringIndex+1), ";")
IF iNumBreaksFound = COUNT_OF(iBreakIndex)
ASSERTLN("GET_DRAW_DEBUG_COMMANDLINE_PARAM_EXISTS: Too many character names contained in character string, please update size of iBreakIndex[", COUNT_OF(iBreakIndex), "]")
RETURN FALSE
ENDIF
iBreakIndex[iNumBreaksFound] = iStringIndex
iNumBreaksFound++
ENDIF
ENDREPEAT
//Now split up the string around the break points and save the individual names into the provided text labels.
IF iNumBreaksFound > 0
IF ARE_STRINGS_EQUAL(sParam, GET_STRING_FROM_STRING(sArgs, 0, iBreakIndex[0]))
RETURN TRUE
ENDIF
IF iNumBreaksFound = 1
IF ARE_STRINGS_EQUAL(sParam, GET_STRING_FROM_STRING(sArgs, iBreakIndex[0]+1, stringLength))
RETURN TRUE
ENDIF
ELIF iNumBreaksFound = 2
IF ARE_STRINGS_EQUAL(sParam, GET_STRING_FROM_STRING(sArgs, iBreakIndex[0]+1, iBreakIndex[1]))
RETURN TRUE
ENDIF
IF ARE_STRINGS_EQUAL(sParam, GET_STRING_FROM_STRING(sArgs, iBreakIndex[1]+1, stringLength))
RETURN TRUE
ENDIF
ENDIF
//// might be more efficient if we up iBreakIndex[]
// INT iBreak
// REPEAT iNumBreaksFound iBreak
// IF iBreak = 0
// IF ARE_STRINGS_EQUAL(sParam, GET_STRING_FROM_STRING(sArgs, 0, iBreakIndex[iBreak]))
// RETURN TRUE
// ENDIF
// ELIF iBreak != iNumBreaksFound-1
// IF ARE_STRINGS_EQUAL(sParam, GET_STRING_FROM_STRING(sArgs, iBreakIndex[iBreak-1]+1, iBreakIndex[iBreak]))
// RETURN TRUE
// ENDIF
// ELSE
// IF ARE_STRINGS_EQUAL(sParam, GET_STRING_FROM_STRING(sArgs, iBreakIndex[iBreak-1]+1, stringLength))
// RETURN TRUE
// ENDIF
// ENDIF
// ENDREPEAT
ELSE
IF ARE_STRINGS_EQUAL(sParam, sArgs)
RETURN TRUE
ENDIF
ENDIF
ENDIF
IF GET_COMMANDLINE_PARAM_EXISTS("sc_DrawDebugFamilyStuff")
PRINTLN("GET_DRAW_DEBUG_COMMANDLINE_PARAM_EXISTS: replace \"sc_DrawDebugFamilyStuff\" with custom \"sc_DrawDebugStuff=custom\".")
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
#ENDIF