////////////////////////////////////////////////////////////////////////////////////////// // // // MISSION NAME : taxiLauncher.sc // // AUTHOR : Ahron Mason // // DESCRIPTION : Handles player calling a cab or entering a cab, // // Also launches TaxiService.sc which handles player in a cab // // // ////////////////////////////////////////////////////////////////////////////////////////// USING "rage_builtins.sch" USING "globals.sch" USING "area_checks.sch" USING "cellphone_public.sch" USING "context_control_public.sch" USING "flow_help_public.sch" USING "taxi_functions.sch" USING "tv_control_public.sch" USING "website_public.sch" //------------------------------------------------------------------------------------------------------------------------------------------------- // :ENUMS: //------------------------------------------------------------------------------------------------------------------------------------------------- /// PURPOSE: state of the launcher ENUM TAXI_LAUNCHER_STATE TL_STATE_IDLE, TL_STATE_PLAYER_NOT_IN_TAXI, TL_STATE_PLAYER_IN_TAXI ENDENUM /// PURPOSE: state for the phone launching ENUM TAXI_LAUNCHER_PHONE_STATE TL_PHONE_STATE_AWAITING_CALL, TL_PHONE_STATE_WAIT_TO_RESET_CALL, TL_PHONE_STATE_CALL_IN_PROGRESS ENDENUM /// PURPOSE: states for the dispatched taxi ENUM TAXI_LAUNCHER_DISPATCHED_STATE TL_DISPATCHED_STATE_IDLE, TL_DISPATCHED_STATE_CREATE_TAXI, TL_DISPATCHED_STATE_DRIVE_TO_PICKUP_PLAYER, TL_DISPATCHED_STATE_PULL_OVER_TO_PICKUP_PLAYER ENDENUM /// PURPOSE: states for controlling player getting into taxis ENUM TAXI_LAUNCHER_ENTER_TAXI_STATE TL_ENTER_TAXI_STATE_IDLE, TL_ENTER_TAXI_STATE_ENTERING, TL_ENTER_TAXI_STATE_INSIDE, TL_ENTER_TAXI_STATE_WAIT_FOR_PLAYER_TO_EXIT ENDENUM /// PURPOSE: states for controlling player getting into taxis ENUM TAXI_LAUNCHER_HAIL_TAXI_STATE TL_HAIL_TAXI_STATE_IDLE, TL_HAIL_TAXI_STATE_DETECT_HAIL, TL_HAIL_TAXI_STATE_SUCCESSFUL_ATTEMPT, TL_HAIL_TAXI_STATE_FAILED_ATTEMPT, TL_HAIL_TAXI_STATE_TAXI_WAITING ENDENUM /// PURPOSE: data used by the taxi dispatched by the phone call STRUCT DISPATCHED_TAXI_STRUCT VEHICLE_INDEX vehicleIndex PED_INDEX pedIndex BOOL bHasActiveTask BOOL bForcedPullOverAtCurrentPosition = FALSE BOOL bFailedZCheck = FALSE FLOAT fDistToTarget FLOAT fDriveToHeading FLOAT fTargetReached INT iNodeSearchNumber INT iTimer_TaxiDispatchDelay INT iSpawnAttempts VECTOR vDistToPlayer VECTOR vDriveToCoords VECTOR vPullOverCoords VECTOR vPlayerCalledCoords VECTOR vPathNodeRequestMin VECTOR vPathNodeRequestMax DRIVINGMODE taxiDrivingModeStandard enumCharacterList eCharDispatchedFor ENDSTRUCT //------------------------------------------------------------------------------------------------------------------------------------------------- // :CONSTANTS //------------------------------------------------------------------------------------------------------------------------------------------------- CONST_FLOAT TAXI_HAIL_DISTANCE 35.0 CONST_FLOAT TAXI_MOVING_GET_IN_SPEED 0.5 CONST_INT ENTER_CAR_AS_PASSENGER_TIME 275 CONST_INT STICK_DEAD_ZONE 28 CONST_INT TIME_DELAY_TAXI_DISPATCHED 10000 CONST_INT PROG_INITIALISE 0 CONST_INT PROG_ATTEMPT_HAIL 1 //------------------------------------------------------------------------------------------------------------------------------------------------- // :VARIABLES //------------------------------------------------------------------------------------------------------------------------------------------------- TAXI_LAUNCHER_STATE eTaxiLauncherState = TL_STATE_IDLE TAXI_LAUNCHER_PHONE_STATE eCallTaxiServiceState = TL_PHONE_STATE_AWAITING_CALL TAXI_LAUNCHER_DISPATCHED_STATE eDispatchedTaxiState = TL_DISPATCHED_STATE_IDLE TAXI_LAUNCHER_ENTER_TAXI_STATE eEnterTaxiState = TL_ENTER_TAXI_STATE_IDLE TAXI_LAUNCHER_HAIL_TAXI_STATE eHailTaxiState = TL_HAIL_TAXI_STATE_IDLE DISPATCHED_TAXI_STRUCT sDispatchedTaxi BOOL bPlayAdditionalFuckYouDialogue BOOL bHintTriggeredByTaxiLauncher BOOL bHelpEnterTaxiDisplayed = FALSE BOOL bUpdateHailTargetThisFrame = TRUE BOOL bPhonecallReachedSuccessfulLine = FALSE BOOL bBlockingPlayerAmbientIdles = FALSE BLIP_INDEX blipWaitingTaxi INT iHailPromptCounter INT iTaxiHailIntention = NEW_CONTEXT_INTENTION INT iTimer_DelayTaxiSearch INT iTimer_HailAnimTriggered INT iTimer_HailFailedDialogueDelay MODEL_NAMES mnTaxiDriverModel = GET_TAXI_DRIVER_MODEL() MODEL_NAMES mnTaxiModel = GET_TAXI_MODEL() // Phonecall Vars structPedsForConversation phonecallStruct STRING playerVoice STRING playerLine1 STRING playerLine3 THREADID tTaxiServiceThread TEXT_LABEL_15 tlTaxiAnimDict = "TAXI_HAIL" VECTOR vPlayerPos VEHICLE_INDEX vehClosestTaxi VEHICLE_INDEX vehHailTarget VEHICLE_SEAT ePlayerChosenSeat //------------------------------------------------------------------------------------------------------------------------------------------------- // :DEBUG FUNCS / PROCS / WIDGETS //------------------------------------------------------------------------------------------------------------------------------------------------- #IF IS_DEBUG_BUILD BLIP_INDEX bDebug_blip1 BLIP_INDEX bDebug_blip2 BLIP_INDEX bDebug_blip3 BOOL bDebug_AddBlips = FALSE BOOL bDebug_CallCab = FALSE BOOL bDebug_DisplayInfo = FALSE BOOL bDebug_DisplayCleanupTTY = FALSE BOOL bDebug_KillPlayerVehicle = FALSE BOOL bDebug_VisualiseDispatchTaxi = FALSE BOOL bDebug_OutputText = FALSE BOOL bDebug_Point1 = TRUE BOOL bDebug_ZeroPlayerCash = FALSE BOOL bDebug_DrawGetPullOverResults = FALSE BOOL bDebug_SetCanPlayerUseTaxiFalse = FALSE BOOL bDebug_SetCanPlayerUseTaxiTrue = FALSE BOOL bDebug_VisualiseIsPointInAngledAreaCheck = FALSE VECTOR vDebug_PointInAngledTest VECTOR vDebug_PointInAngledAreaCheck[2] FLOAT fDebug_PointInAngledAreaWidth BOOL bDebug_UseForceTaxiSpawnCoordsAndHeading = FALSE VECTOR vDebug_ForcedTaxiSpawnCoords FLOAT fDebug_ForcedTaxiSpawnHeading //BOOL bDebugPerformGenerateTaxiSpawnPos = FALSE //BOOL bDebugPerformGetTaxiDriveToPlayerTest = FALSE //BOOL bDebug_TestIsPositionInSpecialArea = FALSE //BOOL bDebugPerformGetTaxiPullInSpotTest = FALSE FLOAT fDebug_DistBetween1n4[8] //FLOAT fDebug_DriveToNodeHeading INT iDebug_CurrentArea VECTOR vDebug_AreaBound1[8] VECTOR vDebug_AreaBound2[8] VECTOR vDebug_DispatchTaxiSpawnPos //VECTOR vDebug_TaxiPos //VECTOR vDebug_DriveToNodePos //VECTOR vDebug_TempPickupPos WIDGET_GROUP_ID widgetGroup /// PURPOSE: /// Sets up the script's widget groups, which get created in RAG->SCRIPT PROC DEBUG_SETUP_WIDGETS() widgetGroup = START_WIDGET_GROUP("taxiLauncher") ADD_WIDGET_BOOL("Output additional TTY info", bDebug_DisplayInfo) ADD_WIDGET_BOOL("Output additional cleanup TTY info", bDebug_DisplayCleanupTTY) ADD_WIDGET_BOOL("Zero Player Cash", bDebug_ZeroPlayerCash) ADD_WIDGET_BOOL("Add/remove some blips", bDebug_AddBlips) ADD_WIDGET_BOOL("Is player in a taxi", g_bPlayerIsInTaxi) ADD_WIDGET_BOOL("Disable Hailing status", g_bTaxiHailingIsDisabled) ADD_WIDGET_BOOL("bDebug_SetCanPlayerUseTaxiFalse", bDebug_SetCanPlayerUseTaxiFalse) ADD_WIDGET_BOOL("bDebug_SetCanPlayerUseTaxiTrue", bDebug_SetCanPlayerUseTaxiTrue) ADD_WIDGET_BOOL("Kill current car", bDebug_KillPlayerVehicle) ADD_WIDGET_BOOL("Call a cab", bDebug_CallCab) ADD_WIDGET_BOOL("Dispatched Taxi : visualise info : ", bDebug_VisualiseDispatchTaxi) ADD_WIDGET_VECTOR_SLIDER("vDebug_ForcedTaxiSpawnCoords : ", vDebug_ForcedTaxiSpawnCoords, -10000.0, 10000.0, 0.0001) ADD_WIDGET_FLOAT_SLIDER("fDebug_ForcedTaxiSpawnHeading : ", fDebug_ForcedTaxiSpawnHeading, -360.0, 360.0, 0.01) ADD_WIDGET_BOOL("Use Forced dispatch taxi spawn coords and heading: ", bDebug_UseForceTaxiSpawnCoordsAndHeading) ADD_WIDGET_BOOL("bDebug_VisualiseIsPointInAngledAreaCheck", bDebug_VisualiseIsPointInAngledAreaCheck) ADD_WIDGET_VECTOR_SLIDER("vDebug_PointInAngledTest : ", vDebug_PointInAngledTest, -10000.0, 10000.0, 0.0001) ADD_WIDGET_VECTOR_SLIDER("vDebug_PointInAngledAreaCheck[0] : ", vDebug_PointInAngledAreaCheck[0], -10000.0, 10000.0, 0.0001) ADD_WIDGET_VECTOR_SLIDER("vDebug_PointInAngledAreaCheck[1] : ", vDebug_PointInAngledAreaCheck[1], -10000.0, 10000.0, 0.0001) ADD_WIDGET_FLOAT_SLIDER("fDebug_PointInAngledAreaWidth : ", fDebug_PointInAngledAreaWidth, 0.0, 1000.0, 0.01) /*ADD_WIDGET_BOOL("display taxi pull over results", bDebug_DrawGetPullOverResults) ADD_WIDGET_BOOL("Debug perform GET_TAXI_PICK_UP_PLAYER_DESTINATION test uses : ", bDebugPerformGetTaxiDriveToPlayerTest) ADD_WIDGET_BOOL("Debug perform GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER test : ", bDebugPerformGenerateTaxiSpawnPos) ADD_WIDGET_BOOL("Debug perform ARE_COORDS_IN_SPECIAL_AREA test uses vDebug_TempPickupPos : ", bDebug_TestIsPositionInSpecialArea) ADD_WIDGET_BOOL("Debug perform GET_TAXI_PULL_OVER_INFO / test uses : ", bDebugPerformGetTaxiPullInSpotTest) ADD_WIDGET_VECTOR_SLIDER("vDebug_DriveToNodePos :", vDebug_DriveToNodePos, -10000.0, 10000.0, 0.0001) ADD_WIDGET_VECTOR_SLIDER("vDebug_TempPickupPos :", vDebug_TempPickupPos, -10000.0, 10000.0, 0.0001)*/ STOP_WIDGET_GROUP() ENDPROC /// PURPOSE: /// updates the script's widgets, based off RAG input PROC DEBUG_UPDATE_WIDGETS() //MONITOR_CUSTOM_DROP_OFF_BLIP() IF bDebug_ZeroPlayerCash //BREAK_ON_NATIVE_COMMAND("PRINTNL", TRUE) DEBIT_BANK_ACCOUNT(GET_CURRENT_PLAYER_PED_ENUM(), BAAC_TAXI, GET_TOTAL_CASH(GET_CURRENT_PLAYER_PED_ENUM())) bDebug_ZeroPlayerCash = FALSE ENDIF IF bDebug_AddBlips IF NOT DOES_BLIP_EXIST(bDebug_blip1) bDebug_blip1 = ADD_BLIP_FOR_COORD(<< -820.1073, -356.7995, 36.5842 >>) SET_TAXI_DROPOFF_LOCATION_FOR_BLIP(bDebug_blip1, << -158.2055, -854.6122, 28.8008 >>, 339.2080) ENDIF IF NOT DOES_BLIP_EXIST(bDebug_blip2) bDebug_blip2 = ADD_BLIP_FOR_COORD(<< -1579.8685, -503.4034, 34.3710 >>) SET_TAXI_DROPOFF_LOCATION_FOR_BLIP(bDebug_blip1, << -158.2055, -854.6122, 28.8008 >>, 339.2080) ENDIF IF NOT DOES_BLIP_EXIST(bDebug_blip3) bDebug_blip3 = ADD_BLIP_FOR_COORD(<< -735.7357, -1185.1532, 9.6465 >>) SET_TAXI_DROPOFF_LOCATION_FOR_BLIP(bDebug_blip1, << -158.2055, -854.6122, 28.8008 >>, 339.2080) ENDIF ELSE IF DOES_BLIP_EXIST(bDebug_blip1) REMOVE_BLIP(bDebug_blip1) ENDIF IF DOES_BLIP_EXIST(bDebug_blip2) REMOVE_BLIP(bDebug_blip2) ENDIF IF DOES_BLIP_EXIST(bDebug_blip3) REMOVE_BLIP(bDebug_blip3) ENDIF ENDIF IF bDebug_SetCanPlayerUseTaxiFalse DISABLE_TAXI_HAILING(TRUE) bDebug_SetCanPlayerUseTaxiFalse = FALSE ELIF bDebug_SetCanPlayerUseTaxiTrue DISABLE_TAXI_HAILING(FALSE) bDebug_SetCanPlayerUseTaxiTrue = FALSE ENDIF IF bDebug_KillPlayerVehicle IF NOT IS_PED_INJURED(PLAYER_PED_ID()) IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) SET_VEHICLE_ENGINE_HEALTH(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), 0) ENDIF ENDIF bDebug_KillPlayerVehicle = FALSE ENDIF IF bDebug_VisualiseIsPointInAngledAreaCheck IF IS_POINT_IN_ANGLED_AREA(vDebug_PointInAngledTest, vDebug_PointInAngledAreaCheck[0], vDebug_PointInAngledAreaCheck[1], fDebug_PointInAngledAreaWidth, TRUE) DRAW_DEBUG_SPHERE(vDebug_PointInAngledTest, 0.5, 10, 200, 50, 150) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " DEBUG: IS_POINT_IN_ANGLED_AREA vDebug_PointInAngledTest = ", vDebug_PointInAngledTest) ENDIF ENDIF IF bDebug_VisualiseDispatchTaxi IF DOES_ENTITY_EXIST(sDispatchedTaxi.vehicleIndex) SET_DEBUG_ACTIVE(TRUE) SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE) VECTOR vTempDrawPos VECTOR vTempPos = GET_ENTITY_COORDS(sDispatchedTaxi.vehicleIndex, FALSE) IF IS_VEHICLE_DRIVEABLE(g_WaitingTaxi) vTempDrawPos = vTempPos vTempDrawPos.Z += 14.0 DRAW_DEBUG_SPHERE(vTempDrawPos, 10.0, 0, 250, 100, 120) ENDIF DRAW_DEBUG_LINE(vDebug_DispatchTaxiSpawnPos, vTempPos, 255, 0, 0, 255) // red DRAW_DEBUG_LINE(sDispatchedTaxi.vDriveToCoords, vTempPos, 255, 165, 0, 255) // orange DRAW_DEBUG_LINE(sDispatchedTaxi.vPullOverCoords , vTempPos, 75, 255, 0, 255) // light green ENDIF ENDIF /* IF bDebugPerformGenerateTaxiSpawnPos IF GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER(vTempReturnCoords, fTempReturnHeading) STRING sTemp OPEN_DEBUG_FILE() SAVE_NEWLINE_TO_DEBUG_FILE() sTemp = "DEBUG : bDebugPerformGenerateTaxiSpawnPos results : vReturnCoords = " SAVE_STRING_TO_DEBUG_FILE(sTemp) SAVE_VECTOR_TO_DEBUG_FILE(vTempReturnCoords) sTemp = " : vReturnHeading = " SAVE_STRING_TO_DEBUG_FILE(sTemp) SAVE_FLOAT_TO_DEBUG_FILE(fTempReturnHeading) SAVE_NEWLINE_TO_DEBUG_FILE() CLOSE_DEBUG_FILE() bDebugPerformGenerateTaxiSpawnPos = FALSE ENDIF ENDIF IF bDebugPerformGetTaxiDriveToPlayerTest iDesinationNodeSearchNumber = 0 IF GET_TAXI_PICK_UP_PLAYER_DESTINATION(vDebug_TempPickupPos, vDebug_DriveToNodePos, fDebug_DriveToNodeHeading, iDesinationNodeSearchNumber) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " bDebugPerformGetTaxiDriveToPlayerTest - return TRUE for vDebug_TempPickupPos : ", vDebug_TempPickupPos, " vDebug_DriveToNodePos = ", vDebug_DriveToNodePos, " fDebug_DriveToNodeHeading = ", fDebug_DriveToNodeHeading) ENDIF SET_DEBUG_ACTIVE(TRUE) SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE) DRAW_DEBUG_SPHERE(vDebug_TempPickupPos, 2.5, 250, 150, 0, 200) DRAW_DEBUG_SPHERE(vTempReturnCoords, 5.0, 0, 150, 150, 200) ENDIF IF bDebugPerformGetTaxiPullInSpotTest vDebug_TaxiPos = vPlayerPos IF GET_TAXI_PULL_OVER_INFO(vDebug_TaxiPos, vDebug_DriveToNodePos, fDebug_DriveToNodeHeading, vTempReturnCoords, fTempReturnHeading) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " bDebugPerformGetTaxiPullInSpotTest - return TRUE for vDebug_TaxiPos : ", vDebug_TaxiPos, " vDebug_DriveToNodePos = ", vDebug_DriveToNodePos, " fDebug_DriveToNodeHeading = ", fDebug_DriveToNodeHeading, " vTempReturnCoords = ", vTempReturnCoords, " fTempReturnHeading = ", fTempReturnHeading) ENDIF //DRAW_DEBUG_SPHERE(vDebug_TaxiPos, 0.25, 50, 0, 250, 200) ENDIF IF bDebug_TestIsPositionInSpecialArea IF ARE_COORDS_IN_SPECIAL_AREA(vDebug_TempPickupPos, vTempReturnCoords, fTempReturnHeading) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " bDebug_TestIsPositionInSpecialArea - return TRUE for vDebug_TempPickupPos : ", vDebug_TempPickupPos, " vTempReturnCoords = ", vTempReturnCoords, " fTempReturnHeading = ", fTempReturnHeading) ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " bDebug_TestIsPositionInSpecialArea - return FALSE for vDebug_TempPickupPos : ", vDebug_TempPickupPos) ENDIF SET_DEBUG_ACTIVE(TRUE) SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE) DRAW_DEBUG_SPHERE(vDebug_TempPickupPos, 2.5, 250, 150, 0, 200) DRAW_DEBUG_SPHERE(vTempReturnCoords, 5.0, 0, 150, 150, 200) ENDIF*/ ENDPROC /// PURPOSE: /// not sure - maybe custom area checks? PROC DEBUG_SETUP_AREAS_WIDGETS() vDebug_AreaBound1[0] = <<-1812.778320,-2764.928711,13.047204>> vDebug_AreaBound2[0] = <<-800.595398,-3344.736816,16.444502>> fDebug_DistBetween1n4[0] = 250.000000 SET_CURRENT_WIDGET_GROUP(widgetGroup) CLEAR_CURRENT_WIDGET_GROUP(widgetGroup) START_WIDGET_GROUP("Area Debug") ADD_WIDGET_BOOL("Output areas to debug file", bDebug_OutputText) ADD_WIDGET_INT_SLIDER("Which area", iDebug_CurrentArea, 0, 7, 1) ADD_WIDGET_BOOL("Is this point 1", bDebug_Point1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[0].x", vDebug_AreaBound1[0].x, -4000, 4000, 0.001) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[0].y", vDebug_AreaBound1[0].y, -4000, 4000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[0].z", vDebug_AreaBound1[0].z, -10, 200, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[0].x", vDebug_AreaBound2[0].x, -4000, 4000, 0.001) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[0].y", vDebug_AreaBound2[0].y, -4000, 4000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[0].z", vDebug_AreaBound2[0].z, -10, 200, 0.1) ADD_WIDGET_FLOAT_SLIDER("fDebug_DistBetween1n4[0]", fDebug_DistBetween1n4[0], 0, 1000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[1].x", vDebug_AreaBound1[1].x, -4000, 4000, 0.001) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[1].y", vDebug_AreaBound1[1].y, -4000, 4000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[1].z", vDebug_AreaBound1[1].z, -10, 200, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[1].x", vDebug_AreaBound2[1].x, -4000, 4000, 0.001) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[1].y", vDebug_AreaBound2[1].y, -4000, 4000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[1].z", vDebug_AreaBound2[1].z, -10, 200, 0.1) ADD_WIDGET_FLOAT_SLIDER("fDebug_DistBetween1n4[1]", fDebug_DistBetween1n4[1], 0, 1000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[2].x", vDebug_AreaBound1[2].x, -4000, 4000, 0.001) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[2].y", vDebug_AreaBound1[2].y, -4000, 4000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[2].z", vDebug_AreaBound1[2].z, -10, 200, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[2].x", vDebug_AreaBound2[2].x, -4000, 4000, 0.001) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[2].y", vDebug_AreaBound2[2].y, -4000, 4000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[2].z", vDebug_AreaBound2[2].z, -10, 200, 0.1) ADD_WIDGET_FLOAT_SLIDER("fDebug_DistBetween1n4[2]", fDebug_DistBetween1n4[2], 0, 1000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[3].x", vDebug_AreaBound1[3].x, -4000, 4000, 0.001) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[3].y", vDebug_AreaBound1[3].y, -4000, 4000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[3].z", vDebug_AreaBound1[3].z, -10, 200, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[3].x", vDebug_AreaBound2[3].x, -4000, 4000, 0.001) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[3].y", vDebug_AreaBound2[3].y, -4000, 4000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[3].z", vDebug_AreaBound2[3].z, -10, 200, 0.1) ADD_WIDGET_FLOAT_SLIDER("fDebug_DistBetween1n4[3]", fDebug_DistBetween1n4[3], 0, 1000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[4].x", vDebug_AreaBound1[4].x, -4000, 4000, 0.001) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[4].y", vDebug_AreaBound1[4].y, -4000, 4000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[4].z", vDebug_AreaBound1[4].z, -10, 200, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[4].x", vDebug_AreaBound2[4].x, -4000, 4000, 0.001) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[4].y", vDebug_AreaBound2[4].y, -4000, 4000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[4].z", vDebug_AreaBound2[4].z, -10, 200, 0.1) ADD_WIDGET_FLOAT_SLIDER("fDebug_DistBetween1n4[4]", fDebug_DistBetween1n4[4], 0, 1000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[5].x", vDebug_AreaBound1[5].x, -4000, 4000, 0.001) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[5].y", vDebug_AreaBound1[5].y, -4000, 4000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[5].z", vDebug_AreaBound1[5].z, -10, 200, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[5].x", vDebug_AreaBound2[5].x, -4000, 4000, 0.001) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[5].y", vDebug_AreaBound2[5].y, -4000, 4000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[5].z", vDebug_AreaBound2[5].z, -10, 200, 0.1) ADD_WIDGET_FLOAT_SLIDER("fDebug_DistBetween1n4[5]", fDebug_DistBetween1n4[5], 0, 1000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[6].x", vDebug_AreaBound1[6].x, -4000, 4000, 0.001) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[6].y", vDebug_AreaBound1[6].y, -4000, 4000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[6].z", vDebug_AreaBound1[6].z, -10, 200, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[6].x", vDebug_AreaBound2[6].x, -4000, 4000, 0.001) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[6].y", vDebug_AreaBound2[6].y, -4000, 4000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[6].z", vDebug_AreaBound2[6].z, -10, 200, 0.1) ADD_WIDGET_FLOAT_SLIDER("fDebug_DistBetween1n4[6]", fDebug_DistBetween1n4[6], 0, 1000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[7].x", vDebug_AreaBound1[7].x, -4000, 4000, 0.001) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[7].y", vDebug_AreaBound1[7].y, -4000, 4000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound1[7].z", vDebug_AreaBound1[7].z, -10, 200, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[7].x", vDebug_AreaBound2[7].x, -4000, 4000, 0.001) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[7].y", vDebug_AreaBound2[7].y, -4000, 4000, 0.1) ADD_WIDGET_FLOAT_SLIDER("vDebug_AreaBound2[7].z", vDebug_AreaBound2[7].z, -10, 200, 0.1) ADD_WIDGET_FLOAT_SLIDER("fDebug_DistBetween1n4[7]", fDebug_DistBetween1n4[7], 0, 1000, 0.1) STOP_WIDGET_GROUP() ENDPROC /// PURPOSE: /// not sure - maybe custom area checks? PROC DEBUG_UPDATE_AREA_WIDGETS() INT i VECTOR vInput = <<0,0,0>> REPEAT 8 i IF VDIST(vDebug_AreaBound1[i], vDebug_AreaBound2[i]) > 0 DRAW_DEBUG_LINE(vDebug_AreaBound1[i], vDebug_AreaBound2[i]) ENDIF ENDREPEAT IF IS_COORD_IN_SPECIFIED_AREA(vInput, AC_PRISON) ENDIF IF bDebug_Point1 vDebug_AreaBound1[iDebug_CurrentArea] = GET_SCRIPT_MOUSE_POINTER_IN_WORLD_COORDS() ELSE vDebug_AreaBound2[iDebug_CurrentArea] = GET_SCRIPT_MOUSE_POINTER_IN_WORLD_COORDS() ENDIF IF bDebug_OutputText i=0 OPEN_DEBUG_FILE() REPEAT 8 i SAVE_NEWLINE_TO_DEBUG_FILE() SAVE_STRING_TO_DEBUG_FILE("BOOL vDebug_AreaBound1[") SAVE_INT_TO_DEBUG_FILE(i) SAVE_STRING_TO_DEBUG_FILE("] = ") SAVE_VECTOR_TO_DEBUG_FILE(vDebug_AreaBound1[i]) SAVE_NEWLINE_TO_DEBUG_FILE() SAVE_NEWLINE_TO_DEBUG_FILE() SAVE_STRING_TO_DEBUG_FILE("BOOL vDebug_AreaBound2[") SAVE_INT_TO_DEBUG_FILE(i) SAVE_STRING_TO_DEBUG_FILE("] = ") SAVE_VECTOR_TO_DEBUG_FILE(vDebug_AreaBound2[i]) SAVE_NEWLINE_TO_DEBUG_FILE() SAVE_NEWLINE_TO_DEBUG_FILE() SAVE_STRING_TO_DEBUG_FILE("FLOAT fDebug_DistBetween1n4[") SAVE_INT_TO_DEBUG_FILE(i) SAVE_STRING_TO_DEBUG_FILE("] = ") SAVE_FLOAT_TO_DEBUG_FILE(fDebug_DistBetween1n4[i]) SAVE_NEWLINE_TO_DEBUG_FILE() ENDREPEAT CLOSE_DEBUG_FILE() bDebug_OutputText = FALSE ENDIF ENDPROC /// PURPOSE: /// used to draw the taxi's pull over to pick up player info /// PARAMS: /// vParkCoords - place parking at /// vOppositeSideCoords - position selected as side of the road /// vNodeCoords - the node coords PROC DEBUG_DRAW_TAXI_PULL_OVER_INFO(VECTOR vParkCoords, VECTOR vOppositeSideCoords, VECTOR vNodeCoords) IF bDebug_DrawGetPullOverResults INT iTempTime = GET_GAME_TIMER() WHILE (GET_GAME_TIMER() - iTempTime) < 3000 SET_DEBUG_ACTIVE(TRUE) SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE) DRAW_DEBUG_SPHERE(vParkCoords, 2.5, 128, 255, 0, 150) // green DRAW_DEBUG_SPHERE(vOppositeSideCoords, 2.5, 255, 0, 0, 150) // red DRAW_DEBUG_SPHERE(vNodeCoords, 1.5, 178, 0, 255, 150) // purple CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PULL_OVER_INFO() : bDebug_DrawGetPullOverResults this frame green = park, purple = node, red = opposite side ") WAIT(0) ENDWHILE ENDIF ENDPROC #ENDIF /// PURPOSE: /// Checks if the entity exists and is not dead. /// PARAMS: /// mEntity - the entity we are checking. /// RETURNS: /// True if the entity exists and is not dead. FUNC BOOL IS_ENTITY_ALIVE(ENTITY_INDEX mEntity) IF DOES_ENTITY_EXIST(mEntity) IF NOT IS_ENTITY_DEAD(mEntity) RETURN TRUE ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Checks that the ped exists, is alive and is not injured /// PARAMS: /// mPed - the ped we are checking /// RETURNS: /// True if the ped exists, is alive and is not injured. false otherwise. FUNC BOOL IS_PED_UNINJURED(PED_INDEX mPed) IF DOES_ENTITY_EXIST(mPed) IF NOT IS_ENTITY_DEAD(mPed) IF NOT IS_PED_INJURED(mPed) RETURN TRUE ENDIF ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Checks that the vehicle exists, is alive, driveable and not on fire /// PARAMS: /// mVehicle - the vehicle we are checking /// RETURNS: /// True if the vehicle exists, is alive, driveable and not on fire. false otherwise. FUNC BOOL IS_VEHICLE_OK(VEHICLE_INDEX mVehicle) IF IS_ENTITY_ALIVE(mVehicle) IF IS_VEHICLE_DRIVEABLE(mVehicle) IF NOT IS_ENTITY_ON_FIRE(mVehicle) RETURN TRUE ENDIF ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// check if iTimeAmount has passed since iTimer was set /// PARAMS: /// iTimer - the timer /// iTimeAmount - the amount of time to check has passed /// RETURNS: /// True is the specified amount of time has passed for the specified timer. FUNC BOOL HAS_TIME_PASSED(INT iTimer, INT iTimeAmount) RETURN (GET_GAME_TIMER() - iTimer) > iTimeAmount ENDFUNC /// PURPOSE: /// blocks specific player controls relating to weapon equip swap, to be called during hail animations /// Implemented for B*2074743 - block aiming during hail animation PROC DISABLE_PLAYER_WEAPON_CONTROLS_FOR_HAIL_THIS_FRAME() // B*2074743 - block aiming during hail animation DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_AIM) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SELECT_WEAPON) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SELECT_NEXT_WEAPON) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SELECT_PREV_WEAPON) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_WEAPON_WHEEL_UD) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_WEAPON_WHEEL_LR) SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_KeepWeaponHolsteredUnlessFired, TRUE) //CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : DISABLE_PLAYER_WEAPON_CONTROLS_FOR_HAIL_THIS_FRAME : ", GET_FRAME_COUNT()) ENDPROC /// PURPOSE: /// used to toggle the ped config flag PCF_AICanDrivePlayerAsRearPassenger of the taxi driver of the vehicleIndex /// this is needed to allow the player to enter as passenger with input press. Input hold will jack the driver /// PARAMS: /// vehicleIndex - vehicle of driver to have flag updated /// bSetActive - if flag is going to be set active or off PROC SET_TAXI_DRIVER_ENTER_AS_PASSENGER_FLAG(VEHICLE_INDEX &vehicleIndex, BOOL bSetActive) IF DOES_ENTITY_EXIST(vehicleIndex) IF IS_VEHICLE_DRIVEABLE(vehicleIndex) PED_INDEX pedIndex = GET_PED_IN_VEHICLE_SEAT(vehicleIndex) IF DOES_ENTITY_EXIST(pedIndex) IF IS_PED_MODEL(pedIndex, GET_TAXI_DRIVER_MODEL()) IF NOT IS_PED_INJURED(pedIndex) // B*1536974 - Press to enter taxi as passenger hold to jack driver - opposite to how it worked on IV // to get IV behaviour you have to ensur this flag is false then task the player in script to enter as rear passenger when input detected SET_PED_CONFIG_FLAG(pedIndex, PCF_AICanDrivePlayerAsRearPassenger, bSetActive) #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SET_TAXI_DRIVER_ENTER_AS_PASSENGER_FLAG() - set : ", bSetActive) ENDIF #ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// get the vehicle seat player should be aiming for based on where they are and if the entry point is clear /// RETURNS: /// VEHICLE_SEAT to use in the TASK_ENTER_VEHICLE task along with direct entry /// returns VS_ANY_PASSENGER if neither of the rear seats are ok to use FUNC VEHICLE_SEAT GET_PLAYER_PREFERRED_REAR_PASSENGER_SEAT(VEHICLE_INDEX &vehIndexTaxi, VECTOR vTempPlayerPosition) BOOL bUseLeftEntry = TRUE VEHICLE_SEAT eTempSeat = VS_BACK_LEFT PED_INDEX pedTempInSeat IF (TAXI_GET_SIDE_COORDS_IS_TO_ENTITY(vehIndexTaxi, GET_ENTITY_COORDS(vehIndexTaxi, FALSE), vTempPlayerPosition) = 1) bUseLeftEntry = FALSE eTempSeat = VS_BACK_RIGHT ENDIF // attempt to enter the prefered side IF IS_ENTRY_POINT_FOR_SEAT_CLEAR(PLAYER_PED_ID(), vehIndexTaxi, eTempSeat, TRUE, bUseLeftEntry) IF IS_VEHICLE_SEAT_FREE(vehIndexTaxi, eTempSeat) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_PLAYER_PREFERRED_REAR_PASSENGER_SEAT : closest side seat empty selected : seat = ", eTempSeat) RETURN eTempSeat ELSE pedTempInSeat = GET_PED_IN_VEHICLE_SEAT(vehIndexTaxi, eTempSeat) IF DOES_ENTITY_EXIST(pedTempInSeat) IF NOT (pedTempInSeat = PLAYER_PED_ID()) // don't jake group members IF NOT IS_PED_GROUP_MEMBER(pedTempInSeat, PLAYER_GROUP_ID()) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_PLAYER_PREFERRED_REAR_PASSENGER_SEAT : closest side seat occupied selected : seat = ", eTempSeat) RETURN eTempSeat ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_PLAYER_PREFERRED_REAR_PASSENGER_SEAT : closest side seat rejected for group member in seat selected : seat = ", eTempSeat) ENDIF ENDIF ENDIF ENDIF ENDIF // back up attempt to enter from opposite side IF bUseLeftEntry bUseLeftEntry = FALSE eTempSeat = VS_BACK_RIGHT ELSE bUseLeftEntry = TRUE eTempSeat = VS_BACK_LEFT ENDIF IF IS_ENTRY_POINT_FOR_SEAT_CLEAR(PLAYER_PED_ID(), vehIndexTaxi, eTempSeat, TRUE, bUseLeftEntry) IF IS_VEHICLE_SEAT_FREE(vehIndexTaxi, eTempSeat) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_PLAYER_PREFERRED_REAR_PASSENGER_SEAT : far side seat empty selected : seat = ", eTempSeat) RETURN eTempSeat ELSE pedTempInSeat = GET_PED_IN_VEHICLE_SEAT(vehIndexTaxi, eTempSeat) IF DOES_ENTITY_EXIST(pedTempInSeat) IF NOT (pedTempInSeat = PLAYER_PED_ID()) // don't jake group members IF NOT IS_PED_GROUP_MEMBER(pedTempInSeat, PLAYER_GROUP_ID()) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_PLAYER_PREFERRED_REAR_PASSENGER_SEAT : far side seat occupied selected : seat = ", eTempSeat) RETURN eTempSeat ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_PLAYER_PREFERRED_REAR_PASSENGER_SEAT : far side seat rejected for group member in seat selected : seat = ", eTempSeat) ENDIF ENDIF ENDIF ENDIF ENDIF RETURN VS_ANY_PASSENGER ENDFUNC /// PURPOSE: /// create the waiting taxi blip for g_WaitingTaxi PROC CREATE_WAITING_TAXI_BLIP() IF DOES_BLIP_EXIST(blipWaitingTaxi) SET_BLIP_ROUTE(blipWaitingTaxi, FALSE) REMOVE_BLIP(blipWaitingTaxi) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : CREATE_WAITING_TAXI_BLIP() : blip already existed removed") ENDIF IF IS_VEHICLE_OK(g_WaitingTaxi) IF NOT DOES_BLIP_EXIST(blipWaitingTaxi) blipWaitingTaxi = ADD_BLIP_FOR_ENTITY(g_WaitingTaxi) SET_BLIP_SPRITE(blipWaitingTaxi, RADAR_TRACE_TAXI) SET_BLIP_NAME_FROM_TEXT_FILE(blipWaitingTaxi, "TXM_BLIP") SET_BLIP_FLASHES(blipWaitingTaxi, TRUE) SET_BLIP_FLASH_TIMER(blipWaitingTaxi, 10000) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : CREATE_WAITING_TAXI_BLIP() : blip added to g_WaitingTaxi") ENDIF ENDIF ENDPROC /// PURPOSE: /// returns the search flags used for getting closest taxi /// RETURNS: /// INT bit set value FUNC INT GET_TAXI_SEARCH_FLAGS() RETURN (VEHICLE_SEARCH_FLAG_RETURN_MISSION_VEHICLES | VEHICLE_SEARCH_FLAG_RETURN_RANDOM_VEHICLES | VEHICLE_SEARCH_FLAG_RETURN_VEHICLES_CONTAINING_GROUP_MEMBERS | VEHICLE_SEARCH_FLAG_RETURN_VEHICLES_WITH_PEDS_ENTERING_OR_EXITING | VEHICLE_SEARCH_FLAG_ALLOW_VEHICLE_OCCUPANTS_TO_BE_PERFORMING_A_SCRIPTED_TASK) ENDFUNC /// PURPOSE: /// Cleanup the process enter closest taxi PROC CLEANUP_ENTER_CLOSEST_TAXI() IF eEnterTaxiState = TL_ENTER_TAXI_STATE_ENTERING SET_PLAYER_CAN_DO_DRIVE_BY(PLAYER_ID(), TRUE) CANCEL_GROUP_GETTING_INTO_CAB() ELIF eEnterTaxiState = TL_ENTER_TAXI_STATE_INSIDE IF HAS_SCRIPT_LOADED("taxiService") SET_SCRIPT_AS_NO_LONGER_NEEDED("taxiService") #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : CLEANUP_ENTER_CLOSEST_TAXI eEnterTaxiState was TL_ENTER_TAXI_STATE_ENTERING - ET_SCRIPT_AS_NO_LONGER_NEEDED(taxiService)") ENDIF #ENDIF ENDIF SET_PLAYER_CAN_DO_DRIVE_BY(PLAYER_ID(), TRUE) CANCEL_GROUP_GETTING_INTO_CAB() ENDIF CLEANUP_WAITING_TAXI() // handles release of g_WaitingTaxi and g_WaitingTaxiDriver //CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " CLEANUP_ENTER_CLOSEST_TAXI() : called CLEANUP_WAITING_TAXI()") IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("TX_H02") // Hold ~INPUT_ENTER~ to enter the cab as a passenger. CLEAR_HELP(TRUE) ENDIF iTimer_DelayTaxiSearch = 0 //reset eEnterTaxiState = TL_ENTER_TAXI_STATE_IDLE //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : CLEANUP_ENTER_CLOSEST_TAXI() : eEnterTaxiState = TL_ENTER_TAXI_STATE_IDLE") ENDIF #ENDIF ENDPROC /// PURPOSE: /// Cleanup the process hail taxi PROC CLEANUP_HAIL_TAXI() // stop scripted player anims IF NOT IS_PED_INJURED(PLAYER_PED_ID()) IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "HAIL_TAXI") STOP_ENTITY_ANIM(PLAYER_PED_ID(), "HAIL_TAXI", tlTaxiAnimDict, REALLY_SLOW_BLEND_OUT) ELIF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "FP_HAIL_TAXI") STOP_ENTITY_ANIM(PLAYER_PED_ID(), "FP_HAIL_TAXI", tlTaxiAnimDict, REALLY_SLOW_BLEND_OUT) ELIF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "FUCK_U") STOP_ENTITY_ANIM(PLAYER_PED_ID(), "FUCK_U", tlTaxiAnimDict, REALLY_SLOW_BLEND_OUT) ELIF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "FORGET_IT") STOP_ENTITY_ANIM(PLAYER_PED_ID(), "FORGET_IT", tlTaxiAnimDict, REALLY_SLOW_BLEND_OUT) ENDIF // B*1515351 - SET_PED_CONFIG_FLAG needs alive check IF iTaxiHailIntention != NEW_CONTEXT_INTENTION SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_KeepWeaponHolsteredUnlessFired, FALSE) ENDIF // B*1991223 - RESET need to block ambient anims during hail anims IF bBlockingPlayerAmbientIdles = TRUE SET_PED_CAN_PLAY_AMBIENT_ANIMS(PLAYER_PED_ID(), TRUE) bBlockingPlayerAmbientIdles = FALSE ENDIF ENDIF REMOVE_ANIM_DICT(tlTaxiAnimDict) IF iTaxiHailIntention != NEW_CONTEXT_INTENTION RELEASE_CONTEXT_INTENTION(iTaxiHailIntention) ENDIF IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("TXM_H01") // Press ~INPUT_CONTEXT~ to hail a Taxi. iHailPromptCounter++ IF iHailPromptCounter = 3 g_savedGlobals.sAmbient.bTaxiHailingHelpDisplayed = TRUE #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " CLEANUP_HAIL_TAXI() : g_savedGlobals.sAmbient.bTaxiHailingHelpDisplayed = TRUE") ENDIF #ENDIF ENDIF CLEAR_HELP(TRUE) ENDIF IF DOES_BLIP_EXIST(blipWaitingTaxi) SET_BLIP_ROUTE(blipWaitingTaxi, FALSE) REMOVE_BLIP(blipWaitingTaxi) ENDIF IF bHintTriggeredByTaxiLauncher IF IS_GAMEPLAY_HINT_ACTIVE() STOP_GAMEPLAY_HINT() ENDIF ENDIF // stop his aknowledge anims IF DOES_ENTITY_EXIST(g_WaitingTaxiDriver) IF NOT IS_PED_INJURED(g_WaitingTaxiDriver) IF IS_ENTITY_PLAYING_ANIM(g_WaitingTaxiDriver, tlTaxiAnimDict, "Aknowledge_R") STOP_ENTITY_ANIM(g_WaitingTaxiDriver, "Aknowledge_R", tlTaxiAnimDict, SLOW_BLEND_OUT) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " CLEANUP_HAIL_TAXI() : stopped driver aknowledge anim Aknowledge_R") ELIF IS_ENTITY_PLAYING_ANIM(g_WaitingTaxiDriver, tlTaxiAnimDict, "Aknowledge_L") STOP_ENTITY_ANIM(g_WaitingTaxiDriver, "Aknowledge_L", tlTaxiAnimDict, SLOW_BLEND_OUT) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " CLEANUP_HAIL_TAXI() : stopped driver aknowledge anim Aknowledge_L") ENDIF ENDIF ENDIF // don't stomp on the global handle g_WaitingTaxi (if player is entering a taxi) IF eEnterTaxiState = TL_ENTER_TAXI_STATE_IDLE CLEANUP_WAITING_TAXI() // handles release of g_WaitingTaxi and g_WaitingTaxiDriver //CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " CLEANUP_HAIL_TAXI() : called CLEANUP_WAITING_TAXI()") ENDIF vehHailTarget = NULL bPlayAdditionalFuckYouDialogue = FALSE bHintTriggeredByTaxiLauncher = FALSE iTimer_HailAnimTriggered = 0 iTimer_HailFailedDialogueDelay = 0 g_iTaxiHailedTime = -1 eHailTaxiState = TL_HAIL_TAXI_STATE_IDLE //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : CLEANUP_HAIL_TAXI() : eHailTaxiState = TL_HAIL_TAXI_STATE_IDLE") ENDIF #ENDIF ENDPROC /// PURPOSE: /// clear all the dispatched taxi data struct PROC CLEANUP_DISPATCHED_TAXI_DATA() // set driver's behaviour and release IF DOES_ENTITY_EXIST(sDispatchedTaxi.pedIndex) IF DOES_ENTITY_BELONG_TO_THIS_SCRIPT(sDispatchedTaxi.pedIndex, FALSE) // don't stomp on the global handle IF sDispatchedTaxi.pedIndex != g_WaitingTaxiDriver IF NOT IS_PED_INJURED(sDispatchedTaxi.pedIndex) // RESET FLAG for cleanup B*1536974 - Press to enter taxi as passenger hold to jack driver - opposite to how it worked on IV // to get IV behaviour you have to ensur this flag is false then task the player in script to enter as rear passenger when input detected SET_PED_CONFIG_FLAG(sDispatchedTaxi.pedIndex, PCF_AICanDrivePlayerAsRearPassenger, FALSE) SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(sDispatchedTaxi.pedIndex, FALSE) IF NOT IS_PED_FLEEING(sDispatchedTaxi.pedIndex) AND NOT IS_PED_IN_COMBAT(sDispatchedTaxi.pedIndex) IF IS_PED_IN_ANY_VEHICLE(sDispatchedTaxi.pedIndex) IF DOES_ENTITY_EXIST(sDispatchedTaxi.vehicleIndex) IF IS_VEHICLE_DRIVEABLE(sDispatchedTaxi.vehicleIndex) IF IS_PED_SITTING_IN_VEHICLE(sDispatchedTaxi.pedIndex, sDispatchedTaxi.vehicleIndex) SEQUENCE_INDEX seq OPEN_SEQUENCE_TASK(seq) // if any of the players buddies are in the taxi then wait for then to get out IF NOT IS_VEHICLE_SEAT_FREE(sDispatchedTaxi.vehicleIndex, VS_BACK_LEFT) OR NOT IS_VEHICLE_SEAT_FREE(sDispatchedTaxi.vehicleIndex, VS_BACK_RIGHT) OR NOT IS_VEHICLE_SEAT_FREE(sDispatchedTaxi.vehicleIndex, VS_FRONT_RIGHT) TASK_PAUSE(NULL, 2000) ELSE TASK_PAUSE(NULL, 500) ENDIF TASK_VEHICLE_DRIVE_WANDER(NULL, sDispatchedTaxi.vehicleIndex, 12.0, DRIVINGMODE_STOPFORCARS | DF_AvoidRestrictedAreas) CLOSE_SEQUENCE_TASK(seq) TASK_PERFORM_SEQUENCE(sDispatchedTaxi.pedIndex, seq) CLEAR_SEQUENCE_TASK(seq) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " CLEANUP_DISPATCHED_TAXI_DATA() : tasked sDispatchedTaxi.pedIndex to TASK_VEHICLE_DRIVE_WANDER") ELSE TASK_SMART_FLEE_PED(sDispatchedTaxi.pedIndex, PLAYER_PED_ID(), 500, -1) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " CLEANUP_DISPATCHED_TAXI_DATA() : tasked sDispatchedTaxi.pedIndex driver to flee as not sat in sDispatchedTaxi.vehicleIndex") ENDIF ELSE TASK_SMART_FLEE_PED(sDispatchedTaxi.pedIndex, PLAYER_PED_ID(), 500, -1) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " CLEANUP_DISPATCHED_TAXI_DATA() : tasked sDispatchedTaxi.pedIndex driver to flee as sDispatchedTaxi.vehicleIndex was not driverable") ENDIF ENDIF ELSE // just walk off not fleeing but on foot TASK_WANDER_STANDARD(sDispatchedTaxi.pedIndex) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " CLEANUP_DISPATCHED_TAXI_DATA() : tasked sDispatchedTaxi.pedIndex to TASK_WANDER_STANDARD on foot") ENDIF ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " CLEANUP_DISPATCHED_TAXI_DATA() : NOT tasked sDispatchedTaxi.pedIndex since IS_PED_FLEEING / combat returned TRUE") ENDIF ENDIF // release assets SET_MODEL_AS_NO_LONGER_NEEDED(GET_ENTITY_MODEL(sDispatchedTaxi.pedIndex)) SET_PED_AS_NO_LONGER_NEEDED(sDispatchedTaxi.pedIndex) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " CLEANUP_DISPATCHED_TAXI_DATA : set sDispatchedTaxi.pedIndex model and vehicle as no longer needed") ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " CLEANUP_DISPATCHED_TAXI_DATA : sDispatchedTaxi.pedIndex = g_WaitingTaxiDriver so not released entity and model") ENDIF ENDIF ENDIF // release vehicle handle IF DOES_ENTITY_EXIST(sDispatchedTaxi.vehicleIndex) IF DOES_ENTITY_BELONG_TO_THIS_SCRIPT(sDispatchedTaxi.vehicleIndex, FALSE) // don't stomp on the global handle IF sDispatchedTaxi.vehicleIndex != g_WaitingTaxi //SET_MODEL_AS_NO_LONGER_NEEDED(ENTITY_MODEL(sDispatchedTaxi.vehicleIndex)) SET_VEHICLE_AS_NO_LONGER_NEEDED(sDispatchedTaxi.vehicleIndex) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " CLEANUP_DISPATCHED_TAXI_DATA : set sDispatchedTaxi.vehicleIndex as no longer needed") ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " CLEANUP_DISPATCHED_TAXI_DATA : sDispatchedTaxi.vehicleIndex = g_WaitingTaxi so not released entity and model") ENDIF ENDIF ENDIF // release asset requests IF eDispatchedTaxiState = TL_DISPATCHED_STATE_CREATE_TAXI SET_MODEL_AS_NO_LONGER_NEEDED(mnTaxiModel) SET_MODEL_AS_NO_LONGER_NEEDED(mnTaxiDriverModel) ENDIF // reset struct vars sDispatchedTaxi.vehicleIndex = NULL sDispatchedTaxi.pedIndex = NULL sDispatchedTaxi.bHasActiveTask = FALSE sDispatchedTaxi.bForcedPullOverAtCurrentPosition = FALSE sDispatchedTaxi.fDistToTarget = 0 sDispatchedTaxi.fDriveToHeading = 0 sDispatchedTaxi.fTargetReached = 45.0 sDispatchedTaxi.iNodeSearchNumber = 0 sDispatchedTaxi.iSpawnAttempts = 0 sDispatchedTaxi.iTimer_TaxiDispatchDelay = 0 sDispatchedTaxi.vDistToPlayer = << 0.0, 0.0, 0.0 >> sDispatchedTaxi.vDriveToCoords = << 0.0, 0.0, 0.0 >> sDispatchedTaxi.vPullOverCoords = << 0.0, 0.0, 0.0 >> sDispatchedTaxi.vPlayerCalledCoords = << 0.0, 0.0, 0.0 >> sDispatchedTaxi.vPathNodeRequestMin = << 0.0, 0.0, 0.0 >> sDispatchedTaxi.vPathNodeRequestMax = << 0.0, 0.0, 0.0 >> sDispatchedTaxi.taxiDrivingModeStandard = DF_SteerAroundStationaryCars|DF_StopForPeds|DF_StopAtLights|DF_ChangeLanesAroundObstructions|DF_StopForCars|DF_ForceJoinInRoadDirection|DF_SteerAroundObjects|DF_UseSwitchedOffNodes|DF_AvoidRestrictedAreas sDispatchedTaxi.eCharDispatchedFor = GLOBAL_CHARACTER_SHEET_GET_MAX_CHARACTERS_FOR_GAMEMODE() // reset state machine eDispatchedTaxiState = TL_DISPATCHED_STATE_IDLE ENDPROC /// PURPOSE: /// resets the taxi launcher and sets eTaxiLauncherState = TL_STATE_IDLE /// PURPOSE: /// reset everything in the script /// PARAMS: /// bResetLauncherState - if TRUE eTaxiLauncherState will get reset to TL_STATE_IDLE PROC RESET_TAXI_LAUNCHER(BOOL bResetLauncherState = TRUE) SET_VEHICLE_MODEL_IS_SUPPRESSED(TAXI, FALSE) CLEANUP_DISPATCHED_TAXI_DATA() CLEANUP_ENTER_CLOSEST_TAXI() CLEANUP_HAIL_TAXI() // expect there will be other variables i'll need to reset here as and when i find them bUpdateHailTargetThisFrame = TRUE bHintTriggeredByTaxiLauncher = FALSE eCallTaxiServiceState = TL_PHONE_STATE_AWAITING_CALL eDispatchedTaxiState = TL_DISPATCHED_STATE_IDLE eHailTaxiState = TL_HAIL_TAXI_STATE_IDLE eEnterTaxiState = TL_ENTER_TAXI_STATE_IDLE iTimer_DelayTaxiSearch = 0 IF bResetLauncherState eTaxiLauncherState = TL_STATE_IDLE ENDIF ENDPROC /// PURPOSE: /// cleanup for the script PROC TAXI_LAUNCHER_SCRIPT_CLEANUP() CLEANUP_WAITING_TAXI() // handles release of g_WaitingTaxi and g_WaitingTaxiDriver RESET_TAXI_LAUNCHER() REMOVE_ANIM_DICT(tlTaxiAnimDict) SET_VEHICLE_MODEL_IS_SUPPRESSED(TAXI, FALSE) SET_MODEL_AS_NO_LONGER_NEEDED(mnTaxiModel) SET_MODEL_AS_NO_LONGER_NEEDED(mnTaxiDriverModel) IF bHintTriggeredByTaxiLauncher IF IS_GAMEPLAY_HINT_ACTIVE() STOP_GAMEPLAY_HINT() ENDIF ENDIF CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " TAXI_LAUNCHER_SCRIPT_CLEANUP() : done") ENDPROC /// PURPOSE: /// queries if g_CustomDropOffBlip exists PROC MONITOR_CUSTOM_DROP_OFF_BLIP() IF g_fTaxiDropOffHeading <> 0 IF DOES_BLIP_EXIST(g_CustomDropOffBlip) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : MONITOR_CUSTOM_DROP_OFF_BLIP() g_CustomDropOffBlip exists") ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : MONITOR_CUSTOM_DROP_OFF_BLIP() set g_CustomDropOffBlip doesn't exists") ENDIF ENDIF ENDPROC /// PURPOSE: /// sets dialogue info for the current player ped PROC IDENTIFY_PLAYER() enumCharacterList eCurrentPlayerChar = GET_CURRENT_PLAYER_PED_ENUM() IF eCurrentPlayerChar = CHAR_MICHAEL playerVoice = "MICHAEL" playerLine1 = "TX_1M" playerLine3 = "TX_3M" ELIF eCurrentPlayerChar = CHAR_FRANKLIN playerVoice = "FRANKLIN" playerLine1 = "TX_1F" playerLine3 = "TX_3F" ELIF eCurrentPlayerChar = CHAR_TREVOR playerVoice = "TREVOR" playerLine1 = "TX_1T" playerLine3 = "TX_3T" ENDIF ENDPROC /// PURPOSE: /// checks for the player being allowed to enter a taxi as a passenger /// RETURNS: /// TRUE if player is allowed to enter as a passenger FUNC BOOL IS_PLAYER_ALLOWED_TO_ENTER_TAXI_AS_PASSENGER() // check global flags for being allowed taxi rides IF NOT IS_PLAYER_ALLOWED_TO_RIDE_IN_TAXIS() #IF IS_DEBUG_BUILD IF bDebug_DisplayCleanupTTY CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_ENTER_TAXI_AS_PASSENGER() - return FALSE - IS_PLAYER_ALLOWED_TO_RIDE_IN_TAXIS") ENDIF #ENDIF RETURN FALSE ENDIF /* already gets tested in // check player isn't injured IF IS_PED_INJURED(PLAYER_PED_ID()) #IF IS_DEBUG_BUILD IF bDebug_DisplayCleanupTTY CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_ENTER_TAXI_AS_PASSENGER() - return FALSE - IS_PED_INJURED(PLAYER_PED_ID())") ENDIF #ENDIF RETURN FALSE ENDIF */ // check the player has control IF NOT IS_PLAYER_PLAYING(PLAYER_ID()) #IF IS_DEBUG_BUILD IF bDebug_DisplayCleanupTTY CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_ENTER_TAXI_AS_PASSENGER() - return FALSE - IS_PLAYER_PLAYING(PLAYER_ID())") ENDIF #ENDIF RETURN FALSE ENDIF // check for player being wanted IF IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0) #IF IS_DEBUG_BUILD IF bDebug_DisplayCleanupTTY CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_ENTER_TAXI_AS_PASSENGER() - return FALSE - IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0)") ENDIF #ENDIF RETURN FALSE ENDIF RETURN TRUE ENDFUNC /// PURPOSE: /// checks for the player being allowed to hail a taxi /// RETURNS: /// TRUE if player is allowed to hail a taxi FUNC BOOL IS_PLAYER_ALLOWED_TO_HAIL_A_TAXI() // don't allow player to hail a whilst getting in one IF eEnterTaxiState != TL_ENTER_TAXI_STATE_IDLE #IF IS_DEBUG_BUILD IF bDebug_DisplayCleanupTTY CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_HAIL_A_TAXI() - return FALSE - eEnterTaxiState != TL_ENTER_TAXI_STATE_IDLE") ENDIF #ENDIF RETURN FALSE ENDIF // don't allow hail if player has an ambient task // apparently checks climbing, on ladders, current task is idle, combat, jumping, shooting IF NOT IS_PLAYER_FREE_FOR_AMBIENT_TASK(PLAYER_ID()) #IF IS_DEBUG_BUILD IF bDebug_DisplayCleanupTTY CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_HAIL_A_TAXI() - return FALSE - IS_PLAYER_FREE_FOR_AMBIENT_TASK(PLAYER_ID())") ENDIF #ENDIF RETURN FALSE ENDIF // aim a weapon IF IS_PLAYER_FREE_AIMING(PLAYER_ID()) OR IS_PLAYER_TARGETTING_ANYTHING(PLAYER_ID()) #IF IS_DEBUG_BUILD IF bDebug_DisplayCleanupTTY CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_HAIL_A_TAXI() - return FALSE - IS_PLAYER_FREE_AIMING(PLAYER_ID())") ENDIF #ENDIF RETURN FALSE ENDIF // in the air IF IS_ENTITY_IN_AIR(PLAYER_PED_ID()) #IF IS_DEBUG_BUILD IF bDebug_DisplayCleanupTTY CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_HAIL_A_TAXI() - return FALSE - IS_ENTITY_IN_AIR(PLAYER_PED_ID())") ENDIF #ENDIF RETURN FALSE ENDIF // falling over (exclude drunk for some reason?) IF NOT g_playerIsDrunk AND IS_PED_RAGDOLL(PLAYER_PED_ID()) #IF IS_DEBUG_BUILD IF bDebug_DisplayCleanupTTY CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_HAIL_A_TAXI() - return FALSE - IS_PED_RAGDOLL(PLAYER_PED_ID())") ENDIF #ENDIF RETURN FALSE ENDIF // already inside a vehicle IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID(), TRUE) #IF IS_DEBUG_BUILD IF bDebug_DisplayCleanupTTY CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_HAIL_A_TAXI() - return FALSE - IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID(), TRUE)") ENDIF #ENDIF RETURN FALSE ENDIF // don't allow hail whilst phone is on screen IF IS_PHONE_ONSCREEN() #IF IS_DEBUG_BUILD IF bDebug_DisplayCleanupTTY CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_HAIL_A_TAXI() - return FALSE - IS_PHONE_ONSCREEN()") ENDIF #ENDIF RETURN FALSE ENDIF // is internet on screen IF IS_BROWSER_OPEN() #IF IS_DEBUG_BUILD IF bDebug_DisplayCleanupTTY CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_HAIL_A_TAXI() - return FALSE -IS_BROWSER_OPEN()") ENDIF #ENDIF RETURN FALSE ENDIF // if player is shopping IF IS_PLAYER_BROWSING_ITEMS_IN_ANY_SHOP() #IF IS_DEBUG_BUILD IF bDebug_DisplayCleanupTTY CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_HAIL_A_TAXI() - return FALSE - IS_PLAYER_BROWSING_ITEMS_IN_ANY_SHOP()") ENDIF #ENDIF RETURN FALSE ENDIF // custom menu active IF IS_CUSTOM_MENU_ON_SCREEN() #IF IS_DEBUG_BUILD IF bDebug_DisplayCleanupTTY CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_HAIL_A_TAXI() - return FALSE - IS_CUSTOM_MENU_ON_SCREEN()") ENDIF #ENDIF RETURN FALSE ENDIF // don't allow taxis during minigames IF IS_MINIGAME_IN_PROGRESS() #IF IS_DEBUG_BUILD IF bDebug_DisplayCleanupTTY CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_HAIL_A_TAXI() - return FALSE - IS_MINIGAME_IN_PROGRESS()") ENDIF #ENDIF RETURN FALSE ENDIF RETURN TRUE ENDFUNC /// PURPOSE: /// checks for the player being allowed to call a taxi /// RETURNS: /// TRUE if player is allowed a taxi FUNC BOOL IS_PLAYER_ALLOWED_TO_CALL_TAXI() // check if a dispatched taxi is already on route to the player IF eDispatchedTaxiState != TL_DISPATCHED_STATE_IDLE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_CALL_TAXI() - return FALSE - eDispatchedTaxiState check") RETURN FALSE ENDIF // don't allow a taxi to be dispatched if player has a hailed taxi waiting IF eHailTaxiState = TL_HAIL_TAXI_STATE_TAXI_WAITING OR eHailTaxiState = TL_HAIL_TAXI_STATE_SUCCESSFUL_ATTEMPT CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_CALL_TAXI() - return FALSE - eHailTaxiState check") RETURN FALSE ENDIF // check if a enter taxi state is idle (player isn't currently getting in a taxi) IF eEnterTaxiState != TL_ENTER_TAXI_STATE_IDLE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_CALL_TAXI() - return FALSE - eEnterTaxiState check") RETURN FALSE ENDIF // check the player isn't currently in a taxi journey IF IS_THREAD_ACTIVE(tTaxiServiceThread) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_CALL_TAXI() - return FALSE - IS_THREAD_ACTIVE(tTaxiServiceThread)") RETURN FALSE ENDIF // check the player isn't already in a taxi IF NOT IS_PLAYER_ALLOWED_TO_ENTER_TAXI_AS_PASSENGER() CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_CALL_TAXI() - return FALSE - IS_PLAYER_ALLOWED_TO_ENTER_TAXI_AS_PASSENGER") RETURN FALSE ENDIF // test for player being in the air (presumably to prevent calls during flights IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) IF IS_ENTITY_IN_AIR(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_CALL_TAXI() - return FALSE - IS_ENTITY_IN_AIR whilst in VEHICLE") RETURN FALSE ENDIF ENDIF IS_PLAYER_IN_ANY_COMMUNICATION_RESTRICTED_AREAS() // ideally perform GET_TAXI_PICK_UP_PLAYER_DESTINATION now and store the pickup position ready // that way if it was unable to get a position the tdispatch service could decline the call // check player is close to the road network VECTOR vNode FLOAT fDistMinFromNode = 50.0 // always search switched off nodes, but if we are in the city ensure they aren't dead ends (stop taxi using driveways). NODE_FLAGS nodeFlags = NF_INCLUDE_SWITCHED_OFF_NODES IF NOT IS_POSITION_IN_ZONE_SAFE_FOR_DEADEND_NODES(vPlayerPos) nodeFlags = NF_INCLUDE_SWITCHED_OFF_NODES | NF_IGNORE_SWITCHED_OFF_DEADENDS CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_CALL_TAXI() : using node flags NF_INCLUDE_SWITCHED_OFF_NODES | NF_IGNORE_SWITCHED_OFF_DEADENDS") ENDIF IF NOT GET_CLOSEST_VEHICLE_NODE(vPlayerPos, vNode, nodeFlags, 100.0, 2.5) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_CALL_TAXI() : return FALSE - failed to find closest valid node nearby :", vPlayerPos) RETURN FALSE ENDIF IF NOT IS_ENTITY_AT_COORD(PLAYER_PED_ID(), vNode, <>) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_CALL_TAXI() : return FALSE - player more than ", fDistMinFromNode, " away from closest valid node") RETURN FALSE ENDIF /*VEHICLE_NODE_ID tempVehNodeID = GET_NTH_CLOSEST_VEHICLE_NODE_ID(vNode, 1, nodeFlags) IF IS_VEHICLE_NODE_ID_VALID(tempVehNodeID) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_CALL_TAXI() : return FALSE - no valid node nearby") RETURN FALSE ENDIF*/ // make sure he's not calling from an inaccessible area IF IS_POSITION_IN_TAXI_RESTRICTED_AREA(vPlayerPos, TRUE) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_CALL_TAXI() : return FALSE - IS_POSITION_IN_TAXI_RESTRICTED_AREA check") RETURN FALSE ENDIF CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : IS_PLAYER_ALLOWED_TO_CALL_TAXI() - return TRUE") RETURN TRUE ENDFUNC /// PURPOSE: /// check if the taxi service is listed for the player to call /// PARAMS: /// ePlayer - the player to check, passing GLOBAL_CHARACTER_SHEET_GET_MAX_CHARACTERS_FOR_GAMEMODE() will test all players and return TRUE if one of them have the taxi listed /// RETURNS: /// TRUE if specified char has taxi listed (if GLOBAL_CHARACTER_SHEET_GET_MAX_CHARACTERS_FOR_GAMEMODE() parameter return TRUE if any of them have listed) FUNC BOOL IS_TAXI_SERVICE_LISTED_IN_PLAYERS_PHONEBOOK(enumCharacterList ePlayer = MAX_CHARACTERS) IF ePlayer = CHAR_MICHAEL OR ePlayer = CHAR_FRANKLIN OR ePlayer = CHAR_TREVOR IF (GLOBAL_CHARACTER_SHEET_GET_PHONEBOOK_STATE(CHAR_TAXI, ENUM_TO_INT(ePlayer))= LISTED) RETURN TRUE ENDIF ELIF ePlayer = GLOBAL_CHARACTER_SHEET_GET_MAX_CHARACTERS_FOR_GAMEMODE() IF (GLOBAL_CHARACTER_SHEET_GET_PHONEBOOK_STATE(CHAR_TAXI, ENUM_TO_INT(CHAR_MICHAEL)) = LISTED OR GLOBAL_CHARACTER_SHEET_GET_PHONEBOOK_STATE(CHAR_TAXI, ENUM_TO_INT(CHAR_FRANKLIN)) = LISTED OR GLOBAL_CHARACTER_SHEET_GET_PHONEBOOK_STATE(CHAR_TAXI, ENUM_TO_INT(CHAR_TREVOR)) = LISTED) RETURN TRUE ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// updates fDropOffDistFromBlip used to check player leaving pulled up taxi /// PARAMS: /// vDestinationCoord - the place the taxi is supposed to reach /// vPullOverCoord - the actual position the taxi pulled up FUNC FLOAT GET_DIST_BETWEEN_VECTORS_NONE_Z(VECTOR vDestinationCoord, VECTOR vPullOverCoord) VECTOR vDiff_Destination_To_ReturnNode vDiff_Destination_To_ReturnNode = vDestinationCoord - vPullOverCoord vDiff_Destination_To_ReturnNode.z = 0.0 RETURN VMAG(vDiff_Destination_To_ReturnNode) ENDFUNC /// PURPOSE: /// generate a positin and heading which will lead the taxi along the path nodes to the player's position /// shouldn't need to load the path nodes prior to the checks on this one, since the spawn dist should easliy be with in 400m loaded around player /// PARAMS: /// vSpawnPos - the positio to set value returned by reference /// fSpawnHeading - the heading value to be returned by reference /// iReturnedNodeNumber - return the node number of the last test, used to setup repeat checks /// nodeFlags - default to NF_INCLUDE_SWITCHED_OFF_NODES /// fMinSpawnRadius - min dist for spawn point from player /// RETURNS: /// TRUE if position and heading were successfully generated FUNC BOOL GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER(VECTOR &vSpawnPos, FLOAT &fSpawnHeading, INT &iReturnedNodeNumber, NODE_FLAGS nodeFlags = NF_INCLUDE_SWITCHED_OFF_NODES, FLOAT fMinSpawnRadius = 25.0) VECTOR vClosestNodeToPlayer, vGeneratedSpawnPos, vResultLinkDir FLOAT fGeneratedHeading = 0.0 INT iNumLanes BOOL bIncludeSwitchedOffNodes = TRUE IF nodeFlags = NF_NONE bIncludeSwitchedOffNodes = FALSE ENDIF BOOL bGeneratedPositionFound = FALSE INT iLoopCounter = 0 FLOAT fZ_MeasureMulti = 100.0 // increased as per B*1183689 FLOAT fZ_Tolerance = 2.5 // B*1430520 VECTOR vPosHeadingTest, vOffset1, vOffset2 TAXI_SPECIAL_AREAS_ENUM eSpecialAreaCheck /*#IF IS_DEBUG_BUILD VECTOR vSpawnPosWithFavDirection FLOAT fSpawnHeadingWithFavDirection #ENDIF*/ IF NOT IS_PED_INJURED(PLAYER_PED_ID()) VECTOR vPlayerCoords = GET_ENTITY_COORDS(PLAYER_PED_ID()) // first check we don't need to force a special spawn position and heading for the taxi if the player is in a special area eSpecialAreaCheck = GET_TAXI_SPECIAL_AREA_AT_COORDS(vPlayerCoords) IF eSpecialAreaCheck != TAXI_SPECIAL_AREAS_INVALID IF GET_TAXI_SPAWN_INFO_FOR_TAXI_SPECIAL_AREA(vPlayerCoords, eSpecialAreaCheck, vSpawnPos, fSpawnHeading) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER special area setup eSpecialAreaCheck = ", eSpecialAreaCheck, " : vSpawnPos = ", vSpawnPos, " : fSpawnHeading = ", fSpawnHeading, " - return TRUE") RETURN TRUE ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER - GET_TAXI_SPAWN_INFO_FOR_TAXI_SPECIAL_AREA - return FALSE") ENDIF ELSE // first get the closest node to the player's position (using high zMulti) to work from (this should stop spawn issues where different z height nodes are around) // without it causes bug 1183689 - player is closest to road node above than on the road he's stood on // so GENERATE_VEHICLE_CREATION_POS_FROM_PATHS returns pos on the roof IF GET_NTH_CLOSEST_VEHICLE_NODE_WITH_HEADING(vPlayerCoords, iReturnedNodeNumber, vClosestNodeToPlayer, fGeneratedHeading, iNumLanes, nodeFlags, fZ_MeasureMulti, fZ_Tolerance) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER - gen closest node to player result : vPlayer = ", vPlayerCoords, " : result vClosestNodeToPlayer = ", vClosestNodeToPlayer, " : node in = ", iReturnedNodeNumber, " : out heading = ", fGeneratedHeading, " : inumlanes = ", iNumLanes) // 5 chances to get a valid node otherwise bail out WHILE (NOT bGeneratedPositionFound AND (iLoopCounter < 5)) IF GENERATE_VEHICLE_CREATION_POS_FROM_PATHS(vClosestNodeToPlayer, vGeneratedSpawnPos, vResultLinkDir, 0, 180, fMinSpawnRadius, bIncludeSwitchedOffNodes, TRUE, FALSE) fGeneratedHeading = TAXI_GET_HEADING_FROM_COORDS(<< 0.0, 0.0, 0.0 >>, vResultLinkDir) // not working reliably so verting back to old setup for now - CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER - gen veh creation pos : search pos (vClosestNodeToPlayer) = ", vClosestNodeToPlayer, " : result pos (vGeneratedSpawnPos) = ", vGeneratedSpawnPos, " : result link direction = ", vResultLinkDir, " fGeneratedHeading = ", fGeneratedHeading) // check the generated spawn point isn't within a special area // if so the function will update the spawn pos to use a suitable position //eSpecialAreaCheck = GET_TAXI_SPECIAL_AREA_AT_COORDS(vPlayerCoords) //IF ARE_COORDS_IN_SPECIAL_AREA(vGeneratedSpawnPos, vGeneratedSpawnPos, fGeneratedHeading) // CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " generate creation pos was inside a special area - updated vGeneratedSpawnPos = ", vGeneratedSpawnPos, " updated fGeneratedHeading = ", fGeneratedHeading) //ENDIF // check the generated position is safe IF IS_SPAWN_POSITION_SAFE_FOR_TAXI(vPlayerCoords, vGeneratedSpawnPos) bGeneratedPositionFound = TRUE vPosHeadingTest = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vGeneratedSpawnPos, fGeneratedHeading, <<0.0, 1.0, 0.0>>) // Vehicle Vector vOffset1 = vPosHeadingTest - vGeneratedSpawnPos // Vector to Player vOffset2 = vClosestNodeToPlayer - vGeneratedSpawnPos IF (GET_ANGLE_BETWEEN_2D_VECTORS(vOffset1.x, vOffset1.y, vOffset2.x, vOffset2.y) > 60.0) fGeneratedHeading += 180 fGeneratedHeading = WRAP(fGeneratedHeading, 0, 360) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), "GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER - revised fGeneratedHeading = ", fGeneratedHeading) ENDIF CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER - update fGeneratedHeading = ", fGeneratedHeading, " vResultLinkDir.Z = ", vResultLinkDir.Z, " : heading from 2d vector = ", GET_HEADING_FROM_VECTOR_2D(vResultLinkDir.X, vResultLinkDir.Y), " : result link direction = ", vResultLinkDir, " ") // check the generated spawn point isn't within a special area //IF ARE_COORDS_IN_SPECIAL_AREA(vGeneratedSpawnPos, vGeneratedSpawnPos, fGeneratedHeading) // CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER - ARE_COORDS_IN_SPECIAL_AREA return TRUE so values updated : vGeneratedSpawnPos = ", vGeneratedSpawnPos, " : fGeneratedHeading = ", fGeneratedHeading) //ENDIF /*#IF IS_DEBUG_BUILD IF GET_NTH_CLOSEST_VEHICLE_NODE_FAVOUR_DIRECTION(vGeneratedSpawnPos, vClosestNodeToPlayer, 0, vSpawnPosWithFavDirection, fSpawnHeadingWithFavDirection, nodeFlags, 1) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER - node fav direction would give : ", " fSpawnHeadingWithFavDirection = ", fSpawnHeadingWithFavDirection, " vSpawnPosWithFavDirection = ", vSpawnPosWithFavDirection) ENDIF #ENDIF*/ vSpawnPos = vGeneratedSpawnPos fSpawnHeading = fGeneratedHeading CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER - vSpawnPos = ", vSpawnPos, " : fSpawnHeading = ", fSpawnHeading, " - return TRUE") RETURN TRUE ELSE iLoopCounter++ CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER : IS_SPAWN_POSITION_SAFE_FOR_TAXI return FALSE vGeneratedSpawnPos :", vGeneratedSpawnPos, " iLoopCounter = ", iLoopCounter) ENDIF ELSE iLoopCounter++ CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER - * GENERATE_VEHICLE_CREATION_POS_FROM_PATHS - returned FALSE bIncludeSwitchedOffNodes = ", bIncludeSwitchedOffNodes, " iLoopCounter = ", iLoopCounter) ENDIF ENDWHILE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER - return FALSE : failed to generate spawn pos from node pos = ", vClosestNodeToPlayer, " iNodeNumber = ", iReturnedNodeNumber) iReturnedNodeNumber++ // increment for retry next frame ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER - GET_NTH_CLOSEST_VEHICLE_NODE_WITH_HEADING to player - return FALSE : iNodeNumber = ", iReturnedNodeNumber) iReturnedNodeNumber++ // increment for retry next frame ENDIF ENDIF ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER - player injured - return FALSE") ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// get a valid node position for the taxi to drive to - handles requesting the path nodes at the position to find a valid node /// PARAMS: /// vDestinationCoord - location we want to reach /// vReturnNodeCoord - the returned coords for the VEHICLE_NODE_ID /// fReturnHeading - the returned node heading /// iReturnedNodeNumber - return the node number of the last test, used to setup repeat checks /// iExtraLoadPathDist - dist around vDestinationCoord to load the path nodes in for the search /// RETURNS: /// TRUE if a valid VEHICLE_NODE_ID was found FUNC BOOL GET_TAXI_PICK_UP_PLAYER_DESTINATION(VECTOR vDestinationCoord, VECTOR &vReturnNodeCoord, FLOAT &fReturnHeading, INT &iReturnedNodeNumber, INT iExtraLoadPathDist = 250) FLOAT zMeasureMult = 3 FLOAT fZ_Tolerance = 2.5 // B*1430520 FLOAT fTempZDiff ENTITY_INDEX entityPointObsuredCheck = NULL INT iNoOfLanes VEHICLE_NODE_ID tempVehNodeID INT iMaxNodeLoopChecksPerFrame = iReturnedNodeNumber + 2 // limit checks per frame INT iMaxNodeLoopChecksInTotal = 50 // don't search past this amount BOOL bFoundSuitableNode = FALSE // always search switched off nodes, but if we are in the city ensure they aren't dead ends (stop taxi using driveways). NODE_FLAGS nodeFlags = NF_INCLUDE_SWITCHED_OFF_NODES IF NOT IS_POSITION_IN_ZONE_SAFE_FOR_DEADEND_NODES(vDestinationCoord) nodeFlags = NF_INCLUDE_SWITCHED_OFF_NODES | NF_IGNORE_SWITCHED_OFF_DEADENDS CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PICK_UP_PLAYER_DESTINATION() : using node flags NF_INCLUDE_SWITCHED_OFF_NODES | NF_IGNORE_SWITCHED_OFF_DEADENDS") ENDIF REQUEST_PATH_NODES_IN_AREA_FOR_TAXI_THIS_FRAME(vDestinationCoord, vDestinationCoord, sDispatchedTaxi.vPathNodeRequestMin, sDispatchedTaxi.vPathNodeRequestMax, iExtraLoadPathDist) IF ARE_REQUEST_PATH_NODES_LOADED_FOR_TAXI(sDispatchedTaxi.vPathNodeRequestMin, sDispatchedTaxi.vPathNodeRequestMax) IF NOT ARE_COORDS_IN_SPECIAL_AREA(vDestinationCoord, vReturnNodeCoord, fReturnHeading) // get closest point that is on a road. // 3 chances to get a valid node otherwise bail out this frame WHILE (NOT bFoundSuitableNode AND (iReturnedNodeNumber < iMaxNodeLoopChecksPerFrame)) IF vDestinationCoord.z = 1 CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PICK_UP_PLAYER_DESTINATION() : zMeasureMult = 0 ") zMeasureMult = 0 ENDIF IF GET_NTH_CLOSEST_VEHICLE_NODE_WITH_HEADING(vDestinationCoord, iReturnedNodeNumber, vReturnNodeCoord, fReturnHeading, iNoOfLanes, nodeFlags, zMeasureMult, fZ_Tolerance) // get the VEHICLE_NODE_ID for returned node positin tempVehNodeID = GET_NTH_CLOSEST_VEHICLE_NODE_ID(vReturnNodeCoord, 1, nodeFlags) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PICK_UP_PLAYER_DESTINATION() : vDestinationCoord = ", vDestinationCoord, " iReturnedNodeNumber = ", iReturnedNodeNumber, " vReturnNodeCoord = ", vReturnNodeCoord, " iNoOfLanes = ", iNoOfLanes) IF IS_VEHICLE_NODE_ID_VALID(tempVehNodeID) // Bug fix B*1245895 - check was returning FALSE for coords with same/similar Z value fTempZDiff = vDestinationCoord.z - vReturnNodeCoord.z IF fTempZDiff < 0.0 fTempZDiff *= -1.0 ENDIF IF IS_COORD_ON_SAME_LEVEL_AS_COORD(vDestinationCoord, vReturnNodeCoord) OR (fTempZDiff < 0.5) // Bug fix B*1245895 - check was returning FALSE for coords with same/similar Z value IF IS_VEHICLE_DRIVEABLE(sDispatchedTaxi.vehicleIndex) entityPointObsuredCheck = sDispatchedTaxi.vehicleIndex ENDIF //check the position isn't obsured IF NOT IS_POINT_OBSCURED_BY_A_MISSION_ENTITY(vReturnNodeCoord, <<3,3,3>>, entityPointObsuredCheck) #IF IS_DEBUG_BUILD // Spoke with JMart the taxi pathfinding doesn't actually care about GPS being allowed so don't fail the search for GPS not be allowed IF NOT GET_VEHICLE_NODE_IS_GPS_ALLOWED(tempVehNodeID) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PICK_UP_PLAYER_DESTINATION() : node GPS not allowed") ENDIF // Since we are now using switched off nodes in the searrch don't fail the search for the selected node being switched off IF NOT GET_VEHICLE_NODE_IS_SWITCHED_OFF(tempVehNodeID) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PICK_UP_PLAYER_DESTINATION() : node is switched off") ENDIF #ENDIF bFoundSuitableNode = TRUE ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PICK_UP_PLAYER_DESTINATION() : IS_POINT_OBSCURED_BY_A_MISSION_ENTITY() return TRUE, bFoundSuitableNode = FALSE") ENDIF ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PICK_UP_PLAYER_DESTINATION() : IS_COORD_ON_SAME_LEVEL_AS_COORD return FALSE") ENDIF ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PICK_UP_PLAYER_DESTINATION() : IS_VEHICLE_NODE_ID_VALID return FALSE") ENDIF ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PICK_UP_PLAYER_DESTINATION() : GET_NTH_CLOSEST_VEHICLE_NODE_WITH_HEADING return FALSE") ENDIF iReturnedNodeNumber++ // fail safe, don't test past iMaxNodeLoopChecksInTotal IF (iReturnedNodeNumber >= iMaxNodeLoopChecksInTotal) // don't search past this amount) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PICK_UP_PLAYER_DESTINATION() : iReturnedNodeNumber = ", iReturnedNodeNumber, " reached max check amount, bFoundSuitableNode = TRUE, FC = ", GET_FRAME_COUNT()) bFoundSuitableNode = TRUE ENDIF // debug print to show reached frame loop limit #IF IS_DEBUG_BUILD IF (iReturnedNodeNumber > iMaxNodeLoopChecksPerFrame) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PICK_UP_PLAYER_DESTINATION() : iReturnedNodeNumber = ", iReturnedNodeNumber, " reached max loop check amount this frame FC = ", GET_FRAME_COUNT()) ENDIF #ENDIF ENDWHILE ELSE // destination in special area bFoundSuitableNode = TRUE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PICK_UP_PLAYER_DESTINATION() : ARE_COORDS_IN_SPECIAL_AREA returned TRUE, vDestinationCoord = ", vDestinationCoord, " vReturnNodeCoord = ", vReturnNodeCoord, " fReturnHeading = ", fReturnHeading) ENDIF IF bFoundSuitableNode sDispatchedTaxi.fDistToTarget = GET_DIST_BETWEEN_VECTORS_NONE_Z(vDestinationCoord, vReturnNodeCoord) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PICK_UP_PLAYER_DESTINATION() : returning TRUE for vReturnNodeCoord = ", vReturnNodeCoord, " fReturnHeading = ", fReturnHeading, " sDispatchedTaxi.fDistToTarget = ", sDispatchedTaxi.fDistToTarget) RETURN TRUE ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PICK_UP_PLAYER_DESTINATION() : returning FALSE") ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// handles taxi driving to the player / or pickup position and detecting when he's close enough to pull over /// RETURNS: /// TRUE if he's reached the pickup player location FUNC BOOL HAS_DISPATCHED_TAXI_ARRIVED_TO_PICKUP_PLAYER() VECTOR vTaxiPos IF NOT sDispatchedTaxi.bHasActiveTask IF GET_TAXI_PICK_UP_PLAYER_DESTINATION(sDispatchedTaxi.vPlayerCalledCoords, sDispatchedTaxi.vDriveToCoords, sDispatchedTaxi.fDriveToHeading, sDispatchedTaxi.iNodeSearchNumber) TASK_VEHICLE_DRIVE_TO_COORD(sDispatchedTaxi.pedIndex, sDispatchedTaxi.vehicleIndex, sDispatchedTaxi.vDriveToCoords, 12.0, DRIVINGSTYLE_NORMAL, GET_ENTITY_MODEL(sDispatchedTaxi.vehicleIndex), sDispatchedTaxi.taxiDrivingModeStandard, (sDispatchedTaxi.fTargetReached - 20), 20) //TASK_VEHICLE_MISSION_COORS_TARGET(sDispatchedTaxi.pedIndex, sDispatchedTaxi.vehicleIndex, sDispatchedTaxi.vDriveToCoords, MISSION_GOTO, 12.0, taxiDrivingModeStandard, (sDispatchedTaxi.fTargetReached - 20), 20, FALSE) // B*1329777 - JMart request Can we just use the regular Goto and not Longrange when tasking the taxi to go to the player's position //TASK_VEHICLE_DRIVE_TO_COORD_LONGRANGE(sDispatchedTaxi.pedIndex, sDispatchedTaxi.vehicleIndex, sDispatchedTaxi.vDriveToCoords, 12.0, taxiDrivingModeStandard, sDispatchedTaxi.fTargetReached) sDispatchedTaxi.bHasActiveTask = TRUE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : HAS_DISPATCHED_TAXI_ARRIVED_TO_PICKUP_PLAYER() : vehicle task drive coord, sDispatchedTaxi.vDriveToCoords = ", sDispatchedTaxi.vDriveToCoords, " sDispatchedTaxi.fDriveToHeading = ", sDispatchedTaxi.fDriveToHeading) ENDIF ELSE vTaxiPos = GET_ENTITY_COORDS(sDispatchedTaxi.vehicleIndex) // check to see when the taxi gets with in range IF TAXI_IS_COORD_IN_RANGE_OF_COORD(vTaxiPos, sDispatchedTaxi.vDriveToCoords, sDispatchedTaxi.fTargetReached) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : HAS_DISPATCHED_TAXI_ARRIVED_TO_PICKUP_PLAYER() return TRUE - reached sDispatchedTaxi.vDriveToCoords : ", sDispatchedTaxi.vDriveToCoords) RETURN TRUE ELIF TAXI_IS_COORD_IN_RANGE_OF_COORD(vTaxiPos, vPlayerPos, 5.0) sDispatchedTaxi.vDriveToCoords = vPlayerPos CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : HAS_DISPATCHED_TAXI_ARRIVED_TO_PICKUP_PLAYER() return TRUE - reached vPlayerPos : ", vPlayerPos, " so updated sDispatchedTaxi.vDriveToCoords to match") RETURN TRUE ELSE // reapply the drive to task if it failed for some reason IF NOT TAXI_IS_PED_PERFORMING_TASK(sDispatchedTaxi.pedIndex, SCRIPT_TASK_VEHICLE_DRIVE_TO_COORD) // B*1329777 - JMart request Can we just use the regular Goto and not Longrange when tasking the taxi to go to the player's position? //IF NOT TAXI_IS_PED_PERFORMING_TASK(sDispatchedTaxi.pedIndex, SCRIPT_TASK_VEHICLE_DRIVE_TO_COORD_LONGRANGE) sDispatchedTaxi.bHasActiveTask = FALSE // commented out for now since performing task return false when it shouldn't see B* sDispatchedTaxi.iNodeSearchNumber = 0 // reset ready for retest CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : HAS_DISPATCHED_TAXI_ARRIVED_TO_PICKUP_PLAYER() : vehicle task drive coord, failed so set to reapply") ENDIF ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Tests Z distance between 2 vectors /// PARAMS: /// vector1 - pull over position /// vector2 - road node /// RETURNS: /// TRUE if Z difference is greater than 0.45 meters, otherwise FALSE FUNC BOOL TEST_VECTOR_Z_DIFFERENCE(VECTOR vector1, VECTOR vector2) IF(vector1.z - vector2.z > 0.45) OR (vector1.z - vector2.z < -0.45) RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Z checks taxi pull over position, Finds a valid position for the taxi to stop at, that passes the Z check. /// PARAMS: /// vReturnPullOverPosition - the taxi needing to pull over position /// vNodePosition - closest road node /// RETURNS: /// TRUE if Z check failed and another postion had to be found. FALSE, if Z check passed FUNC BOOL DO_PARK_Z_CHECK(VECTOR &vReturnPullOverPosition, VECTOR vNodePosition) FLOAT zCoord IF NOT GET_GROUND_Z_FOR_3D_COORD(<>,zCoord) vReturnPullOverPosition = vNodePosition RETURN FALSE ENDIF VECTOR tempVec = << vReturnPullOverPosition.x, vReturnPullOverPosition.y, zCoord >> IF TEST_VECTOR_Z_DIFFERENCE(tempVec,vNodePosition) VECTOR vDirection = (vNodePosition-tempVec)/5.0 INT i FOR i = 1 TO 5 tempVec = tempVec + vDirection IF NOT TEST_VECTOR_Z_DIFFERENCE(tempVec,vNodePosition) vReturnPullOverPosition = tempVec RETURN TRUE ENDIF ENDFOR vReturnPullOverPosition = vNodePosition RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// get a valid position and heading for the taxi to pull over based from passed in node coords /// PARAMS: /// vTaxiCoords - the taxi needing to pull over position /// vDestinationNodeCoords - the destination node's position /// fDestinationNodeHeading - the destination node's heading /// vRetunPullOverPosition - the position the taxi should park /// fReturnPullOverHeading - the desired heading the taxi should use to park /// RETURNS: /// TRUE if a valid positon was found FUNC BOOL GET_TAXI_PULL_OVER_INFO(VECTOR vTaxiCoords, VECTOR vDestinationNodeCoords, FLOAT fDestinationNodeHeading, VECTOR &vReturnPullOverPosition, FLOAT &fReturnPullOverHeading) VECTOR vNodePosition VECTOR vRoadSideForwards VECTOR vRoadSideBackwards VEHICLE_NODE_ID tempVehNodeID // always search switched off nodes, but if we are in the city ensure they aren't dead ends (stop taxi using driveways). NODE_FLAGS nodeFlags = NF_INCLUDE_SWITCHED_OFF_NODES IF NOT IS_POSITION_IN_ZONE_SAFE_FOR_DEADEND_NODES(vDestinationNodeCoords) nodeFlags = NF_INCLUDE_SWITCHED_OFF_NODES | NF_IGNORE_SWITCHED_OFF_DEADENDS CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PULL_OVER_INFO() : using node flags NF_INCLUDE_SWITCHED_OFF_NODES | NF_IGNORE_SWITCHED_OFF_DEADENDS") ENDIF // get the VEHICLE_NODE_ID for node position tempVehNodeID = GET_NTH_CLOSEST_VEHICLE_NODE_ID(vDestinationNodeCoords, 1, nodeFlags) // check there is a valid vehicle node at the destination IF IS_VEHICLE_NODE_ID_VALID(tempVehNodeID) GET_VEHICLE_NODE_POSITION(tempVehNodeID, vNodePosition) #IF IS_DEBUG_BUILD IF NOT ARE_VECTORS_ALMOST_EQUAL(vNodePosition, vDestinationNodeCoords, 0.5) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PULL_OVER_INFO() : passed in node coords didn't match the cloest node position : vDestinationNodeCoords = ", vDestinationNodeCoords, " vNodePosition = ", vNodePosition) ENDIF #ENDIF // try to find a position on both sides of the road IF GET_POSITION_BY_SIDE_OF_ROAD(vNodePosition, 0, vRoadSideForwards) // iDirection - should be a direction (0=forwards, 1=back, -1=doesn't matter) AND GET_POSITION_BY_SIDE_OF_ROAD(vNodePosition, 1, vRoadSideBackwards) // iDirection - should be a direction (0=forwards, 1=back, -1=doesn't matter) VECTOR v1, v2, v3 v1 = vRoadSideForwards - vNodePosition v2 = << -v1.y, v1.x, 0.0 >> v3 = vTaxiCoords - vDestinationNodeCoords FLOAT fDotProduct = DOT_PRODUCT(v2, v3) IF fDotProduct < 0.0 vReturnPullOverPosition = vRoadSideForwards fReturnPullOverHeading = fDestinationNodeHeading //z check - B* 1869986 IF DO_PARK_Z_CHECK(vReturnPullOverPosition,vNodePosition) sDispatchedTaxi.bFailedZCheck = TRUE ENDIF CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PULL_OVER_INFO() : return TRUE cloest side found (forwards)", " vReturnPullOverPosition : ", vReturnPullOverPosition, " fReturnPullOverHeading = ", fReturnPullOverHeading) #IF IS_DEBUG_BUILD DEBUG_DRAW_TAXI_PULL_OVER_INFO(vReturnPullOverPosition, vRoadSideBackwards, vNodePosition) #ENDIF ELSE vReturnPullOverPosition = vRoadSideBackwards fReturnPullOverHeading += 180 fReturnPullOverHeading = WRAP(fReturnPullOverHeading, 0, 360) //z check - B* 1869986 IF DO_PARK_Z_CHECK(vReturnPullOverPosition,vNodePosition) sDispatchedTaxi.bFailedZCheck = TRUE ENDIF CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PULL_OVER_INFO() : return TRUE cloest side found (backwards)", " vReturnPullOverPosition : ", vReturnPullOverPosition, " fReturnPullOverHeading = ", fReturnPullOverHeading) #IF IS_DEBUG_BUILD DEBUG_DRAW_TAXI_PULL_OVER_INFO(vReturnPullOverPosition, vRoadSideForwards, vNodePosition) #ENDIF ENDIF RETURN TRUE // try to find any valid position at the side of the road ELIF GET_POSITION_BY_SIDE_OF_ROAD(vNodePosition, -1, vRoadSideForwards) // iDirection - should be a direction (0=forwards, 1=back, -1=doesn't matter) vReturnPullOverPosition = vRoadSideForwards fReturnPullOverHeading = fDestinationNodeHeading CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PULL_OVER_INFO() : return TRUE just the one position found vReturnPullOverPosition : ", vReturnPullOverPosition) RETURN TRUE // unable to find a valid position at the side of the road ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PULL_OVER_INFO() : return FALSE unable to find a valid position by the side of the road vDestinationNodeCoords : ", vDestinationNodeCoords) ENDIF ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : GET_TAXI_PULL_OVER_INFO() : return FALSE IS_VEHICLE_NODE_ID_VALID vDestinationNodeCoords : ", vDestinationNodeCoords) ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// handles the taxi pulling over to pickup the player /// RETURNS: /// TRUE if taxi has pulled over successfully FUNC BOOL HAS_DISPATCHED_TAXI_PULLED_OVER_TO_PICKUP_PLAYER() VECTOR vTaxiPos vTaxiPos = GET_ENTITY_COORDS(sDispatchedTaxi.vehicleIndex, FALSE) IF NOT sDispatchedTaxi.bHasActiveTask // if player has got close to taxi before it's reached it's pull up position allow the task to be reapplied using current position IF NOT sDispatchedTaxi.bForcedPullOverAtCurrentPosition IF GET_TAXI_PULL_OVER_INFO(vTaxiPos, sDispatchedTaxi.vDriveToCoords, sDispatchedTaxi.fDriveToHeading, sDispatchedTaxi.vPullOverCoords, sDispatchedTaxi.fDriveToHeading) IF NOT IS_ENTITY_DEAD(sDispatchedTaxi.pedIndex) SET_DRIVER_ABILITY(sDispatchedTaxi.pedIndex, 0.5) //z check - B* 1869986 IF sDispatchedTaxi.bFailedZCheck TASK_VEHICLE_DRIVE_TO_COORD(sDispatchedTaxi.pedIndex, sDispatchedTaxi.vehicleIndex, sDispatchedTaxi.vPullOverCoords, 10, DRIVINGSTYLE_NORMAL, GET_ENTITY_MODEL(sDispatchedTaxi.vehicleIndex), sDispatchedTaxi.taxiDrivingModeStandard, 5, GET_DISTANCE_BETWEEN_COORDS(vTaxiPos,sDispatchedTaxi.vPullOverCoords)) sDispatchedTaxi.bFailedZCheck = FALSE ELSE // info: apparently TASK_VEHICLE_PARK should work from as far 50m away also as the path nodes are loaded. Needs to kick in earlier than later. // can take up to 10 metres to stop, so best to pass in a position offset from the actual spot you want to stop //TASK_VEHICLE_PARK(sDispatchedTaxi.pedIndex, sDispatchedTaxi.vehicleIndex, sDispatchedTaxi.vPullOverCoords, sDispatchedTaxi.fDriveToHeading, PARK_TYPE_PULL_OVER, 90, TRUE) TASK_VEHICLE_PARK(sDispatchedTaxi.pedIndex, sDispatchedTaxi.vehicleIndex, sDispatchedTaxi.vPullOverCoords, sDispatchedTaxi.fDriveToHeading, PARK_TYPE_PULL_OVER, 90, TRUE) ENDIF ENDIF sDispatchedTaxi.bHasActiveTask = TRUE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : HAS_DISPATCHED_TAXI_PULLED_OVER_TO_PICKUP_PLAYER() applied park task ", " sDispatchedTaxi.vPullOverCoords : ", sDispatchedTaxi.vPullOverCoords, " sDispatchedTaxi.fDriveToHeading = ", sDispatchedTaxi.fDriveToHeading) ENDIF ELSE SET_DRIVER_ABILITY(sDispatchedTaxi.pedIndex, 0.5) sDispatchedTaxi.vPullOverCoords = vTaxiPos TASK_VEHICLE_TEMP_ACTION(sDispatchedTaxi.pedIndex, sDispatchedTaxi.vehicleIndex, TEMPACT_HANDBRAKESTRAIGHT, 15000) sDispatchedTaxi.bHasActiveTask = TRUE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : HAS_DISPATCHED_TAXI_PULLED_OVER_TO_PICKUP_PLAYER() applied TEMPACT_HANDBRAKESTRAIGHT task ", " sDispatchedTaxi.vPullOverCoords : ", sDispatchedTaxi.vPullOverCoords) // info: apparently TASK_VEHICLE_PARK should work from as far 50m away also as the path nodes are loaded. Needs to kick in earlier than later. // can take up to 10 metres to stop, so best to pass in a position offset from the actual spot you want to stop //TASK_VEHICLE_PARK(sDispatchedTaxi.pedIndex, sDispatchedTaxi.vehicleIndex, sDispatchedTaxi.vPullOverCoords, sDispatchedTaxi.fDriveToHeading, PARK_TYPE_PULL_OVER, 90, TRUE) //bTaxiDriverHasActiveTask = TRUE //CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : HAS_DISPATCHED_TAXI_PULLED_OVER_TO_PICKUP_PLAYER() applied park task ", // " sDispatchedTaxi.vPullOverCoords : ", sDispatchedTaxi.vPullOverCoords, " sDispatchedTaxi.fDriveToHeading = ", sDispatchedTaxi.fDriveToHeading) ENDIF ELSE IF NOT TAXI_IS_PED_PERFORMING_TASK(sDispatchedTaxi.pedIndex, SCRIPT_TASK_VEHICLE_PARK) IF IS_VEHICLE_STOPPED(sDispatchedTaxi.vehicleIndex) //AND TAXI_IS_COORD_IN_RANGE_OF_COORD(vTaxiPos, sDispatchedTaxi.vPullOverCoords, 15.0) // seems they can pull over far away TASK_VEHICLE_TEMP_ACTION(sDispatchedTaxi.pedIndex, sDispatchedTaxi.vehicleIndex, TEMPACT_WAIT, 1000000) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : HAS_DISPATCHED_TAXI_PULLED_OVER_TO_PICKUP_PLAYER() : driver tasked TEMPACT_WAIT") CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : HAS_DISPATCHED_TAXI_PULLED_OVER_TO_PICKUP_PLAYER() : return TRUE - stopped at : ", vTaxiPos) RETURN TRUE ENDIF ELSE // if the player get close and the vehicle is already stopped just left him get in IF TAXI_IS_COORD_IN_RANGE_OF_COORD(vTaxiPos, vPlayerPos, 5.0) IF IS_VEHICLE_STOPPED(sDispatchedTaxi.vehicleIndex) OR IS_VEHICLE_STOPPED_AT_TRAFFIC_LIGHTS(sDispatchedTaxi.vehicleIndex) TASK_VEHICLE_TEMP_ACTION(sDispatchedTaxi.pedIndex, sDispatchedTaxi.vehicleIndex, TEMPACT_WAIT, 1000000) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : HAS_DISPATCHED_TAXI_PULLED_OVER_TO_PICKUP_PLAYER() : driver tasked TEMPACT_WAIT") CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : HAS_DISPATCHED_TAXI_PULLED_OVER_TO_PICKUP_PLAYER() : return TRUE - stopped early for player prox : ", vTaxiPos) RETURN TRUE ENDIF ENDIF IF NOT sDispatchedTaxi.bForcedPullOverAtCurrentPosition // allow player to flag it earlier if he gets close to it before it's had a chance finish it's pull over task IF NOT TAXI_IS_COORD_IN_RANGE_OF_COORD(vTaxiPos, sDispatchedTaxi.vPullOverCoords, 10.0) IF TAXI_IS_COORD_IN_RANGE_OF_COORD(vTaxiPos, vPlayerPos, 5.0) sDispatchedTaxi.vDriveToCoords = vPlayerPos sDispatchedTaxi.bForcedPullOverAtCurrentPosition = TRUE sDispatchedTaxi.bHasActiveTask = FALSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : HAS_DISPATCHED_TAXI_PULLED_OVER_TO_PICKUP_PLAYER() : player got close before pulled over so reapplied") ENDIF ENDIF ENDIF ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Creates a taxi ready to drive to the player - for when they have rang for a taxi PROC DISPATCHED_STATE_CREATE_TAXI() IF IS_PLAYER_PLAYING(PLAYER_ID()) // might not be needed now? // B*1339179 - Taxi came a bit too quickly - always have a minimum time of 10 seconds then it arriving. Les Bug IF HAS_TIME_PASSED(sDispatchedTaxi.iTimer_TaxiDispatchDelay, TIME_DELAY_TAXI_DISPATCHED) REQUEST_MODEL(mnTaxiModel) REQUEST_MODEL(mnTaxiDriverModel) IF HAS_MODEL_LOADED(mnTaxiModel) IF HAS_MODEL_LOADED(mnTaxiDriverModel) VECTOR vSpawnPos FLOAT fHeading NODE_FLAGS nodeFlags // Info from J Mart - switched off nodes should be ok in most case, but if we are in the city ensure they aren't dead ends (stop taxi using driveways). IF IS_POSITION_IN_ZONE_SAFE_FOR_DEADEND_NODES(GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE)) // COUNTRYSIDE / OK FOR DEADEND NODES - // try to make taxi spawn on major road networks first to fix issues where they spawn in blocked off areas/deadends IF sDispatchedTaxi.iSpawnAttempts < 2 nodeFlags = NF_NONE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : DISPATCHED_STATE_CREATE_TAXI() : countryside : using node flags NF_NONE : iSpawnAttempts = ", sDispatchedTaxi.iSpawnAttempts) // then attempt spawn not using deadends ELIF sDispatchedTaxi.iSpawnAttempts < 5 nodeFlags = NF_INCLUDE_SWITCHED_OFF_NODES | NF_IGNORE_SWITCHED_OFF_DEADENDS CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : DISPATCHED_STATE_CREATE_TAXI() : countryside : using node flags NF_INCLUDE_SWITCHED_OFF_NODES | NF_IGNORE_SWITCHED_OFF_DEADENDS : iSpawnAttempts = ", sDispatchedTaxi.iSpawnAttempts) ELSE nodeFlags = NF_INCLUDE_SWITCHED_OFF_NODES CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : DISPATCHED_STATE_CREATE_TAXI() : countryside : using node flags NF_INCLUDE_SWITCHED_OFF_NODES : iSpawnAttempts = ", sDispatchedTaxi.iSpawnAttempts) ENDIF ELSE // CITY / NOT OK FOR DEADEND NODES - // try to make taxi spawn on major road networks first to fix issues where they spawn in blocked off areas/deadends IF sDispatchedTaxi.iSpawnAttempts < 5 nodeFlags = NF_NONE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : DISPATCHED_STATE_CREATE_TAXI() : using node flags NF_NONE : iSpawnAttempts = ", sDispatchedTaxi.iSpawnAttempts) ELSE nodeFlags = NF_INCLUDE_SWITCHED_OFF_NODES | NF_IGNORE_SWITCHED_OFF_DEADENDS CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : DISPATCHED_STATE_CREATE_TAXI() : area NOT safe for DeadEnds : using node flags NF_INCLUDE_SWITCHED_OFF_NODES | NF_IGNORE_SWITCHED_OFF_DEADENDS : iSpawnAttempts = ", sDispatchedTaxi.iSpawnAttempts) ENDIF ENDIF IF GENERATE_TAXI_SPAWN_POS_AND_HEADING_TO_PLAYER(vSpawnPos, fHeading, sDispatchedTaxi.iNodeSearchNumber, nodeFlags, DEFAULT) #IF IS_DEBUG_BUILD vDebug_DispatchTaxiSpawnPos = vSpawnPos IF bDebug_UseForceTaxiSpawnCoordsAndHeading vSpawnPos = vDebug_ForcedTaxiSpawnCoords fHeading = fDebug_ForcedTaxiSpawnHeading CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : DISPATCHED_STATE_CREATE_TAXI() : DEBUG! forcing spawn coords & heading") ENDIF #ENDIF CLEAR_AREA(vSpawnPos, 5.0, TRUE) IF CREATE_TAXI_AND_DRIVER(sDispatchedTaxi.vehicleIndex, sDispatchedTaxi.pedIndex, vSpawnPos, fHeading) sDispatchedTaxi.fDistToTarget = GET_DIST_BETWEEN_VECTORS_NONE_Z(GET_ENTITY_COORDS(sDispatchedTaxi.vehicleIndex), GET_ENTITY_COORDS(PLAYER_PED_ID())) sDispatchedTaxi.bHasActiveTask = FALSE // reset ready for next task sDispatchedTaxi.iNodeSearchNumber = 0 // reset ready for destination node search eDispatchedTaxiState = TL_DISPATCHED_STATE_DRIVE_TO_PICKUP_PLAYER CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : eDispatchedTaxiState = TL_DISPATCHED_STATE_DRIVE_TO_PICKUP_PLAYER : fc = ", GET_FRAME_COUNT()) ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " DISPATCHED_STATE_CREATE_TAXI - CREATE_TAXI - return FALSE") ENDIF ELSE // fail safe for create taxi not being able to generate suitable creation node IF sDispatchedTaxi.iNodeSearchNumber >= 5 // limit to 5 so taxi is still trying to generate a path close to the player sDispatchedTaxi.iSpawnAttempts++ // 10 retry attempts since it might just be the player's camera angle blocking a successful spawn IF sDispatchedTaxi.iSpawnAttempts > 10 CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : DISPATCHED_STATE_CREATE_TAXI - Bail Out : failed to generate taxi creation position! : fc = ", GET_FRAME_COUNT()) CLEANUP_DISPATCHED_TAXI_DATA() ELSE sDispatchedTaxi.iNodeSearchNumber = 0 // reset ready for retry sDispatchedTaxi.iTimer_TaxiDispatchDelay = (GET_GAME_TIMER() - (TIME_DELAY_TAXI_DISPATCHED - 1000)) // retry go through in a seconds time CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : DISPATCHED_STATE_CREATE_TAXI - setup Retry : failed to generate taxi creation position! : fc = ", GET_FRAME_COUNT()) ENDIF ENDIF ENDIF ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " DISPATCHED_STATE_CREATE_TAXI - HAS_MODEL_LOADED(mnTaxiDriverModel) - return FALSE") ENDIF ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " DISPATCHED_STATE_CREATE_TAXI - HAS_MODEL_LOADED(mnTaxiModel) - return FALSE") ENDIF ENDIF ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " DISPATCHED_STATE_CREATE_TAXI - IS_PLAYER_PLAYING() - return FALSE") ENDIF ENDPROC /// PURPOSE: /// handles the created taxi driving over to the player PROC DISPATCHED_STATE_DRIVE_TO_PICKUP_PLAYER() IF HAS_DISPATCHED_TAXI_ARRIVED_TO_PICKUP_PLAYER() sDispatchedTaxi.bHasActiveTask = FALSE // reset ready for next task eDispatchedTaxiState = TL_DISPATCHED_STATE_PULL_OVER_TO_PICKUP_PLAYER CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : eDispatchedTaxiState = TL_DISPATCHED_STATE_PULL_OVER_TO_PICKUP_PLAYER : fc = ", GET_FRAME_COUNT()) ENDIF ENDPROC /// PURPOSE: /// Handles the created taxi finding a pull over spot to park up near the player upon arrival PROC DISPATCHED_STATE_PULL_OVER_TO_PICKUP_PLAYER() IF HAS_DISPATCHED_TAXI_PULLED_OVER_TO_PICKUP_PLAYER() // only set this up as waiting if player isn't getting into a taxi and there isn't one waiting IF eEnterTaxiState = TL_ENTER_TAXI_STATE_IDLE AND eHailTaxiState != TL_HAIL_TAXI_STATE_TAXI_WAITING // clear ready for next updated state CLEANUP_HAIL_TAXI() //update handles IF STORE_CAR_AS_TAXI_WAITING_FOR_PLAYER(sDispatchedTaxi.vehicleIndex, sDispatchedTaxi.pedIndex) g_iTaxiHailedTime = 0 IF IS_VEHICLE_OK(g_WaitingTaxi) START_VEHICLE_HORN(g_WaitingTaxi, 2500, GET_HASH_KEY("NORMAL")) ENDIF IF DOES_ENTITY_EXIST(g_WaitingTaxiDriver) IF NOT IS_PED_INJURED(g_WaitingTaxiDriver) TASK_LOOK_AT_ENTITY(g_WaitingTaxiDriver, PLAYER_PED_ID(), 3000) TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), g_WaitingTaxiDriver, 3000) ENDIF ENDIF CREATE_WAITING_TAXI_BLIP() // set the taxi hailing taxi to taxi waiting eHailTaxiState = TL_HAIL_TAXI_STATE_TAXI_WAITING CLEANUP_DISPATCHED_TAXI_DATA() CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : DISPATCHED_STATE_PULL_OVER_TO_PICKUP_PLAYER() : marked taxi as waiting : fc = ", GET_FRAME_COUNT()) ELSE CLEANUP_DISPATCHED_TAXI_DATA() CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : DISPATCHED_STATE_PULL_OVER_TO_PICKUP_PLAYER() : failed attempt to mark taxi as waiting : fc = ", GET_FRAME_COUNT()) ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// check if the taxi already have a fare on board /// NOTE: doesn't safety check entity /// RETURNS: /// TRUE if found ped in rear seat who isn't in player group FUNC BOOL DOES_TAXI_ALREADY_HAVE_A_FARE(VEHICLE_INDEX &vehicleIndex) PED_INDEX pedIndex IF NOT IS_VEHICLE_SEAT_FREE(vehicleIndex, VS_BACK_LEFT) pedIndex = GET_PED_IN_VEHICLE_SEAT (vehicleIndex, VS_BACK_LEFT) IF NOT (pedIndex = PLAYER_PED_ID()) // don't worry if it's got player group member in IF NOT IS_PED_GROUP_MEMBER(pedIndex, PLAYER_GROUP_ID()) // not sure why this is here! but there you go IF IS_TAXI_LIGHT_ON(vehicleIndex) SET_TAXI_LIGHTS(vehicleIndex, FALSE) ENDIF RETURN TRUE ENDIF ENDIF ENDIF IF NOT IS_VEHICLE_SEAT_FREE(vehicleIndex, VS_BACK_RIGHT) pedIndex = GET_PED_IN_VEHICLE_SEAT (vehicleIndex, VS_BACK_RIGHT) IF NOT (pedIndex = PLAYER_PED_ID()) // don't worry if it's got player group member in IF NOT IS_PED_GROUP_MEMBER(pedIndex, PLAYER_GROUP_ID()) // not sure why this is here! but there you go IF IS_TAXI_LIGHT_ON(vehicleIndex) SET_TAXI_LIGHTS(vehicleIndex, FALSE) ENDIF RETURN TRUE ENDIF ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Player comment for hailed taxi not stopping /// FUNC needs improving PROC PLAY_FUCK_YOU_DIALOGUE() BOOL bFlag // shout 'fuck you' IF (bPlayAdditionalFuckYouDialogue) IF HAS_TIME_PASSED(iTimer_HailFailedDialogueDelay, 1000) IF (GET_SCRIPT_TASK_STATUS(PLAYER_PED_ID(), SCRIPT_TASK_PLAY_ANIM) = FINISHED_TASK) IF (GET_SCRIPT_TASK_STATUS(PLAYER_PED_ID(), SCRIPT_TASK_PERFORM_SEQUENCE) = FINISHED_TASK) IF NOT IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "HAIL_TAXI") AND NOT IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "FP_HAIL_TAXI") AND NOT IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "FUCK_U") AND NOT IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "FORGET_IT") IF NOT (g_playerIsDrunk) // has player been shut up for mission? bFlag = IS_AMBIENT_SPEECH_DISABLED(PLAYER_PED_ID()) //bFlag = TRUE IF NOT (bFlag) STOP_PED_SPEAKING(PLAYER_PED_ID(), TRUE) ENDIF PLAY_PED_AMBIENT_SPEECH(PLAYER_PED_ID(), "TAXI_DRIVES_PAST") IF NOT (bFlag) STOP_PED_SPEAKING(PLAYER_PED_ID(), FALSE) ENDIF ENDIF SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_KeepWeaponHolsteredUnlessFired, FALSE) // B*1991223 - RESET need to block ambient anims during hail anims IF bBlockingPlayerAmbientIdles = TRUE SET_PED_CAN_PLAY_AMBIENT_ANIMS(PLAYER_PED_ID(), TRUE) bBlockingPlayerAmbientIdles = FALSE ENDIF bPlayAdditionalFuckYouDialogue = FALSE ENDIF ENDIF ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// check if the player is moving the analogue sticks /// RETURNS: /// TRUE if movement detected FUNC BOOL IS_PLAYER_MOVING() // get stick vec INT LSx, LSy, RSx, RSy GET_CONTROL_VALUE_OF_ANALOGUE_STICKS(LSx, LSy, RSx, RSy) IF (LSx > 64) OR (LSx < -64) OR (LSy > 64) OR (LSy < -64) RETURN(TRUE) ENDIF RETURN(FALSE) ENDFUNC /// PURPOSE: /// stops the gameplay hint cam if it was applied by the launcher PROC CLEAR_HINT_CAM_IF_PLAYER_IS_MOVING() IF IS_GAMEPLAY_HINT_ACTIVE() IF bHintTriggeredByTaxiLauncher IF IS_PLAYER_MOVING() STOP_GAMEPLAY_HINT() ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// check if the vehicle is going below TAXI_MOVING_GET_IN_SPEED /// PARAMS: /// vehicleIndex - vehicle to check /// RETURNS: /// TRUE if speed is less than TAXI_MOVING_GET_IN_SPEED FUNC BOOL IS_CAR_ALMOST_STOPPED(VEHICLE_INDEX vehicleIndex) IF IS_VEHICLE_DRIVEABLE(vehicleIndex) IF (GET_ENTITY_SPEED(vehicleIndex) < TAXI_MOVING_GET_IN_SPEED) RETURN(TRUE) ENDIF ELSE RETURN(TRUE) ENDIF RETURN(FALSE) ENDFUNC /// PURPOSE: /// check if the vehicle's roll is ok /// PARAMS: /// vehicleIndex - /// RETURNS: /// TRUE if roll is ok FUNC BOOL IS_CAR_ROLL_ACCEPTABLE(VEHICLE_INDEX vehicleIndex) IF IS_VEHICLE_DRIVEABLE(vehicleIndex) //IF (GET_ENTITY_ROLL(vehicleIndex) < 45.0) //AND (GET_ENTITY_ROLL(vehicleIndex) > -45.0) IF IS_ENTITY_UPRIGHT(vehicleIndex) RETURN(TRUE) ENDIF ENDIF RETURN(FALSE) ENDFUNC PROC STOP_PLAYER_RAGDOLLING() IF IS_PLAYER_PLAYING(PLAYER_ID()) IF NOT (IS_PED_RAGDOLL(PLAYER_PED_ID())) EXIT ENDIF SET_PED_CAN_RAGDOLL (PLAYER_PED_ID(), TRUE ) //CREATE_NM_MESSAGE(NM_START_STOP , NM_BALANCE_MSG) //SEND_NM_MESSAGE(PLAYER_PED_ID()) SET_PED_TO_ANIMATED(PLAYER_PED_ID(), FALSE) ENDIF ENDPROC FUNC BOOL HAS_PLAYER_CANCELLED_GETTING_IN_TAXI() VECTOR vec IF IS_CONTROL_PRESSED(FRONTEND_CONTROL, INPUT_ENTER) RETURN(FALSE) ENDIF // get camera heading in world FLOAT fCamHeading VECTOR vGameCamVec vec = GET_GAMEPLAY_CAM_ROT() fCamHeading = vec.z vGameCamVec = <<0.0, 1.0, 0.0>> ROTATE_VECTOR(vGameCamVec, <<0.0, 0.0, fCamHeading>>) // get stick vec INT LSx, LSy, RSx, RSy VECTOR vStickVec GET_CONTROL_VALUE_OF_ANALOGUE_STICKS(LSx, LSy, RSx, RSy) vec.x = LSx / 128.0 vec.y = LSy / -128.0 vec.z = 0.0 // check the stick is moving IF (VMAG(vec) < 0.5) RETURN(FALSE) ENDIF vStickVec = <<0.0, 1.0, 0.0>> ROTATE_VECTOR(vStickVec, <<0.0, 0.0, fCamHeading>>) ROTATE_VECTOR(vStickVec, <<0.0, 0.0, GET_HEADING_FROM_VECTOR_2D(vec.x, vec.y)>>) // get player heading vec VECTOR vPlayerVec FLOAT fPlayerHeading IF IS_PLAYER_PLAYING(PLAYER_ID()) fPlayerHeading = GET_ENTITY_HEADING(PLAYER_PED_ID()) vPlayerVec = <<0.0, 1.0, 0.0>> ROTATE_VECTOR(vPlayerVec, <<0.0, 0.0, fPlayerHeading>>) ENDIF // // draw player and stick vec // VECTOR pos, pos2 // IF IS_PLAYER_PLAYING(PLAYER_ID()) // // player vec // GET_ENTITY_COORDS(PLAYER_PED_ID(), pos.x, pos.y, pos.z) // pos2 = pos + vPlayerVec // LINE(pos.x, pos.y, pos.z, pos2.x, pos2.y, pos2.z) // // stick vec // pos2 = pos + vStickVec // LINE(pos.x, pos.y, pos.z, pos2.x, pos2.y, pos2.z) // ENDIF // check the angle between stick and player heading IF (GET_ANGLE_BETWEEN_2D_VECTORS(vPlayerVec.x, vPlayerVec.y, vStickVec.x, vStickVec.y) > 60.0) RETURN(TRUE) ENDIF RETURN(FALSE) ENDFUNC /// PURPOSE: /// updates the player's allowed to ride in taxi's status /// Scripts can set the status to false so this safe guards against the scripts not resetting the status back when they terminate PROC UPDATE_PLAYER_ALLOWED_TO_RIDE_IN_TAXIS_STATUS() // taxi script appears to track hailing disabled using bool (g_bTaxiHailingIsDisabled) and a stored script name (g_sTaxiHailingDisabledByThisScript) IF NOT IS_PLAYER_ALLOWED_TO_RIDE_IN_TAXIS() IF ARE_STRINGS_EQUAL("NULL", g_sTaxiHailingDisabledByThisScript) DISABLE_TAXI_HAILING(FALSE) ELSE IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(GET_HASH_KEY(g_sTaxiHailingDisabledByThisScript)) = 0 DISABLE_TAXI_HAILING(FALSE) ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// checks to decide if it's safe for the player be given the enter vehicle task /// NOTE: safe checks will have already been performed at this stage /// RETURNS: /// TRUE if ok to apply task FUNC BOOL IS_PLAYER_OK_TO_USE_ENTER_VEHICLE_TASK(VEHICLE_INDEX &vehicleIndex) // can't apply task when player doesn't have controls IF NOT IS_PLAYER_PLAYING(PLAYER_ID()) RETURN FALSE ENDIF // only process enter controls when player gets close IF NOT IS_ENTITY_AT_ENTITY(PLAYER_PED_ID(), vehicleIndex, <<5.0, 5.0, 2.0>>, FALSE) RETURN FALSE ENDIF // make sure the player doesn't try to enter a speeding vehicle IF GET_ENTITY_SPEED(vehicleIndex) > 0.5 RETURN FALSE ENDIF // interior check - don't give enter task if player isn't in same room //IF GET_ROOM_KEY_FROM_ENTITY(vehicleIndex) != GET_ROOM_KEY_FROM_ENTITY(PLAYER_PED_ID()) IF GET_INTERIOR_FROM_ENTITY(vehicleIndex) != GET_INTERIOR_FROM_ENTITY(PLAYER_PED_ID()) RETURN FALSE ENDIF // taxi not suitable for player to enter IF NOT IS_CAR_ROLL_ACCEPTABLE(vehicleIndex) RETURN FALSE ENDIF RETURN TRUE ENDFUNC /// PURPOSE: /// Get handles to the closest taxi for PROCESS_PLAYER_ENTER_CLOSEST_TAXI /// and also the most desireable to hail for PROCESS_PLAYER_HAILING_TAXI /// using GET_PED_NEARBY_VEHICLES FUNC BOOL ALT_UPDATE_TAXI_SEARCH_HANDLES() // only search for taxis if the player isn't currently getting into one IF eEnterTaxiState = TL_ENTER_TAXI_STATE_IDLE IF HAS_TIME_PASSED(iTimer_DelayTaxiSearch, 500) INT iMaxDesiredTaxiHandles INT iHailTargetIndex = -1 INT iClosestTaxiIndex = -1 INT iCount INT i INT iNumTaxisFound = 0 FLOAT fTaxiScore FLOAT fTaxiHighScore = -99999 FLOAT fMinRange VECTOR vTaxiCoords FLOAT fDistance VECTOR vPlayerForward VECTOR vDiff // only update the hail taxi target if we are waiting for the player to hail IF (eHailTaxiState != TL_HAIL_TAXI_STATE_IDLE AND eHailTaxiState != TL_HAIL_TAXI_STATE_DETECT_HAIL) bUpdateHailTargetThisFrame = FALSE ENDIF // and when the update timer has passed IF bUpdateHailTargetThisFrame iMaxDesiredTaxiHandles = 3 // grab three closest taxis fMinRange = TAXI_HAIL_DISTANCE // only worry about vehicles with in the hail distance ELSE // if we aren't searching for hail targets this frame only need a small number of close vehicle iMaxDesiredTaxiHandles = 1 // only grab the one closest taxi fMinRange = 10.0 // only worry about vehicles with 10m ENDIF VEHICLE_INDEX vehIndexArray[12] // this function returns vehicles in order of closeness iCount = GET_PED_NEARBY_VEHICLES(PLAYER_PED_ID(), vehIndexArray) IF iCount > 0 FOR i = 0 TO (iCount - 1) IF iNumTaxisFound < iMaxDesiredTaxiHandles // if the entity doesn't exist (drop out the loop since all other entities shouldn't exist either IF DOES_ENTITY_EXIST(vehIndexArray[i]) // check the vehicle is a taxi IF (GET_ENTITY_MODEL(vehIndexArray[i]) = mnTaxiModel) // dist check first (break out loop if veh isn't in range since the array in filled closest first) vTaxiCoords = GET_ENTITY_COORDS(vehIndexArray[i], FALSE) fDistance = VDIST2(vPlayerPos, vTaxiCoords) IF fDistance <= (fMinRange * fMinRange) // check the taxi and it's driver is suitable IF IS_PLAYER_OK_TO_ENTER_VEHICLE_AS_PASSENGER(vehIndexArray[i], mnTaxiModel, mnTaxiDriverModel) // Store the closest Taxi IF iClosestTaxiIndex = -1 iClosestTaxiIndex = i //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ALT_UPDATE_TAXI_SEARCH_HANDLES : Closest taxi set this frame : ", GET_FRAME_COUNT(), " array index = ", i) ENDIF #ENDIF ENDIF // only care about the rest of the checks if searching for a taxi to hail IF bUpdateHailTargetThisFrame // don't hail the waiting taxi (potential move this check to hail so he never hails when one is pulled up waiting? IF (vehIndexArray[i] != g_WaitingTaxi) // not allowed to hail taxis with light off //IF NOT DOES_TAXI_HAVE_LIGHT_ON(vehicleIndex) // don't consider if not in same interior IF GET_INTERIOR_FROM_ENTITY(vehIndexArray[i]) = GET_INTERIOR_FROM_ENTITY(PLAYER_PED_ID()) // Update hail score fTaxiScore = 1.0 // score the distance fDistance /= fDistance fDistance -= TAXI_HAIL_DISTANCE fDistance *= -1.0 fDistance /= TAXI_HAIL_DISTANCE fDistance *= 0.5 // min score is 0.5 fDistance += 0.5 // multiple score by distance score fTaxiScore *= fDistance fDistance = vPlayerPos.z - vTaxiCoords.z IF fDistance < 0.0 fDistance *= -1.0 ENDIF // don't hail taxi if the Z diff is too high IF fDistance < 4.0 // if taxi isn't inside 120 2D arc of player don't consider it (using Sam's IS_ENTITY_IN_ARC_2D) vPlayerForward = GET_ENTITY_FORWARD_VECTOR(PLAYER_PED_ID()) vDiff = vTaxiCoords - vPlayerPos IF (((vPlayerForward.x*vDiff.x)+(vPlayerForward.y*vDiff.y)) / VDIST(vDiff, <<0,0,0>>)) > COS(120) // reduce score if taxi is off screen IF IS_SPHERE_VISIBLE(vTaxiCoords, 2) fTaxiScore *= 0.5 ENDIF // reduce score if taxi is occupied, so unoccupied taxis have priority IF DOES_TAXI_ALREADY_HAVE_A_FARE(vehIndexArray[i]) fTaxiScore *= 0.2 ENDIF // disregard if unside down or in water IF NOT IS_ENTITY_UPRIGHT(vehIndexArray[i]) OR IS_ENTITY_IN_WATER(vehIndexArray[i]) fTaxiScore = 0 ENDIF // set the highscore and store the index for the hail target IF fTaxiScore > fTaxiHighScore fTaxiHighScore = fTaxiScore iHailTargetIndex = i #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ALT_UPDATE_TAXI_SEARCH_HANDLES : Updated iHailTargetIndex = ", i, " score = ", fTaxiHighScore) ENDIF #ENDIF ENDIF ELSE //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ALT_UPDATE_TAXI_SEARCH_HANDLES : taxi ", i, " rejected wasn't infront of player ") ENDIF #ENDIF ENDIF ELSE //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ALT_UPDATE_TAXI_SEARCH_HANDLES : taxi ", i, " rejected Z diff to high = ", fDistance) ENDIF #ENDIF ENDIF ELSE //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ALT_UPDATE_TAXI_SEARCH_HANDLES : taxi ", i, " rejected interior check ") ENDIF #ENDIF ENDIF //ENDIF ELSE //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ALT_UPDATE_TAXI_SEARCH_HANDLES : taxi ", i, " rejected taxi is g_WaitingTaxi ") ENDIF #ENDIF ENDIF ENDIF //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ALT_UPDATE_TAXI_SEARCH_HANDLES : i = ", i, " grabbed handle to taxi") ENDIF #ENDIF iNumTaxisFound++ ELSE //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ALT_UPDATE_TAXI_SEARCH_HANDLES : taxi ", i, " rejected not suitable") ENDIF #ENDIF ENDIF ELSE //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ALT_UPDATE_TAXI_SEARCH_HANDLES : i = ", i, " looped ended as detected veh dist out of range = ", fDistance) ENDIF #ENDIF i = iCount ENDIF ENDIF ELSE //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ALT_UPDATE_TAXI_SEARCH_HANDLES : i = ", i, " looped ended as detected veh didn't exist ") ENDIF #ENDIF i = iCount ENDIF ELSE //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ALT_UPDATE_TAXI_SEARCH_HANDLES : i = ", i, " looped ended as iNumTaxisFound = ", iNumTaxisFound) ENDIF #ENDIF i = iCount ENDIF ENDFOR ENDIF // Store the closest Taxi IF iClosestTaxiIndex = -1 // ensure the previous taxi's driver's flag is reset to normal behaviour SET_TAXI_DRIVER_ENTER_AS_PASSENGER_FLAG(vehClosestTaxi, FALSE) vehClosestTaxi = NULL // reset timer for delaying search for hailable taxis //iTimer_DelayTaxiSearch = GET_GAME_TIMER() ELSE //iTimer_DelayTaxiSearch = 0 // ensure the taxi search goes through every frame when a taxi is in range // update the handle if it's changed IF vehClosestTaxi != vehIndexArray[iClosestTaxiIndex] // ensure the previous taxi's driver's flag is reset to normal behaviour SET_TAXI_DRIVER_ENTER_AS_PASSENGER_FLAG(vehClosestTaxi, FALSE) vehClosestTaxi = vehIndexArray[iClosestTaxiIndex] // Set the new closest driver's flag so the player can enter as passenger SET_TAXI_DRIVER_ENTER_AS_PASSENGER_FLAG(vehClosestTaxi, TRUE) #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ALT_UPDATE_TAXI_SEARCH_HANDLES : Closest taxi updated this frame : ", GET_FRAME_COUNT(), " array index = ", iClosestTaxiIndex) ENDIF #ENDIF ENDIF #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ALT_UPDATE_TAXI_SEARCH_HANDLES : Closest taxi set this frame : ", GET_FRAME_COUNT(), " array index = ", iClosestTaxiIndex) ENDIF #ENDIF ENDIF // update whether or not we want to search for hail targets next opportunity IF bUpdateHailTargetThisFrame // Store the hail Taxi IF iHailTargetIndex = -1 vehHailTarget = NULL ELSE vehHailTarget = vehIndexArray[iHailTargetIndex] #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ALT_UPDATE_TAXI_SEARCH_HANDLES : Hail target taxi set this frame : ", GET_FRAME_COUNT(), " array index = ", iHailTargetIndex) ENDIF #ENDIF ENDIF bUpdateHailTargetThisFrame = FALSE // don't recheck next frame ELSE bUpdateHailTargetThisFrame = TRUE // recheck next frame ENDIF // reset timer for delaying search for taxis iTimer_DelayTaxiSearch = GET_GAME_TIMER() //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ALT_UPDATE_TAXI_SEARCH_HANDLES : handles update this frame : ", GET_FRAME_COUNT()) ENDIF #ENDIF RETURN TRUE ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Get handles to the closest taxi for PROCESS_PLAYER_ENTER_CLOSEST_TAXI /// and also the most desireable to hail for PROCESS_PLAYER_HAILING_TAXI /// using GET_RANDOM_VEHICLE_IN_SPHERE PROC UPDATE_TAXI_SEARCH_HANDLES() // only search for taxis if the player is currently getting into one IF eEnterTaxiState = TL_ENTER_TAXI_STATE_IDLE IF HAS_TIME_PASSED(iTimer_DelayTaxiSearch, 750) INT iHailTargetIndex = -1 INT iClosestTaxiIndex = -1 INT iCount INT i FLOAT fTaxiScore FLOAT fTaxiHighScore = -99999 FLOAT fMinRange = TAXI_HAIL_DISTANCE // only worry about vehicles with in the hail distance VECTOR vTaxiCoords FLOAT fDistance VECTOR vPlayerForward VECTOR vDiff FLOAT fClosestTaxiDist = 9999999.0 iCount = 3 VEHICLE_INDEX vehIndexArray[3] vehIndexArray[0] = GET_RANDOM_VEHICLE_IN_SPHERE(vPlayerPos, TAXI_HAIL_DISTANCE * 0.33, mnTaxiModel, VEHICLE_SEARCH_FLAG_RETURN_RANDOM_VEHICLES | VEHICLE_SEARCH_FLAG_CHECK_VEHICLE_OCCUPANTS_STATES | VEHICLE_SEARCH_FLAG_RETURN_MISSION_VEHICLES | VEHICLE_SEARCH_FLAG_ALLOW_VEHICLE_OCCUPANTS_TO_BE_PERFORMING_A_SCRIPTED_TASK) vehIndexArray[1] = GET_RANDOM_VEHICLE_IN_SPHERE(vPlayerPos, TAXI_HAIL_DISTANCE * 0.66, mnTaxiModel, VEHICLE_SEARCH_FLAG_RETURN_RANDOM_VEHICLES | VEHICLE_SEARCH_FLAG_CHECK_VEHICLE_OCCUPANTS_STATES | VEHICLE_SEARCH_FLAG_RETURN_MISSION_VEHICLES | VEHICLE_SEARCH_FLAG_ALLOW_VEHICLE_OCCUPANTS_TO_BE_PERFORMING_A_SCRIPTED_TASK) vehIndexArray[2] = GET_RANDOM_VEHICLE_IN_SPHERE(vPlayerPos, TAXI_HAIL_DISTANCE * 1.00, mnTaxiModel, VEHICLE_SEARCH_FLAG_RETURN_RANDOM_VEHICLES | VEHICLE_SEARCH_FLAG_CHECK_VEHICLE_OCCUPANTS_STATES | VEHICLE_SEARCH_FLAG_RETURN_MISSION_VEHICLES | VEHICLE_SEARCH_FLAG_ALLOW_VEHICLE_OCCUPANTS_TO_BE_PERFORMING_A_SCRIPTED_TASK) FOR i = 0 TO (iCount - 1) // check the taxi and it's driver is suitable IF IS_PLAYER_OK_TO_ENTER_VEHICLE_AS_PASSENGER(vehIndexArray[i], mnTaxiModel, mnTaxiDriverModel) vTaxiCoords = GET_ENTITY_COORDS(vehIndexArray[i], FALSE) fDistance = VDIST2(vPlayerPos, vTaxiCoords) // only worry about taxis close enough to hail IF fDistance <= (fMinRange * fMinRange) // update the closest taxi index IF fDistance < fClosestTaxiDist fClosestTaxiDist = fDistance iClosestTaxiIndex = i //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : UPDATE_TAXI_SEARCH_HANDLES : Closest taxi updated dist = ", fClosestTaxiDist, " array index = ", i) ENDIF #ENDIF ENDIF // don't hail the waiting taxi (potential move this check to hail so he never hails when one is pulled up waiting? IF (vehIndexArray[i] != g_WaitingTaxi) // not allowed to hail taxis with light off //IF NOT DOES_TAXI_HAVE_LIGHT_ON(vehicleIndex[i]) // don't consider if not in same interior IF GET_INTERIOR_FROM_ENTITY(vehIndexArray[i]) = GET_INTERIOR_FROM_ENTITY(PLAYER_PED_ID()) // Update hail score fTaxiScore = 1.0 // score the distance fDistance /= fDistance fDistance -= TAXI_HAIL_DISTANCE fDistance *= -1.0 fDistance /= TAXI_HAIL_DISTANCE fDistance *= 0.5 // min score is 0.5 fDistance += 0.5 // multiple score by distance score fTaxiScore *= fDistance // don't hail taxi if the Z diff is too different fDistance = vPlayerPos.z - vTaxiCoords.z IF fDistance < 0.0 fDistance *= -1.0 ENDIF IF fDistance < 4.0 // if taxi isn't inside 120 2D arc of player don't consider it (using Sam's IS_ENTITY_IN_ARC_2D) vPlayerForward = GET_ENTITY_FORWARD_VECTOR(PLAYER_PED_ID()) vDiff = vTaxiCoords - vPlayerPos IF (((vPlayerForward.x*vDiff.x)+(vPlayerForward.y*vDiff.y)) / VDIST(vDiff, <<0,0,0>>)) > COS(120) // reduce score if taxi is off screen IF IS_SPHERE_VISIBLE(vTaxiCoords, 2) fTaxiScore *= 0.5 ENDIF // reduce score if taxi is occupied, so unoccupied taxis have priority IF DOES_TAXI_ALREADY_HAVE_A_FARE(vehIndexArray[i]) fTaxiScore *= 0.2 ENDIF // set the highscore and store the index for the hail target IF fTaxiScore > fTaxiHighScore fTaxiHighScore = fTaxiScore iHailTargetIndex = i //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : UPDATE_TAXI_SEARCH_HANDLES : Updated iHailTargetIndex = ", i, " score = ", fTaxiHighScore) ENDIF #ENDIF ENDIF ELSE //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : UPDATE_TAXI_SEARCH_HANDLES : taxi ", i, " rejected wasn't infront of player ") ENDIF #ENDIF ENDIF ELSE //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : UPDATE_TAXI_SEARCH_HANDLES : taxi ", i, " rejected Z diff to high = ", fDistance) ENDIF #ENDIF ENDIF ELSE //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : UPDATE_TAXI_SEARCH_HANDLES : taxi ", i, " rejected interior check ") ENDIF #ENDIF ENDIF //ENDIF ELSE //#IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : UPDATE_TAXI_SEARCH_HANDLES : taxi ", i, " rejected taxi is g_WaitingTaxi ") ENDIF #ENDIF ENDIF ENDIF ENDIF ENDFOR // Store the closest Taxi IF iClosestTaxiIndex = -1 vehClosestTaxi = NULL ELSE // discard the taxi if its not going to be close enough to enter IF fClosestTaxiDist < (10.0 * 10.0) vehClosestTaxi = vehIndexArray[iClosestTaxiIndex] #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : UPDATE_TAXI_SEARCH_HANDLES : Closest taxi set this frame : ", GET_FRAME_COUNT(), " array index = ", iClosestTaxiIndex) ENDIF #ENDIF ELSE vehClosestTaxi = NULL ENDIF ENDIF iTimer_DelayTaxiSearch = GET_GAME_TIMER() // only update the hail target when one isn't waiting IF (eHailTaxiState = TL_HAIL_TAXI_STATE_IDLE OR eHailTaxiState = TL_HAIL_TAXI_STATE_DETECT_HAIL) IF iHailTargetIndex = -1 vehHailTarget = NULL ELSE vehHailTarget = vehIndexArray[iHailTargetIndex] #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : UPDATE_TAXI_SEARCH_HANDLES : Hail target taxi set this frame : ", GET_FRAME_COUNT(), " array index = ", iHailTargetIndex) ENDIF #ENDIF ENDIF ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// check if the waiting taxi should cleanup /// RETURNS: /// TRUE if reason to cleanup found FUNC BOOL SHOULD_WAITING_TAXI_CLEANUP() // Check for hailed taxi timing out IF eHailTaxiState = TL_HAIL_TAXI_STATE_TAXI_WAITING IF g_iTaxiHailedTime = -1 OR g_iTaxiHailedTime = 0 g_iTaxiHailedTime = GET_GAME_TIMER() ELSE IF HAS_TIME_PASSED(g_iTaxiHailedTime, 30000) IF eEnterTaxiState = TL_ENTER_TAXI_STATE_IDLE OR eEnterTaxiState = TL_ENTER_TAXI_STATE_WAIT_FOR_PLAYER_TO_EXIT IF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), g_WaitingTaxi, TRUE) // Bug fix - extra check to make sure player isn't in the process of getting in the taxi CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), ": SHOULD_WAITING_TAXI_CLEANUP : return TRUE : hail timer expired : timer = ", g_iTaxiHailedTime) RETURN TRUE ENDIF ENDIF ENDIF ENDIF ENDIF // taxi checks IF IS_VEHICLE_OK(g_WaitingTaxi) VECTOR vTaxiCoords = GET_ENTITY_COORDS(g_WaitingTaxi, FALSE) // Check for player abandoning taxi IF eHailTaxiState = TL_HAIL_TAXI_STATE_TAXI_WAITING IF NOT TAXI_IS_COORD_IN_RANGE_OF_COORD(vPlayerPos, vTaxiCoords, 75.0) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_WAITING_TAXI_CLEANUP : return TRUE : player abandoned taxi") RETURN TRUE ENDIF ENDIF // player attacked taxi IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(g_WaitingTaxi, PLAYER_PED_ID()) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_WAITING_TAXI_CLEANUP : return TRUE : damaged taxi check") RETURN TRUE ENDIF // bullet fired near taxi IF IS_BULLET_IN_AREA(vTaxiCoords, 7.0, FALSE) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_WAITING_TAXI_CLEANUP : return TRUE : bullet fired near taxi") RETURN TRUE ENDIF FLOAT fProjectileRadiusCheck = 15.0 VECTOR vMin, vMax // is one of the player's projectiles nearby? vMin = vTaxiCoords vMax = vMin vMin.x= vMin.x - fProjectileRadiusCheck vMin.y = vMin.y -fProjectileRadiusCheck vMin.z = vMin.z - fProjectileRadiusCheck vMax.x = vMax.x + fProjectileRadiusCheck vMax.y = vMax.y + fProjectileRadiusCheck vMax.z = vMax.z + fProjectileRadiusCheck IF IS_PROJECTILE_IN_AREA(vMin, vMax, TRUE) CPRINTLN(DEBUG_TAXI_SERVICE, " : SHOULD_WAITING_TAXI_CLEANUP : return TRUE : projectile near taxi") RETURN TRUE ENDIF IF TAXI_IS_COORD_IN_RANGE_OF_COORD(vPlayerPos, vTaxiCoords, 20.0) // aiming at the taxi IF IS_PLAYER_FREE_AIMING_AT_ENTITY(PLAYER_ID(), g_WaitingTaxi) OR IS_PLAYER_TARGETTING_ENTITY(PLAYER_ID(), g_WaitingTaxi) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_WAITING_TAXI_CLEANUP : return TRUE : aiming at the taxi") RETURN TRUE ENDIF // check for player shooting near waiting taxi IF IS_PED_SHOOTING(PLAYER_PED_ID()) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_WAITING_TAXI_CLEANUP : return TRUE : player shooting check") RETURN TRUE ENDIF ENDIF ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_TAXI_SERVICE_END_EARLY : return TRUE : taxi ok check") RETURN TRUE ENDIF // check the driver is ok IF IS_PED_UNINJURED(g_WaitingTaxiDriver) IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(g_WaitingTaxiDriver, PLAYER_PED_ID()) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_WAITING_TAXI_CLEANUP : return TRUE : damaged taxi driver check") RETURN TRUE ENDIF ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_WAITING_TAXI_CLEANUP : return TRUE : taxi driver ok check") RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// handles the player hailing nearby taxi PROC HAIL_STATE_DETECT_HAIL() PLAY_FUCK_YOU_DIALOGUE() CLEAR_HINT_CAM_IF_PLAYER_IS_MOVING() // don't process taxi hailing if a taxi wasn't found to hail IF DOES_ENTITY_EXIST(vehHailTarget) // contains safe checks on taxi and it's driver IF IS_PLAYER_OK_TO_ENTER_VEHICLE_AS_PASSENGER(vehHailTarget, mnTaxiModel, mnTaxiDriverModel) IF IS_PLAYER_ALLOWED_TO_HAIL_A_TAXI() REQUEST_ANIM_DICT(tlTaxiAnimDict) IF HAS_ANIM_DICT_LOADED(tlTaxiAnimDict) IF NOT IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "HAIL_TAXI") AND NOT IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "FP_HAIL_TAXI") AND NOT IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "FUCK_U") AND NOT IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "FORGET_IT") IF NOT DOES_TAXI_ALREADY_HAVE_A_FARE(vehHailTarget) IF NOT IS_TAXI_LIGHT_ON(vehHailTarget) SET_TAXI_LIGHTS(vehHailTarget, TRUE) ENDIF ENDIF IF iTaxiHailIntention = NEW_CONTEXT_INTENTION REGISTER_CONTEXT_INTENTION(iTaxiHailIntention, CP_TAXI_PRIORITY, "TXM_H01", TRUE) // Press ~INPUT_CONTEXT~ to hail a Taxi. #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " PROCESS_PLAYER_HAILING_TAXI() : REGISTER_CONTEXT_INTENTION - TX_H01") ENDIF #ENDIF ENDIF // Wait to detect player input for taxi hail IF HAS_CONTEXT_BUTTON_TRIGGERED(iTaxiHailIntention) IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("TXM_H01") // Press ~INPUT_CONTEXT~ to hail a Taxi. CLEAR_HELP() ENDIF // B*1991223 - RESET need to block ambient anims during hail anims IF bBlockingPlayerAmbientIdles = FALSE SET_PED_CAN_PLAY_AMBIENT_ANIMS(PLAYER_PED_ID(), FALSE) bBlockingPlayerAmbientIdles = TRUE ENDIF // task the player TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), vehHailTarget, 5000) PLAY_HAIL_ANIMS_AND_DIALOGUE() // B*2074743 - block aiming during hail animation DISABLE_PLAYER_WEAPON_CONTROLS_FOR_HAIL_THIS_FRAME() iTimer_HailAnimTriggered = GET_GAME_TIMER() RELEASE_CONTEXT_INTENTION(iTaxiHailIntention) // Failed attempt if taxi already has passengers IF DOES_TAXI_ALREADY_HAVE_A_FARE(vehHailTarget) IF IS_VEHICLE_DRIVEABLE(vehHailTarget) SET_TAXI_LIGHTS(vehHailTarget, FALSE) ENDIF bHintTriggeredByTaxiLauncher = FALSE eHailTaxiState = TL_HAIL_TAXI_STATE_FAILED_ATTEMPT #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " PROCESS_PLAYER_HAILING_TAXI() : eHailTaxiState = TL_HAIL_TAXI_STATE_FAILED_ATTEMPT") ENDIF #ENDIF ELSE // Successful attempt to hail a taxi //update handles g_WaitingTaxi = vehicleIndex, g_WaitingTaxiDriver = pedIndex PED_INDEX pedIndex pedIndex = GET_PED_IN_VEHICLE_SEAT(vehHailTarget) IF STORE_CAR_AS_TAXI_WAITING_FOR_PLAYER(vehHailTarget, pedIndex) //release handle vehHailTarget = NULL TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), g_WaitingTaxi, 5000) g_iTaxiHailedTime = GET_GAME_TIMER() IF IS_VEHICLE_DRIVEABLE(g_WaitingTaxi) IF NOT IS_GAMEPLAY_HINT_ACTIVE() SET_GAMEPLAY_VEHICLE_HINT(g_WaitingTaxi, <<0,0,0>>, TRUE, 4000) bHintTriggeredByTaxiLauncher = TRUE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " PROCESS_PLAYER_HAILING_TAXI() : TRIGGER hint cam for taxi hail") ENDIF ENDIF g_savedGlobals.sAmbient.bTaxiHailingHelpDisplayed = TRUE eHailTaxiState = TL_HAIL_TAXI_STATE_SUCCESSFUL_ATTEMPT #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " PROCESS_PLAYER_HAILING_TAXI() : eHailTaxiState = TL_HAIL_TAXI_STATE_SUCCESSFUL_ATTEMPT") ENDIF #ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ELSE CLEANUP_HAIL_TAXI() ENDIF ELSE CLEANUP_HAIL_TAXI() ENDIF ENDPROC /// PURPOSE: /// handle taxi driver gesturing to player to get in PROC HAIL_TAXI_STATE_SUCCESSFUL_ATTEMPT() // contains safe checks on taxi and it's driver IF IS_TAXI_AND_DRIVER_OK_FOR_PLAYER_TO_ENTER_AS_PASSENGER(g_WaitingTaxi, g_WaitingTaxiDriver, mnTaxiModel, mnTaxiDriverModel) BOOL bFlag = FALSE IF IS_CONTROL_PRESSED(FRONTEND_CONTROL, INPUT_ENTER) bFlag = TRUE ENDIF IF HAS_TIME_PASSED(iTimer_HailAnimTriggered, 1000) IF (GET_SCRIPT_TASK_STATUS(PLAYER_PED_ID(), SCRIPT_TASK_PLAY_ANIM) = FINISHED_TASK) IF NOT IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "HAIL_TAXI") AND NOT IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "FP_HAIL_TAXI") AND NOT IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "FUCK_U") AND NOT IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "FORGET_IT") IF (GET_SCRIPT_TASK_STATUS(PLAYER_PED_ID(), SCRIPT_TASK_PERFORM_SEQUENCE) = FINISHED_TASK) SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_KeepWeaponHolsteredUnlessFired, FALSE) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " HAIL_TAXI_STATE_SUCCESSFUL_ATTEMPT: PCF_KeepWeaponHolsteredUnlessFired, FALSE") // B*1991223 - RESET need to block ambient anims during hail anims IF bBlockingPlayerAmbientIdles = TRUE SET_PED_CAN_PLAY_AMBIENT_ANIMS(PLAYER_PED_ID(), TRUE) bBlockingPlayerAmbientIdles = FALSE ENDIF bFlag = TRUE ENDIF ENDIF ENDIF ENDIF IF (bFlag) REQUEST_ANIM_DICT(tlTaxiAnimDict) IF HAS_ANIM_DICT_LOADED(tlTaxiAnimDict) // chance shouting for taxi IF GET_RANDOM_INT_IN_RANGE(0, 10) < 8 IF NOT IS_ANY_DIALOGUE_PLAYING(NULL, FALSE) BOOL bPauseAmbientSpeech = IS_AMBIENT_SPEECH_DISABLED(PLAYER_PED_ID()) IF bPauseAmbientSpeech STOP_PED_SPEAKING(PLAYER_PED_ID(), FALSE) ENDIF PLAY_PED_AMBIENT_SPEECH(PLAYER_PED_ID(), "TAXI_HAIL", SPEECH_PARAMS_SHOUTED) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " HAIL_TAXI_STATE_SUCCESSFUL_ATTEMPT() : trigger TAXI_HAIL dialogue : bPauseAmbientSpeech = ", bPauseAmbientSpeech) IF bPauseAmbientSpeech STOP_PED_SPEAKING(PLAYER_PED_ID(), TRUE) ENDIF ENDIF ENDIF SEQUENCE_INDEX seq OPEN_SEQUENCE_TASK(seq) TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), 5000, SLF_WHILE_NOT_IN_FOV) IF IS_PLAYER_TO_RIGHT_OF_CAR(g_WaitingTaxi) TASK_PLAY_ANIM(NULL, tlTaxiAnimDict, "Aknowledge_R", NORMAL_BLEND_IN, SLOW_BLEND_OUT, -1, AF_SECONDARY|AF_UPPERBODY|AF_ABORT_ON_WEAPON_DAMAGE|AF_EXIT_AFTER_INTERRUPTED) ELSE TASK_PLAY_ANIM(NULL, tlTaxiAnimDict, "Aknowledge_L", NORMAL_BLEND_IN, SLOW_BLEND_OUT, -1, AF_SECONDARY|AF_UPPERBODY|AF_ABORT_ON_WEAPON_DAMAGE|AF_EXIT_AFTER_INTERRUPTED) ENDIF TASK_VEHICLE_MISSION(NULL, g_WaitingTaxi, g_WaitingTaxi, MISSION_PULL_OVER, 12.0, DRIVINGMODE_STOPFORCARS_STRICT, 3, 3) TASK_VEHICLE_MISSION(NULL, g_WaitingTaxi, g_WaitingTaxi, MISSION_STOP, 12.0, DRIVINGMODE_STOPFORCARS_STRICT, 3, 3) CLOSE_SEQUENCE_TASK(seq) TASK_PERFORM_SEQUENCE(g_WaitingTaxiDriver, seq) CLEAR_SEQUENCE_TASK(seq) //INCREMENT_INT_STAT_NO_MESSAGE(STAT_NUMBER_TAXIS_HAILED, 1) CREATE_WAITING_TAXI_BLIP() eHailTaxiState = TL_HAIL_TAXI_STATE_TAXI_WAITING #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " HAIL_TAXI_STATE_SUCCESSFUL_ATTEMPT() : eHailTaxiState = TL_HAIL_TAXI_STATE_TAXI_WAITING") ENDIF #ENDIF ENDIF ENDIF ELSE CLEANUP_HAIL_TAXI() ENDIF ENDPROC /// PURPOSE: /// player aknowledges failed attempt PROC HAIL_TAXI_STATE_FAILED_ATTEMPT() // wait for the hail anims to end IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "HAIL_TAXI") OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "FP_HAIL_TAXI") EXIT ELIF HAS_TIME_PASSED(iTimer_HailAnimTriggered, 3000) REQUEST_ANIM_DICT(tlTaxiAnimDict) IF HAS_ANIM_DICT_LOADED(tlTaxiAnimDict) // contains checks to make anim can play safely IF IS_PLAYER_ALLOWED_TO_HAIL_A_TAXI() CLEAR_PED_TASKS(PLAYER_PED_ID()) SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_KeepWeaponHolsteredUnlessFired, TRUE) IF (GET_RANDOM_INT_IN_RANGE(0,3) < 2) TASK_PLAY_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "FORGET_IT", SLOW_BLEND_IN, REALLY_SLOW_BLEND_OUT, -1, AF_UPPERBODY|AF_SECONDARY) ELSE TASK_PLAY_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "FUCK_U", SLOW_BLEND_IN, REALLY_SLOW_BLEND_OUT, -1, AF_UPPERBODY|AF_SECONDARY) ENDIF ENDIF IF (GET_RANDOM_INT_IN_RANGE(0,5) = 1) IF NOT (g_playerIsDrunk) bPlayAdditionalFuckYouDialogue = TRUE //CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), "Played additional taxi fuck you dialogue ") ENDIF ENDIF iTimer_HailAnimTriggered = GET_GAME_TIMER() // reset for fuck you dialogue iTimer_HailFailedDialogueDelay = GET_GAME_TIMER() // dialogue delay // B*1991223 - RESET need to block ambient anims during hail anims IF bBlockingPlayerAmbientIdles = TRUE SET_PED_CAN_PLAY_AMBIENT_ANIMS(PLAYER_PED_ID(), TRUE) bBlockingPlayerAmbientIdles = FALSE ENDIF IF iTaxiHailIntention <> NEW_CONTEXT_INTENTION RELEASE_CONTEXT_INTENTION(iTaxiHailIntention) //SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_KeepWeaponHolsteredUnlessFired, FALSE) CPRINTLN(DEBUG_TAXI_SERVICE, "HAIL_TAXI_STATE_FAILED_ATTEMPT() - RELEASE_CONTEXT_INTENTION iTaxiHailIntention") ENDIF eHailTaxiState = TL_HAIL_TAXI_STATE_IDLE #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " HAIL_TAXI_STATE_FAILED_ATTEMPT() : eHailTaxiState = TL_HAIL_TAXI_STATE_IDLE") ENDIF #ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// handles taxi which is classed as waiting for the player PROC HAIL_TAXI_STATE_TAXI_WAITING() IF IS_TAXI_AND_DRIVER_OK_FOR_PLAYER_TO_ENTER_AS_PASSENGER(g_WaitingTaxi, g_WaitingTaxiDriver, mnTaxiModel, mnTaxiDriverModel) IF NOT SHOULD_WAITING_TAXI_CLEANUP() IF NOT TAXI_IS_PED_PERFORMING_TASK(g_WaitingTaxiDriver, SCRIPT_TASK_VEHICLE_TEMP_ACTION) TASK_VEHICLE_TEMP_ACTION(g_WaitingTaxiDriver, g_WaitingTaxi, TEMPACT_WAIT, 1000000) ENDIF // B*1536974 - Press to enter taxi as passenger hold to jack driver - opposite to how it worked on IV // to get IV behaviour you have to ensur this flag is false then task the player in script to enter as rear passenger when input detected SET_PED_CONFIG_FLAG(g_WaitingTaxiDriver, PCF_AICanDrivePlayerAsRearPassenger, TRUE) CLEAR_HINT_CAM_IF_PLAYER_IS_MOVING() // taxi blip flash updated (if exists) could get here from entering nearby taxi IF DOES_BLIP_EXIST(blipWaitingTaxi) SET_BLIP_FLASH_TIMER(blipWaitingTaxi, 10000) ENDIF ELSE CLEANUP_HAIL_TAXI() ENDIF ELSE CLEANUP_HAIL_TAXI() ENDIF ENDPROC /// PURPOSE: /// handles script task for the player getting in the taxi vehicleIndex /// Sets eEnterTaxiState = TL_ENTER_TAXI_STATE_ENTERING when attempt has been made /// NOTE: safe checks will have already been performed at this stage PROC DETECT_PLAYER_ATTEMPT_TO_ENTER_TAXI() IF IS_PLAYER_OK_TO_USE_ENTER_VEHICLE_TASK(vehClosestTaxi) //IF NOT IS_ENTITY_UPRIGHT(vehIndexArray[i]) //OR IS_ENTITY_IN_WATER(vehIndexArray[i]) // if it's the hailed taxi pull up help text IF NOT bHelpEnterTaxiDisplayed // only show help if this is a taxi we have called / hailed IF (vehClosestTaxi = g_WaitingTaxi) AND eHailTaxiState = TL_HAIL_TAXI_STATE_TAXI_WAITING IF NOT IS_HELP_MESSAGE_ON_SCREEN() IF NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("TX_H02") // Hold ~INPUT_ENTER~ to enter the cab as a passenger. IF g_savedGlobals.sAmbient.iTaxiEnterPromptDisplayed < 5 PRINT_HELP("TX_H02") //Hold ~INPUT_ENTER~ to enter the cab as a passenger. g_savedGlobals.sAmbient.iTaxiEnterPromptDisplayed++ ENDIF bHelpEnterTaxiDisplayed = TRUE ENDIF ENDIF ENDIF ENDIF VEHICLE_INDEX vehTemp = GET_VEHICLE_PED_IS_ENTERING(PLAYER_PED_ID()) // this will return active task so when he's also pathing to the vehicle // check for player getting into the taxi IF DOES_ENTITY_EXIST(vehTemp) IF (vehTemp = vehClosestTaxi) // grab handle to the taxi driver PED_INDEX pedIndex = GET_PED_IN_VEHICLE_SEAT(vehClosestTaxi) // all safe checks have already been performed in IS_PLAYER_OK_TO_ENTER_VEHICLE_AS_PASSENGER // if this taxi isn't the current waiting taxi cleanup the hailed state IF eHailTaxiState = TL_HAIL_TAXI_STATE_TAXI_WAITING OR eHailTaxiState = TL_HAIL_TAXI_STATE_SUCCESSFUL_ATTEMPT IF (vehClosestTaxi != g_WaitingTaxi) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : DETECT_PLAYER_ATTEMPT_TO_ENTER_TAXI reset eHailTaxiState for already inside a taxi which isn't g_WaitingTaxi") CLEANUP_HAIL_TAXI() ENDIF ENDIF DISABLE_SELECTOR_THIS_FRAME() // B*1559411 - block char switching whilst entering a taxi //update handles g_WaitingTaxi = vehicleIndex, g_WaitingTaxiDriver = pedIndex IF STORE_CAR_AS_TAXI_WAITING_FOR_PLAYER(vehClosestTaxi, pedIndex) //release handle - don't do this since we can kick back here from enter failed //vehClosestTaxi = NULL IF bHintTriggeredByTaxiLauncher // B* 1478914 - stop hint cam when player getting in IF IS_GAMEPLAY_HINT_ACTIVE() STOP_GAMEPLAY_HINT() ENDIF bHintTriggeredByTaxiLauncher = FALSE ENDIF // just doing this when player is in seat now //SET_PLAYER_GROUP_MEMBERS_INTO_TAXI(g_WaitingTaxi, ePlayerChosenSeat) // GET_GROUP_INTO_CAB(GET_NEAREST_PASSENGER_SIDE(g_WaitingTaxi)) IF NOT IS_PED_INJURED(g_WaitingTaxiDriver) AND IS_VEHICLE_DRIVEABLE(g_WaitingTaxi) IF IS_PED_SITTING_IN_VEHICLE(g_WaitingTaxiDriver, g_WaitingTaxi) IF NOT TAXI_IS_PED_PERFORMING_TASK(g_WaitingTaxiDriver, SCRIPT_TASK_VEHICLE_TEMP_ACTION) TASK_VEHICLE_TEMP_ACTION(g_WaitingTaxiDriver, g_WaitingTaxi, TEMPACT_WAIT, 10000) ENDIF ENDIF ENDIF bHelpEnterTaxiDisplayed = FALSE eEnterTaxiState = TL_ENTER_TAXI_STATE_ENTERING CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : DETECT_PLAYER_ATTEMPT_TO_ENTER_TAXI() : eEnterTaxiState = TL_ENTER_TAXI_STATE_ENTERING FC = ", GET_FRAME_COUNT()) ENDIF ENDIF ENDIF ELSE // should'nt require any cleanup at this point IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("TX_H02") // Hold ~INPUT_ENTER~ to enter the cab as a passenger. CLEAR_HELP() ENDIF ENDIF ENDPROC /// PURPOSE: /// updates the player's script task to get into the taxi vehicleIndex /// NOTE: safe checks will have already been performed at this stage PROC UPDATE_PLAYER_ENTER_TAXI_TASK() IF IS_PLAYER_OK_TO_USE_ENTER_VEHICLE_TASK(g_WaitingTaxi) // should only get tasked to enter g_waitingtaxi VEHICLE_INDEX vehTemp = GET_VEHICLE_PED_IS_ENTERING(PLAYER_PED_ID()) // this will return active task so when he's also pathing to the vehicle // check for player getting into the taxi IF DOES_ENTITY_EXIST(vehTemp) IF (vehTemp = vehClosestTaxi) DISABLE_SELECTOR_THIS_FRAME() // B*1559411 - block char switching whilst entering a taxi // make sure the driver waits until the player gets in IF NOT IS_PED_INJURED(g_WaitingTaxiDriver) AND IS_VEHICLE_DRIVEABLE(g_WaitingTaxi) IF IS_PED_SITTING_IN_VEHICLE(g_WaitingTaxiDriver, g_WaitingTaxi) IF NOT TAXI_IS_PED_PERFORMING_TASK(g_WaitingTaxiDriver, SCRIPT_TASK_VEHICLE_TEMP_ACTION) TASK_VEHICLE_TEMP_ACTION(g_WaitingTaxiDriver, g_WaitingTaxi, TEMPACT_WAIT, 1000000) ENDIF ENDIF ENDIF ELSE eEnterTaxiState = TL_ENTER_TAXI_STATE_IDLE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : UPDATE_PLAYER_ENTER_TAXI_TASK reset to IS_PLAYER_OK_TO_USE_ENTER_VEHICLE_TASK player entering different vehicle check FC = ", GET_FRAME_COUNT()) ENDIF ELSE eEnterTaxiState = TL_ENTER_TAXI_STATE_IDLE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : UPDATE_PLAYER_ENTER_TAXI_TASK reset to IS_PLAYER_OK_TO_USE_ENTER_VEHICLE_TASK player not entering vehicle now check FC = ", GET_FRAME_COUNT()) ENDIF ELSE eEnterTaxiState = TL_ENTER_TAXI_STATE_IDLE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : UPDATE_PLAYER_ENTER_TAXI_TASK reset to IS_PLAYER_OK_TO_USE_ENTER_VEHICLE_TASK check FC = ", GET_FRAME_COUNT()) ENDIF ENDPROC /// PURPOSE: /// handle awaiting player attempt to enter a taxi state PROC ENTER_TAXI_STATE_IDLE() // don't process checks if the closest taxi hasn't been found IF DOES_ENTITY_EXIST(vehClosestTaxi) // make sure the taxi is suitable to get in IF IS_PLAYER_OK_TO_ENTER_VEHICLE_AS_PASSENGER(vehClosestTaxi, mnTaxiModel, mnTaxiDriverModel) // don't process checks if player is already in vehicle IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) // now Handles by UPDATE_TAXI_SEARCH_HANDLES() //vehIndexTemp = GET_CLOSEST_VEHICLE(vPlayerPos, 10.0, TAXI, GET_TAXI_SEARCH_FLAGS()) // once detected enter taxi attempt g_WaitingTaxi and g_WaitingTaxiDriver handles are updated DETECT_PLAYER_ATTEMPT_TO_ENTER_TAXI() ELSE IF IS_PED_SITTING_IN_ANY_VEHICLE(PLAYER_PED_ID()) // check the vehicle he's in isn't infact the taxi IF IS_PED_SITTING_IN_VEHICLE(PLAYER_PED_ID(), vehClosestTaxi) //IF (GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID(), FALSE) = vehClosestTaxi) // grab handle to the taxi driver PED_INDEX pedIndex = GET_PED_IN_VEHICLE_SEAT(vehClosestTaxi) // all safe checks have already been performed in IS_PLAYER_OK_TO_ENTER_VEHICLE_AS_PASSENGER // store the seat Player is in to task the group members to enter IF NOT IS_VEHICLE_SEAT_FREE(vehClosestTaxi, VS_BACK_LEFT) IF (GET_PED_IN_VEHICLE_SEAT(vehClosestTaxi, VS_BACK_LEFT) = PLAYER_PED_ID()) ePlayerChosenSeat = VS_BACK_LEFT CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ENTER_TAXI_STATE_IDLE player already sat in taxi seat VS_BACK_LEFT") ENDIF ENDIF IF NOT IS_VEHICLE_SEAT_FREE(vehClosestTaxi, VS_BACK_RIGHT) IF (GET_PED_IN_VEHICLE_SEAT(vehClosestTaxi, VS_BACK_RIGHT) = PLAYER_PED_ID()) ePlayerChosenSeat = VS_BACK_RIGHT CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ENTER_TAXI_STATE_IDLE player already sat in taxi seat VS_BACK_RIGHT") ENDIF ENDIF // if this taxi isn't the current waiting taxi cleanup the hailed state IF eHailTaxiState = TL_HAIL_TAXI_STATE_TAXI_WAITING OR eHailTaxiState = TL_HAIL_TAXI_STATE_SUCCESSFUL_ATTEMPT IF (vehClosestTaxi != g_WaitingTaxi) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ENTER_TAXI_STATE_IDLE reset eHailTaxiState for entering a veh which isn't g_WaitingTaxi") CLEANUP_HAIL_TAXI() ENDIF ENDIF DISABLE_SELECTOR_THIS_FRAME() // B*1559411 - block char switching whilst entering a taxi //update handles g_WaitingTaxi = vehicleIndex, g_WaitingTaxiDriver = pedIndex IF STORE_CAR_AS_TAXI_WAITING_FOR_PLAYER(vehClosestTaxi, pedIndex) //release handle vehClosestTaxi = NULL eEnterTaxiState = TL_ENTER_TAXI_STATE_INSIDE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ENTER_TAXI_STATE_IDLE() : TL_ENTER_TAXI_STATE_IDLE -> TL_ENTER_TAXI_STATE_INSIDE FC = ", GET_FRAME_COUNT()) ENDIF ELSE // got in a vehicle which wasn't the closest taxi so cleanup CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ENTER_TAXI_STATE_IDLE() : cleanup for entering veh which wasn't vehClosestTaxi FC = ", GET_FRAME_COUNT()) CLEANUP_ENTER_CLOSEST_TAXI() ENDIF ENDIF ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// Player is process of entering taxi using scripted task PROC ENTER_TAXI_STATE_ENTERING() // make sure the vehicle the player has been tasks to enter is still ok IF IS_PLAYER_OK_TO_ENTER_VEHICLE_AS_PASSENGER(g_WaitingTaxi, mnTaxiModel, mnTaxiDriverModel) // check for the player making it into the taxi (IS_PLAYER_OK_TO_ENTER_VEHICLE_AS_PASSENGER checks driver if in driver seat) IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), g_WaitingTaxi) IF IS_PED_SITTING_IN_VEHICLE(PLAYER_PED_ID(), g_WaitingTaxi) eEnterTaxiState = TL_ENTER_TAXI_STATE_INSIDE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ENTER_TAXI_STATE_ENTERING() : TL_ENTER_TAXI_STATE_ENTERING -> TL_ENTER_TAXI_STATE_INSIDE FC = ", GET_FRAME_COUNT()) ENDIF DISABLE_SELECTOR_THIS_FRAME() // B*1559411 - block char switching whilst entering a taxi ELSE UPDATE_PLAYER_ENTER_TAXI_TASK() ENDIF ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ENTER_TAXI_STATE_ENTERING() : cleanup for IS_PLAYER_OK_TO_USE_ENTER_VEHICLE_TASK check") CLEANUP_ENTER_CLOSEST_TAXI() ENDIF ENDPROC /// PURPOSE: /// Player has successfully got in the back of a taxi - launche the taxiService.sc script PROC ENTER_TAXI_STATE_INSIDE() // make sure the vehicle the player has been tasks to enter is still ok IF IS_PLAYER_OK_TO_ENTER_VEHICLE_AS_PASSENGER(g_WaitingTaxi, mnTaxiModel, mnTaxiDriverModel) // check for the player making it into the taxi (IS_PLAYER_OK_TO_ENTER_VEHICLE_AS_PASSENGER checks driver if in driver seat) IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), g_WaitingTaxi) IF IS_PED_SITTING_IN_VEHICLE(PLAYER_PED_ID(), g_WaitingTaxi) DISABLE_SELECTOR_THIS_FRAME() // B*1559411 - block char switching whilst entering a taxi // store the seat the player is in to task the group members IF GET_PED_IN_VEHICLE_SEAT(g_WaitingTaxi, VS_BACK_LEFT) = PLAYER_PED_ID() ePlayerChosenSeat = VS_BACK_LEFT CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ENTER_TAXI_STATE_INSIDE() : stored ePlayerChosenSeat = VS_BACK_LEFT") ELSE ePlayerChosenSeat = VS_BACK_RIGHT CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ENTER_TAXI_STATE_INSIDE() : stored ePlayerChosenSeat = VS_BACK_RIGHT but test only based of not being in back left seat") ENDIF SET_PLAYER_GROUP_MEMBERS_INTO_TAXI(g_WaitingTaxi, ePlayerChosenSeat) // GET_GROUP_INTO_CAB(GET_NEAREST_PASSENGER_SIDE(g_WaitingTaxi)) // make sure the driver waits until the script kicks in IF NOT IS_PED_INJURED(g_WaitingTaxiDriver) AND IS_VEHICLE_DRIVEABLE(g_WaitingTaxi) IF IS_PED_SITTING_IN_VEHICLE(g_WaitingTaxiDriver, g_WaitingTaxi) IF NOT TAXI_IS_PED_PERFORMING_TASK(g_WaitingTaxiDriver, SCRIPT_TASK_VEHICLE_TEMP_ACTION) TASK_VEHICLE_TEMP_ACTION(g_WaitingTaxiDriver, g_WaitingTaxi, TEMPACT_WAIT, 1000000) ENDIF ENDIF ENDIF // make sure any taxi on route to the player cleans up CLEANUP_DISPATCHED_TAXI_DATA() CLEANUP_HAIL_TAXI() IF bHelpEnterTaxiDisplayed IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("TX_H02") // Hold ~INPUT_ENTER~ to enter the cab as a passenger. CLEAR_HELP() ENDIF bHelpEnterTaxiDisplayed = FALSE ENDIF NON_GROUPED_PASSENGERS_SHOULD_FLEE() SET_JACKED_PED_TO_FLEE() SET_PLAYER_CAN_DO_DRIVE_BY(PLAYER_ID(), FALSE) // request the taxiService.sc script REQUEST_SCRIPT("taxiService") IF HAS_SCRIPT_LOADED("taxiService") tTaxiServiceThread = START_NEW_SCRIPT("taxiService", SPECIAL_ABILITY_STACK_SIZE) SET_SCRIPT_AS_NO_LONGER_NEEDED("taxiService") eTaxiLauncherState = TL_STATE_PLAYER_IN_TAXI CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ENTER_TAXI_STATE_INSIDE() : TL_ENTER_TAXI_STATE_INSIDE launched taxiService.sc FC = ", GET_FRAME_COUNT()) ENDIF ENDIF ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ENTER_TAXI_STATE_INSIDE() : player got out cab so RESET_TAXI_LAUNCHER() FC = ", GET_FRAME_COUNT()) RESET_TAXI_LAUNCHER() ENDIF ELSE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : ENTER_TAXI_STATE_INSIDE() : cleanup for IS_PLAYER_OK_TO_USE_ENTER_VEHICLE_TASK check FC = ", GET_FRAME_COUNT()) CLEANUP_ENTER_CLOSEST_TAXI() ENDIF ENDPROC /// PURPOSE: /// Check reasons to reset and cleanup the dispatched taxi /// RETURNS: /// TRUE if dispatched taxi should cleanup FUNC BOOL SHOULD_DISPATCHED_TAXI_CLEANUP() // check for player leaving area taxi was requested from if so clenup IF NOT TAXI_IS_COORD_IN_RANGE_OF_COORD(vPlayerPos, sDispatchedTaxi.vPlayerCalledCoords, 100.0) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_DISPATCHED_TAXI_CLEANUP() : return TRUE : Player left area taxi requested from ") RETURN TRUE ENDIF // cleanup if player char has changed IF GET_PLAYER_PED_ENUM(PLAYER_PED_ID()) <> sDispatchedTaxi.eCharDispatchedFor CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_DISPATCHED_TAXI_CLEANUP() : return TRUE : Player char changed ") RETURN TRUE ENDIF // cleanup if player has a waiting taxi IF eHailTaxiState = TL_HAIL_TAXI_STATE_TAXI_WAITING CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_DISPATCHED_TAXI_CLEANUP() : return TRUE : eHailTaxiState = TL_HAIL_TAXI_STATE_TAXI_WAITING") RETURN TRUE ENDIF // stage specific checks IF eDispatchedTaxiState = TL_DISPATCHED_STATE_DRIVE_TO_PICKUP_PLAYER OR eDispatchedTaxiState = TL_DISPATCHED_STATE_PULL_OVER_TO_PICKUP_PLAYER IF NOT IS_PED_UNINJURED(sDispatchedTaxi.pedIndex) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_DISPATCHED_TAXI_CLEANUP() : return TRUE : sDispatchedTaxi.pedIndex injured") RETURN TRUE ENDIF IF NOT IS_VEHICLE_OK(sDispatchedTaxi.vehicleIndex) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_DISPATCHED_TAXI_CLEANUP() : return TRUE : sDispatchedTaxi.vehicleIndex veh wrecked") RETURN TRUE ENDIF // driver no longer in the taxi IF NOT IS_PED_SITTING_IN_VEHICLE(sDispatchedTaxi.pedIndex, sDispatchedTaxi.vehicleIndex) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_DISPATCHED_TAXI_CLEANUP() : return TRUE : sDispatchedTaxi.pedIndex not sat in DispatchedTaxi.vehicleIndex") RETURN TRUE ENDIF IF IS_PED_FLEEING(sDispatchedTaxi.pedIndex) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_DISPATCHED_TAXI_CLEANUP() : return TRUE : sDispatchedTaxi.pedIndex is fleeing") RETURN TRUE ENDIF IF IS_PED_IN_COMBAT(sDispatchedTaxi.pedIndex) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_DISPATCHED_TAXI_CLEANUP() : return TRUE : sDispatchedTaxi.pedIndex is in combat") RETURN TRUE ENDIF // player attacked taxi IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(sDispatchedTaxi.vehicleIndex, PLAYER_PED_ID()) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_DISPATCHED_TAXI_CLEANUP : return TRUE : damaged taxi check") RETURN TRUE ENDIF IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(sDispatchedTaxi.pedIndex, PLAYER_PED_ID()) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_DISPATCHED_TAXI_CLEANUP : return TRUE : damaged taxi driver check") RETURN TRUE ENDIF VECTOR vTaxiCoords = GET_ENTITY_COORDS(sDispatchedTaxi.vehicleIndex, FALSE) // bullet fired near taxi IF IS_BULLET_IN_AREA(vTaxiCoords, 7.0, FALSE) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_DISPATCHED_TAXI_CLEANUP : return TRUE : bullet fired near taxi") RETURN TRUE ENDIF FLOAT fProjectileRadiusCheck = 15.0 VECTOR vMin, vMax // is one of the player's projectiles nearby? vMin = vTaxiCoords vMax = vMin vMin.x= vMin.x - fProjectileRadiusCheck vMin.y = vMin.y -fProjectileRadiusCheck vMin.z = vMin.z - fProjectileRadiusCheck vMax.x = vMax.x + fProjectileRadiusCheck vMax.y = vMax.y + fProjectileRadiusCheck vMax.z = vMax.z + fProjectileRadiusCheck IF IS_PROJECTILE_IN_AREA(vMin, vMax, TRUE) CPRINTLN(DEBUG_TAXI_SERVICE, " : SHOULD_DISPATCHED_TAXI_CLEANUP : return TRUE : projectile near taxi") RETURN TRUE ENDIF IF TAXI_IS_COORD_IN_RANGE_OF_COORD(vPlayerPos, vTaxiCoords, 20.0) // aiming at the taxi IF IS_PLAYER_FREE_AIMING_AT_ENTITY(PLAYER_ID(), sDispatchedTaxi.vehicleIndex) OR IS_PLAYER_TARGETTING_ENTITY(PLAYER_ID(), sDispatchedTaxi.vehicleIndex) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_DISPATCHED_TAXI_CLEANUP : return TRUE : aiming at the taxi") RETURN TRUE ENDIF // check for player shooting near waiting taxi IF IS_PED_SHOOTING(PLAYER_PED_ID()) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : SHOULD_DISPATCHED_TAXI_CLEANUP : return TRUE : player shooting check") RETURN TRUE ENDIF ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// handles the player calling for a taxi and it arriving to pick him up PROC PROCESS_TAXI_PHONECALLS() // Player starts by calling the taxi firm IF eCallTaxiServiceState = TL_PHONE_STATE_AWAITING_CALL IF IS_CALLING_CONTACT(CHAR_TAXI) #IF IS_DEBUG_BUILD OR bDebug_CallCab #ENDIF IF IS_TAXI_SERVICE_LISTED_IN_PLAYERS_PHONEBOOK(GET_CURRENT_PLAYER_PED_ENUM()) IDENTIFY_PLAYER() ADD_PED_FOR_DIALOGUE(phonecallStruct, 0, PLAYER_PED_ID(), playerVoice) ADD_PED_FOR_DIALOGUE(phonecallStruct, 1, NULL, "TaxiDispatch") CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " IS_CALLING_CONTACT(CHAR_TAXI)") IF IS_PLAYER_ALLOWED_TO_CALL_TAXI() // #if USE_TU_CHANGES // IF IS_CURRENT_MISSION_DLC() //Added by Steve T to make taxi calls DLC compliant. 06.02.14 // // IF PLAYER_CALL_CHAR_CELLPHONE_MULTIPART_WITH_3_LINES_USING_V_CONTENT_IN_DLC(phonecallStruct, CHAR_TAXI, "TAXISAU", playerLine1, playerLine1, "TX_2", "TX_2", playerLine3, playerLine3, CONV_PRIORITY_NON_CRITICAL_CALL) // #IF IS_DEBUG_BUILD OR bDebug_CallCab #ENDIF // bPhonecallReachedSuccessfulLine = FALSE // eCallTaxiServiceState = TL_PHONE_STATE_CALL_IN_PROGRESS // CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), "PROCESS_TAXI_PHONECALLS : TL_PHONE_STATE_AWAITING_CALL -> TL_PHONE_STATE_CALL_IN_PROGRESS : using ", // " FirstRootLabel = ", playerLine1, " FirstSpecificLabel = ", playerLine1, " SecondRootLabel = TX_2 ", " SecondSpecificLabel = TX_2", // " ThirdRootLabel = ", playerLine3, " ThirdSpecificLabel = ", playerLine3) // ENDIF // // ELSE // #endif IF PLAYER_CALL_CHAR_CELLPHONE_MULTIPART_WITH_3_LINES(phonecallStruct, CHAR_TAXI, "TAXISAU", playerLine1, playerLine1, "TX_2", "TX_2", playerLine3, playerLine3, CONV_PRIORITY_NON_CRITICAL_CALL) #IF IS_DEBUG_BUILD OR bDebug_CallCab #ENDIF bPhonecallReachedSuccessfulLine = FALSE eCallTaxiServiceState = TL_PHONE_STATE_CALL_IN_PROGRESS CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), "PROCESS_TAXI_PHONECALLS : TL_PHONE_STATE_AWAITING_CALL -> TL_PHONE_STATE_CALL_IN_PROGRESS : using ", " FirstRootLabel = ", playerLine1, " FirstSpecificLabel = ", playerLine1, " SecondRootLabel = TX_2 ", " SecondSpecificLabel = TX_2", " ThirdRootLabel = ", playerLine3, " ThirdSpecificLabel = ", playerLine3) ENDIF // #if USE_TU_CHANGES // ENDIF // #endif ELSE // #if USE_TU_CHANGES // IF IS_CURRENT_MISSION_DLC() //Added by Steve T to make taxi calls DLC compliant. 06.02.14 // // IF PLAYER_CALL_CHAR_CELLPHONE_MULTIPART_WITH_2_LINES_USING_V_CONTENT_IN_DLC(phonecallStruct, CHAR_TAXI, "TAXISAU", playerLine1, playerLine1, "TX_2A", "TX_2A", CONV_PRIORITY_NON_CRITICAL_CALL) // eCallTaxiServiceState = TL_PHONE_STATE_WAIT_TO_RESET_CALL // CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), "PROCESS_TAXI_PHONECALLS : TL_PHONE_STATE_AWAITING_CALL -> TL_PHONE_STATE_WAIT_TO_RESET_CALL : using ", // " FirstRootLabel = ", playerLine1, " FirstSpecificLabel = ", playerLine1, " SecondRootLabel = TX_2A ", " SecondSpecificLabel = TX_2A") // ENDIF // // ELSE // #endif IF PLAYER_CALL_CHAR_CELLPHONE_MULTIPART_WITH_2_LINES(phonecallStruct, CHAR_TAXI, "TAXISAU", playerLine1, playerLine1, "TX_2A", "TX_2A", CONV_PRIORITY_NON_CRITICAL_CALL) eCallTaxiServiceState = TL_PHONE_STATE_WAIT_TO_RESET_CALL CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), "PROCESS_TAXI_PHONECALLS : TL_PHONE_STATE_AWAITING_CALL -> TL_PHONE_STATE_WAIT_TO_RESET_CALL : using ", " FirstRootLabel = ", playerLine1, " FirstSpecificLabel = ", playerLine1, " SecondRootLabel = TX_2A ", " SecondSpecificLabel = TX_2A") ENDIF // #if USE_TU_CHANGES // ENDIF // #endif ENDIF ENDIF ENDIF // state to wait in until an unsuccessful call for a taxi has finished ELIF eCallTaxiServiceState = TL_PHONE_STATE_WAIT_TO_RESET_CALL IF HAS_CELLPHONE_CALL_FINISHED() eCallTaxiServiceState = TL_PHONE_STATE_AWAITING_CALL CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), "PROCESS_TAXI_PHONECALLS : TL_PHONE_STATE_WAIT_TO_RESET_CALL -> TL_PHONE_STATE_AWAITING_CALL") ENDIF // successful call to order a taxi ELIF eCallTaxiServiceState = TL_PHONE_STATE_CALL_IN_PROGRESS IF HAS_CELLPHONE_CALL_FINISHED() // check for player hanging up before phnecall finished IF WAS_LAST_CELLPHONE_CALL_INTERRUPTED() // if phonecall reached successful line allow register as successful call anyway IF NOT bPhonecallReachedSuccessfulLine eCallTaxiServiceState = TL_PHONE_STATE_AWAITING_CALL CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), "PROCESS_TAXI_PHONECALLS : TL_PHONE_STATE_CALL_IN_PROGRESS -> TL_PHONE_STATE_AWAITING_CALL : WAS_LAST_CELLPHONE_CALL_INTERRUPTED()") ENDIF // check if the player receives an injury or starts ragdolling then during the phonecall ELIF HAS_CELLPHONE_JUST_BEEN_FORCED_AWAY() // if phonecall reached successful line allow register as successful call anyway IF NOT bPhonecallReachedSuccessfulLine eCallTaxiServiceState = TL_PHONE_STATE_AWAITING_CALL CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), "PROCESS_TAXI_PHONECALLS : TL_PHONE_STATE_CALL_IN_PROGRESS -> TL_PHONE_STATE_AWAITING_CALL : HAS_CELLPHONE_JUST_BEEN_FORCED_AWAY()") ENDIF ENDIF // successful phonecall IF eCallTaxiServiceState != TL_PHONE_STATE_AWAITING_CALL IF NOT HAS_ONE_TIME_HELP_DISPLAYED(FHM_TAXI_PHONE_INTRODUCED) SET_ONE_TIME_HELP_MESSAGE_DISPLAYED(FHM_TAXI_PHONE_INTRODUCED) ENDIF CLEANUP_DISPATCHED_TAXI_DATA() sDispatchedTaxi.iTimer_TaxiDispatchDelay = GET_GAME_TIMER() // set timer ready for delay sDispatchedTaxi.vPlayerCalledCoords = vPlayerPos // set position player is when call was processed sDispatchedTaxi.eCharDispatchedFor = GET_PLAYER_PED_ENUM(PLAYER_PED_ID()) // store which ped we are dispatched for sDispatchedTaxi.iNodeSearchNumber = 0 // set ready for creation node checks sDispatchedTaxi.iSpawnAttempts = 0 // set ready for creation checks // set the dispatched taxi state running eDispatchedTaxiState = TL_DISPATCHED_STATE_CREATE_TAXI CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), "PROCESS_TAXI_PHONECALLS : eDispatchedTaxiState = TL_DISPATCHED_STATE_CREATE_TAXI") eCallTaxiServiceState = TL_PHONE_STATE_AWAITING_CALL CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), "PROCESS_TAXI_PHONECALLS : TL_PHONE_STATE_CALL_IN_PROGRESS -> TL_PHONE_STATE_AWAITING_CALL : dispatched taxi") ENDIF ELSE // register when we've reached the positive response line to set call as successful IF NOT bPhonecallReachedSuccessfulLine // info from Steven - If audio added SFX pauses at a later date it may screw up your logic. // Unfortunately GET_CURRENTLY_PLAYING_STANDARD_CONVERSATION_ROOT() & GET_CURRENTLY_PLAYING_STANDARD_CONVERSATION_LABEL() don't work for this IF GET_CURRENT_SCRIPTED_CONVERSATION_LINE() = 1 CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), "PROCESS_TAXI_PHONECALLS : TL_PHONE_STATE_CALL_IN_PROGRESS : reached successful call line > 2 TX_2 : ") bPhonecallReachedSuccessfulLine = TRUE ENDIF ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// we now have to maintain some checks everyframe the player is not in a taxi PROC PROCESS_EVERYFRAME_NOT_IN_TAXI_UPDATES() // B*2074743 - need to call the aim blocking everyframe the hail animation is active IF eHailTaxiState = TL_HAIL_TAXI_STATE_SUCCESSFUL_ATTEMPT OR eHailTaxiState = TL_HAIL_TAXI_STATE_FAILED_ATTEMPT IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "HAIL_TAXI") OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), tlTaxiAnimDict, "FP_HAIL_TAXI") DISABLE_PLAYER_WEAPON_CONTROLS_FOR_HAIL_THIS_FRAME() ENDIF ENDIF //CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : PROCESS_EVERYFRAME_NOT_IN_TAXI_UPDATES hit this frame: ", GET_FRAME_COUNT()) ENDPROC /// PURPOSE: /// handles creating the dispatched taxi and navigating it to the player PROC PROCESS_DISPATCHED_TAXI() // Check reasons to reset and cleanup the dispatched taxi IF eDispatchedTaxiState != TL_DISPATCHED_STATE_IDLE IF SHOULD_DISPATCHED_TAXI_CLEANUP() CLEANUP_DISPATCHED_TAXI_DATA() CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " PROCESS_DISPATCHED_TAXI() : CLEANUP_DISPATCHED_TAXI_DATA()") ENDIF ENDIF // state where the script will wait until a request to dispatch a taxi has been processed IF eDispatchedTaxiState = TL_DISPATCHED_STATE_IDLE // create a taxi to go over to the player ELIF eDispatchedTaxiState = TL_DISPATCHED_STATE_CREATE_TAXI DISPATCHED_STATE_CREATE_TAXI() // handle driving the taxi over to the player ELIF eDispatchedTaxiState = TL_DISPATCHED_STATE_DRIVE_TO_PICKUP_PLAYER DISPATCHED_STATE_DRIVE_TO_PICKUP_PLAYER() // make the taxi pull over to pickup the player ELIF eDispatchedTaxiState = TL_DISPATCHED_STATE_PULL_OVER_TO_PICKUP_PLAYER DISPATCHED_STATE_PULL_OVER_TO_PICKUP_PLAYER() ENDIF ENDPROC /// PURPOSE: /// handles the player hailing taxis PROC PROCESS_PLAYER_HAILING_TAXI() // state to wait until a hail target has been found by UPDATE_TAXI_SEARCH_HANDLES IF eHailTaxiState = TL_HAIL_TAXI_STATE_IDLE IF DOES_ENTITY_EXIST(vehHailTarget) eHailTaxiState = TL_HAIL_TAXI_STATE_DETECT_HAIL #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " PROCESS_PLAYER_HAILING_TAXI() : TL_HAIL_TAXI_STATE_IDLE -> TL_HAIL_TAXI_STATE_DETECT_HAIL") ENDIF #ENDIF ENDIF // waiting to for player to attempt to hail a taxi ELIF eHailTaxiState = TL_HAIL_TAXI_STATE_DETECT_HAIL HAIL_STATE_DETECT_HAIL() // taxi driver responses - gestures player to get in ELIF eHailTaxiState = TL_HAIL_TAXI_STATE_SUCCESSFUL_ATTEMPT HAIL_TAXI_STATE_SUCCESSFUL_ATTEMPT() // player aknowledges failed attempt ELIF eHailTaxiState = TL_HAIL_TAXI_STATE_FAILED_ATTEMPT HAIL_TAXI_STATE_FAILED_ATTEMPT() // Taxi is classed a waiting (blipped up waits for player to enter) ELIF eHailTaxiState = TL_HAIL_TAXI_STATE_TAXI_WAITING HAIL_TAXI_STATE_TAXI_WAITING() ENDIF ENDPROC /// PURPOSE: /// handles the player getting into the back of the closest taxi PROC PROCESS_PLAYER_ENTER_CLOSEST_TAXI() // Waiting to detect player attempt to enter a taxi IF eEnterTaxiState = TL_ENTER_TAXI_STATE_IDLE ENTER_TAXI_STATE_IDLE() // Player has been tasked to enter the Taxi, wait to see if he gets in ELIF eEnterTaxiState = TL_ENTER_TAXI_STATE_ENTERING ENTER_TAXI_STATE_ENTERING() // Player is in the back of the taxi - launch the taxiService.sc script ELIF eEnterTaxiState = TL_ENTER_TAXI_STATE_INSIDE ENTER_TAXI_STATE_INSIDE() // State waiting until player left the taxi ELIF eEnterTaxiState = TL_ENTER_TAXI_STATE_WAIT_FOR_PLAYER_TO_EXIT IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) eEnterTaxiState = TL_ENTER_TAXI_STATE_IDLE #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " PROCESS_PLAYER_ENTER_CLOSEST_TAXI() : TL_ENTER_TAXI_STATE_WAIT_FOR_PLAYER_TO_EXIT -> TL_ENTER_TAXI_STATE_IDLE : FC = ", GET_FRAME_COUNT()) ENDIF #ENDIF ELSE #IF IS_DEBUG_BUILD IF bDebug_DisplayInfo CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " PROCESS_PLAYER_ENTER_CLOSEST_TAXI() : TL_ENTER_TAXI_STATE_WAIT_FOR_PLAYER_TO_EXIT waiting for player to leave veh : FC = ", GET_FRAME_COUNT()) ENDIF #ENDIF ENDIF ENDIF ENDPROC SCRIPT IF HAS_FORCE_CLEANUP_OCCURRED(FORCE_CLEANUP_FLAG_SP_TO_MP|FORCE_CLEANUP_FLAG_MAGDEMO) CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : force cleanup occured, script set to terminate") TAXI_LAUNCHER_SCRIPT_CLEANUP() TERMINATE_THIS_THREAD() ENDIF #IF IS_DEBUG_BUILD DEBUG_SETUP_WIDGETS() #ENDIF //#IF IS_DEBUG_BUILD DEBUG_SETUP_AREAS_WIDGETS() #ENDIF g_savedGlobals.sAmbient.bTaxiHailingHelpDisplayed = TRUE WHILE TRUE SWITCH eTaxiLauncherState // State where the launch will wait until it's safe to run CASE TL_STATE_IDLE IF IS_TAXI_SERVICE_SAFE_TO_RUN() eTaxiLauncherState = TL_STATE_PLAYER_NOT_IN_TAXI CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : TL_STATE_IDLE -> TL_STATE_PLAYER_NOT_IN_TAXI") ELSE WAIT(500) ENDIF BREAK // State where player can use a taxi CASE TL_STATE_PLAYER_NOT_IN_TAXI IF IS_TAXI_SERVICE_SAFE_TO_RUN() // used multiple times so only grabbed once per frame, injured status is tested in IS_TAXI_SERVICE_SAFE_TO_RUN vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE) PROCESS_TAXI_PHONECALLS() IF IS_PLAYER_ALLOWED_TO_ENTER_TAXI_AS_PASSENGER() SET_VEHICLE_MODEL_IS_SUPPRESSED(TAXI, FALSE) // We now have first instance of something which needs to be maintained everyframe PROCESS_EVERYFRAME_NOT_IN_TAXI_UPDATES() // optimisation - only process funcs if handles weren't updated this frame IF NOT ALT_UPDATE_TAXI_SEARCH_HANDLES() PROCESS_DISPATCHED_TAXI() PROCESS_PLAYER_HAILING_TAXI() PROCESS_PLAYER_ENTER_CLOSEST_TAXI() ENDIF ELSE RESET_TAXI_LAUNCHER(FALSE) eTaxiLauncherState = TL_STATE_PLAYER_NOT_IN_TAXI // esure we remain in this launcher state UPDATE_PLAYER_ALLOWED_TO_RIDE_IN_TAXIS_STATUS() WAIT(500) ENDIF ELSE RESET_TAXI_LAUNCHER() eTaxiLauncherState = TL_STATE_IDLE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : TL_STATE_PLAYER_NOT_IN_TAXI -> TL_STATE_IDLE") ENDIF BREAK // State where TaxiService.sc has been launched and we await the script terminating CASE TL_STATE_PLAYER_IN_TAXI IF NOT IS_THREAD_ACTIVE(tTaxiServiceThread) RESET_TAXI_LAUNCHER() // because the taxiService script can terminate before player is completely out the taxi - wait to recheck eEnterTaxiState = TL_ENTER_TAXI_STATE_WAIT_FOR_PLAYER_TO_EXIT eTaxiLauncherState = TL_STATE_IDLE CPRINTLN(DEBUG_TAXI_SERVICE, GET_THIS_SCRIPT_NAME(), " : TL_STATE_PLAYER_IN_TAXI -> TL_STATE_IDLE") ENDIF BREAK ENDSWITCH #IF IS_DEBUG_BUILD DEBUG_UPDATE_WIDGETS() #ENDIF //#IF IS_DEBUG_BUILD DEBUG_UPDATE_AREA_WIDGETS() #ENDIF WAIT(0) ENDWHILE ENDSCRIPT