// ***************************************************************************************** // ***************************************************************************************** // // MISSION NAME : carwash_shared.sch // AUTHOR : Aaron Gandaa // DESCRIPTION : Car Wash Shared Structs and Functions // // ***************************************************************************************** // ***************************************************************************************** //---------------------- // INCLUDES //---------------------- USING "rgeneral_include.sch" USING "RC_Helper_Functions.sch" USING "RC_Asset_Public.sch" USING "RC_Camera_Public.sch" USING "cost_halo.sch" USING "net_ambience.sch" USING "net_cash_transactions.sch" USING "commands_volume.sch" #IF IS_DEBUG_BUILD USING "shared_debug.sch" #ENDIF //---------------------- // ENUM //---------------------- ENUM eCarwashAreaState ECA_NULL, ECA_ENTERED_AREA, ECA_INAREA, ECA_EXITED_AREA ENDENUM ENUM CARWASH_PARTSTATE CPS_NULL, CPS_STARTUP, CPS_WARMUP, CPS_ACTIVE, CPS_WARMDOWN, CPS_SHUTDOWN, CPS_FINISHED ENDENUM ENUM CARWASH_LOCATIONID CARWASH_LOCID_LONG = 1, CARWASH_LOCID_SHORT = 2 ENDENUM //---------------------- // CONSTANTS //--------------------- CONST_FLOAT CAR_WASH_ACTIVE_RANGE 90.0 CONST_FLOAT ROLLER_RADIUS 0.55 CONST_FLOAT ROLLER_SPINRATE 360.0 CONST_FLOAT VROLLER_CHECKDIFF 0.95 CONST_FLOAT VROLLER_ZSHIFT 1.5 CONST_FLOAT VROLLER_CHECKZSHIFT 0.5 CONST_FLOAT DEFAULT_DUALVROLL_SEP 3.75 // 4.0 CONST_INT COST_CARWASH 15 CONST_FLOAT VROLLER_SEP 1.75 //0.825 CONST_FLOAT AUTODRIVE_TOLERANCE 30.0 CONST_FLOAT JET_TRIGGER_DIST 0.6 CONST_FLOAT ROLLER_TRIGGER_DIST 1.25 CONST_INT CAMERASTATE_LASTCAMERA 98 CONST_INT CAMERASTATE_ALLDONE 99 CONST_INT CARWASH_AXIS_X 0 CONST_INT CARWASH_AXIS_Y 0 INT ROLLER_CHECK_INTERVAL = 125 INT SHAPE_CHECK_INTERVAL = 128 CONST_INT BLOCKED_SHAPE_CHECK_INTERVAL 250 FLOAT ROLLER_SHIFT_FACTOR = 0.625 //---------------------- // STRUCT //---------------------- STRUCT CARWASH_CAMERA BOOL bSetup = FALSE VECTOR vPosition[2] VECTOR vRotation[2] INT iInterpTime = 0 FLOAT fFov CAMERA_INDEX cameraID ENDSTRUCT STRUCT CARWASH_VROLLER2 BOOL bSetup = FALSE OBJECT_INDEX pivotID CARWASH_PARTSTATE state OBJECT_INDEX rollerID[2] PTFX_ID fxBrushID[2] FLOAT fOffset[2] FLOAT fTgtOffset[2] FLOAT fRollerSpinAngle = 0.0 FLOAT fSpinRate = 0.0 FLOAT fMoveRate = 1.0 // rate the brush moves in meters per second FLOAT fSensorOffset[2] // this is how far away from the center the sensors are FLOAT fSensorRadius[2] VECTOR vBasePosition INT iSpinSoundID = -1 INT iMoveSoundID = -1 INT iHitSoundID = -1 FLOAT fOriginalSep BOOL bCollisionOn = TRUE BOOL bOldCollision BOOL bSensorOn[2] SHAPETEST_INDEX shapeTestID VEHICLE_INDEX activeVehicle SHAPETEST_INDEX brushShapeTestID[2] INT iNextBrushShapeTestTime[2] INT iNextShapeTestTime FLOAT fShutDownMoveRate = 0.3 BOOL bHitCheck[2] BOOL bOldHitCheck[2] ENDSTRUCT STRUCT CARWASH_JETS BOOL bSetup = FALSE BOOL bSteam = FALSE CARWASH_PARTSTATE state OBJECT_INDEX pivotID INT iNextCheckTime INT iSoundID = -1 INT iSplashSoundID = -1 FLOAT fTriggerDist FLOAT fSeperation = 0.0 FLOAT fHeight = 0.0 VECTOR vBasePos STRING sJetName PTFX_ID fxJets[4] SHAPETEST_INDEX shapeTestID INT iNextShapeTestTime ENDSTRUCT STRUCT CARWASH_HROLLER CARWASH_PARTSTATE state BOOL bSetup = FALSE VECTOR vPosition // this is the position of the roller when it starts VECTOR vContactPoint // this is the contact point for the line test, the brush should be ROLLER_RADIUS m above this VECTOR vOldRollerPos FLOAT fRollerPivotAngle = 0.0 FLOAT fRollerSpinAngle = 0.0 FLOAT fSpinRate = 0.0 FLOAT fMoveRate = 2.5 // rate the brush moves in meters per second FLOAT fTriggerDist INT iSpinSoundID = -1 INT iMoveSoundID = -1 INT iHitSoundID = -1 OBJECT_INDEX rollerID SHAPETEST_INDEX shapeTestID PTFX_ID fxBrushID FLOAT fGroundZero = 0.0 // this is the z height of floor when the carwash is empty FLOAT fTargetZ = 0.0 FLOAT fOriginalZ = 0.0 INT iNextCheckTime INT iNextShapeTestTime ENDSTRUCT STRUCT CARWASH_TRACK VECTOR vTrackPoint[2] VECTOR vBlockMinMax[2] VECTOR vBlockPoint[2] VECTOR vVehicleSnapPoint FLOAT fTrackHeading FLOAT fTrackInterpolate = 0.0 VECTOR vDirection INT iDominantBlockAxis ENDSTRUCT STRUCT CARWASH_HANDLER CARWASH_TRACK cTrack CARWASH_JETS soapJets CARWASH_JETS waterJets CARWASH_JETS steamJets CARWASH_HROLLER horzRoller CARWASH_VROLLER2 vertRoller CAMERA_STRUCT carWashCamera[7] BUILDING_NAME_ENUM iplSwap STRING sWayPointRec FLOAT fForwardSpeed = 1.5 FLOAT fBoostSpeed FLOAT fFinalCameraInterpolate = 0.8 // when we get to here INT iCurrentCameraState = 0 CAMERA_INDEX cameraID BOOL bTimerStarted = FALSE BOOL bTallVehicle BOOL bThrottleBoosted BOOL bSkipped = FALSE BOOL bIsAllowedInMP = FALSE INT iNextBlockCheckTime INT iLastTimeUsed = 0 SHAPETEST_INDEX shapeTestID INT iBlockCounts = 0 INT iTaskSequenceSize = 0 // NUMBER OF TASKS IN SEQUENCE CARWASH_LOCATIONID iLocationID = CARWASH_LOCID_LONG VECTOR vNoPedWalkMin VECTOR vNoPedWalkMax BOOL bCarwashAborted = FALSE BOOL bBackInterruptCheck = FALSE BOOL bOldUpdateCheck = FALSE INT iAutoAbortTimer // if the time gets bigger than this automatically exit as something has gone wrong TIME_DATATYPE iAutoAbortTimerMP // ENDSTRUCT //---------------------- // VARIABLES //---------------------- VECTOR vRollerRadius = <<0, 0, ROLLER_RADIUS * 1.1>> BOOL bDrawDebugCarwash = FALSE VECTOR vRollerVertPosFX = <<0, 0, -1.125>> VECTOR vRollerVertRotFX = <<0, 0, 0>> VECTOR vRollerHorzRotFX = <<0, 90, 0>> VECTOR vJetRotFX = <<90, 90, 0>> VECTOR vSteamRotFX = <<0, 0, 0>> VECTOR vSteamPosFX = <<0, 0.1, -0.76>> FLOAT fRumbleFactor = 1.0 BOOL bUseOldVerticleBrushCheck = FALSE BOOL bDebugForceClearPedTasks = FALSE BOOL bDebugForceRestartTasks = FALSE BOOL bIsDriverRunningCarwashSequence = FALSE BOOL bIsDriverFinishedCarwashSequence = FALSE INT iDriverCarwashSequenceProgress = -1 BOOL bUseNewMPVertRollers = TRUE BOOL bUseNewSweptSphereTest = TRUE FLOAT fSweepSphereRadius = 1.0 FLOAT fShapeTestXSeperation = 3.0 #IF IS_DEBUG_BUILD FLOAT fCarDebugRatio INT iDebugCarWashTimer BOOL bCreateBlockCar FLOAT fBlockCarPlaceT = 0.5 #ENDIF //---------------------- // MISC FUNCTIONS //---------------------- /* PROC PROCESS_EVENT_CARWASH_NETWORK_SCRIPT_EVENT(CARWASH_HANDLER &ch, INT iCount) SCRIPT_EVENT_DATA_CARWASH_EVENT sEvent IF GET_EVENT_DATA(SCRIPT_EVENT_QUEUE_NETWORK, iCount, sEvent, SIZE_OF(sEvent)) CPRINTLN(DEBUG_MISSION, "[CARWASH] - NETWORK SCRIPT EVENT RECIEVED") IF (ENUM_TO_INT(ch.iLocationID) = sEvent.iCarwashID) CPRINTLN(DEBUG_MISSION, "[CARWASH] - NETWORK SCRIPT EVENT PROCESSED BY CARWASH:", ENUM_TO_INT(ch.iLocationID)) ENDIF ENDIF ENDPROC PROC PROCESS_CARWASH_NETWORK_SCRIPT_EVENT(CARWASH_HANDLER &ch, INT iEventID) STRUCT_EVENT_COMMON_DETAILS Details GET_EVENT_DATA(SCRIPT_EVENT_QUEUE_NETWORK, iEventID, Details, SIZE_OF(Details)) SWITCH Details.Type CASE SCRIPT_EVENT_CARWASH_EVENT PROCESS_EVENT_CARWASH_NETWORK_SCRIPT_EVENT(ch, iEventID) BREAK ENDSWITCH ENDPROC PROC PROCESS_CARWASH_NETWORK_EVENTS(CARWASH_HANDLER &ch) INT iCount EVENT_NAMES ThisScriptEvent REPEAT GET_NUMBER_OF_EVENTS(SCRIPT_EVENT_QUEUE_NETWORK) iCount ThisScriptEvent = GET_EVENT_AT_INDEX(SCRIPT_EVENT_QUEUE_NETWORK, iCount) SWITCH ThisScriptEvent CASE EVENT_NETWORK_SCRIPT_EVENT PROCESS_CARWASH_NETWORK_SCRIPT_EVENT(ch, iCount) BREAK ENDSWITCH ENDREPEAT ENDPROC */ PROC UPDATE_VEHICLE_DOOR_DAMAGE_BIT_FIELD(VEHICLE_INDEX veh, INT &iBitField) iBitField = 0 IF NOT IS_THIS_MODEL_A_CAR(GET_ENTITY_MODEL(veh)) EXIT ENDIF IF IS_VEHICLE_DOOR_DAMAGED(veh, SC_DOOR_FRONT_LEFT) SET_BIT(iBitField, 0) ENDIF IF IS_VEHICLE_DOOR_DAMAGED(veh, SC_DOOR_FRONT_RIGHT) SET_BIT(iBitField, 1) ENDIF IF IS_VEHICLE_DOOR_DAMAGED(veh, SC_DOOR_REAR_LEFT) SET_BIT(iBitField, 2) ENDIF IF IS_VEHICLE_DOOR_DAMAGED(veh, SC_DOOR_REAR_RIGHT) SET_BIT(iBitField, 3) ENDIF ENDPROC FUNC BOOL IS_ANY_VEHICLE_MAIN_DOOR_BROKEN(VEHICLE_INDEX veh) IF NOT IS_THIS_MODEL_A_CAR(GET_ENTITY_MODEL(veh)) RETURN TRUE ENDIF IF IS_VEHICLE_DOOR_DAMAGED(veh, SC_DOOR_FRONT_LEFT) RETURN TRUE ENDIF IF IS_VEHICLE_DOOR_DAMAGED(veh, SC_DOOR_FRONT_RIGHT) RETURN TRUE ENDIF IF IS_VEHICLE_DOOR_DAMAGED(veh, SC_DOOR_REAR_LEFT) RETURN TRUE ENDIF IF IS_VEHICLE_DOOR_DAMAGED(veh, SC_DOOR_REAR_RIGHT) RETURN TRUE ENDIF IF IS_VEHICLE_A_CONVERTIBLE(veh, TRUE) IF GET_CONVERTIBLE_ROOF_STATE(veh) = CRS_ROOF_STUCK_LOWERED RETURN TRUE ENDIF ENDIF RETURN FALSE ENDFUNC PROC REMOVE_CARWASH_STUCK_CHECK(VEHICLE_INDEX veh) IF NOT IS_ENTITY_ALIVE(veh) EXIT ENDIF IF DOES_VEHICLE_HAVE_STUCK_VEHICLE_CHECK(veh) REMOVE_VEHICLE_STUCK_CHECK(veh) CPRINTLN(DEBUG_MISSION, "[CARWASH] - Removed stuck check") ENDIF IF DECOR_EXIST_ON(veh, "Carwash_Vehicle_Decorator") DECOR_REMOVE(veh, "Carwash_Vehicle_Decorator") CPRINTLN(DEBUG_MISSION, "[CARWASH] - Vehicle Decorator Removed") ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() IF NETWORK_HAS_CONTROL_OF_ENTITY(veh) SET_VEHICLE_DOORS_LOCKED_FOR_ALL_PLAYERS(veh, FALSE) CPRINTLN(DEBUG_MISSION, "[CARWASH] - Carwash Network Door Lock Released") ENDIF ENDIF ENDPROC PROC UPDATE_COLLISIONS_FOR_CARWASH(CARWASH_HANDLER &ch, VEHICLE_INDEX veh) IF DOES_ENTITY_EXIST(ch.horzRoller.rollerID) SET_ENTITY_NO_COLLISION_ENTITY(veh, ch.horzRoller.rollerID, TRUE) SET_ENTITY_NO_COLLISION_ENTITY(ch.horzRoller.rollerID, veh, TRUE) ENDIF IF DOES_ENTITY_EXIST(ch.vertRoller.rollerID[0]) SET_ENTITY_NO_COLLISION_ENTITY(veh, ch.vertRoller.rollerID[0], TRUE) SET_ENTITY_NO_COLLISION_ENTITY(ch.vertRoller.rollerID[0], veh, TRUE) ENDIF IF DOES_ENTITY_EXIST(ch.vertRoller.rollerID[1]) SET_ENTITY_NO_COLLISION_ENTITY(veh, ch.vertRoller.rollerID[1], TRUE) SET_ENTITY_NO_COLLISION_ENTITY(ch.vertRoller.rollerID[1], veh, TRUE) ENDIF ENDPROC PROC RESET_COLLISIONS_FOR_CARWASH(CARWASH_HANDLER &ch, VEHICLE_INDEX veh = NULL) IF DOES_ENTITY_EXIST(ch.horzRoller.rollerID) SET_ENTITY_COLLISION(ch.horzRoller.rollerID, TRUE) ENDIF REMOVE_CARWASH_STUCK_CHECK(veh) ENDPROC PROC STOP_ALL_CARWASH_SOUNDS(CARWASH_HANDLER &ch) SAFE_STOP_AND_RELEASE_SOUND_ID(ch.horzRoller.iSpinSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(ch.horzRoller.iMoveSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(ch.horzRoller.iHitSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(ch.vertRoller.iSpinSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(ch.vertRoller.iMoveSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(ch.vertRoller.iHitSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(ch.soapJets.iSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(ch.soapJets.iSplashSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(ch.waterJets.iSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(ch.waterJets.iSplashSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(ch.steamJets.iSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(ch.steamJets.iSplashSoundID) ENDPROC PROC SHUTDOWN_CARWASH_JETS_PARTICLES(CARWASH_JETS &roll) INT i REPEAT COUNT_OF (roll.fxJets) i SAFE_REMOVE_PARTICLE_FX(roll.fxJets[i]) ENDREPEAT ENDPROC PROC STOP_ALL_CARWASH_PARTICLES(CARWASH_HANDLER &ch) SHUTDOWN_CARWASH_JETS_PARTICLES(ch.waterJets) SHUTDOWN_CARWASH_JETS_PARTICLES(ch.soapJets) SHUTDOWN_CARWASH_JETS_PARTICLES(ch.steamJets) SAFE_REMOVE_PARTICLE_FX(ch.vertRoller.fxBrushID[0]) SAFE_REMOVE_PARTICLE_FX(ch.vertRoller.fxBrushID[1]) SAFE_REMOVE_PARTICLE_FX(ch.horzRoller.fxBrushID) ENDPROC PROC CARWASH_NETWORK_WAIT(INT time = 60) IF NOT NETWORK_IS_GAME_IN_PROGRESS() EXIT ENDIF CPRINTLN(DEBUG_MISSION, "---------- CREATE WAIT FOR ", time, "MS ", GET_GAME_TIMER()) TIME_DATATYPE abortTime = GET_NETWORK_TIME() WHILE (ABSI(GET_TIME_DIFFERENCE(GET_NETWORK_TIME(), abortTime)) < time) WAIT(0) ENDWHILE CPRINTLN(DEBUG_MISSION, "---------- CREATE WAIT FOR ", time, "MS COMPLETE ", GET_GAME_TIMER()) ENDPROC PROC PRINT_PLAYER_CAR_DIMENSIONS() IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) VECTOR vMin, vMax GET_MODEL_DIMENSIONS(GET_ENTITY_MODEL(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())), vMin, vMax) CPRINTLN(DEBUG_MISSION, "----------CAR DUMP DATA -----------") IF IS_ENTITY_ALIVE(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())) CPRINTLN(DEBUG_MISSION, "MODEL:", GET_MODEL_NAME_OF_VEHICLE_FOR_DEBUG_ONLY(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()))) ELSE CPRINTLN(DEBUG_MISSION, "MODEL: dead vehicle") ENDIF CPRINTLN(DEBUG_MISSION, "MIN:", vMin, " MAX:", vMax) CPRINTLN(DEBUG_MISSION, "L:", ABSF(vMax.y - vMin.y), " W:", ABSF(vMax.x - vMin.x), " H:", ABSF(vMax.z - vMin.z)) CPRINTLN(DEBUG_MISSION, "---------- CAR DUMP END -----------") ENDIF ENDPROC PROC PRINT_ENTITY_MODEL_DIMENSIONS(MODEL_NAMES mdl, STRING str) VECTOR vMin, vMax GET_MODEL_DIMENSIONS(mdl, vMin, vMax) CPRINTLN(DEBUG_MISSION, "----------MODEL DUMP DATA -----------") CPRINTLN(DEBUG_MISSION, "MODEL:", str) CPRINTLN(DEBUG_MISSION, "MIN:", vMin, " MAX:", vMax) CPRINTLN(DEBUG_MISSION, "L:", ABSF(vMax.y - vMin.y), " W:", ABSF(vMax.x - vMin.x), " H:", ABSF(vMax.z - vMin.z)) CPRINTLN(DEBUG_MISSION, "---------- MODEL DUMP END -----------") ENDPROC FUNC BOOL IS_CARWASH_PED_OK(PED_INDEX ped) IF NOT DOES_ENTITY_EXIST(ped) RETURN FALSE ENDIF IF IS_ENTITY_DEAD(ped) RETURN FALSE ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() IF NOT IS_PED_A_PLAYER(ped) RETURN FALSE ENDIF ENDIF RETURN NOT IS_PED_DEAD_OR_DYING(ped) ENDFUNC PROC APPLY_CARWASH_WASH_TO_VEHICLE(VEHICLE_INDEX veh, FLOAT washDecal, FLOAT dirtLevel) IF NETWORK_HAS_CONTROL_OF_ENTITY(veh) WASH_DECALS_FROM_VEHICLE(veh, washDecal) SET_VEHICLE_DIRT_LEVEL(veh, dirtLevel) ENDIF ENDPROC PROC SET_CARWASH_CAR_LOCK_STATE(VEHICLE_INDEX ind, LOCK_STATE lock) IF NOT NETWORK_IS_GAME_IN_PROGRESS() SET_VEHICLE_DOORS_LOCKED(ind, lock) EXIT ENDIF IF NOT IS_VEHICLE_A_PERSONAL_VEHICLE(ind) AND NOT IS_VEHICLE_A_TEST_DRIVE_VEHICLE(ind) SET_VEHICLE_DOORS_LOCKED(ind, lock) ENDIF ENDPROC PROC START_CARWASH_TIMER(CARWASH_HANDLER &ch) ch.bTimerStarted = TRUE IF g_bInMultiplayer ch.iAutoAbortTimerMP = GET_NETWORK_TIME() ELSE ch.iAutoAbortTimer = GET_GAME_TIMER() ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() IF IS_COMMERCE_STORE_OPEN() EXIT ENDIF ENDIF CPRINTLN(DEBUG_MISSION, "[CARWASH]:Carwash ", ENUM_TO_INT(ch.iLocationID), " Timer Started") ENDPROC FUNC INT GET_CARWASH_TIMER_ELAPSED(CARWASH_HANDLER &ch) IF g_bInMultiplayer RETURN GET_TIME_DIFFERENCE(GET_NETWORK_TIME(), ch.iAutoAbortTimerMP) ELSE RETURN GET_GAME_TIMER() - ch.iAutoAbortTimer ENDIF ENDFUNC FUNC BOOL HAS_ABORT_TIME_EXPIRED(CARWASH_HANDLER &ch) INT iAbortTime = PICK_INT((ch.iLocationID = CARWASH_LOCID_LONG), 20000, 15000) IF g_bInMultiplayer RETURN (GET_CARWASH_TIMER_ELAPSED(ch) > iAbortTime) AND (ch.bTimerStarted) ENDIF RETURN GET_GAME_TIMER() > (ch.iAutoAbortTimer + iAbortTime) ENDFUNC /// PURPOSE: /// /// PARAMS: /// carwashInd - PROC CHARGE_PLAYER_FOR_CARWASH(CARWASH_LOCATIONID carwashInd = CARWASH_LOCID_LONG) VEHICLE_INDEX veh INT iScriptTransactionIndex IF NOT g_bInMultiplayer CHARGE_CURRENT_PLAYER_PED_ACCOUNT_BALANCE(COST_CARWASH) ELSE veh = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()) IF IS_ENTITY_OK(veh) IF GET_PED_IN_VEHICLE_SEAT(veh) = PLAYER_PED_ID() //Just charge as much as possible up to the cost. INT iCost = COST_CARWASH INT iDifference IF NOT NETWORK_CAN_SPEND_MONEY2(iCost, FALSE, FALSE, TRUE, iDifference) iCost -= iDifference IF iCost <= 0 EXIT ENDIF ENDIF // B*1885699 - Changes to Cash Spent Priorities - Take money from cash then bank (This wasn't actually ever fixed properly until now!) IF USE_SERVER_TRANSACTIONS() TRIGGER_FIRE_AND_FORGET_SERVICE_TRANSACTION(SERVICE_SPEND_CARWASH, iCost, iScriptTransactionIndex, FALSE, FALSE, TRUE) g_cashTransactionData[iScriptTransactionIndex].cashInfo.iItemHash = ENUM_TO_INT(GET_ENTITY_MODEL(veh)) g_cashTransactionData[iScriptTransactionIndex].cashInfo.iLocation = ENUM_TO_INT(carwashInd) ELSE NETWORK_SPENT_CARWASH(iCost, ENUM_TO_INT(GET_ENTITY_MODEL(veh)), ENUM_TO_INT(carwashInd), FALSE, TRUE) ENDIF ENDIF ENDIF ENDIF ENDPROC FUNC BOOL IS_CARWASH_PART_RUNNING(CARWASH_PARTSTATE state) RETURN NOT ((state = CPS_NULL) OR (state = CPS_SHUTDOWN)) ENDFUNC FUNC BOOL IS_VEHICLE_USING_CARWASH(VEHICLE_INDEX veh) IF NOT IS_ENTITY_OK(veh) RETURN FALSE ENDIF RETURN DECOR_EXIST_ON(veh, "Carwash_Vehicle_Decorator") ENDFUNC FUNC BOOL IS_ENTITY_A_CARWASH_PART(ENTITY_INDEX obj) IF GET_ENTITY_MODEL(obj) = PROP_CARWASH_ROLLER_HORZ RETURN TRUE ENDIF IF GET_ENTITY_MODEL(obj) = PROP_CARWASH_ROLLER_VERT RETURN TRUE ENDIF IF GET_ENTITY_MODEL(obj) = PROP_LD_TEST_01 RETURN TRUE ENDIF RETURN FALSE ENDFUNC FUNC BOOL IS_ENTITY_BIG_ENOUGH_TO_BLOCK_CARWASH(ENTITY_INDEX obj) VECTOR vMin, vMax, vSize GET_MODEL_DIMENSIONS(GET_ENTITY_MODEL(obj), vMin, vMax) vSize.x = ABSF(vMax.x - vMin.x) vSize.y = ABSF(vMax.y - vMin.y) vSize.z = ABSF(vMax.z - vMin.z) RETURN (vSize.x >= 1.4) AND (vSize.y >= 1.4) AND (vSize.z >= 1.4) ENDFUNC FUNC BOOL IS_THIS_ENTITY_A_DUMPSTER(ENTITY_INDEX obj) IF GET_ENTITY_MODEL(obj) = PROP_DUMPSTER_01A RETURN TRUE ENDIF IF GET_ENTITY_MODEL(obj) = PROP_DUMPSTER_02A RETURN TRUE ENDIF IF GET_ENTITY_MODEL(obj) = PROP_DUMPSTER_02B RETURN TRUE ENDIF IF GET_ENTITY_MODEL(obj) = PROP_DUMPSTER_3A RETURN TRUE ENDIF IF GET_ENTITY_MODEL(obj) = PROP_DUMPSTER_4A RETURN TRUE ENDIF IF GET_ENTITY_MODEL(obj) = PROP_DUMPSTER_4B RETURN TRUE ENDIF RETURN FALSE ENDFUNC FUNC BOOL CAN_THIS_ENTITY_BLOCK_THE_CARWASH(ENTITY_INDEX obj) IF DOES_ENTITY_EXIST(obj) IF IS_ENTITY_A_VEHICLE(obj) RETURN TRUE ENDIF IF IS_ENTITY_A_PED(obj) RETURN FALSE ENDIF IF IS_ENTITY_A_CARWASH_PART(obj) RETURN FALSE ENDIF IF IS_THIS_ENTITY_A_DUMPSTER(obj) RETURN TRUE ENDIF IF IS_ENTITY_BIG_ENOUGH_TO_BLOCK_CARWASH(obj) RETURN TRUE ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Check if ped is network carwash driver /// PARAMS: /// ped - ped index FUNC BOOL IS_PED_IN_CAR_WITH_CARWASH_DRIVER(PED_INDEX ped) VEHICLE_INDEX veh IF NOT IS_CARWASH_PED_OK(ped) RETURN FALSE ENDIF IF NOT IS_PED_IN_ANY_VEHICLE(ped) RETURN FALSE ENDIF veh = GET_VEHICLE_PED_IS_IN(ped) IF NOT IS_ENTITY_OK(veh) RETURN FALSE ENDIF PED_INDEX driveped = GET_PED_IN_VEHICLE_SEAT(veh) IF NOT IS_CARWASH_PED_OK(driveped) RETURN FALSE ENDIF IF (g_bInMultiplayer) PLAYER_INDEX player = NETWORK_GET_PLAYER_INDEX_FROM_PED(driveped) IF (player = INVALID_PLAYER_INDEX()) RETURN FALSE ENDIF IF NOT IS_NET_PLAYER_OK(player, TRUE, FALSE) GlobalPlayerBD[NATIVE_TO_INT(player)].bDrivingThroughCarwash = FALSE RETURN FALSE ENDIF RETURN GlobalPlayerBD[NATIVE_TO_INT(player)].bDrivingThroughCarwash //RETURN IS_NET_PLAYER_OK(player, TRUE, FALSE) AND GlobalPlayerBD[NATIVE_TO_INT(player)].bDrivingThroughCarwash ENDIF RETURN TRUE ENDFUNC PROC DO_CARWASH_PAD_RUMBLE(INT iDuration, INT iFreq) IF IS_PED_IN_CAR_WITH_CARWASH_DRIVER(PLAYER_PED_ID()) FLOAT fFinalFreq = (TO_FLOAT(iFreq) * fRumbleFactor) fFinalFreq = CLAMP(fFinalFreq, 0, 256) //SET_PAD_SHAKE(PAD1, iDuration, FLOOR(fFinalFreq)) // old function has been depreciated SET_CONTROL_SHAKE(PLAYER_CONTROL, iDuration, FLOOR(fFinalFreq)) ENDIF ENDPROC FUNC BOOL IS_ANY_NET_PLAYER_DRIVING_IN_CARWASH() INT i REPEAT NUM_NETWORK_PLAYERS i IF GlobalPlayerBD[i].bDrivingThroughCarwash RETURN TRUE ENDIF ENDREPEAT RETURN FALSE ENDFUNC FUNC BOOL CHECK_ENTITY_IS_VEHICLE_OK(ENTITY_INDEX hitEntity, BOOL bCheckDriver = TRUE) VEHICLE_INDEX veh IF IS_ENTITY_A_VEHICLE(hitEntity) AND IS_ENTITY_OK(hitEntity) veh = GET_VEHICLE_INDEX_FROM_ENTITY_INDEX(hitEntity) IF (bCheckDriver) IF NOT IS_CARWASH_PED_OK(GET_PED_IN_VEHICLE_SEAT(veh)) RETURN FALSE ENDIF ENDIF IF NOT IS_VEHICLE_USING_CARWASH(veh) RETURN FALSE ENDIF RETURN TRUE ENDIF RETURN FALSE ENDFUNC PROC UPDATE_EMERGENCY_PLAYER_WARP_OUT_FOR_CARWASH() IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<40.279442,-1398.855957,23.846724>>, <<-0.984962,-1398.240234,32.011398>>, 5.750000) CPRINTLN(DEBUG_MISSION, "[CARWASH]: UPDATE_EMERGENCY_PLAYER_WARP_OUT_FOR_CARWASH - PLAYER IS STUCK IN WALL BEHIND CARWASH 1") SET_ENTITY_COORDS(PLAYER_PED_ID(), <<-3.4237, -1396.3101, 28.2554>>) SET_ENTITY_HEADING(PLAYER_PED_ID(), 85.1922) ENDIF ENDPROC /* /// PURPOSE: /// Handle push block - stops vehicles from driving in /// PARAMS: /// ct - carwash track /// veh - vehicle /// blockRadius - block radius FUNC FLOAT UPDATE_VEHICLE_IN_CARWASH(CARWASH_TRACK &ct, VEHICLE_INDEX veh, FLOAT fwdSpeed, FLOAT startDirt) // move car along and stop people dicking about with sun roof VECTOR v FLOAT r = GET_RATIO_OF_CLOSEST_POINT_ON_LINE(GET_ENTITY_COORDS(veh), ct.vTrackPoint[0], ct.vTrackPoint[1], FALSE) IF (r <= 1) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_EXIT) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_ROOF) v = GET_CLOSEST_POINT_ON_LINE(GET_ENTITY_COORDS(veh), ct.vTrackPoint[0], ct.vTrackPoint[1], FALSE) IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(veh, v) < 4.0 SET_ENTITY_HEADING(veh, ct.fTrackHeading) //SET_VEHICLE_ENGINE_ON(veh, TRUE, TRUE) SET_VEHICLE_FORWARD_SPEED(veh, fwdSpeed) IF (r > 0.0) SET_VEHICLE_DIRT_LEVEL(veh, startDirt * (1.0 - r)) ENDIF ENDIF ENDIF RETURN r ENDFUNC */ PROC SNAP_VEHICLE_BACK_ON_TRACK(VEHICLE_INDEX veh, CARWASH_TRACK &ct) VECTOR v = GET_CLOSEST_POINT_ON_LINE(GET_ENTITY_COORDS(veh), ct.vTrackPoint[0], ct.vTrackPoint[1], FALSE) SET_ENTITY_COORDS_GROUNDED(veh, v) SET_ENTITY_HEADING(veh, ct.fTrackHeading) SET_VEHICLE_ON_GROUND_PROPERLY(veh) ENDPROC /// PURPOSE: /// Handle push block - stops vehicles from driving in /// PARAMS: /// ct - carwash track /// veh - vehicle /// blockRadius - block radius PROC UPDATE_VEHICLE_PUSH_BLOCK(CARWASH_TRACK &ct, VEHICLE_INDEX veh, FLOAT blockRadius = 2.0) VECTOR v IF NOT IS_VECTOR_ZERO(ct.vBlockPoint[0]) AND NOT IS_VECTOR_ZERO(ct.vBlockPoint[1]) IF IS_ENTITY_IN_RANGE_COORDS(veh, ct.vBlockPoint[0], blockRadius) v = NORMALISE_VECTOR(GET_ENTITY_COORDS(veh) - ct.vBlockPoint[0]) SET_ENTITY_VELOCITY(veh, v * 2.0) ELIF IS_ENTITY_IN_RANGE_COORDS(veh, ct.vBlockPoint[1], blockRadius) v = NORMALISE_VECTOR(GET_ENTITY_COORDS(veh) - ct.vBlockPoint[1]) SET_ENTITY_VELOCITY(veh, v * 2.0) ENDIF ENDIF ENDPROC /// PURPOSE: /// Tells the Global BD That this ped is not driver in carwash /// PARAMS: /// ped - ped index PROC FORCE_CLEAR_NET_PED_DRIVING_CARWASH_STATUS(PED_INDEX ped) PLAYER_INDEX player = NETWORK_GET_PLAYER_INDEX_FROM_PED(ped) IF (player = INVALID_PLAYER_INDEX()) EXIT ENDIF GlobalPlayerBD[NATIVE_TO_INT(player)].bDrivingThroughCarwash = FALSE ENDPROC /// PURPOSE: /// Sets Global BD Net Ped Driving State /// PARAMS: /// ped - ped index /// ok - state PROC SET_NET_PED_DRIVING_CARWASH_STATUS(PED_INDEX ped, BOOL ok) PLAYER_INDEX player = NETWORK_GET_PLAYER_INDEX_FROM_PED(ped) IF (player = INVALID_PLAYER_INDEX()) EXIT ENDIF IF NOT IS_CARWASH_PED_OK(ped) GlobalPlayerBD[NATIVE_TO_INT(player)].bDrivingThroughCarwash = FALSE EXIT ENDIF GlobalPlayerBD[NATIVE_TO_INT(player)].bDrivingThroughCarwash = OK ENDPROC PROC DISABLE_CONTROL_ACTIONS_FOR_CARWASH() DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_ROOF) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_EXIT) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_HEADLIGHT) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SCRIPT_RRIGHT) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_ATTACK) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_ATTACK2) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_PASSENGER_AIM) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_PASSENGER_ATTACK) RC_DISABLE_CONTROL_ACTIONS_FOR_LEAD_IN() IF NOT (g_bInMultiplayer) DISABLE_SELECTOR_THIS_FRAME() ENDIF ENDPROC /// PURPOSE: /// Loads the carwash models PROC REQUEST_AND_LOAD_CARWASH_ASSETS_MP(ASSET_REQUESTER &as, STRING wayPointName = NULL) ADD_ASSET_REQUEST_FOR_MODEL(as, 0, PROP_CARWASH_ROLLER_HORZ) ADD_ASSET_REQUEST_FOR_MODEL(as, 1, PROP_CARWASH_ROLLER_VERT) ADD_ASSET_REQUEST_FOR_MODEL(as, 2, PROP_LD_TEST_01) IF HINT_SCRIPT_AUDIO_BANK("SCRIPT\\CARWASH") PRINTLN("[CARWASH] Audio bank hinted") ENDIF ADD_ASSET_REQUEST_FOR_PTFX(as, 3) IF NOT IS_STRING_NULL_OR_EMPTY(wayPointName) ADD_ASSET_REQUEST_FROM_STRING(as, 4, ASSET_WAYREC, wayPointName) ENDIF WHILE NOT HAVE_ASSET_REQUESTS_LOADED(as) SET_INPUT_EXCLUSIVE(FRONTEND_CONTROL, INPUT_CONTEXT) SET_INPUT_EXCLUSIVE(FRONTEND_CONTROL, INPUT_VEH_EXIT) DISABLE_CONTROL_ACTIONS_FOR_CARWASH() WAIT(0) ENDWHILE ENDPROC PROC REQUEST_AND_LOAD_CARWASH_ASSETS(ASSET_REQUESTER &as, STRING wayPointName = NULL) ADD_ASSET_REQUEST_FOR_MODEL(as, 0, PROP_CARWASH_ROLLER_HORZ) ADD_ASSET_REQUEST_FOR_MODEL(as, 1, PROP_CARWASH_ROLLER_VERT) ADD_ASSET_REQUEST_FOR_MODEL(as, 2, PROP_LD_TEST_01) ADD_ASSET_REQUEST_FROM_STRING(as, 3, ASSET_AUDIOBANK, "SCRIPT\\CARWASH") ADD_ASSET_REQUEST_FOR_PTFX(as, 4) IF NOT IS_STRING_NULL_OR_EMPTY(wayPointName) ADD_ASSET_REQUEST_FROM_STRING(as, 5, ASSET_WAYREC, wayPointName) ENDIF WHILE NOT HAVE_ASSET_REQUESTS_LOADED(as) SET_INPUT_EXCLUSIVE(FRONTEND_CONTROL, INPUT_CONTEXT) SET_INPUT_EXCLUSIVE(FRONTEND_CONTROL, INPUT_VEH_EXIT) DISABLE_CONTROL_ACTIONS_FOR_CARWASH() WAIT(0) ENDWHILE ENDPROC /// PURPOSE: /// Loads the carwash models PROC RELEASE_CARWASH_MODEL_ASSETS(ASSET_REQUESTER &as) _UNLOAD_ASSET_FROM_REQUESTER(as, 0) _UNLOAD_ASSET_FROM_REQUESTER(as, 1) _UNLOAD_ASSET_FROM_REQUESTER(as, 2) ENDPROC FUNC BOOL IS_CARWASH_POSITION_OCCUPIED(VECTOR v, FLOAT rad, BOOL bVisibleCheck = TRUE) IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) AND IS_ENTITY_IN_RANGE_COORDS(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), v, rad) RETURN TRUE ENDIF IF NOT IS_SPHERE_VISIBLE(v, rad) AND (bVisibleCheck = TRUE) RETURN FALSE ENDIF RETURN IS_POSITION_OCCUPIED(v, rad, FALSE, TRUE, FALSE, FALSE, FALSE, NULL, TRUE) ENDFUNC /// PURPOSE: /// Places vehicle along a two point track, gives it a speed and a go to order /// PARAMS: /// ind - vehicle index /// v1 - position 1 /// v2 - position 2 /// fRatio - ratio along track - 0 is back, 1 is front /// fSpeed - speed to move aong PROC SET_VEHICLE_ALONG_LINE(VEHICLE_INDEX ind, VECTOR v1, VECTOR v2, FLOAT fRatio, FLOAT fSpeed = 0.0) VECTOR v FLOAT head PED_INDEX ped IF NOT IS_ENTITY_OK(ind) EXIT ENDIF v = INTERPOLATE_VECTOR(v1, v2, fRatio, FALSE) head = GET_HEADING_FROM_COORDS(v1, v2) SET_ENTITY_COORDS(ind, v) SET_ENTITY_HEADING(ind, head) FREEZE_ENTITY_POSITION(ind, FALSE) IF (fSpeed = 0.0) EXIT ENDIF SET_VEHICLE_ENGINE_ON(ind, TRUE, TRUE) SET_VEHICLE_FORWARD_SPEED(ind, fSpeed) IF (fRatio > 1.0) EXIT ENDIF ped = GET_PED_IN_VEHICLE_SEAT(ind) IF NOT IS_CARWASH_PED_OK(ped) EXIT ENDIF CPRINTLN(DEBUG_MISSION, "CAR RATIO:", fRatio, " SPEED:", fSpeed, " DEST:", v2) TASK_VEHICLE_DRIVE_TO_COORD(ped, ind, v2, fSpeed, DRIVINGSTYLE_STRAIGHTLINE, GET_ENTITY_MODEL(ind), DRIVINGMODE_PLOUGHTHROUGH, 0.5, 1000.0) ENDPROC //---------------------- // TRACK FUNCTIONS //---------------------- PROC SET_CARWASH_IPL(CARWASH_HANDLER &ch, BUILDING_NAME_ENUM ipl) ch.iplSwap = ipl SET_BUILDING_STATE(ch.iplSwap, BUILDINGSTATE_DESTROYED) ENDPROC PROC SET_CARWASH_WAYPOINT_REC(CARWASH_HANDLER &ch, STRING s) ch.sWayPointRec = s ENDPROC /// PURPOSE: /// Sets up a carwash track /// PARAMS: /// ct - carwash track reference /// v1 - track point 1 /// v2 - track point 2 PROC SETUP_CARWASH_TRACK(CARWASH_TRACK &ct, VECTOR v1, VECTOR v2) ct.vTrackPoint[0] = v1 ct.vTrackPoint[1] = v2 ct.vDirection = NORMALISE_VECTOR(v2 - v1) ct.fTrackHeading = GET_HEADING_BETWEEN_VECTORS_2D(ct.vTrackPoint[0], ct.vTrackPoint[1]) CLEAR_CYLINDER_OF_ENTITIES(ct.vTrackPoint[0], ct.vTrackPoint[1], 3.0, FALSE, NOT g_bInMultiplayer, FALSE, TRUE, NOT g_bInMultiplayer) ENDPROC PROC SETUP_CARWASH_BLOCK_MIN_MAX(CARWASH_TRACK &ct, VECTOR v1, VECTOR v2) ct.vBlockMinMax[0] = v1 ct.vBlockMinMax[1] = v2 IF ABSF(v2.x - v1.x) > ABSF(v2.y - v1.y) ct.iDominantBlockAxis = CARWASH_AXIS_X ELSE ct.iDominantBlockAxis = CARWASH_AXIS_Y ENDIF ENDPROC /// PURPOSE: /// Setup block points - these stop other vehicles driving in MP /// PARAMS: /// ct - carwash track reference /// v1 - point 1 /// v2 - point 2 PROC SETUP_CARWASH_BLOCK_POINTS(CARWASH_TRACK &ct, VECTOR v1, VECTOR v2) ct.vBlockPoint[0] = v1 ct.vBlockPoint[1] = v2 ENDPROC PROC DRAW_DEBUG_CARWASH_TRACK(CARWASH_TRACK &ct) /* DRAW_DEBUG_LINE(ct.vTrackPoint[0], ct.vTrackPoint[1]) DRAW_DEBUG_SPHERE(INTERPOLATE_VECTOR(ct.vTrackPoint[0], ct.vTrackPoint[1], fInter), 0.5) DRAW_DEBUG_BOX(ct.vBlockMinMax[0], ct.vBlockMinMax[1]) DRAW_DEBUG_CIRCLE(ct.vTrackPoint[1], 1.0, 0, 255, 0, 255) DRAW_DEBUG_CIRCLE(ct.vBlockPoint[0], 1.0, 255, 0, 0, 255) DRAW_DEBUG_CIRCLE(ct.vBlockPoint[1], 1.0, 255, 0, 0, 255) */ DRAW_DEBUG_SPHERE(ct.vBlockMinMax[0], 0.0625) DRAW_DEBUG_SPHERE(ct.vBlockMinMax[1], 0.0625) DRAW_DEBUG_LINE(ct.vBlockMinMax[0], ct.vBlockMinMax[1]) ENDPROC PROC DRAW_DEBUG_CARWASH(CARWASH_HANDLER &ct) /* DRAW_DEBUG_LINE(ct.vTrackPoint[0], ct.vTrackPoint[1]) DRAW_DEBUG_SPHERE(INTERPOLATE_VECTOR(ct.vTrackPoint[0], ct.vTrackPoint[1], fInter), 0.5) DRAW_DEBUG_BOX(ct.vBlockMinMax[0], ct.vBlockMinMax[1]) DRAW_DEBUG_CIRCLE(ct.vTrackPoint[1], 1.0, 0, 255, 0, 255) DRAW_DEBUG_CIRCLE(ct.vBlockPoint[0], 1.0, 255, 0, 0, 255) DRAW_DEBUG_CIRCLE(ct.vBlockPoint[1], 1.0, 255, 0, 0, 255) */ DRAW_DEBUG_SPHERE(ct.cTrack.vBlockMinMax[0], 0.0625) DRAW_DEBUG_SPHERE(ct.cTrack.vBlockMinMax[1], 0.0625) DRAW_DEBUG_LINE(ct.cTrack.vBlockMinMax[0], ct.cTrack.vBlockMinMax[1]) ENDPROC /// PURPOSE: /// Places vehicle along a two point track, gives it a speed and a go to order /// PARAMS: /// ind - vehicle index /// v1 - position 1 /// v2 - position 2 /// fRatio - ratio along track - 0 is back, 1 is front /// fSpeed - speed to move aong PROC SET_VEHICLE_ALONG_CARWASH_TRACK(VEHICLE_INDEX ind, CARWASH_TRACK &ct, FLOAT fRatio, FLOAT fSpeed = 0.0) VECTOR v FLOAT head PED_INDEX ped // work out point along the track we are v = INTERPOLATE_VECTOR(ct.vTrackPoint[0], ct.vTrackPoint[1], fRatio, FALSE) // get the closest point to this point on the groove track head = GET_HEADING_FROM_COORDS(ct.vTrackPoint[0], ct.vTrackPoint[1]) SET_ENTITY_COORDS_GROUNDED(ind, v + <<0, 0, 0.1>>) SET_ENTITY_HEADING(ind, head) FREEZE_ENTITY_POSITION(ind, FALSE) IF (fSpeed = 0.0) EXIT ENDIF SET_VEHICLE_ENGINE_ON(ind, TRUE, TRUE) IF (fRatio > 1.0) EXIT ENDIF SET_VEHICLE_FORWARD_SPEED(ind, fSpeed) ped = GET_PED_IN_VEHICLE_SEAT(ind) IF NOT IS_CARWASH_PED_OK(ped) EXIT ENDIF v = INTERPOLATE_VECTOR(ct.vTrackPoint[0], ct.vTrackPoint[1], 1.1, FALSE) CPRINTLN(DEBUG_MISSION, "CAR RATIO:", fRatio, " SPEED:", fSpeed, " DEST:", v) TASK_VEHICLE_DRIVE_TO_COORD(ped, ind, v, fSpeed, DRIVINGSTYLE_STRAIGHTLINE, GET_ENTITY_MODEL(ind), DRIVINGMODE_PLOUGHTHROUGH, 0.5, 1000.0) ENDPROC /// PURPOSE: /// Get Ratio of Closest Point To Track /// PARAMS: /// v - point to test /// c - cartrack reference /// RETURNS: /// Ratio - not clamped FUNC FLOAT GET_RATIO_ALONG_CARWASH_TRACK(VECTOR v, CARWASH_TRACK &c, BOOL clmp = FALSE) RETURN GET_RATIO_OF_CLOSEST_POINT_ON_LINE(v, c.vTrackPoint[0], c.vTrackPoint[1], clmp) ENDFUNC /// PURPOSE: /// Get Ratio of Closest Point To Track /// PARAMS: /// v - point to test /// c - cartrack reference /// RETURNS: /// Ratio - not clamped FUNC FLOAT GET_HEADING_ALONG_CARWASH_TRACK(CARWASH_TRACK &c) RETURN GET_HEADING_BETWEEN_VECTORS_2D(c.vTrackPoint[0], c.vTrackPoint[1]) ENDFUNC //---------------------- // HROLLER FUNCTIONS //---------------------- PROC SHUTDOWN_CARWASH_HROLLER(CARWASH_HROLLER &roll) IF IS_CARWASH_PART_RUNNING(roll.state) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iMoveSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iSpinSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iHitSoundID) roll.state = CPS_NULL ENDIF ENDPROC PROC SHARED_CLEANUP_DELETE_CARWASH_HROLLER(CARWASH_HROLLER &roll) roll.state = CPS_ACTIVE SHUTDOWN_CARWASH_HROLLER(roll) ENDPROC /// PURPOSE: /// Cleanup the hroller /// PARAMS: /// roll - roller reference PROC DELETE_CARWASH_HROLLER(CARWASH_HROLLER &roll) SHARED_CLEANUP_DELETE_CARWASH_HROLLER(roll) SAFE_DELETE_OBJECT(roll.rollerID) ENDPROC /// PURPOSE: /// Cleanup the hroller /// PARAMS: /// roll - roller reference PROC CLEANUP_CARWASH_HROLLER(CARWASH_HROLLER &roll) SHARED_CLEANUP_DELETE_CARWASH_HROLLER(roll) SAFE_RELEASE_OBJECT(roll.rollerID) ENDPROC PROC START_CARWASH_HROLLER_PARTICLES(CARWASH_HROLLER &roll) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID) IF IS_ENTITY_OK(roll.rollerID) //AND NOT (g_bInMultiplayer) IF NOT DOES_PARTICLE_FX_LOOPED_EXIST(roll.fxBrushID) roll.fxBrushID = START_PARTICLE_FX_LOOPED_ON_ENTITY("ent_amb_car_wash", roll.rollerID, <<0.0, 0.0, 0.0>>, vRollerHorzRotFX) ENDIF ENDIF ENDPROC /// PURPOSE: /// Update the carwash roller /// PARAMS: /// roll - roller reference PROC _UPDATE_CARWASH_HROLLER_INTERNAL(CARWASH_HROLLER &roll) INT iHits VECTOR vec VECTOR vHitPos, vHitNormal SHAPETEST_STATUS shapeStatus ENTITY_INDEX hitEntity IF NOT roll.bSetup = TRUE EXIT ENDIF // do shape test IF (IS_CARWASH_PART_RUNNING(roll.state)) IF (roll.shapeTestID = NULL) IF (GET_GAME_TIMER() > roll.iNextShapeTestTime) roll.shapeTestID = START_SHAPE_TEST_LOS_PROBE(roll.vPosition, roll.vPosition - <<0, 0, 5.0>>, SCRIPT_INCLUDE_VEHICLE, roll.rollerID, SCRIPT_SHAPETEST_OPTION_IGNORE_NO_COLLISION) IF (roll.shapeTestID = NULL) CPRINTLN(DEBUG_MISSION, "[CARWASH]: CAN'T GET SHAPETEST FOR HORIZONTAL BRUSH") ENDIF ENDIF ELSE shapeStatus = GET_SHAPE_TEST_RESULT(roll.shapeTestID, iHits, vHitPos, vHitNormal, hitEntity) IF (shapeStatus = SHAPETEST_STATUS_RESULTS_READY) IF (iHits > 0) // set the ground zero point IF (roll.fGroundZero = 0.0) roll.fGroundZero = vHitPos.z + ROLLER_RADIUS ENDIF // work out contact point roll.vContactPoint = vHitPos + vRollerRadius // work out target point we should be moving towards IF (roll.vContactPoint.z = roll.fGroundZero) roll.fTargetZ = roll.vPosition.z - (ROLLER_RADIUS * 1.1) ELSE roll.fTargetZ = roll.vContactPoint.z + 0.1 IF CHECK_ENTITY_IS_VEHICLE_OK(hitEntity) SET_ENTITY_NO_COLLISION_ENTITY(hitEntity, roll.rollerID, TRUE) SET_ENTITY_NO_COLLISION_ENTITY(roll.rollerID, hitEntity, TRUE) IF (roll.iHitSoundID = -1) roll.iHitSoundID = GET_SOUND_ID() PLAY_SOUND_FROM_ENTITY(roll.iHitSoundID, "BRUSHES_HIT_CAR", roll.rollerID, "CARWASH_SOUNDS") ENDIF ENDIF ENDIF ENDIF ENDIF roll.shapeTestID = NULL roll.iNextShapeTestTime = GET_GAME_TIMER() + SHAPE_CHECK_INTERVAL ENDIF ELSE SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iHitSoundID) roll.fTargetZ = roll.fOriginalZ ENDIF // move the roller to get to contact point vec = GET_ENTITY_COORDS(roll.rollerID) IF (vec.z < roll.fTargetZ) vec.z += roll.fMoveRate * TIMESTEP() IF (vec.z > roll.fTargetZ) vec.z = roll.fTargetZ ENDIF ENDIF IF (vec.z > roll.fTargetZ) vec.z -= roll.fMoveRate * TIMESTEP() IF (vec.z < roll.fTargetZ) DO_CARWASH_PAD_RUMBLE(64, 64) vec.z = roll.fTargetZ ENDIF ENDIF IF (roll.fGroundZero <> 0.0) vec.z = CLAMP(vec.z,roll.fGroundZero, roll.fOriginalZ) ENDIF // set position and rotation IF NOT ARE_VECTORS_EQUAL(roll.vOldRollerPos, vec) SET_ENTITY_COORDS(roll.rollerID, vec) ENDIF roll.vOldRollerPos = vec // draw some debug crap IF bDrawDebugCarwash = TRUE DRAW_DEBUG_CIRCLE(<>, roll.fTriggerDist) DRAW_DEBUG_SPHERE(roll.vPosition, 0.0625) DRAW_DEBUG_LINE(roll.vPosition, roll.vContactPoint - vRollerRadius) DRAW_DEBUG_SPHERE(roll.vContactPoint - vRollerRadius, 0.03125) ENDIF ENDPROC /// PURPOSE: /// Update the dual roller /// PARAMS: /// roll - roller reference PROC UPDATE_CARWASH_HROLLER(CARWASH_HROLLER &roll, BOOL bSomeOneIn = TRUE) INT iHits VECTOR vHitPos, vHitNormal SHAPETEST_STATUS shapeStatus ENTITY_INDEX hitEntity VECTOR v = roll.vPosition FLOAT tStep = ROLLER_SPINRATE * TIMESTEP() v.z = roll.fGroundZero IF IS_CARWASH_PART_RUNNING(roll.state) IF (bSomeOneIn = FALSE) CPRINTLN(DEBUG_MISSION, "Carwash HRoller - Shutdown No One is In Carwash") roll.state = CPS_SHUTDOWN ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() AND NOT IS_ANY_NET_PLAYER_DRIVING_IN_CARWASH() CPRINTLN(DEBUG_MISSION, "Carwash HRoller - NET Shutdown No One is In Carwash") roll.state = CPS_SHUTDOWN ENDIF ENDIF SWITCH (roll.state) CASE CPS_NULL IF g_bInMultiplayer IF NOT IS_ANY_NET_PLAYER_DRIVING_IN_CARWASH() EXIT ENDIF ENDIF IF IS_ANY_VEHICLE_NEAR_POINT(roll.vPosition, 4.0) IF (roll.shapeTestID = NULL) IF (GET_GAME_TIMER() > roll.iNextShapeTestTime) roll.shapeTestID = START_SHAPE_TEST_CAPSULE(roll.vPosition, roll.vPosition - <<0, 0, 6.0>>, roll.fTriggerDist * 1.2, SCRIPT_INCLUDE_VEHICLE, roll.rollerID, SCRIPT_SHAPETEST_OPTION_IGNORE_NO_COLLISION) ENDIF ELSE shapeStatus = GET_SHAPE_TEST_RESULT(roll.shapeTestID, iHits, vHitPos, vHitNormal, hitEntity) IF (shapeStatus = SHAPETEST_STATUS_RESULTS_READY) IF CHECK_ENTITY_IS_VEHICLE_OK(hitEntity) roll.state = CPS_STARTUP SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iSpinSoundID) roll.iSpinSoundID = GET_SOUND_ID() PLAY_SOUND_FROM_ENTITY(roll.iSpinSoundID, "BRUSHES_SPINNING", roll.rollerID, "CARWASH_SOUNDS") CPRINTLN(DEBUG_MISSION, "[CARWASH]: HROLLER STARTUP") ENDIF ENDIF roll.shapeTestID = NULL roll.iNextShapeTestTime = GET_GAME_TIMER() + SHAPE_CHECK_INTERVAL ENDIF ENDIF BREAK CASE CPS_STARTUP IF (bSomeOneIn = FALSE) roll.state = CPS_SHUTDOWN ELSE roll.fSpinRate += tStep IF (roll.fSpinRate >= ROLLER_SPINRATE) roll.fSpinRate = ROLLER_SPINRATE roll.state = CPS_ACTIVE START_CARWASH_HROLLER_PARTICLES(roll) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iMoveSoundID) roll.iMoveSoundID = GET_SOUND_ID() PLAY_SOUND_FROM_ENTITY(roll.iMoveSoundID, "BRUSHES_MOVE", roll.rollerID, "CARWASH_SOUNDS") ENDIF ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() AND NOT IS_ANY_NET_PLAYER_DRIVING_IN_CARWASH() roll.state = CPS_SHUTDOWN ENDIF BREAK CASE CPS_ACTIVE IF (bSomeOneIn = FALSE) roll.state = CPS_SHUTDOWN ELIF (GET_GAME_TIMER() > roll.iNextCheckTime) IF NOT IS_CARWASH_POSITION_OCCUPIED(v, roll.fTriggerDist) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID) roll.state = CPS_SHUTDOWN ENDIF roll.iNextCheckTime = GET_GAME_TIMER() + ROLLER_CHECK_INTERVAL ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() AND NOT IS_ANY_NET_PLAYER_DRIVING_IN_CARWASH() roll.state = CPS_SHUTDOWN ENDIF BREAK CASE CPS_SHUTDOWN roll.shapetestID = NULL SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iHitSoundID) roll.fSpinRate -= tStep //bDoShapeTest = TRUE IF (roll.fSpinRate <= 0) roll.fSpinRate = 0 roll.state = CPS_NULL SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iMoveSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iSpinSoundID) ENDIF BREAK ENDSWITCH roll.fRollerSpinAngle += roll.fSpinRate * TIMESTEP() IF (roll.fRollerSpinAngle > 360.0) roll.fRollerSpinAngle -= 360.0 ENDIF _UPDATE_CARWASH_HROLLER_INTERNAL(roll) SET_ENTITY_HEADING(roll.rollerID, roll.fRollerPivotAngle) SET_ENTITY_ROTATION(roll.rollerID, GET_ENTITY_ROTATION(roll.rollerID) + <>) ENDPROC /// PURPOSE: /// Create the carwash horizontal roller /// PARAMS: /// roll - roller reference /// pos - position of the roller arm joint /// head - heading PROC CREATE_CARWASH_HROLLER(CARWASH_HROLLER &roll, VECTOR pos, FLOAT head = 0.0, FLOAT gz = 0.0) FLOAT z roll.vPosition = pos roll.rollerID = CREATE_OBJECT(PROP_CARWASH_ROLLER_HORZ, pos, FALSE) roll.vContactPoint = pos roll.fTargetZ = pos.z roll.fOriginalZ = pos.z roll.fRollerPivotAngle = head roll.bSetup = TRUE roll.iNextCheckTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(1, ROLLER_CHECK_INTERVAL) roll.iNextShapeTestTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(2, SHAPE_CHECK_INTERVAL) roll.fTriggerDist = ROLLER_TRIGGER_DIST IF (gz = 0.0) IF GET_GROUND_Z_FOR_3D_COORD(pos, z) IF (z <> 0) AND (z <> INVALID_WORLD_Z) roll.fGroundZero = z + ROLLER_RADIUS CPRINTLN(DEBUG_MISSION, "[CARWASH] - HRoller GroundZero:", roll.fGroundZero) ENDIF ENDIF ELSE roll.fGroundZero = gz ENDIF IF IS_ENTITY_OK(roll.rollerID) SET_ENTITY_HEADING(roll.rollerID, head) FREEZE_ENTITY_POSITION(roll.rollerID, TRUE) SET_ENTITY_COLLISION(roll.rollerID, TRUE) SET_ENTITY_INVINCIBLE(roll.rollerID, TRUE) //SET_ENTITY_HAS_GRAVITY(roll.rollerID, FALSE) ENDIF // we need to do a forced update here so the roller can find the ground point UPDATE_CARWASH_HROLLER(roll) ENDPROC //---------------------- // VERTROLLER FUNCTIONS //---------------------- PROC START_CARWASH_VERTROLLER_PARTICLES(CARWASH_VROLLER2 &roll) INT i REPEAT COUNT_OF(roll.rollerID) i SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[i]) IF IS_ENTITY_OK(roll.rollerID[i]) //AND NOT (g_bInMultiplayer) IF NOT DOES_PARTICLE_FX_LOOPED_EXIST(roll.fxBrushID[i]) roll.fxBrushID[i] = START_PARTICLE_FX_LOOPED_ON_ENTITY("ent_amb_car_wash", roll.rollerID[i], vRollerVertPosFX, vRollerVertRotFX) ENDIF ENDIF ENDREPEAT ENDPROC PROC SHUTDOWN_CARWASH_VERTROLLER(CARWASH_VROLLER2 &roll) IF IS_CARWASH_PART_RUNNING(roll.state) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[0]) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[1]) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iMoveSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iSpinSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iHitSoundID) roll.state = CPS_NULL ENDIF ENDPROC PROC SHARED_CLEANUP_DELETE_CARWASH_VERTROLLER(CARWASH_VROLLER2 &roll) roll.state = CPS_NULL SHUTDOWN_CARWASH_VERTROLLER(roll) SAFE_DELETE_OBJECT(roll.pivotID) ENDPROC /// PURPOSE: /// Update the dual roller /// PARAMS: /// roll - roller reference PROC CLEANUP_CARWASH_VERTROLLER(CARWASH_VROLLER2 &roll) SHARED_CLEANUP_DELETE_CARWASH_VERTROLLER(roll) SAFE_RELEASE_OBJECT(roll.rollerID[0]) SAFE_RELEASE_OBJECT(roll.rollerID[1]) ENDPROC /// PURPOSE: /// Update the dual roller /// PARAMS: /// roll - roller reference PROC DELETE_CARWASH_VERTROLLER(CARWASH_VROLLER2 &roll) SHARED_CLEANUP_DELETE_CARWASH_VERTROLLER(roll) SAFE_DELETE_OBJECT(roll.rollerID[0]) SAFE_DELETE_OBJECT(roll.rollerID[1]) ENDPROC PROC UPDATE_CARWASH_VERTROLLER_MOVEMENT(CARWASH_VROLLER2 &roll) INT i FLOAT fOldSpinAngle = roll.fRollerSpinAngle FLOAT fOldOffset[2] // handle and moving spinning IF (roll.fSpinRate >= ROLLER_SPINRATE) roll.fSpinRate = ROLLER_SPINRATE ENDIF IF (roll.fSpinRate <= 0) roll.fSpinRate = 0 ENDIF roll.fRollerSpinAngle += roll.fSpinRate * TIMESTEP() IF (roll.fRollerSpinAngle < 0) roll.fRollerSpinAngle += 360.0 ENDIF IF (roll.fRollerSpinAngle > 360.0) roll.fRollerSpinAngle -= 360.0 ENDIF REPEAT COUNT_OF(roll.rollerID) i fOldOffset[i] = roll.fOffset[i] IF (roll.fOffset[i] < roll.fTgtOffset[i]) roll.fOffset[i] += roll.fMoveRate * TIMESTEP() IF (roll.fOffset[i] > roll.fTgtOffset[i]) DO_CARWASH_PAD_RUMBLE(SHAPE_CHECK_INTERVAL, 64) roll.fOffset[i] = roll.fTgtOffset[i] ENDIF ENDIF IF (roll.fOffset[i] > roll.fTgtOffset[i]) roll.fOffset[i] -= roll.fMoveRate * TIMESTEP() IF (roll.fOffset[i] < roll.fTgtOffset[i]) DO_CARWASH_PAD_RUMBLE(SHAPE_CHECK_INTERVAL, 64) roll.fOffset[i] = roll.fTgtOffset[i] ENDIF ENDIF IF (fOldOffset[i] <> roll.fOffset[i]) SET_ENTITY_COORDS(roll.rollerID[i], GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <>)) ENDIF IF (fOldSpinAngle <> roll.fRollerSpinAngle) SET_ENTITY_HEADING(roll.rollerID[i], roll.fRollerSpinAngle) ENDIF ENDREPEAT ENDPROC PROC UPDATE_CARWASH_VERTROLLER_COLLISION(CARWASH_VROLLER2 &roll) IF (roll.bCollisionOn <> roll.bOldCollision) CPRINTLN(DEBUG_MISSION, "TURNING BRUSH ROL COLLISION:", roll.bCollisionOn) SET_ENTITY_COLLISION(roll.rollerID[0], roll.bCollisionOn) SET_ENTITY_COLLISION(roll.rollerID[1], roll.bCollisionOn) ENDIF roll.bOldCollision = roll.bCollisionOn ENDPROC /// PURPOSE: /// Update the dual roller /// PARAMS: /// roll - roller reference PROC UPDATE_CARWASH_VERTROLLER(CARWASH_VROLLER2 &roll, BOOL bSomeOneIn = TRUE, BOOL bAborted = FALSE) VECTOR vec FLOAT tStep = ROLLER_SPINRATE * TIMESTEP() VECTOR v1, v2 ENTITY_INDEX hitEntity SHAPETEST_STATUS shapeStatus VECTOR vHitPos, vHitNormal INT i, iHits PLANE_SIDE psd //FLOAT fDist FLOAT vWidth FLOAT vLength VECTOR vvMin, vvMax VEHICLE_INDEX vehicleIndex INT iDriverSeatBoneIndex = -1 IF NOT roll.bSetup = TRUE EXIT ENDIF UPDATE_CARWASH_VERTROLLER_MOVEMENT(roll) IF IS_CARWASH_PART_RUNNING(roll.state) IF (bSomeOneIn = FALSE) CPRINTLN(DEBUG_MISSION, "Carwash VRoller - Shutdown No One is In Carwash") roll.state = CPS_SHUTDOWN ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() AND NOT IS_ANY_NET_PLAYER_DRIVING_IN_CARWASH() CPRINTLN(DEBUG_MISSION, "Carwash VRoller - NET Shutdown No One is In Carwash") bSomeOneIn = FALSE roll.state = CPS_SHUTDOWN ENDIF IF (bSomeOneIn = FALSE) roll.fSpinRate -= (tStep * 2.0) IF (roll.fSpinRate <= 0) roll.fSpinRate = 0 SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iMoveSoundID) ENDIF ENDIF ELSE roll.fSpinRate -= (tStep * 2.0) IF (roll.fSpinRate <= 0) roll.fSpinRate = 0 SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iMoveSoundID) ENDIF ENDIF // check sensors FLOAT fFirstCheckYShift = -1.5 // we shift the file in check by this abount FLOAT fCheckYShift = -ROLLER_RADIUS // BOOL bBrushesDone IF NOT (bAborted) AND (roll.state <> CPS_SHUTDOWN) IF (GET_GAME_TIMER() > roll.iNextShapeTestTime) vec = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, roll.fSensorOffset[0], 0>>) roll.bSensorOn[0] = IS_CARWASH_POSITION_OCCUPIED(vec, roll.fSensorRadius[0]) vec = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, roll.fSensorOffset[1], 0>>) roll.bSensorOn[1] = IS_CARWASH_POSITION_OCCUPIED(vec, roll.fSensorRadius[1]) roll.iNextShapeTestTime = GET_GAME_TIMER() + SHAPE_CHECK_INTERVAL ENDIF IF (bDrawDebugCarwash = TRUE) vec = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, roll.fSensorOffset[0], 0>>) IF (roll.bSensorOn[0]) DRAW_DEBUG_CIRCLE(vec, roll.fSensorRadius[0], 0, 255, 0, 255) ELSE DRAW_DEBUG_CIRCLE(vec, roll.fSensorRadius[0], 255, 0, 0, 255) ENDIF vec = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, roll.fSensorOffset[1], 0>>) IF (roll.bSensorOn[1]) DRAW_DEBUG_CIRCLE(vec, roll.fSensorRadius[1], 0, 255, 0, 255) ELSE DRAW_DEBUG_CIRCLE(vec, roll.fSensorRadius[1], 0, 0, 255, 255) ENDIF DRAW_DEBUG_LINE(GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<-2.5, fFirstCheckYShift, VROLLER_CHECKZSHIFT>>), GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<2.5, fFirstCheckYShift, VROLLER_CHECKZSHIFT>>)) vec = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, 0, VROLLER_CHECKZSHIFT>>) DRAW_DEBUG_LINE(vec, vec + GET_ENTITY_FORWARD_VECTOR(roll.pivotID)) ENDIF ENDIF SWITCH (roll.state) CASE CPS_NULL IF NOT (bAborted) IF (bSomeOneIn = TRUE) AND (roll.bSensorOn[0]) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iSpinSoundID) roll.iSpinSoundID = GET_SOUND_ID() PLAY_SOUND_FROM_ENTITY(roll.iSpinSoundID, "BRUSHES_SPINNING", roll.pivotID, "CARWASH_SOUNDS") roll.fTgtOffset[0] = -ROLLER_RADIUS roll.fTgtOffset[1] = ROLLER_RADIUS CPRINTLN(DEBUG_MISSION, "[CARWASH] - VERT BRUSHES ACTIVATED") roll.bCollisionOn = FALSE CPRINTLN(DEBUG_MISSION, "[CARWASH] - TURNING BRUSH COLLISION OFF ON STARTUP") //SET_ENTITY_COLLISION(roll.rollerID[0], roll.bCollisionOn) //SET_ENTITY_COLLISION(roll.rollerID[1], roll.bCollisionOn) roll.state = CPS_STARTUP roll.bHitCheck[0] = FALSE roll.bHitCheck[1] = FALSE roll.bOldHitCheck[0] = FALSE roll.bOldHitCheck[1] = FALSE ENDIF ENDIF BREAK CASE CPS_STARTUP roll.fSpinRate += tStep vec = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, roll.fSensorOffset[0], 0>>) vehicleIndex = GET_RANDOM_VEHICLE_IN_SPHERE(vec, 2.0, DUMMY_MODEL_FOR_SCRIPT, VEHICLE_SEARCH_FLAG_RETURN_VEHICLES_CONTAINING_A_PLAYER | VEHICLE_SEARCH_FLAG_ALLOW_VEHICLE_OCCUPANTS_TO_BE_PERFORMING_A_SCRIPTED_TASK) IF CHECK_ENTITY_IS_VEHICLE_OK(vehicleIndex) SET_ENTITY_NO_COLLISION_ENTITY(vehicleIndex, roll.rollerID[0], TRUE) SET_ENTITY_NO_COLLISION_ENTITY(vehicleIndex, roll.rollerID[1], TRUE) CPRINTLN(DEBUG_MISSION, "[CARWASH] - COLLISION OFF BETWEEN BUMPERS") ENDIF IF (roll.fSpinRate >= ROLLER_SPINRATE) roll.fSpinRate = ROLLER_SPINRATE START_CARWASH_VERTROLLER_PARTICLES(roll) roll.iMoveSoundID = GET_SOUND_ID() PLAY_SOUND_FROM_ENTITY(roll.iMoveSoundID, "BRUSHES_MOVE", roll.pivotID, "CARWASH_SOUNDS") CPRINTLN(DEBUG_MISSION, "[CARWASH] - VERT BRUSH SPIN UP COMPLETE") roll.state = CPS_WARMUP ENDIF BREAK CASE CPS_WARMUP IF (roll.shapeTestID = NULL) IF (bUseOldVerticleBrushCheck) vec = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, -1, 0>>) roll.shapeTestID = START_SHAPE_TEST_CAPSULE(vec, vec + <<0, 0, 1>>, 2.5, SCRIPT_INCLUDE_VEHICLE) ELSE vec = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<-3.0, fFirstCheckYShift, VROLLER_CHECKZSHIFT>>) roll.shapeTestID = START_SHAPE_TEST_LOS_PROBE(vec, GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, fFirstCheckYShift, VROLLER_CHECKZSHIFT>>), SCRIPT_INCLUDE_VEHICLE) ENDIF IF (roll.shapeTestID = NULL) CPRINTLN(DEBUG_MISSION, "[CARWASH] - UPDATE_CARWASH_VERTROLLER - CPS_WARMUP - CAN'T GET VALID SHAPE TEST") ENDIF ELSE shapeStatus = GET_SHAPE_TEST_RESULT(roll.shapeTestID, iHits, vHitPos, vHitNormal, hitEntity) IF (shapeStatus = SHAPETEST_STATUS_RESULTS_READY) IF CHECK_ENTITY_IS_VEHICLE_OK(hitEntity) roll.activeVehicle = GET_VEHICLE_INDEX_FROM_ENTITY_INDEX(hitEntity) IF IS_ENTITY_ALIVE(roll.activeVehicle) CPRINTLN(DEBUG_MISSION, "[CARWASH] - ACTIVE VEHICLE XX GET:", GET_MODEL_NAME_OF_VEHICLE_FOR_DEBUG_ONLY(roll.activeVehicle)) ELSE CPRINTLN(DEBUG_MISSION, "[CARWASH] - ACTIVE VEHICLE XX GET: dead vehicle") ENDIF GET_MODEL_DIMENSIONS(GET_ENTITY_MODEL(roll.activeVehicle), vvMin, vvMax) vWidth = ABSF(vvMax.x - vvMin.x) IF (bUseOldVerticleBrushCheck) CPRINTLN(DEBUG_MISSION, "[CARWASH] - USING OLD STYLE BRUSH CHECK:") roll.fTgtOffset[0] = -((ROLLER_RADIUS * 0.75) + (vWidth / 2.0)) roll.fTgtOffset[1] = (ROLLER_RADIUS * 0.75) + (vWidth / 2.0) ELSE vec = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(roll.pivotID, vHitPos + (GET_ENTITY_FORWARD_VECTOR(roll.pivotID) * -fFirstCheckYShift)) CPRINTLN(DEBUG_MISSION, "[CARWASH] - VROLLER MOVE RATE IS 1.5") roll.fMoveRate = 1.5 //roll.fTgtOffset[0] = v.x - ROLLER_RADIUS //roll.fTgtOffset[1] = (v.x * -1) + ROLLER_RADIUS ENDIF IF (iHits = 0) CPRINTLN(DEBUG_MISSION, "[CARWASH] - SOMETHING HAS COCKED UP HERE DEFAULTING TO DEFAULT WIDTH") roll.fTgtOffset[0] = -((ROLLER_RADIUS) + (vWidth / 2.0)) roll.fTgtOffset[1] = (ROLLER_RADIUS) + (vWidth / 2.0) ENDIF roll.state = CPS_ACTIVE roll.fMoveRate = 1.5 roll.bHitCheck[0] = FALSE roll.bHitCheck[1] = FALSE roll.bOldHitCheck[0] = FALSE roll.bOldHitCheck[1] = FALSE roll.iNextBrushShapeTestTime[0] = GET_GAME_TIMER() + 32 roll.iNextBrushShapeTestTime[1] = GET_GAME_TIMER() + 64 ENDIF ENDIF roll.shapeTestID = NULL ENDIF BREAK CASE CPS_ACTIVE // wait till car is in front of brushes before pulling them in. IF IS_ENTITY_ALIVE(roll.activeVehicle) SET_ENTITY_NO_COLLISION_ENTITY(roll.activeVehicle, roll.rollerID[0], TRUE) SET_ENTITY_NO_COLLISION_ENTITY(roll.activeVehicle, roll.rollerID[1], TRUE) GET_MODEL_DIMENSIONS(GET_ENTITY_MODEL(roll.activeVehicle), vvMin, vvMax) vLength = ABSF(vvMax.y - vvMin.y) / 2.0 vWidth = ABSF(vvMax.x - vvMin.x) psd = GET_PLANE_SIDE(GET_ENTITY_FORWARD_VECTOR(roll.pivotID), GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, vLength, 0>>), GET_ENTITY_COORDS(roll.activeVehicle)) IF (psd = INFRONT_PLANE) roll.fTgtOffset[0] = -(ROLLER_RADIUS) roll.fTgtOffset[1] = (ROLLER_RADIUS) ELSE IF (bUseOldVerticleBrushCheck) CPRINTLN(DEBUG_MISSION, "[CARWASH] - USING OLD STYLE BRUSH CHECK:") roll.fTgtOffset[0] = -((ROLLER_RADIUS * ROLLER_SHIFT_FACTOR) + (vWidth / 2.0)) roll.fTgtOffset[1] = (ROLLER_RADIUS * ROLLER_SHIFT_FACTOR) + (vWidth / 2.0) CPRINTLN(DEBUG_MISSION, "[CARWASH] - VROLLER MOVE RATE IS 1.0") roll.fMoveRate = 1.0 ELSE REPEAT COUNT_OF(roll.rollerID) i v1 = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, fCheckYShift, VROLLER_CHECKZSHIFT>>) IF (i = 0) v2 = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<-fShapeTestXSeperation, fCheckYShift, VROLLER_CHECKZSHIFT>>) ELSE v2 = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <>) ENDIF iDriverSeatBoneIndex = GET_ENTITY_BONE_INDEX_BY_NAME(roll.activeVehicle, "seat_dside_f") IF (iDriverSeatBoneIndex <> -1) vec = GET_WORLD_POSITION_OF_ENTITY_BONE(roll.activeVehicle, iDriverSeatBoneIndex) v1.z = vec.z v2.z = vec.z ENDIF IF bDrawDebugCarwash DRAW_DEBUG_LINE(v1, v2) ENDIF IF (roll.brushShapeTestID[i] = NULL) IF (GET_GAME_TIMER() > roll.iNextBrushShapeTestTime[i]) IF (bUseNewSweptSphereTest = TRUE) OR (GET_VEHICLE_MOD(roll.activeVehicle, MOD_SPOILER) != -1) roll.brushShapeTestID[i] = START_SHAPE_TEST_SWEPT_SPHERE(v2, v1, fSweepSphereRadius, SCRIPT_INCLUDE_VEHICLE) ELSE roll.brushShapeTestID[i] = START_SHAPE_TEST_LOS_PROBE(v2, v1, SCRIPT_INCLUDE_VEHICLE) ENDIF IF (roll.brushShapeTestID[i] = NULL) CPRINTLN(DEBUG_MISSION, "[CARWASH]: CAN'T GET SHAPETEST FOR VERTICAL BRUSH ", i) ENDIF ENDIF ELSE shapeStatus = GET_SHAPE_TEST_RESULT(roll.brushShapeTestID[i], iHits, vHitPos, vHitNormal, hitEntity) IF (shapeStatus = SHAPETEST_STATUS_RESULTS_READY) roll.bOldHitCheck[i] = roll.bHitCheck[i] roll.bHitCheck[i] = FALSE IF (iHits > 0) IF (bDrawDebugCarwash) DRAW_DEBUG_SPHERE(vHitPos, 0.06625) ENDIF //CPRINTLN(DEBUG_MISSION, "HIT HIT HIT - BRUSH:", i) roll.bHitCheck[i] = TRUE ENDIF IF CHECK_ENTITY_IS_VEHICLE_OK(hitEntity) vec = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(roll.pivotID, vHitPos + (GET_ENTITY_FORWARD_VECTOR(roll.pivotID) * -fCheckYShift)) roll.bHitCheck[i] = TRUE IF (i = 0) roll.fTgtOffset[i] = vec.x - ROLLER_RADIUS ELSE roll.fTgtOffset[i] = vec.x + ROLLER_RADIUS ENDIF ENDIF ENDIF roll.brushShapeTestID[i] = NULL roll.iNextBrushShapeTestTime[i] = GET_GAME_TIMER() + 120 ENDIF IF (roll.bOldHitCheck[i] <> roll.bHitCheck[i]) IF (roll.bOldHitCheck[i] = TRUE) AND (roll.bHitCheck[i] = FALSE) CPRINTLN(DEBUG_MISSION, "CARWASH BRUSH ", i, " ISN'T HITTING ANYTHING ANY MORE") // bBrushesDone = true ENDIF IF (roll.bOldHitCheck[i] = FALSE) AND (roll.bHitCheck[i] = TRUE) CPRINTLN(DEBUG_MISSION, "CARWASH BRUSH ", i, " HAS STARTED HITTING THINGS") ENDIF ENDIF ENDREPEAT // // STH: Removed bBrushesDone for b*2019238 - The hit test was briefly returning false in middle of cars pass through rollers, so the rollers came together and clipped through rest of the car // IF (bBrushesDone = TRUE) // CPRINTLN(DEBUG_MISSION, "CARWASH BRUSHED START WARM DOWN") // roll.fTgtOffset[0] = -(ROLLER_RADIUS) // roll.fTgtOffset[1] = (ROLLER_RADIUS) // roll.fMoveRate = roll.fShutDownMoveRate // CPRINTLN(DEBUG_MISSION, "[CARWASH] - VROLLER MOVE RATE IS ", roll.fShutDownMoveRate) // SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[0]) // SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[1]) // roll.state = CPS_WARMDOWN // EXIT // ENDIF ENDIF ENDIF // check to see if car is properly in front of point psd = GET_PLANE_SIDE(GET_ENTITY_FORWARD_VECTOR(roll.pivotID), GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, vLength * 1.25, 0>>), GET_ENTITY_COORDS(roll.activeVehicle)) IF (psd = INFRONT_PLANE) roll.fSpinRate -= (tStep * 2) IF (roll.fSpinRate < 0) roll.fSpinRate = 0 SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iHitSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iSpinSoundID) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[0]) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[1]) CPRINTLN(DEBUG_MISSION, "[CARWASH] - BRUSHES ARE IN FRONT TURNING THEM OFF") ENDIF ENDIF ENDIF IF NOT (roll.bSensorOn[0] OR roll.bSensorOn[1]) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[0]) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[1]) CPRINTLN(DEBUG_MISSION, "[CARWASH] - SHUTDOWN SPIN RATE:", roll.fSpinRate) roll.state = CPS_SHUTDOWN ENDIF BREAK CASE CPS_WARMDOWN IF IS_ENTITY_ALIVE(roll.activeVehicle) SET_ENTITY_NO_COLLISION_ENTITY(roll.activeVehicle, roll.rollerID[0], TRUE) SET_ENTITY_NO_COLLISION_ENTITY(roll.activeVehicle, roll.rollerID[1], TRUE) GET_MODEL_DIMENSIONS(GET_ENTITY_MODEL(roll.activeVehicle), vvMin, vvMax) vLength = ABSF(vvMax.y - vvMin.y) / 2.0 vWidth = ABSF(vvMax.x - vvMin.x) // check to see if car is properly in front of point psd = GET_PLANE_SIDE(GET_ENTITY_FORWARD_VECTOR(roll.pivotID), GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, vLength * 1.25, 0>>), GET_ENTITY_COORDS(roll.activeVehicle)) IF (psd = INFRONT_PLANE) roll.fSpinRate -= (tStep * 2) IF (roll.fSpinRate < 0) roll.fSpinRate = 0 SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iHitSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iSpinSoundID) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[0]) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[1]) roll.state = CPS_SHUTDOWN //CPRINTLN(DEBUG_MISSION, "[CARWASH] - BRUSHES ARE IN FRONT TURNING THEM OFF") ENDIF ENDIF ENDIF IF NOT (roll.bSensorOn[0] OR roll.bSensorOn[1]) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[0]) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[1]) CPRINTLN(DEBUG_MISSION, "[CARWASH] - SHUTDOWN SPIN RATE:", roll.fSpinRate) roll.state = CPS_SHUTDOWN ENDIF BREAK CASE CPS_SHUTDOWN SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iHitSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iSpinSoundID) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[0]) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[1]) roll.fSpinRate -= tStep roll.fTgtOffset[0] = -VROLLER_SEP //-ROLLER_RADIUS * 2.0 roll.fTgtOffset[1] = VROLLER_SEP //ROLLER_RADIUS * 2.0 roll.fMoveRate = 1.5 CPRINTLN(DEBUG_MISSION, "[CARWASH] - VROLLER MOVE RATE IS ", roll.fMoveRate) roll.bHitCheck[0] = FALSE roll.bHitCheck[1] = FALSE roll.bOldHitCheck[0] = FALSE roll.bOldHitCheck[1] = FALSE IF (roll.fSpinRate <= 0) roll.fSpinRate = 0 SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iMoveSoundID) ENDIF // if aborted wait till area is clear before allowing collsion to turn back on IF (GET_GAME_TIMER() > roll.iNextShapeTestTime) IF NOT IS_CARWASH_POSITION_OCCUPIED(roll.vBasePosition, 1.0) roll.bCollisionOn = TRUE CPRINTLN(DEBUG_MISSION, "[CARWASH] - TURNING BRUSH COLLISION ON AFTER SHUTDOWN") SET_ENTITY_COLLISION(roll.rollerID[0], roll.bCollisionOn) SET_ENTITY_COLLISION(roll.rollerID[1], roll.bCollisionOn) roll.iNextShapeTestTime = 0 roll.state = CPS_NULL ELSE roll.iNextShapeTestTime = GET_GAME_TIMER() + SHAPE_CHECK_INTERVAL ENDIF ENDIF BREAK ENDSWITCH ENDPROC /// PURPOSE: /// Update the dual roller /// PARAMS: /// roll - roller reference PROC UPDATE_CARWASH_VERTROLLER_MP(CARWASH_VROLLER2 &roll, BOOL bSomeOneIn = TRUE, BOOL bAborted = FALSE) VECTOR vec, v1, v2 VEHICLE_INDEX vehicleIndex FLOAT fFirstCheckYShift = -1.5 // we shift the file in check by this abount FLOAT fCheckYShift = -ROLLER_RADIUS INT i, iHits ENTITY_INDEX hitEntity SHAPETEST_STATUS shapeStatus VECTOR vHitPos, vHitNormal FLOAT tStep = ROLLER_SPINRATE * TIMESTEP() INT iDriverSeatBoneIndex = -1 PLANE_SIDE psd FLOAT vLength VECTOR vvMin, vvMax IF NOT roll.bSetup = TRUE EXIT ENDIF UPDATE_CARWASH_VERTROLLER_MOVEMENT(roll) IF IS_CARWASH_PART_RUNNING(roll.state) IF (bSomeOneIn = FALSE) CPRINTLN(DEBUG_MISSION, "Carwash VRoller - Shutdown No One is In Carwash") roll.state = CPS_SHUTDOWN ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() AND NOT IS_ANY_NET_PLAYER_DRIVING_IN_CARWASH() CPRINTLN(DEBUG_MISSION, "Carwash VRoller - NET Shutdown No One is In Carwash") bSomeOneIn = FALSE roll.state = CPS_SHUTDOWN ENDIF IF (bSomeOneIn = FALSE) roll.fSpinRate -= (tStep * 2.0) IF (roll.fSpinRate <= 0) roll.fSpinRate = 0 SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iMoveSoundID) ENDIF ENDIF ELSE roll.fSpinRate -= (tStep * 2.0) IF (roll.fSpinRate <= 0) roll.fSpinRate = 0 SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iMoveSoundID) ENDIF ENDIF // update sensors IF NOT (bAborted) AND (roll.state <> CPS_SHUTDOWN) IF (GET_GAME_TIMER() > roll.iNextShapeTestTime) vec = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, roll.fSensorOffset[0], 0>>) roll.bSensorOn[0] = IS_CARWASH_POSITION_OCCUPIED(vec, roll.fSensorRadius[0]) vec = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, roll.fSensorOffset[1], 0>>) roll.bSensorOn[1] = IS_CARWASH_POSITION_OCCUPIED(vec, roll.fSensorRadius[1]) roll.iNextShapeTestTime = GET_GAME_TIMER() + SHAPE_CHECK_INTERVAL ENDIF ENDIF // draw debug for sensors IF (bDrawDebugCarwash = TRUE) vec = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, roll.fSensorOffset[0], 0>>) IF (roll.bSensorOn[0]) DRAW_DEBUG_CIRCLE(vec, roll.fSensorRadius[0], 0, 255, 0, 255) ELSE DRAW_DEBUG_CIRCLE(vec, roll.fSensorRadius[0], 255, 0, 0, 255) ENDIF vec = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, roll.fSensorOffset[1], 0>>) IF (roll.bSensorOn[1]) DRAW_DEBUG_CIRCLE(vec, roll.fSensorRadius[1], 0, 255, 0, 255) ELSE DRAW_DEBUG_CIRCLE(vec, roll.fSensorRadius[1], 0, 0, 255, 255) ENDIF DRAW_DEBUG_LINE(GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<-2.5, fFirstCheckYShift, VROLLER_CHECKZSHIFT>>), GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<2.5, fFirstCheckYShift, VROLLER_CHECKZSHIFT>>)) vec = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, 0, VROLLER_CHECKZSHIFT>>) DRAW_DEBUG_LINE(vec, vec + GET_ENTITY_FORWARD_VECTOR(roll.pivotID)) ENDIF // update state SWITCH (roll.state) CASE CPS_NULL // if the front sensor is on run shape test IF NOT (roll.bSensorOn[0]) EXIT ENDIF IF (roll.shapeTestID = NULL) vec = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, roll.fSensorOffset[0], 0>>) roll.shapeTestID = START_SHAPE_TEST_CAPSULE(vec, vec + <<0, 0, 1>>, 2.25, SCRIPT_INCLUDE_VEHICLE) ELSE shapeStatus = GET_SHAPE_TEST_RESULT(roll.shapeTestID, iHits, vHitPos, vHitNormal, hitEntity) IF (shapeStatus = SHAPETEST_STATUS_RESULTS_READY) IF CHECK_ENTITY_IS_VEHICLE_OK(hitEntity) vehicleIndex = GET_VEHICLE_INDEX_FROM_ENTITY_INDEX(hitEntity) IF IS_DIRECTION_WITHIN_DEGRESS_OF_DESIRED_DIRECTION_SIGNED(GET_ENTITY_FORWARD_VECTOR(vehicleIndex), GET_ENTITY_FORWARD_VECTOR(roll.pivotID), 10.0) CPRINTLN(DEBUG_MISSION, "[CARWASH] - PLAYER IS POINTING THE RIGHT WAY") vec = GET_ENTITY_SPEED_VECTOR(vehicleIndex, TRUE) IF (vec.y <= 0) CPRINTLN(DEBUG_MISSION, "[CARWASH] - PLAYER IS POINTING THE RIGHT WAY BUT IS REVERSING OR STOPPED") ELSE roll.state = CPS_STARTUP roll.activeVehicle = vehicleIndex SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iSpinSoundID) roll.iSpinSoundID = GET_SOUND_ID() PLAY_SOUND_FROM_ENTITY(roll.iSpinSoundID, "BRUSHES_SPINNING", roll.pivotID, "CARWASH_SOUNDS") CPRINTLN(DEBUG_MISSION, "[CARWASH] - PLAYER IS POINTING THE RIGHT WAY AND MOVING IN THE RIGHT WAY") ENDIF ENDIF ENDIF ENDIF roll.shapeTestID = NULL ENDIF BREAK CASE CPS_STARTUP roll.fSpinRate += tStep SET_ENTITY_NO_COLLISION_ENTITY(roll.activeVehicle, roll.rollerID[0], TRUE) SET_ENTITY_NO_COLLISION_ENTITY(roll.activeVehicle, roll.rollerID[1], TRUE) IF IS_ENTITY_ALIVE(roll.activeVehicle) CPRINTLN(DEBUG_MISSION, "[CARWASH] - COLLISION OFF BETWEEN BUMPERS AND ", GET_MODEL_NAME_OF_VEHICLE_FOR_DEBUG_ONLY(roll.activeVehicle)) ELSE CPRINTLN(DEBUG_MISSION, "[CARWASH] - COLLISION OFF BETWEEN BUMPERS AND dead vehicle") ENDIF IF (roll.fSpinRate >= ROLLER_SPINRATE) roll.fSpinRate = ROLLER_SPINRATE START_CARWASH_VERTROLLER_PARTICLES(roll) roll.iMoveSoundID = GET_SOUND_ID() PLAY_SOUND_FROM_ENTITY(roll.iMoveSoundID, "BRUSHES_MOVE", roll.pivotID, "CARWASH_SOUNDS") CPRINTLN(DEBUG_MISSION, "[CARWASH] - VERT BRUSH SPIN UP COMPLETE") roll.state = CPS_WARMUP ENDIF BREAK CASE CPS_WARMUP CPRINTLN(DEBUG_MISSION, "[CARWASH] - SET VERTROLL STATE - CPS_ACTIVE") roll.state = CPS_ACTIVE BREAK CASE CPS_ACTIVE IF NOT CHECK_ENTITY_IS_VEHICLE_OK(roll.activeVehicle) roll.state = CPS_WARMDOWN EXIT ENDIF IF NOT IS_CARWASH_PED_OK(GET_PED_IN_VEHICLE_SEAT(roll.activeVehicle)) CPRINTLN(DEBUG_MISSION, "[CARWASH] - SET VERTROLL STATE - CPS_WARMDOWN - PED IN CAR IS NOT OKAY") roll.state = CPS_WARMDOWN EXIT ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() AND NOT IS_ANY_NET_PLAYER_DRIVING_IN_CARWASH() roll.state = CPS_WARMDOWN EXIT ENDIF // wait for vehicle to leave GET_MODEL_DIMENSIONS(GET_ENTITY_MODEL(roll.activeVehicle), vvMin, vvMax) vLength = ABSF(vvMax.y - vvMin.y) / 2.0 psd = GET_PLANE_SIDE(GET_ENTITY_FORWARD_VECTOR(roll.pivotID), GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<0, vLength, 0>>), GET_ENTITY_COORDS(roll.activeVehicle)) IF (psd = INFRONT_PLANE) roll.fTgtOffset[0] = -(ROLLER_RADIUS) roll.fTgtOffset[1] = (ROLLER_RADIUS) CPRINTLN(DEBUG_MISSION, "[CARWASH] - SET VERTROLL STATE - CPS_WARMDOWN - CAR HAS GONE PAST BRUSHES") roll.state = CPS_WARMDOWN EXIT ENDIF REPEAT COUNT_OF(roll.rollerID) i IF (i = 0) v1 = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<1.0, fCheckYShift, VROLLER_CHECKZSHIFT>>) v2 = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<-fShapeTestXSeperation, fCheckYShift, VROLLER_CHECKZSHIFT>>) ELSE v1 = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<-1.0, fCheckYShift, VROLLER_CHECKZSHIFT>>) v2 = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <>) ENDIF iDriverSeatBoneIndex = GET_ENTITY_BONE_INDEX_BY_NAME(roll.activeVehicle, "seat_dside_f") IF (iDriverSeatBoneIndex <> -1) vec = GET_WORLD_POSITION_OF_ENTITY_BONE(roll.activeVehicle, iDriverSeatBoneIndex) v1.z = vec.z v2.z = vec.z ENDIF IF (roll.brushShapeTestID[i] = NULL) IF (GET_GAME_TIMER() > roll.iNextBrushShapeTestTime[i]) IF (bUseNewSweptSphereTest = TRUE) OR (GET_VEHICLE_MOD(roll.activeVehicle, MOD_SPOILER) != -1) roll.brushShapeTestID[i] = START_SHAPE_TEST_SWEPT_SPHERE(v2, v1, fSweepSphereRadius, SCRIPT_INCLUDE_VEHICLE) ELSE roll.brushShapeTestID[i] = START_SHAPE_TEST_LOS_PROBE(v2, v1, SCRIPT_INCLUDE_VEHICLE) ENDIF IF (roll.brushShapeTestID[i] = NULL) CPRINTLN(DEBUG_MISSION, "[CARWASH]: CAN'T GET SHAPETEST FOR VERTICAL BRUSH ", i) ENDIF ENDIF ELSE shapeStatus = GET_SHAPE_TEST_RESULT(roll.brushShapeTestID[i], iHits, vHitPos, vHitNormal, hitEntity) IF (shapeStatus = SHAPETEST_STATUS_RESULTS_READY) roll.bOldHitCheck[i] = roll.bHitCheck[i] roll.bHitCheck[i] = FALSE IF (iHits > 0) //IF (bDrawDebugCarwash) DRAW_DEBUG_SPHERE(vHitPos, 0.06625) //ENDIF roll.bHitCheck[i] = TRUE ENDIF IF CHECK_ENTITY_IS_VEHICLE_OK(hitEntity) vec = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(roll.pivotID, vHitPos + (GET_ENTITY_FORWARD_VECTOR(roll.pivotID) * -fCheckYShift)) IF (i = 0) roll.fTgtOffset[i] = vec.x - ROLLER_RADIUS ELSE roll.fTgtOffset[i] = vec.x + ROLLER_RADIUS ENDIF ENDIF ENDIF roll.brushShapeTestID[i] = NULL roll.iNextBrushShapeTestTime[i] = GET_GAME_TIMER() + 120 ENDIF IF (roll.bOldHitCheck[i] <> roll.bHitCheck[i]) IF (roll.bOldHitCheck[i] = TRUE) AND (roll.bHitCheck[i] = FALSE) CPRINTLN(DEBUG_MISSION, "CARWASH BRUSH ", i, " ISN'T HITTING ANYTHING ANY MORE") ENDIF IF (roll.bOldHitCheck[i] = FALSE) AND (roll.bHitCheck[i] = TRUE) CPRINTLN(DEBUG_MISSION, "CARWASH BRUSH ", i, " HAS STARTED HITTING THINGS") ENDIF ENDIF ENDREPEAT SET_ENTITY_NO_COLLISION_ENTITY(roll.activeVehicle, roll.rollerID[0], TRUE) SET_ENTITY_NO_COLLISION_ENTITY(roll.activeVehicle, roll.rollerID[1], TRUE) IF (bAborted) CPRINTLN(DEBUG_MISSION, "[CARWASH] - SET VERTROLL STATE - CPS_WARMDOWN - PED IN CAR IS NOT OKAY") roll.state = CPS_WARMDOWN EXIT ENDIF BREAK CASE CPS_WARMDOWN roll.activeVehicle = NULL roll.fTgtOffset[0] = -roll.fOriginalSep / 2.0 roll.fTgtOffset[1] = roll.fOriginalSep / 2.0 roll.fSpinRate -= (tStep) IF (roll.fSpinRate <= 0) roll.fSpinRate = 0 SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iHitSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iSpinSoundID) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[0]) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[1]) ENDIF IF (roll.fTgtOffset[0] = roll.fOffset[0]) AND (roll.fTgtOffset[1] = roll.fOffset[1]) AND (roll.fSpinRate = 0) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iMoveSoundID) CPRINTLN(DEBUG_MISSION, "[CARWASH] - SET VERTROLL STATE - CPS_SHUTDOWN") roll.state = CPS_SHUTDOWN ENDIF BREAK CASE CPS_SHUTDOWN SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iMoveSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iHitSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iSpinSoundID) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[0]) SAFE_REMOVE_PARTICLE_FX(roll.fxBrushID[1]) roll.fTgtOffset[0] = -roll.fOriginalSep / 2.0 roll.fTgtOffset[1] = roll.fOriginalSep / 2.0 roll.fMoveRate = 1.5 // if aborted wait till area is clear before allowing collsion to turn back on IF (GET_GAME_TIMER() > roll.iNextShapeTestTime) IF NOT IS_CARWASH_POSITION_OCCUPIED(roll.vBasePosition, 1.0) roll.bCollisionOn = TRUE roll.iNextShapeTestTime = 0 CPRINTLN(DEBUG_MISSION, "[CARWASH] - SET VERTROLL STATE - CPS_NULL") roll.state = CPS_NULL ELSE roll.iNextShapeTestTime = GET_GAME_TIMER() + SHAPE_CHECK_INTERVAL ENDIF ENDIF BREAK ENDSWITCH ENDPROC PROC RESET_CARWASH_VERTROLLER_PROPS(CARWASH_VROLLER2 &roll) VECTOR v IF IS_ENTITY_ALIVE(roll.pivotID) SET_ENTITY_COORDS_NO_OFFSET(roll.pivotID, roll.vBasePosition) ENDIF IF IS_ENTITY_ALIVE(roll.rollerID[0]) v = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <>) SET_ENTITY_COORDS(roll.rollerID[0], v) ENDIF IF IS_ENTITY_ALIVE(roll.rollerID[1]) v = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <>) SET_ENTITY_COORDS(roll.rollerID[1], v) ENDIF ENDPROC PROC CREATE_CARWASH_VERTROLLER(CARWASH_VROLLER2 &roll, VECTOR pos, FLOAT head, float sep = DEFAULT_DUALVROLL_SEP, FLOAT zShift = 0.0) FLOAT z VECTOR v IF GET_GROUND_Z_FOR_3D_COORD(pos + <<0, 0, 0.3>>, z) //pos.z = z ENDIF roll.vBasePosition = pos roll.fOriginalSep = sep pos.z += zShift// roll.vBasePosition = pos roll.pivotID = CREATE_OBJECT(PROP_LD_TEST_01, pos, FALSE) // setup pivot IF IS_ENTITY_ALIVE(roll.pivotID) FREEZE_ENTITY_POSITION(roll.pivotID, TRUE) SET_ENTITY_COORDS_NO_OFFSET(roll.pivotID, pos) SET_ENTITY_HEADING(roll.pivotID, head) SET_ENTITY_COLLISION(roll.pivotID, FALSE) ENDIF CPRINTLN(DEBUG_MISSION, "[CARWASH] - VROLLER PIVOT BASE POSITION:", pos) // create left brush v = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<-sep / 2.0, 0, VROLLER_ZSHIFT>>) roll.rollerID[0] = CREATE_OBJECT(PROP_CARWASH_ROLLER_VERT, v, FALSE) roll.fTgtOffset[0] = -sep / 2.0 roll.fOffset[0] = -sep / 2.0 FREEZE_ENTITY_POSITION(roll.rollerID[0], TRUE) SET_ENTITY_COLLISION(roll.rollerID[0], TRUE) SET_ENTITY_INVINCIBLE(roll.rollerID[0], TRUE) SET_ENTITY_HAS_GRAVITY(roll.rollerID[0], FALSE) SET_ENTITY_COORDS(roll.rollerID[0], v) // create left brush v = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <>) roll.rollerID[1] = CREATE_OBJECT(PROP_CARWASH_ROLLER_VERT, v, FALSE) roll.fTgtOffset[1] = sep / 2.0 roll.fOffset[1] = sep / 2.0 FREEZE_ENTITY_POSITION(roll.rollerID[1], TRUE) SET_ENTITY_COLLISION(roll.rollerID[1], TRUE) SET_ENTITY_INVINCIBLE(roll.rollerID[1], TRUE) SET_ENTITY_HAS_GRAVITY(roll.rollerID[1], FALSE) SET_ENTITY_COORDS(roll.rollerID[1], v) // finialize roll.fRollerSpinAngle = 0.0 roll.state = CPS_NULL roll.bSetup = TRUE roll.fSensorOffset[0] = -1.275 roll.fSensorRadius[0] = 1.25 roll.fSensorOffset[1] = 0.0 roll.fSensorRadius[1] = 0.620 roll.fTgtOffset[0] = -VROLLER_SEP roll.fTgtOffset[1] = VROLLER_SEP roll.iNextShapeTestTime = 0 ENDPROC //---------------------- // JETS FUNCTIONS //---------------------- /// PURPOSE: /// Create the carwash jets /// PARAMS: /// roll - roller reference /// pos - the middle point between the two arms - ground based /// head - heading /// sep - the distance between the arm joints /// steam - are these steam jets (their positioning is forced) PROC CREATE_CARWASH_JETS(CARWASH_JETS &roll, VECTOR pos, FLOAT head = 0.0, FLOAT sep = DEFAULT_DUALVROLL_SEP, BOOL steam = FALSE, FLOAT jetTrig = JET_TRIGGER_DIST) FLOAT z IF IS_STRING_NULL_OR_EMPTY(roll.sJetName) roll.sJetName = "ent_amb_car_wash_jet" ENDIF roll.bSetup = TRUE roll.fSeperation = sep / 2.0 roll.pivotID = CREATE_OBJECT(PROP_LD_TEST_01, pos, FALSE) roll.bSteam = steam IF IS_ENTITY_OK(roll.pivotID) SET_ENTITY_HEADING(roll.pivotID, head) FREEZE_ENTITY_POSITION(roll.pivotID, TRUE) ENDIF IF GET_GROUND_Z_FOR_3D_COORD(pos, z) roll.fHeight = ABSF(pos.z - z) ENDIF CPRINTLN(DEBUG_MISSION, "[CARWASH] - JETS BASE POS:", pos, " HEIGHT:", roll.fHeight) roll.fTriggerDist = jetTrig roll.vBasePos = pos roll.vBasePos.z = z ENDPROC PROC SET_CARWASH_JETS_PARTICLES(CARWASH_JETS &roll, STRING str) roll.sJetName = str ENDPROC PROC START_CARWASH_JETS_PARTICLES(CARWASH_JETS &roll, STRING str = NULL) IF NOT IS_STRING_EMPTY_HUD(str) roll.sJetName = str ENDIF SHUTDOWN_CARWASH_JETS_PARTICLES(roll) IS_VECTOR_ZERO(vSteamRotFX) IF (roll.bSteam = FALSE) roll.fxJets[0] = START_PARTICLE_FX_LOOPED_ON_ENTITY(roll.sJetName, roll.pivotID, <>, -vJetRotFX) roll.fxJets[1] = START_PARTICLE_FX_LOOPED_ON_ENTITY(roll.sJetName, roll.pivotID, <<-roll.fSeperation, 0, -roll.fHeight * 0.25>>, vJetRotFX) roll.fxJets[2] = START_PARTICLE_FX_LOOPED_ON_ENTITY(roll.sJetName, roll.pivotID, <>, -vJetRotFX) roll.fxJets[3] = START_PARTICLE_FX_LOOPED_ON_ENTITY(roll.sJetName, roll.pivotID, <<-roll.fSeperation, 0, -roll.fHeight * 0.75>>, vJetRotFX) ELSE roll.fxJets[0] = START_PARTICLE_FX_LOOPED_ON_ENTITY(roll.sJetName, roll.pivotID, vSteamPosFX, <<0, 90, 0>>) roll.fxJets[1] = START_PARTICLE_FX_LOOPED_ON_ENTITY(roll.sJetName, roll.pivotID, <<-1.96, 0.1, -2.16>>, <<0, 35, 0>>) roll.fxJets[2] = START_PARTICLE_FX_LOOPED_ON_ENTITY(roll.sJetName, roll.pivotID, <<1.96, 0.1, -2.16>>, <<0, 145, 0>>) ENDIF ENDPROC PROC SHUTDOWN_CARWASH_JETS(CARWASH_JETS &roll) IF IS_CARWASH_PART_RUNNING(roll.state) SHUTDOWN_CARWASH_JETS_PARTICLES(roll) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iSplashSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iSoundID) roll.state = CPS_NULL ENDIF ENDPROC PROC SHARED_CLEANUP_DELETE_CARWASH_JETS(CARWASH_JETS &roll) roll.state = CPS_ACTIVE SHUTDOWN_CARWASH_JETS(roll) SAFE_DELETE_OBJECT(roll.pivotID) ENDPROC /// PURPOSE: /// Update the dual roller /// PARAMS: /// roll - roller reference PROC CLEANUP_CARWASH_JETS(CARWASH_JETS &roll) SHARED_CLEANUP_DELETE_CARWASH_JETS(roll) ENDPROC /// PURPOSE: /// Update the dual roller /// PARAMS: /// roll - roller reference PROC DELETE_CARWASH_JETS(CARWASH_JETS &roll) SHARED_CLEANUP_DELETE_CARWASH_JETS(roll) ENDPROC /// PURPOSE: /// Update the dual roller /// PARAMS: /// roll - roller reference PROC UPDATE_CARWASH_JETS(CARWASH_JETS &roll, BOOL bSomeOneIn = TRUE) INT iHits VECTOR v1, v2 VECTOR vHitPos, vHitNormal SHAPETEST_STATUS shapeStatus ENTITY_INDEX hitEntity IF NOT IS_ENTITY_OK(roll.pivotID) or (roll.bSetup = FALSE) EXIT ENDIF #IF IS_DEBUG_BUILD IF bDrawDebugCarwash = TRUE DRAW_DEBUG_SPHERE(GET_ENTITY_COORDS(roll.pivotID), 0.03125) VECTOR v = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, vSteamPosFX) DRAW_DEBUG_SPHERE(v, 0.0625, 0, 255, 0, 255) DRAW_DEBUG_CIRCLE(roll.vBasePos, roll.fTriggerDist) ENDIF #ENDIF IF IS_CARWASH_PART_RUNNING(roll.state) IF (bSomeOneIn = FALSE) CPRINTLN(DEBUG_MISSION, "Carwash Water - Shutdown No One is In Carwash") roll.state = CPS_SHUTDOWN ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() AND NOT IS_ANY_NET_PLAYER_DRIVING_IN_CARWASH() CPRINTLN(DEBUG_MISSION, "Carwash Water - NET Shutdown No One is In Carwash") roll.state = CPS_SHUTDOWN ENDIF ENDIF SWITCH (roll.state) CASE CPS_NULL IF (GET_GAME_TIMER() > roll.iNextShapeTestTime) AND (bSomeOneIn = TRUE) IF (roll.bSteam = FALSE) IF (roll.shapeTestID = NULL) IF (GET_GAME_TIMER() > roll.iNextShapeTestTime) v1 = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<-roll.fSeperation * 0.8, 0, -roll.fHeight * 0.75>>) v2 = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <>) roll.shapeTestID = START_SHAPE_TEST_LOS_PROBE(v1, v2, SCRIPT_INCLUDE_VEHICLE, roll.pivotID, SCRIPT_SHAPETEST_OPTION_IGNORE_NO_COLLISION) STOP_FIRE_IN_RANGE(roll.vBasePos, roll.fTriggerDist) ENDIF ELSE shapeStatus = GET_SHAPE_TEST_RESULT(roll.shapeTestID, iHits, vHitPos, vHitNormal, hitEntity) IF (shapeStatus = SHAPETEST_STATUS_RESULTS_READY) IF CHECK_ENTITY_IS_VEHICLE_OK(hitEntity) roll.state = CPS_STARTUP CPRINTLN(DEBUG_MISSION, "[CARWASH]: PARTICLE STARTUP") ENDIF roll.iNextShapeTestTime = GET_GAME_TIMER() + SHAPE_CHECK_INTERVAL ENDIF roll.shapeTestID = NULL ENDIF ELSE roll.iNextShapeTestTime = GET_GAME_TIMER() + SHAPE_CHECK_INTERVAL IF IS_CARWASH_POSITION_OCCUPIED(roll.vBasePos, roll.fTriggerDist) roll.state = CPS_STARTUP roll.shapeTestID = NULL ENDIF ENDIF ENDIF BREAK CASE CPS_STARTUP roll.state = CPS_ACTIVE START_CARWASH_JETS_PARTICLES(roll) STOP_FIRE_IN_RANGE(roll.vBasePos, roll.fTriggerDist * 1.2) roll.iSoundID = GET_SOUND_ID() IF (roll.bSteam = FALSE) CPRINTLN(DEBUG_MISSION, "[CARWASH]: PARTICLE ACTIVE") PLAY_SOUND_FROM_ENTITY(roll.iSoundID, "SPRAY", roll.pivotID, "CARWASH_SOUNDS") ELSE PLAY_SOUND_FROM_ENTITY(roll.iSoundID, "DRYER", roll.pivotID, "CARWASH_SOUNDS") ENDIF BREAK CASE CPS_ACTIVE IF (bSomeOneIn = FALSE) CPRINTLN(DEBUG_MISSION, "Carwash Water - Splash Start") roll.state = CPS_SHUTDOWN EXIT ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() AND NOT IS_ANY_NET_PLAYER_DRIVING_IN_CARWASH() roll.state = CPS_SHUTDOWN EXIT ENDIF IF (roll.bSteam = FALSE) STOP_FIRE_IN_RANGE(roll.vBasePos, roll.fTriggerDist * 1.2) IF (roll.shapeTestID = NULL) IF (GET_GAME_TIMER() > roll.iNextShapeTestTime) v1 = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <<-roll.fSeperation * 0.8, 0, -roll.fHeight * 0.75>>) v2 = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(roll.pivotID, <>) roll.shapeTestID = START_SHAPE_TEST_LOS_PROBE(v1, v2, SCRIPT_INCLUDE_VEHICLE, roll.pivotID, SCRIPT_SHAPETEST_OPTION_IGNORE_NO_COLLISION) ENDIF ELSE shapeStatus = GET_SHAPE_TEST_RESULT(roll.shapeTestID, iHits, vHitPos, vHitNormal, hitEntity) IF (shapeStatus = SHAPETEST_STATUS_RESULTS_READY) IF NOT CHECK_ENTITY_IS_VEHICLE_OK(hitEntity) roll.state = CPS_SHUTDOWN ELSE IF (roll.iSplashSoundID = -1) roll.iSplashSoundID = GET_SOUND_ID() PLAY_SOUND_FROM_ENTITY(roll.iSplashSoundID, "SPRAY_CAR", roll.pivotID, "CARWASH_SOUNDS") CPRINTLN(DEBUG_MISSION, "Carwash Water - Splash Start") ENDIF IF IS_PED_IN_THIS_VEHICLE(PLAYER_PED_ID(), GET_VEHICLE_INDEX_FROM_ENTITY_INDEX(hitEntity)) //CPRINTLN(DEBUG_MISSION, "Carwash Water - Pad Rumble") DO_CARWASH_PAD_RUMBLE(SHAPE_CHECK_INTERVAL, 64) ENDIF ENDIF roll.iNextShapeTestTime = GET_GAME_TIMER() + SHAPE_CHECK_INTERVAL ENDIF roll.shapeTestID = NULL ENDIF IF (IS_PED_ON_ANY_BIKE(PLAYER_PED_ID()) OR IS_PED_ON_FOOT(PLAYER_PED_ID())) OR (IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) AND NOT ARE_ALL_VEHICLE_WINDOWS_INTACT(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()))) vHitPos = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(roll.pivotID, GET_ENTITY_COORDS(PLAYER_PED_ID())) IF (ABSF(vHitPos.x) < roll.fSeperation) AND (ABSF(vHitPos.y) < 1.2) AND (vHitPos.z < -roll.fHeight * 0.25) //CPRINTLN(DEBUG_MISSION, "Carwash Water - Wet") SET_PED_WETNESS_HEIGHT(PLAYER_PED_ID(), 3.0) ENDIF ENDIF ELIF (GET_GAME_TIMER() > roll.iNextCheckTime) DO_CARWASH_PAD_RUMBLE(ROLLER_CHECK_INTERVAL, 16) IF NOT IS_CARWASH_POSITION_OCCUPIED(roll.vBasePos, roll.fTriggerDist * 1.25) roll.state = CPS_SHUTDOWN ENDIF roll.iNextCheckTime = GET_GAME_TIMER() + ROLLER_CHECK_INTERVAL ENDIF BREAK CASE CPS_SHUTDOWN CPRINTLN(DEBUG_MISSION, "[CARWASH]: PARTICLE SHUTDOWN") SHUTDOWN_CARWASH_JETS_PARTICLES(roll) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iSplashSoundID) SAFE_STOP_AND_RELEASE_SOUND_ID(roll.iSoundID) roll.state = CPS_NULL BREAK ENDSWITCH ENDPROC //---------------------- // CAM FUNCTIONS //---------------------- PROC SETUP_CARWASH_CAMERA(CARWASH_CAMERA &cam, VECTOR pos, VECTOR rot, FLOAT fov) cam.bSetup = TRUE cam.vPosition[0] = pos cam.vRotation[0] = rot cam.vPosition[1] = <<0, 0, 0>> cam.vRotation[1] = <<0, 0, 0>> cam.iInterpTime = 0 cam.fFov = fov ENDPROC PROC SETUP_CARWASH_CAMERA_INTERPOLATE(CARWASH_CAMERA &cam, VECTOR pos, VECTOR rot, VECTOR pos2, VECTOR rot2, FLOAT fov, INT itime) cam.bSetup = TRUE cam.vPosition[0] = pos cam.vRotation[0] = rot cam.vPosition[1] = pos2 cam.vRotation[1] = rot2 cam.iInterpTime = itime cam.fFov = fov ENDPROC PROC DISABLE_CARWASH_CAMERA(CARWASH_CAMERA &cr) IF DOES_CAM_EXIST(cr.cameraID) SET_CAM_ACTIVE(cr.cameraID, FALSE) RENDER_SCRIPT_CAMS(FALSE, FALSE) ENDIF ENDPROC PROC DESTROY_CARWASH_CAMERA(CARWASH_CAMERA &cr) IF DOES_CAM_EXIST(cr.cameraID) DISABLE_CARWASH_CAMERA(cr) DESTROY_CAM(cr.cameraID) ENDIF cr.cameraID = NULL ENDPROC FUNC BOOL ENABLE_CARWASH_CAMERA(CARWASH_CAMERA &cr) IF NOT (cr.bSetup = TRUE) RETURN FALSE ENDIF IF NOT DOES_CAM_EXIST(cr.cameraID) cr.cameraID = CREATE_CAM_WITH_PARAMS("DEFAULT_SCRIPTED_CAMERA", <<0, 0, 0>>, <<0, 0, 0>>, 60.0, TRUE) ENDIF SET_CAM_PARAMS(cr.cameraID, cr.vPosition[0], cr.vRotation[0], cr.fFov, 0) SET_CAM_ACTIVE(cr.cameraID, TRUE) RENDER_SCRIPT_CAMS(TRUE, FALSE) IF (cr.iInterpTime > 0) AND NOT IS_VECTOR_ZERO(cr.vPosition[1]) CPRINTLN(DEBUG_MISSION, "CAMERA INTERPOLATE") SET_CAM_PARAMS(cr.cameraID, cr.vPosition[1], cr.vRotation[1], cr.fFov, cr.iInterpTime) ENDIF RETURN TRUE ENDFUNC //---------------------- // HANDLER FUNCTIONS //---------------------- FUNC BOOL RESTART_CARWASH_VEHICLE_TASK(VEHICLE_INDEX veh, CARWASH_HANDLER &ch) IF NOT IS_ENTITY_OK(veh) CPRINTLN(DEBUG_MISSION, "[CARWASH] - Aborting as vehicle is broken") RETURN FALSE ENDIF PED_INDEX ped = GET_PED_IN_VEHICLE_SEAT(veh) IF NOT IS_ENTITY_OK(veh) CPRINTLN(DEBUG_MISSION, "[CARWASH] - Aborting as vehicle has no driver") RETURN FALSE ENDIF IF NOT GET_IS_WAYPOINT_RECORDING_LOADED(ch.sWayPointRec) CPRINTLN(DEBUG_MISSION, "[CARWASH] - Waypoint recording not loaded") RETURN FALSE ENDIF SET_VEHICLE_DOORS_SHUT(veh, TRUE) IF NETWORK_HAS_CONTROL_OF_ENTITY(veh) SET_VEHICLE_DOORS_LOCKED_FOR_ALL_PLAYERS(veh, TRUE) CPRINTLN(DEBUG_MISSION, "[CARWASH] - Carwash Network Door Lock Activated") ENDIF SEQUENCE_INDEX seqCarWash OPEN_SEQUENCE_TASK(seqCarWash) TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(NULL, veh, ch.sWayPointRec, DRIVINGMODE_PLOUGHTHROUGH, 0, EWAYPOINT_NAVMESH_TO_INITIAL_WAYPOINT | EWAYPOINT_USE_TIGHTER_TURN_SETTINGS | EWAYPOINT_DO_NOT_RESPOND_TO_COLLISION_EVENTS, -1, ch.fForwardSpeed, FALSE, 1.25) TASK_STAND_STILL(NULL, 3000) CLOSE_SEQUENCE_TASK(seqCarWash) TASK_PERFORM_SEQUENCE(ped, seqCarWash) CLEAR_SEQUENCE_TASK(seqCarWash) VEHICLE_WAYPOINT_PLAYBACK_OVERRIDE_SPEED(veh, ch.fForwardSpeed) iDriverCarwashSequenceProgress = -1 ch.iTaskSequenceSize = 2 CPRINTLN(DEBUG_MISSION, "[CARWASH] - Task Restarted") RETURN TRUE ENDFUNC FUNC BOOL SET_VEHICLE_THROUGH_CARWASH(VEHICLE_INDEX veh, CARWASH_HANDLER &ch, INT iDelay = 0) IF NOT IS_ENTITY_OK(veh) CPRINTLN(DEBUG_MISSION, "[CARWASH] - Aborting as vehicle is broken") RETURN FALSE ENDIF PED_INDEX ped = GET_PED_IN_VEHICLE_SEAT(veh) IF NOT IS_ENTITY_OK(veh) CPRINTLN(DEBUG_MISSION, "[CARWASH] - Aborting as vehicle has no driver") RETURN FALSE ENDIF IF DOES_VEHICLE_HAVE_ROOF(veh) CPRINTLN(DEBUG_MISSION, "[CARWASH] - Car has a roof that's good then") ENDIF IF IS_VEHICLE_A_CONVERTIBLE(veh, TRUE) CPRINTLN(DEBUG_MISSION, "[CARWASH] - Car is a convertable - Convertable Roof State:", ENUM_TO_INT(GET_CONVERTIBLE_ROOF_STATE(veh))) ENDIF IF IS_STRING_NULL_OR_EMPTY(ch.sWayPointRec) CPRINTLN(DEBUG_MISSION, "[CARWASH] - Waypoint not set up") SET_VEHICLE_ALONG_CARWASH_TRACK(veh, ch.cTrack, 0.0, ch.fForwardSpeed) RETURN FALSE ENDIF IF NOT GET_IS_WAYPOINT_RECORDING_LOADED(ch.sWayPointRec) CPRINTLN(DEBUG_MISSION, "[CARWASH] - Waypoint recording not loaded") ENDIF // need to turn off player control when in carwash IF (g_bInMultiplayer) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Dis-Enabling Player Controls") SET_PLAYER_CONTROL(PLAYER_ID(), FALSE, SPC_ALLOW_PLAYER_DAMAGE) IF NETWORK_HAS_CONTROL_OF_ENTITY(veh) SET_VEHICLE_DOORS_LOCKED_FOR_ALL_PLAYERS(veh, TRUE) CPRINTLN(DEBUG_MISSION, "[CARWASH] - Carwash Network Door Lock Activated") ENDIF ENDIF CPRINTLN(DEBUG_MISSION, "[CARWASH] - Spoiler Mod:", GET_VEHICLE_MOD(veh, MOD_SPOILER)) CPRINTLN(DEBUG_MISSION, "[CARWASH] - Shutting Doors") SET_VEHICLE_DOORS_SHUT(veh, FALSE) CLEAR_PED_TASKS(ped) SET_ENTITY_VELOCITY(veh, <<0, 0, 0>>) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Clear Ped Tasks and Set Car Velocity to Zero") CPRINTLN(DEBUG_MISSION, "[CARWASH]:Number of Car Seats:", GET_VEHICLE_MAX_NUMBER_OF_PASSENGERS(veh)) SEQUENCE_INDEX seqCarWash ch.iTaskSequenceSize = 2 OPEN_SEQUENCE_TASK(seqCarWash) IF iDelay > 0 TASK_STAND_STILL(NULL, iDelay) ch.iTaskSequenceSize ++ ENDIF TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(NULL, veh, ch.sWayPointRec, DRIVINGMODE_PLOUGHTHROUGH, 0, EWAYPOINT_NAVMESH_TO_INITIAL_WAYPOINT | EWAYPOINT_USE_TIGHTER_TURN_SETTINGS | EWAYPOINT_DO_NOT_RESPOND_TO_COLLISION_EVENTS, -1, ch.fForwardSpeed, FALSE, 1.25) TASK_STAND_STILL(NULL, 3000) CLOSE_SEQUENCE_TASK(seqCarWash) TASK_PERFORM_SEQUENCE(ped, seqCarWash) CLEAR_SEQUENCE_TASK(seqCarWash) VEHICLE_WAYPOINT_PLAYBACK_OVERRIDE_SPEED(veh, ch.fForwardSpeed) iDriverCarwashSequenceProgress = -1 ch.bCarwashAborted = FALSE PRINT_PLAYER_CAR_DIMENSIONS() ADD_VEHICLE_STUCK_CHECK_WITH_WARP(veh,0.2,1000,FALSE,FALSE,FALSE,-1) CPRINTLN(DEBUG_MISSION, "[CARWASH] - Adding stuck check") IF NOT DECOR_EXIST_ON(veh, "Carwash_Vehicle_Decorator") DECOR_SET_BOOL(veh, "Carwash_Vehicle_Decorator", TRUE) CPRINTLN(DEBUG_MISSION, "[CARWASH] - Adding vehicle decorator") ENDIF START_CARWASH_TIMER(ch) RETURN TRUE ENDFUNC FUNC BOOL IS_CARWASH_VEHICLE_STUCK(VEHICLE_INDEX vehPlayerCar) IF NOT DOES_VEHICLE_HAVE_STUCK_VEHICLE_CHECK(vehPlayerCar) RETURN FALSE ENDIF IF IS_VEHICLE_STUCK_TIMER_UP(vehPlayerCar,VEH_STUCK_ON_ROOF,5000) OR IS_VEHICLE_STUCK_TIMER_UP(vehPlayerCar,VEH_STUCK_ON_SIDE, 5000) OR IS_VEHICLE_STUCK_TIMER_UP(vehPlayerCar,VEH_STUCK_HUNG_UP, 5000) OR IS_VEHICLE_STUCK_TIMER_UP(vehPlayerCar,VEH_STUCK_JAMMED, 5000) RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Handle push block - stops vehicles from driving in /// PARAMS: /// ct - carwash track /// veh - vehicle /// blockRadius - block radius FUNC FLOAT UPDATE_VEHICLE_THROUGH_CARWASH(CARWASH_HANDLER &ch, VEHICLE_INDEX veh, FLOAT startDirt) // move car along and stop people dicking about with sun roof VECTOR v FLOAT r = GET_RATIO_OF_CLOSEST_POINT_ON_LINE(GET_ENTITY_COORDS(veh), ch.cTrack.vTrackPoint[0], ch.cTrack.vTrackPoint[1], FALSE) IF (r <= 1) IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), veh) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_EXIT) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_ROOF) //DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_MAP) ENDIF IF GET_PED_IN_VEHICLE_SEAT(veh) = PLAYER_PED_ID() DISABLE_CONTROL_ACTIONS_FOR_CARWASH() //DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_MAP) ENDIF IF NETWORK_HAS_CONTROL_OF_ENTITY(veh) v = GET_CLOSEST_POINT_ON_LINE(GET_ENTITY_COORDS(veh), ch.cTrack.vTrackPoint[0], ch.cTrack.vTrackPoint[1], FALSE) IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(veh, v) < 4.0 IF (r > 0.0) APPLY_CARWASH_WASH_TO_VEHICLE(veh, 0.005, startDirt * (1.0 - r)) ENDIF ENDIF ENDIF ENDIF // force collsion on rollers to be off IF (NETWORK_IS_GAME_IN_PROGRESS() = FALSE) UPDATE_COLLISIONS_FOR_CARWASH(ch, veh) ENDIF IF NETWORK_HAS_CONTROL_OF_ENTITY(veh) IF r > 0.85 AND (NOT ch.bThrottleBoosted) AND ch.fBoostSpeed > 0.0 CPRINTLN(DEBUG_MISSION, "Setting new override speed: ", ch.fBoostSpeed) VEHICLE_WAYPOINT_PLAYBACK_OVERRIDE_SPEED(veh, ch.fBoostSpeed) ch.bThrottleBoosted = TRUE ENDIF ENDIF RETURN r ENDFUNC PROC UPDATE_CARWASH_PARTS(CARWASH_HANDLER &ch) BOOL update = TRUE IF (g_bInMultiplayer) update = IS_ANY_NET_PLAYER_DRIVING_IN_CARWASH() IF (update) ch.iLastTimeUsed = GET_GAME_TIMER() ENDIF IF (update = FALSE) AND (ch.bOldUpdateCheck = TRUE) //SCRIPT_ASSERT("NO ONE IS USING CARWASH ANYMORE") CPRINTLN(DEBUG_MISSION, "[CARWASH] NO ONE IS USING CARWASH ANYMORE") ch.vertRoller.fSpinRate = 0.0 ch.bTimerStarted = FALSE ENDIF ENDIF IF (NETWORK_IS_GAME_IN_PROGRESS() AND bUseNewMPVertRollers) UPDATE_CARWASH_VERTROLLER_MP(ch.vertRoller, update, ch.bCarwashAborted) ELSE UPDATE_CARWASH_VERTROLLER(ch.vertRoller, update, ch.bCarwashAborted) ENDIF IF (g_bInMultiplayer) ch.bOldUpdateCheck = update // don't bother to update if no one has used it for 0.5 seconds IF (GET_GAME_TIMER() > ch.iLastTimeUsed + 1500) ch.shapeTestID = NULL ch.iBlockCounts = 0 EXIT ENDIF ENDIF UPDATE_CARWASH_HROLLER(ch.horzRoller, update) UPDATE_CARWASH_JETS(ch.waterJets, update) UPDATE_CARWASH_JETS(ch.soapJets, update) UPDATE_CARWASH_JETS(ch.steamJets, update) ENDPROC PROC SNAP_VEHICLE_TO_CARWASH_START(VEHICLE_INDEX veh, CARWASH_HANDLER &ch, BOOL bForceSnap = FALSE) VECTOR fwd IF IS_ENTITY_OK(veh) ENABLE_CAMERA_STRUCT(ch.carwashCamera[0], ch.cameraID, ch.bTallVehicle, TRUE) // snap car if angle between forward and carwash track is less than 60 degrees (cos(60) = 0.5) fwd = GET_ENTITY_FORWARD_VECTOR(veh) IF NOT IS_DIRECTION_WITHIN_DEGRESS_OF_DESIRED_DIRECTION(ch.cTrack.vDirection, fwd, AUTODRIVE_TOLERANCE) OR (bForceSnap = TRUE) //IF (DOT_PRODUCT_XY(ch.cTrack.vDirection, fwd) < COS(60.0)) OR (bForceSnap = TRUE) SET_ENTITY_COORDS_GROUNDED(veh, GET_CLOSEST_POINT_ON_LINE(GET_ENTITY_COORDS(veh), ch.cTrack.vTrackPoint[0], ch.cTrack.vTrackPoint[1], FALSE) + <<0, 0, 0.1>>) SET_ENTITY_HEADING(veh, ch.cTrack.fTrackHeading) SET_VEHICLE_ON_GROUND_PROPERLY(veh) SET_VEHICLE_FORWARD_SPEED(veh, 0.0) ENDIF SET_VEHICLE_DOORS_SHUT(veh, FALSE) ch.iCurrentCameraState = 0 ch.bIsAllowedInMP = FALSE ch.shapeTestID = NULL ch.iBlockCounts = 0 // B*1439838 - only the machine who owns this can call this IF (g_bInMultiplayer) IF NOT NETWORK_HAS_CONTROL_OF_ENTITY(veh) EXIT ENDIF ENDIF SET_CARWASH_CAR_LOCK_STATE(veh, VEHICLELOCK_LOCKED) IF IS_VEHICLE_A_CONVERTIBLE(veh, FALSE) RAISE_CONVERTIBLE_ROOF(veh, FALSE) ENDIF ENDIF ENDPROC PROC SHUTDOWN_CARWASH_CAMERA(CAMERA_INDEX cameraID, BOOL bForce = FALSE) VEHICLE_INDEX ind IF DOES_CAM_EXIST(cameraID) SHUTDOWN_CAMERA(cameraID) DUMMY_REFERENCE_BOOL(bForce) SET_EVERYONE_IGNORE_PLAYER(PLAYER_ID(), FALSE) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Carwash Camera ShutDown - ", bForce) IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) ind = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()) IF IS_ENTITY_OK(ind) IF NOT IS_VEHICLE_A_PERSONAL_VEHICLE(ind) IF GET_PED_IN_VEHICLE_SEAT(ind) = PLAYER_PED_ID() SET_CARWASH_CAR_LOCK_STATE(ind, VEHICLELOCK_UNLOCKED) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Carwash car doors unlocked") ENDIF ENDIF ENDIF ENDIF ENDIF ENDPROC FUNC BOOL IS_THERE_A_VEHICLE_IN_FRONT(VEHICLE_INDEX veh) VECTOR checkpoint VECTOR dmin, dmax GET_MODEL_DIMENSIONS(GET_ENTITY_MODEL(veh), dmin, dmax) checkPoint = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(veh, <<0, dmax.y + 0.325, 0>>) //DRAW_DEBUG_SPHERE(checkPoint, 0.0625) //DRAW_DEBUG_LINE(checkPoint, checkPoint + <<0, 0, 10>>) RETURN IS_POSITION_OCCUPIED(checkPoint, 0.75, FALSE, TRUE, FALSE, FALSE, TRUE, veh) ENDFUNC FUNC BOOL IS_THERE_A_VEHICLE_IN_FRONT_SHAPETEST(CARWASH_HANDLER &ch, VEHICLE_INDEX veh) IF (GET_GAME_TIMER() < ch.iNextBlockCheckTime) RETURN FALSE ENDIF INT iHits VECTOR checkpoint VECTOR dmin, dmax VECTOR vHitPos, vHitNormal SHAPETEST_STATUS shapeStatus ENTITY_INDEX hitEntity IF (ch.shapeTestID = NULL) GET_MODEL_DIMENSIONS(GET_ENTITY_MODEL(veh), dmin, dmax) IF (ch.bBackInterruptCheck = FALSE) checkPoint = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(veh, <<0, dmax.y + 0.325, 0>>) ELSE checkPoint = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(veh, <<0, dmin.y - 0.325, 0>>) ENDIF /* // flip this - not sure if i can do variable = ! variable in this IF (ch.bBackInterruptCheck) ch.bBackInterruptCheck = FALSE ELSE ch.bBackInterruptCheck = TRUE ENDIF */ IF (g_bInMultiplayer) ch.shapeTestID = START_SHAPE_TEST_CAPSULE(checkPoint - <<0, 0, 0.1>>, checkPoint + <<0, 0, 0.1>>, 0.75, SCRIPT_INCLUDE_VEHICLE | SCRIPT_INCLUDE_OBJECT, veh) ELSE ch.shapeTestID = START_SHAPE_TEST_CAPSULE(checkPoint - <<0, 0, 0.1>>, checkPoint + <<0, 0, 0.1>>, 0.75, SCRIPT_INCLUDE_VEHICLE, veh) ENDIF RETURN FALSE ELSE shapeStatus = GET_SHAPE_TEST_RESULT(ch.shapeTestID, iHits, vHitPos, vHitNormal, hitEntity) IF (shapeStatus = SHAPETEST_STATUS_RESULTS_READY) IF DOES_ENTITY_EXIST(hitEntity) IF CAN_THIS_ENTITY_BLOCK_THE_CARWASH(hitEntity) ch.iBlockCounts ++ RETURN TRUE ELSE ch.iBlockCounts = 0 ENDIF ENDIF ENDIF ch.iNextBlockCheckTime = GET_GAME_TIMER() + 500 ch.shapeTestID = NULL ENDIF RETURN FALSE ENDFUNC FUNC FLOAT GET_CURRENT_RATIO_FOR_VEHICLE_IN_CARWASH(CARWASH_HANDLER &ch, VEHICLE_INDEX veh) IF NOT IS_ENTITY_ALIVE(veh) RETURN 0.0 ENDIF RETURN GET_RATIO_OF_CLOSEST_POINT_ON_LINE(GET_ENTITY_COORDS(veh), ch.cTrack.vBlockPoint[0], ch.cTrack.vBlockPoint[1], FALSE) ENDFUNC PROC EMERGENCY_ABORT_CARWASH(CARWASH_HANDLER &ch, VEHICLE_INDEX veh = NULL) //SCRIPT_ASSERT("EMERGENCY CARWASH ABORT!!") CPRINTLN(DEBUG_MISSION, "[CARWASH]:Emergency Carwash Terminate") ch.iCurrentCameraState = CAMERASTATE_ALLDONE RESET_COLLISIONS_FOR_CARWASH(ch) STOP_ALL_CARWASH_SOUNDS(ch) STOP_ALL_CARWASH_PARTICLES(ch) SHUTDOWN_CARWASH_CAMERA(ch.cameraID, TRUE) SET_NET_PED_DRIVING_CARWASH_STATUS(PLAYER_PED_ID(), FALSE) DELETE_CARWASH_JETS(ch.waterJets) DELETE_CARWASH_JETS(ch.soapJets) DELETE_CARWASH_JETS(ch.steamJets) SET_EVERYONE_IGNORE_PLAYER(PLAYER_ID(), FALSE) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Re-Enabling Player Controls") SET_PLAYER_CONTROL(PLAYER_ID(), TRUE) IF (g_bInMultiplayer) PLAYER_INDEX player = NETWORK_GET_PLAYER_INDEX_FROM_PED(PLAYER_PED_ID()) IF (player != INVALID_PLAYER_INDEX()) IF (GlobalPlayerBD[NATIVE_TO_INT(player)].bDrivingThroughCarwash = TRUE) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Setting player to net be in carwash") GlobalPlayerBD[NATIVE_TO_INT(player)].bDrivingThroughCarwash = FALSE ENDIF ENDIF ENDIF IF DOES_ENTITY_EXIST(veh) SET_CARWASH_CAR_LOCK_STATE(veh, VEHICLELOCK_UNLOCKED) REMOVE_CARWASH_STUCK_CHECK(veh) IF NETWORK_IS_GAME_IN_PROGRESS() IF NETWORK_HAS_CONTROL_OF_ENTITY(veh) SET_VEHICLE_DOORS_LOCKED_FOR_ALL_PLAYERS(veh, FALSE) ENDIF ENDIF ENDIF SET_PED_PATHS_BACK_TO_ORIGINAL(ch.vNoPedWalkMin, ch.vNoPedWalkMax) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Unblocking ped area:", ch.vNoPedWalkMin, " ", ch.vNoPedWalkMax) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Carwash car doors unlocked") ch.shapeTestID = NULL ch.iBlockCounts = 0 ch.bCarwashAborted = TRUE ch.bTimerStarted = FALSE //SET_VEHICLE_AND_OCCUPANTS_INVINCIBLE(veh, FALSE) IF IS_AUDIO_SCENE_ACTIVE("CAR_WASH_SCENE") CPRINTLN(DEBUG_MISSION, "Carwash Stop Audio Scene") STOP_AUDIO_SCENE("CAR_WASH_SCENE") ENDIF ENDPROC FUNC BOOL IS_PED_RUNNING_TASK_OR_HAS_FINISHED(PED_INDEX ped, SCRIPT_TASK_NAME task) IF (GET_SCRIPT_TASK_STATUS(ped, task) = PERFORMING_TASK) RETURN TRUE ENDIF IF (GET_SCRIPT_TASK_STATUS(ped, task) = WAITING_TO_START_TASK) RETURN TRUE ENDIF RETURN (GET_SCRIPT_TASK_STATUS(ped, task) = FINISHED_TASK) ENDFUNC PROC SHUT_CARWASH_VEHICLE_DOORS(VEHICLE_INDEX veh) IF NETWORK_IS_GAME_IN_PROGRESS() IF NETWORK_HAS_CONTROL_OF_ENTITY(veh) SET_VEHICLE_DOORS_SHUT(veh, TRUE) ENDIF EXIT ENDIF SET_VEHICLE_DOORS_SHUT(veh, TRUE) ENDPROC FUNC BOOL UPDATE_CARWASH_HANDLER_CAMERAS(CARWASH_HANDLER &ch, VEHICLE_INDEX veh) PED_INDEX driver FLOAT fRatio = GET_CURRENT_RATIO_FOR_VEHICLE_IN_CARWASH(ch, veh) BOOL bAbort = FALSE BOOL bAbortLastCamera = FALSE #IF IS_DEBUG_BUILD fCarDebugRatio = fRatio iDebugCarWashTimer = GET_CARWASH_TIMER_ELAPSED(ch) #ENDIF IF NOT IS_ENTITY_OK(veh) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Emergency Carwash Terminate - Vehicle Is Not OK") EMERGENCY_ABORT_CARWASH(ch, veh) RETURN TRUE ENDIF // B*1926983 - Car Wash animation stops when player enters Xbox Store and then backing out // Reset the timer if the player is in the xbox store or the game will bust out IF NETWORK_IS_GAME_IN_PROGRESS() IF IS_COMMERCE_STORE_OPEN() START_CARWASH_TIMER(ch) ENDIF ENDIF IF IS_PAUSE_MENU_ACTIVE() START_CARWASH_TIMER(ch) ENDIF // update carwash tasks driver = GET_PED_IN_VEHICLE_SEAT(veh) IF IS_CARWASH_PED_OK(driver) bIsDriverRunningCarwashSequence = ((GET_SCRIPT_TASK_STATUS(driver, SCRIPT_TASK_PERFORM_SEQUENCE) = PERFORMING_TASK) OR (GET_SCRIPT_TASK_STATUS(driver, SCRIPT_TASK_PERFORM_SEQUENCE) = WAITING_TO_START_TASK)) IF (bIsDriverRunningCarwashSequence) iDriverCarwashSequenceProgress = GET_SEQUENCE_PROGRESS(driver) bIsDriverFinishedCarwashSequence = (GET_SCRIPT_TASK_STATUS(driver, SCRIPT_TASK_PERFORM_SEQUENCE) = FINISHED_TASK) AND (iDriverCarwashSequenceProgress = (ch.iTaskSequenceSize - 1)) ENDIF IF (bDebugForceClearPedTasks) CPRINTLN(DEBUG_MISSION, "[CARWASH] DEBUG - FORCE CLEAR PED TASKS") IF IS_PED_IN_ANY_VEHICLE(driver) TASK_LEAVE_ANY_VEHICLE(driver) ENDIF //CLEAR_PED_TASKS(driver) bDebugForceClearPedTasks = FALSE ENDIF IF (bDebugForceRestartTasks) RESTART_CARWASH_VEHICLE_TASK(veh, ch) CPRINTLN(DEBUG_MISSION, "[CARWASH] DEBUG - FORCE RESTART TASKS") bDebugForceRestartTasks = FALSE ENDIF ENDIF #IF IS_DEBUG_BUILD IF bDrawDebugCarwash DRAW_DEBUG_SPHERE(INTERPOLATE_VECTOR(ch.cTrack.vTrackPoint[0], ch.cTrack.vTrackPoint[1], fBlockCarPlaceT, FALSE), 0.0625) ENDIF IF (bCreateBlockCar) CREATE_VEHICLE(GET_ENTITY_MODEL(veh), INTERPOLATE_VECTOR(ch.cTrack.vTrackPoint[0], ch.cTrack.vTrackPoint[1], fBlockCarPlaceT, FALSE), ch.cTrack.fTrackHeading, FALSE) bCreateBlockCar = FALSE ENDIF #ENDIF // abort if driver is killed IF (g_bInMultiplayer) IF IS_PLAYER_ON_MP_AMBIENT_SCRIPT(PLAYER_ID(), MPAM_TYPE_TIME_TRIAL) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Aborting as Driver is part of Time Trial") bAbort = TRUE ENDIF IF IS_PLAYER_ON_MP_AMBIENT_SCRIPT(PLAYER_ID(), MPAM_TYPE_RC_TIME_TRIAL) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Aborting as Driver is part of RC Time Trial") bAbort = TRUE ENDIF IF NOT IS_CARWASH_PED_OK(driver) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Aborting as Driver is dead") bAbort = TRUE ENDIF IF IS_PED_IN_VEHICLE(driver, veh, FALSE) IF NOT IS_PED_SITTING_IN_VEHICLE(driver, veh) CPRINTLN(DEBUG_MISSION, "[CARWASH]: ABORT! - Driver is has fallen out of car") bAbort = TRUE ENDIF ENDIF IF NOT IS_PED_IN_CAR_WITH_CARWASH_DRIVER(PLAYER_PED_ID()) CPRINTLN(DEBUG_MISSION, "[CARWASH]: As Ped isn't in carwash car") bAbort = TRUE ENDIF /* ELIF (NOT IS_STRING_NULL_OR_EMPTY(ch.sWayPointRec)) IF NOT IS_PED_RUNNING_TASK_OR_HAS_FINISHED(driver, SCRIPT_TASK_PERFORM_SEQUENCE) AND (ch.iCurrentCameraState >= 1) CPRINTLN(DEBUG_MISSION, "[CARWASH]: As Ped driving abandonded task") bAbort = TRUE ENDIF */ IF ARE_VEHICLE_TYRES_BURST(veh, 3) CPRINTLN(DEBUG_MISSION, "[CARWASH]: At least 3 tyres are burst - Car will probably not make it through - Emergency Exit") bAbort = TRUE ENDIF IF NOT IS_ANY_NET_PLAYER_DRIVING_IN_CARWASH() CPRINTLN(DEBUG_MISSION, "[CARWASH]: Emergency Exit - No one at all are using carwash anymore") bAbort = TRUE ENDIF IF IS_PED_BEING_JACKED(driver) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Aborting as Driver is being jacked") bAbort = TRUE ENDIF IF IS_CARWASH_VEHICLE_STUCK(veh) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Emergency Exit - Carwash car is stuck") bAbort = TRUE ENDIF IF HAS_ABORT_TIME_EXPIRED(ch) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Carwash has taken too long to finish something has gone wrong - Emergency Exit") EMERGENCY_ABORT_CARWASH(ch, veh) RETURN TRUE ENDIF IF (bAbort = TRUE) EMERGENCY_ABORT_CARWASH(ch, veh) RETURN TRUE ENDIF IF NOT NETWORK_HAS_CONTROL_OF_ENTITY(veh) NETWORK_USE_LOGARITHMIC_BLENDING_THIS_FRAME(veh) ENDIF ELSE IF HAS_ABORT_TIME_EXPIRED(ch) AND (ch.bSkipped = FALSE) SAFE_FADE_SCREEN_OUT_TO_BLACK(500, TRUE) APPLY_CARWASH_WASH_TO_VEHICLE(veh, 100.0, 0.0) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Carwash has taken too long - Emergency Exit SP - Fade to End") ch.bSkipped = TRUE RETURN TRUE ENDIF ENDIF // check if task has been aborted IF (driver = PLAYER_PED_ID()) IF (NOT bIsDriverRunningCarwashSequence) AND ((iDriverCarwashSequenceProgress > -1) AND (iDriverCarwashSequenceProgress < ch.iTaskSequenceSize)) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Emergency - task has aborted improperly") RESTART_CARWASH_VEHICLE_TASK(veh, ch) ENDIF IF (bIsDriverFinishedCarwashSequence) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Sequence Finished") ENDIF ENDIF IF IS_THERE_A_VEHICLE_IN_FRONT_SHAPETEST(ch, veh) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Someone has tried to drive in - abort") EMERGENCY_ABORT_CARWASH(ch, veh) RETURN TRUE ENDIF IF (ch.iCurrentCameraState <> CAMERASTATE_ALLDONE) DISABLE_CELLPHONE_THIS_FRAME_ONLY() SET_EVERYONE_IGNORE_PLAYER(PLAYER_ID(), TRUE) IF (ch.iCurrentCameraState > 0) HIDE_HUD_AND_RADAR_THIS_FRAME() IF (GET_BUILDING_STATE(ch.iplSwap) != BUILDINGSTATE_DESTROYED) SET_BUILDING_STATE(ch.iplSwap, BUILDINGSTATE_DESTROYED) CPRINTLN(DEBUG_MISSION, "[CARWASH]: The IPL hasn't been swapped for some reason - Swap it back") ENDIF ENDIF ENDIF SWITCH (ch.iCurrentCameraState) CASE 0 CPRINTLN(DEBUG_MISSION, "[CARWASH]:Switching To Camera 0 - Ratio", fRatio) CLEAR_CYLINDER_OF_FIRE(ch.cTrack.vTrackPoint[0], ch.cTrack.vTrackPoint[1], 3.0, NOT g_bInMultiplayer) SET_PED_PATHS_IN_AREA(ch.vNoPedWalkMin, ch.vNoPedWalkMax, FALSE) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Blocking ped area:", ch.vNoPedWalkMin, " ", ch.vNoPedWalkMax) IF GET_BUILDING_STATE(ch.iplSwap) <> BUILDINGSTATE_DESTROYED CPRINTLN(DEBUG_MISSION, "[CARWASH]: Building Swap didn't happen properly?") SET_BUILDING_STATE(ch.iplSwap, BUILDINGSTATE_DESTROYED) ENDIF ENABLE_CAMERA_STRUCT(ch.carwashCamera[0], ch.cameraID, ch.bTallVehicle, FALSE, GRAPH_TYPE_CUBIC_EASE_IN_OUT, GRAPH_TYPE_CUBIC_EASE_IN_OUT) START_CARWASH_TIMER(ch) IF NOT g_bInMultiplayer CLEAR_AREA_OF_PEDS(GET_PLAYER_COORDS(GET_PLAYER_INDEX()), 50.0) ENDIF CPRINTLN(DEBUG_MISSION, "[CARWASH]:Carwash car doors locked") //SET_VEHICLE_AND_OCCUPANTS_INVINCIBLE(veh) ch.iCurrentCameraState ++ IF NOT IS_AUDIO_SCENE_ACTIVE("CAR_WASH_SCENE") START_AUDIO_SCENE("CAR_WASH_SCENE") CPRINTLN(DEBUG_MISSION, "[CARWASH]:Carwash Start Audio Scene") ENDIF IF NOT g_bInMultiplayer SET_ENTITY_COORDS(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), ch.cTrack.vVehicleSnapPoint) SET_ENTITY_HEADING(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), ch.cTrack.fTrackHeading) IF IS_VEHICLE_A_CONVERTIBLE(veh, FALSE) RAISE_CONVERTIBLE_ROOF(veh, TRUE) ENDIF SET_CARWASH_CAR_LOCK_STATE(veh, VEHICLELOCK_LOCKED) //PRINT_HELP("CWASH_SKIPRIDE") ELSE // B*1439838 - only the machine who owns this can call this IF NETWORK_HAS_CONTROL_OF_ENTITY(veh) SET_CARWASH_CAR_LOCK_STATE(veh, VEHICLELOCK_CANNOT_ENTER) IF IS_VEHICLE_A_CONVERTIBLE(veh, FALSE) RAISE_CONVERTIBLE_ROOF(veh, FALSE) ENDIF ENDIF ENDIF BREAK CASE 1 IF HAS_CAMERA_STRUCT_FINISHED_INTERPOLATING(ch.carwashCamera[0], fRatio) CLEAR_CYLINDER_OF_FIRE(ch.cTrack.vTrackPoint[0], ch.cTrack.vTrackPoint[1], 3.0, NOT g_bInMultiplayer) ENABLE_CAMERA_STRUCT(ch.carwashCamera[1], ch.cameraID, ch.bTallVehicle, FALSE, GRAPH_TYPE_LINEAR) SHUT_CARWASH_VEHICLE_DOORS(veh) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Switching to Camera 1 - Car Ratio:", fRatio) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Time Elapsed:", GET_CARWASH_TIMER_ELAPSED(ch)) START_CARWASH_TIMER(ch) ch.iCurrentCameraState ++ ENDIF BREAK CASE 2 IF HAS_CAMERA_STRUCT_FINISHED_INTERPOLATING(ch.carwashCamera[1], fRatio) CLEAR_CYLINDER_OF_FIRE(ch.cTrack.vTrackPoint[0], ch.cTrack.vTrackPoint[1], 3.0, NOT g_bInMultiplayer) IF (ch.carWashCamera[2].bSetup) ENABLE_CAMERA_STRUCT(ch.carwashCamera[2], ch.cameraID, ch.bTallVehicle, FALSE, GRAPH_TYPE_LINEAR) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Switching to Camera 2 - Car Ratio:", fRatio) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Time Elapsed:", GET_CARWASH_TIMER_ELAPSED(ch)) ch.iCurrentCameraState ++ ELSE ENABLE_CAMERA_STRUCT(ch.carwashCamera[6], ch.cameraID, ch.bTallVehicle, FALSE, GRAPH_TYPE_LINEAR) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Switching to Camera 6 - Car Ratio:", fRatio) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Time Elapsed;", GET_CARWASH_TIMER_ELAPSED(ch)) APPLY_CARWASH_WASH_TO_VEHICLE(veh, 50.0, 0.0) ch.iCurrentCameraState = CAMERASTATE_LASTCAMERA ENDIF SHUT_CARWASH_VEHICLE_DOORS(veh) START_CARWASH_TIMER(ch) ENDIF BREAK CASE 3 IF HAS_CAMERA_STRUCT_FINISHED_INTERPOLATING(ch.carwashCamera[2], fRatio) CLEAR_CYLINDER_OF_FIRE(ch.cTrack.vTrackPoint[0], ch.cTrack.vTrackPoint[1], 3.0, NOT g_bInMultiplayer) IF (ch.carWashCamera[3].bSetup) ENABLE_CAMERA_STRUCT(ch.carwashCamera[3], ch.cameraID, ch.bTallVehicle, FALSE, GRAPH_TYPE_LINEAR) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Switching to Camera 3 - Car Ratio:", fRatio) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Time Elapsed;", GET_CARWASH_TIMER_ELAPSED(ch)) ch.iCurrentCameraState ++ ELSE ENABLE_CAMERA_STRUCT(ch.carwashCamera[6], ch.cameraID, ch.bTallVehicle, FALSE, GRAPH_TYPE_LINEAR) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Switching to Camera 6 - Car Ratio:", fRatio) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Time Elapsed;", GET_CARWASH_TIMER_ELAPSED(ch)) APPLY_CARWASH_WASH_TO_VEHICLE(veh, 50.0, 0.0) ch.iCurrentCameraState = CAMERASTATE_LASTCAMERA ENDIF SHUT_CARWASH_VEHICLE_DOORS(veh) START_CARWASH_TIMER(ch) ENDIF BREAK CASE 4 IF HAS_CAMERA_STRUCT_FINISHED_INTERPOLATING(ch.carwashCamera[3], fRatio) CLEAR_CYLINDER_OF_FIRE(ch.cTrack.vTrackPoint[0], ch.cTrack.vTrackPoint[1], 3.0, NOT g_bInMultiplayer) IF (ch.carWashCamera[4].bSetup) ENABLE_CAMERA_STRUCT(ch.carwashCamera[4], ch.cameraID, ch.bTallVehicle, FALSE, GRAPH_TYPE_LINEAR) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Switching to Camera 4 - Car Ratio:", fRatio) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Time Elapsed;", GET_CARWASH_TIMER_ELAPSED(ch)) ch.iCurrentCameraState ++ ELSE ENABLE_CAMERA_STRUCT(ch.carwashCamera[6], ch.cameraID, ch.bTallVehicle, FALSE, GRAPH_TYPE_LINEAR) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Switching to Camera 6 - Car Ratio:", fRatio) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Time Elapsed:", GET_CARWASH_TIMER_ELAPSED(ch)) APPLY_CARWASH_WASH_TO_VEHICLE(veh, 50.0, 0.0) ch.iCurrentCameraState = CAMERASTATE_LASTCAMERA ENDIF SHUT_CARWASH_VEHICLE_DOORS(veh) START_CARWASH_TIMER(ch) ENDIF BREAK CASE 5 IF HAS_CAMERA_STRUCT_FINISHED_INTERPOLATING(ch.carwashCamera[4], fRatio) CLEAR_CYLINDER_OF_FIRE(ch.cTrack.vTrackPoint[0], ch.cTrack.vTrackPoint[1], 3.0, NOT g_bInMultiplayer) IF (ch.carWashCamera[5].bSetup) ENABLE_CAMERA_STRUCT(ch.carwashCamera[5], ch.cameraID, ch.bTallVehicle, FALSE, GRAPH_TYPE_LINEAR) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Switching to Camera 5 - Car Ratio:", fRatio) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Time Elapsed:", GET_CARWASH_TIMER_ELAPSED(ch)) ch.iCurrentCameraState ++ ELSE ENABLE_CAMERA_STRUCT(ch.carwashCamera[6], ch.cameraID, ch.bTallVehicle, FALSE, GRAPH_TYPE_LINEAR) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Switching to Camera 6 - Car Ratio:", fRatio) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Time Elapsed:", GET_CARWASH_TIMER_ELAPSED(ch)) APPLY_CARWASH_WASH_TO_VEHICLE(veh, 50.0, 0.0) ch.iCurrentCameraState = CAMERASTATE_LASTCAMERA ENDIF SHUT_CARWASH_VEHICLE_DOORS(veh) START_CARWASH_TIMER(ch) ENDIF BREAK CASE 6 IF HAS_CAMERA_STRUCT_FINISHED_INTERPOLATING(ch.carwashCamera[5], fRatio) AND (fRatio >= ch.fFinalCameraInterpolate) CLEAR_CYLINDER_OF_FIRE(ch.cTrack.vTrackPoint[0], ch.cTrack.vTrackPoint[1], 3.0, NOT g_bInMultiplayer) IF NOT IS_POSITION_OCCUPIED(ch.carwashCamera[6].vPosition[0], 2.0, FALSE, TRUE, FALSE, FALSE, FALSE, veh) ENABLE_CAMERA_STRUCT(ch.carwashCamera[6], ch.cameraID, ch.bTallVehicle, FALSE, GRAPH_TYPE_DECEL) ENDIF CPRINTLN(DEBUG_MISSION, "[CARWASH]:Switching to Camera 6 - Car Ratio:", fRatio) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Time Elapsed:", GET_CARWASH_TIMER_ELAPSED(ch)) APPLY_CARWASH_WASH_TO_VEHICLE(veh, 100.0, 0.0) IF NOT g_bInMultiplayer //REMOVE_DECALS_FROM_VEHICLE(veh) ENDIF ch.iCurrentCameraState = CAMERASTATE_LASTCAMERA SHUT_CARWASH_VEHICLE_DOORS(veh) START_CARWASH_TIMER(ch) ENDIF BREAK CASE CAMERASTATE_LASTCAMERA IF IS_POSITION_OCCUPIED(ch.carwashCamera[6].vPosition[0], 2.0, FALSE, TRUE, FALSE, FALSE, FALSE, veh) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Car in the way of last camera") bAbortLastCamera = TRUE ENDIF IF HAS_CAMERA_STRUCT_FINISHED_INTERPOLATING(ch.carwashCamera[6], fRatio) OR (bAbortLastCamera) CPRINTLN(DEBUG_MISSION, "Carwash Finished") CPRINTLN(DEBUG_MISSION, "[CARWASH]:Time Elapsed:", GET_CARWASH_TIMER_ELAPSED(ch)) CLEAR_CYLINDER_OF_FIRE(ch.cTrack.vTrackPoint[0], ch.cTrack.vTrackPoint[1], 3.0, NOT g_bInMultiplayer) SHUTDOWN_CARWASH_CAMERA(ch.cameraID, FALSE) IF IS_AUDIO_SCENE_ACTIVE("CAR_WASH_SCENE") STOP_AUDIO_SCENE("CAR_WASH_SCENE") CPRINTLN(DEBUG_MISSION, "[CARWASH]:Carwash Stop Audio Scene") ENDIF IF IS_PED_IN_CAR_WITH_CARWASH_DRIVER(PLAYER_PED_ID()) CLEAR_PED_TASKS(PLAYER_PED_ID()) ENDIF FORCE_CLEAR_NET_PED_DRIVING_CARWASH_STATUS(PLAYER_PED_ID()) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Re-Enabling Player Controls") SET_PLAYER_CONTROL(PLAYER_ID(), TRUE) //SET_VEHICLE_AND_OCCUPANTS_INVINCIBLE(veh, FALSE) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Carwash is complete") ch.iCurrentCameraState = CAMERASTATE_ALLDONE ch.shapeTestID = NULL ch.iBlockCounts = 0 bIsDriverFinishedCarwashSequence = FALSE bIsDriverRunningCarwashSequence = FALSE iDriverCarwashSequenceProgress = -1 SET_EVERYONE_IGNORE_PLAYER(PLAYER_ID(), FALSE) APPLY_CARWASH_WASH_TO_VEHICLE(veh, 100.0, 0.0) REMOVE_CARWASH_STUCK_CHECK(veh) IF NOT g_bInMultiplayer //REMOVE_DECALS_FROM_VEHICLE(veh) ENDIF SET_CARWASH_CAR_LOCK_STATE(veh, VEHICLELOCK_UNLOCKED) SET_PED_PATHS_BACK_TO_ORIGINAL(ch.vNoPedWalkMin, ch.vNoPedWalkMax) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Unblocking ped area:", ch.vNoPedWalkMin, " ", ch.vNoPedWalkMax) CPRINTLN(DEBUG_MISSION, "[CARWASH]:Carwash car doors unlocked") REGISTER_SCRIPT_IN_COMPLETION_PERCENTAGE_TOTAL(CP_CARWSH) RETURN TRUE ELSE HIDE_HUD_AND_RADAR_THIS_FRAME() ENDIF BREAK CASE CAMERASTATE_ALLDONE IF IS_AUDIO_SCENE_ACTIVE("CAR_WASH_SCENE") CPRINTLN(DEBUG_MISSION, "Carwash Stop Audio Scene") STOP_AUDIO_SCENE("CAR_WASH_SCENE") ENDIF SHUTDOWN_CARWASH_CAMERA(ch.cameraID, FALSE) ch.shapeTestID = NULL ch.iBlockCounts = 0 ch.bTimerStarted = FALSE bIsDriverFinishedCarwashSequence = FALSE bIsDriverRunningCarwashSequence = FALSE iDriverCarwashSequenceProgress = -1 BREAK ENDSWITCH RETURN FALSE ENDFUNC PROC DELETE_CARWASH_HANDLER(CARWASH_HANDLER &ch) VEHICLE_INDEX ind IF NOT NETWORK_IS_GAME_IN_PROGRESS() RC_END_CUTSCENE_MODE() ENDIF CPRINTLN(DEBUG_MISSION, "Delete Carwash") FORCE_CLEAR_NET_PED_DRIVING_CARWASH_STATUS(PLAYER_PED_ID()) DISABLE_CELLPHONE(FALSE) ch.shapeTestID = NULL ch.iBlockCounts = 0 RESET_COLLISIONS_FOR_CARWASH(ch) STOP_ALL_CARWASH_SOUNDS(ch) STOP_ALL_CARWASH_PARTICLES(ch) DELETE_CARWASH_VERTROLLER(ch.vertRoller) DELETE_CARWASH_HROLLER(ch.horzRoller) DELETE_CARWASH_JETS(ch.waterJets) DELETE_CARWASH_JETS(ch.soapJets) DELETE_CARWASH_JETS(ch.steamJets) SET_BUILDING_STATE(ch.iplSwap, BUILDINGSTATE_NORMAL) SHUTDOWN_CAMERA(ch.cameraID) IF IS_AUDIO_SCENE_ACTIVE("CAR_WASH_SCENE") CPRINTLN(DEBUG_MISSION, "Carwash Stop Audio Scene") STOP_AUDIO_SCENE("CAR_WASH_SCENE") ENDIF IF DOES_ENTITY_EXIST(PLAYER_PED_ID()) IS_ENTITY_DEAD(PLAYER_PED_ID()) IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) ind = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()) IF IS_ENTITY_OK(ind) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Unlocking Car") SET_CARWASH_CAR_LOCK_STATE(ind, VEHICLELOCK_UNLOCKED) REMOVE_CARWASH_STUCK_CHECK(ind) ENDIF ENDIF ENDIF IF (g_bInMultiplayer) PLAYER_INDEX player = NETWORK_GET_PLAYER_INDEX_FROM_PED(PLAYER_PED_ID()) IF (player != INVALID_PLAYER_INDEX()) IF (GlobalPlayerBD[NATIVE_TO_INT(player)].bDrivingThroughCarwash = TRUE) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Setting player to net be in carwash") GlobalPlayerBD[NATIVE_TO_INT(player)].bDrivingThroughCarwash = FALSE ENDIF ENDIF ENDIF ind = GET_PLAYERS_LAST_VEHICLE() IF IS_ENTITY_OK(ind) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Unlocking Players Last Vehicle") SET_CARWASH_CAR_LOCK_STATE(ind, VEHICLELOCK_UNLOCKED) REMOVE_CARWASH_STUCK_CHECK(ind) ENDIF SET_PED_PATHS_BACK_TO_ORIGINAL(ch.vNoPedWalkMin, ch.vNoPedWalkMax) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Unblocking ped area:", ch.vNoPedWalkMin, " ", ch.vNoPedWalkMax) // Enable car wash scenarios SET_SCENARIO_TYPE_ENABLED("DRIVE", TRUE) SET_SCENARIO_TYPE_ENABLED("WORLD_VEHICLE_DRIVE_SOLO", TRUE) ENDPROC PROC SHARED_CARWASH_SCRIPT_CLEANUP(CARWASH_HANDLER &ch, BOOL bSkip = FALSE) VECTOR v DELETE_CARWASH_HANDLER(ch) IF (g_bInMultiplayer) PLAYER_INDEX player = NETWORK_GET_PLAYER_INDEX_FROM_PED(PLAYER_PED_ID()) IF (player != INVALID_PLAYER_INDEX()) IF (GlobalPlayerBD[NATIVE_TO_INT(player)].bDrivingThroughCarwash = TRUE) CPRINTLN(DEBUG_MISSION, "[CARWASH]: Setting player to net be in carwash") GlobalPlayerBD[NATIVE_TO_INT(player)].bDrivingThroughCarwash = FALSE ENDIF ENDIF ENDIF // B*1331838 - Player wasn't being charged on skip IF (bSkip = TRUE) CLEAR_PED_TASKS(PLAYER_PED_ID()) SET_VEHICLE_ALONG_CARWASH_TRACK(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), ch.cTrack, 1.0, 0.0) SET_VEHICLE_ON_GROUND_PROPERLY(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())) SET_ENTITY_VELOCITY(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), <<0, 0, 0>>) WAIT(0) IS_CARWASH_PED_OK(PLAYER_PED_ID()) v = GET_ENTITY_COORDS(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())) v.z = INVALID_WORLD_Z SET_ENTITY_COORDS(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), v) APPLY_CARWASH_WASH_TO_VEHICLE(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), 500.0, 0.0) SET_CARWASH_CAR_LOCK_STATE(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), VEHICLELOCK_UNLOCKED) WAIT(125) DO_SCREEN_FADE_IN(500) WAIT(1000) REGISTER_SCRIPT_IN_COMPLETION_PERCENTAGE_TOTAL(CP_CARWSH) CHARGE_PLAYER_FOR_CARWASH(ch.iLocationID) ELIF NOT NETWORK_IS_GAME_IN_PROGRESS() CLEAR_PED_TASKS(PLAYER_PED_ID()) ENDIF IF NOT (g_bInMultiplayer) REACTIVATE_NAMED_WORLD_BRAINS_WAITING_TILL_OUT_OF_RANGE("launcher_CarWash") ENDIF ENDPROC /// PURPOSE: /// Gets bank balance of current player /// RETURNS: /// FUNC INT GET_CARWASH_CURRENT_PLAYER_PED_ACCOUNT_BALANCE() IF NETWORK_IS_GAME_IN_PROGRESS() RETURN NETWORK_GET_VC_BALANCE() ENDIF RETURN GET_TOTAL_CASH(GET_CURRENT_PLAYER_PED_ENUM()) ENDFUNC FUNC BOOL DO_WE_HAVE_ENOUGH_MONEY_FOR(INT iCost) IF NETWORK_IS_GAME_IN_PROGRESS() RETURN NETWORK_GET_CAN_SPEND_FROM_BANK_AND_WALLET(iCost) ENDIF RETURN (GET_TOTAL_CASH(GET_CURRENT_PLAYER_PED_ENUM()) >= iCost) ENDFUNC FUNC BOOL AM_I_DRIVING_CLOSEST_CAR_TO_CARWASH(COST_HALO& halo, VEHICLE_INDEX &vehOut) INT iCount, i INT iCar = -1 FLOAT fDist, fMinDist = 1.0 VEHICLE_INDEX array[32] IF NOT NETWORK_IS_GAME_IN_PROGRESS() RETURN TRUE ENDIF IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) RETURN FALSE ENDIF iCount = GET_PED_NEARBY_VEHICLES(PLAYER_PED_ID(), array) REPEAT iCount i IF IS_ENTITY_OK(array[i]) fDist = GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(array[i], halo.vTriggerPoint) IF (fDist < fMinDist) OR (fMinDist = -1.0) fMinDist = fDist iCar = i ENDIF ENDIF ENDREPEAT //CPRINTLN(DEBUG_MISSION, "[CARWASH] - CDM:iCar = ", iCar) IF (iCar = -1) //DISPLAY_TEXT_WITH_LITERAL_STRING(0.1, 0.2, "STRING", "NO CAR") RETURN FALSE ENDIF //CPRINTLN(DEBUG_MISSION, "[CARWASH] - CDM: driver = ", (GET_PED_IN_VEHICLE_SEAT(array[iCar]) != PLAYER_PED_ID())) IF (GET_PED_IN_VEHICLE_SEAT(array[iCar]) != PLAYER_PED_ID()) RETURN FALSE //DISPLAY_TEXT_WITH_LITERAL_STRING(0.1, 0.2, "STRING", "NOT DRIVING CAR") ENDIF vehOut = array[iCar] RETURN TRUE ENDFUNC FUNC INT COUNT_NUMBER_OF_CARS_IN_CARWASH_HALO(COST_HALO& halo) INT iCount, i VEHICLE_INDEX array[32] FLOAT fDist INT iCarCount iCount = GET_PED_NEARBY_VEHICLES(PLAYER_PED_ID(), array) REPEAT iCount i IF IS_ENTITY_OK(array[i]) fDist = GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(array[i], halo.vTriggerPoint) IF (fDist <= (halo.fTriggerDist * 2.5)) iCarCount ++ ENDIF ENDIF ENDREPEAT RETURN iCarCount ENDFUNC FUNC BOOL CAN_PLAYER_TRIGGER_CARWASH_HALO_IN_CAR(COST_HALO& halo) VEHICLE_INDEX array[32] INT iCount, i INT iCar = -1 FLOAT fDist, fMinDist = 1.0 IF NOT NETWORK_IS_GAME_IN_PROGRESS() RETURN TRUE ENDIF iCount = GET_PED_NEARBY_VEHICLES(PLAYER_PED_ID(), array) REPEAT iCount i IF IS_ENTITY_OK(array[i]) fDist = GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(array[i], halo.vTriggerPoint) IF (fDist <= (halo.fTriggerDist * 2.5)) IF (fDist < fMinDist) OR (fMinDist = -1.0) fMinDist = fDist iCar = i ENDIF ENDIF ENDIF ENDREPEAT IF (iCar = -1) //DISPLAY_TEXT_WITH_LITERAL_STRING(0.1, 0.2, "STRING", "NO CAR") RETURN FALSE ENDIF /* DRAW_DEBUG_LINE(GET_ENTITY_COORDS(array[iCar]) - <<0, 0, 2>>, GET_ENTITY_COORDS(array[iCar]) + <<0, 0, 2>>) DRAW_DEBUG_LINE(GET_ENTITY_COORDS(array[iCar]), GET_ENTITY_COORDS(PLAYER_PED_ID())) */ IF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), array[iCar]) //DISPLAY_TEXT_WITH_LITERAL_STRING(0.1, 0.2, "STRING", "PLAYER NOT IN CAR") RETURN FALSE ENDIF RETURN TRUE ENDFUNC /// PURPOSE: /// Updates the cost halos /// PARAMS: /// halo - array of halos /// hndlr - handler reference (string and other stuff) /// bNoWay - if we've passed the no way check /// bFadeLaunch - do we fade when we launch /// RETURNS: /// Returns true if we have launched the script FUNC BOOL UPDATE_CARWASH_COSTHALO_HANDLER(COST_HALO& halo[], COSTHALO_HANDLER& hndlr, BOOL bNoWay = FALSE, BOOL bFadeLaunch = FALSE, BOOL bAutoLaunch = TRUE, INT iStack = DEFAULT_STACK_SIZE) INT i VEHICLE_INDEX vehCheck IF (hndlr.bShowMarkers) i = 0 REPEAT COUNT_OF(halo) i DRAW_COST_HALO(halo[i]) ENDREPEAT ENDIF SWITCH (hndlr.selectState) CASE APPROACH_HALO i = 0 IF IS_COSTHALO_ALLOWED_TO_LAUNCH(hndlr.bAllowOnMission) //CPRINTLN(DEBUG_MISSION, "[CARWASH] - CDM: IS_COSTHALO_ALLOWED_TO_LAUNCH TRUE") REPEAT COUNT_OF(halo) i //CPRINTLN(DEBUG_MISSION, "[CARWASH] - CDM: halo[",i,"].bIsActive:", halo[i].bIsActive) IF IS_PLAYER_IN_COST_HALO(halo[i]) AND (halo[i].bIsActive) //CPRINTLN(DEBUG_MISSION, "[CARWASH] - CDM: IS_PLAYER_IN_COST_HALO TRUE") hndlr.iSelectedHalo = i IF IS_PLAYER_ON_MP_AMBIENT_SCRIPT(PLAYER_ID(), MPAM_TYPE_TIME_TRIAL) OR IS_PLAYER_ON_MP_AMBIENT_SCRIPT(PLAYER_ID(), MPAM_TYPE_RC_TIME_TRIAL) SET_COSTHALO_HANDLER_STATE(hndlr, CLOSED_HALO) ELIF (halo[i].bClosed) OR (GET_MISSION_FLAG() AND (hndlr.bAllowOnMission = FALSE)) SET_COSTHALO_HANDLER_STATE(hndlr, CLOSED_HALO) ELIF (GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0) SET_COSTHALO_HANDLER_STATE(hndlr, WANTED_HALO) ELIF (bNoWay) SET_COSTHALO_HANDLER_STATE(hndlr, DENIED_HALO) ELIF (halo[i].bCustomCheck) SET_COSTHALO_HANDLER_STATE(hndlr, CUSTOMCHECK_HALO) //ELIF (GET_CARWASH_CURRENT_PLAYER_PED_ACCOUNT_BALANCE() < halo[hndlr.iSelectedHalo].iCost) ELIF NOT DO_WE_HAVE_ENOUGH_MONEY_FOR(halo[hndlr.iSelectedHalo].iCost) SET_COSTHALO_HANDLER_STATE(hndlr, CANTAFFORD_HALO) ELIF IS_PLAYER_IN_A_BUST_VEHICLE() SET_COSTHALO_HANDLER_STATE(hndlr, DAMAGED_HALO) ELIF AM_I_DRIVING_CLOSEST_CAR_TO_CARWASH(halo[i], vehCheck) SET_COSTHALO_HANDLER_STATE(hndlr, TRIGGER_HALO) ENDIF //CPRINTLN(DEBUG_MISSION, "[CARWASH] - CDM: IS_PLAYER_IN_A_BUST_VEHICLE:",IS_PLAYER_IN_A_BUST_VEHICLE()) //CPRINTLN(DEBUG_MISSION, "[CARWASH] - CDM: AM_I_DRIVING_CLOSEST_CAR_TO_CARWASH:",AM_I_DRIVING_CLOSEST_CAR_TO_CARWASH(halo[i], vehCheck)) ENDIF ENDREPEAT ELSE CLEAR_COSTHALO_HANDLER_HELP(hndlr) ENDIF BREAK CASE CUSTOMCHECK_HALO IF NOT (hndlr.bTriggerHelpShown) PRINT_COSTHALO_HELP(hndlr, hndlr.sCustomString) ENDIF IF IS_PLAYER_OUT_OF_COST_HALO(halo[hndlr.iSelectedHalo]) OR (halo[i].bCustomCheck = FALSE) SET_COSTHALO_HANDLER_STATE(hndlr, APPROACH_HALO) RETURN FALSE ENDIF BREAK CASE CANTAFFORD_HALO IF NOT (hndlr.bTriggerHelpShown) PRINT_COSTHALO_HELP_WITH_NUMBER(hndlr, hndlr.sPoorString, halo[hndlr.iSelectedHalo].iCost) ENDIF IF IS_PLAYER_OUT_OF_COST_HALO(halo[hndlr.iSelectedHalo]) OR DO_WE_HAVE_ENOUGH_MONEY_FOR(halo[hndlr.iSelectedHalo].iCost) //(GET_CARWASH_CURRENT_PLAYER_PED_ACCOUNT_BALANCE() >= halo[hndlr.iSelectedHalo].iCost) SET_COSTHALO_HANDLER_STATE(hndlr, APPROACH_HALO) RETURN FALSE ENDIF BREAK CASE CLOSED_HALO IF NOT (hndlr.bTriggerHelpShown) PRINT_COSTHALO_HELP(hndlr, hndlr.sBrokenString) ENDIF IF IS_PLAYER_OUT_OF_COST_HALO(halo[hndlr.iSelectedHalo]) OR NOT IS_COSTHALO_ALLOWED_TO_LAUNCH(hndlr.bAllowOnMission) SET_COSTHALO_HANDLER_STATE(hndlr, APPROACH_HALO) RETURN FALSE ENDIF BREAK CASE DENIED_HALO IF NOT (hndlr.bTriggerHelpShown) PRINT_COSTHALO_HELP(hndlr, hndlr.sNoWayString) ENDIF IF IS_PLAYER_OUT_OF_COST_HALO(halo[hndlr.iSelectedHalo]) OR (bNoWay = FALSE) OR NOT IS_COSTHALO_ALLOWED_TO_LAUNCH(hndlr.bAllowOnMission) SET_COSTHALO_HANDLER_STATE(hndlr, APPROACH_HALO) RETURN FALSE ENDIF BREAK CASE DAMAGED_HALO IF NOT (hndlr.bTriggerHelpShown) PRINT_COSTHALO_HELP(hndlr, hndlr.sDamagedString) ENDIF IF IS_PLAYER_OUT_OF_COST_HALO(halo[hndlr.iSelectedHalo]) OR NOT IS_COSTHALO_ALLOWED_TO_LAUNCH(hndlr.bAllowOnMission) SET_COSTHALO_HANDLER_STATE(hndlr, APPROACH_HALO) RETURN FALSE ENDIF BREAK CASE WANTED_HALO IF NOT (hndlr.bTriggerHelpShown) PRINT_COSTHALO_HELP(hndlr, hndlr.sWantedString) ENDIF IF IS_PLAYER_OUT_OF_COST_HALO(halo[hndlr.iSelectedHalo]) OR (GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) = 0) SET_COSTHALO_HANDLER_STATE(hndlr, APPROACH_HALO) RETURN FALSE ENDIF BREAK CASE WRONGWAY_HALO IF NOT (hndlr.bTriggerHelpShown) IF IS_PLAYER_UPRIGHT() PRINT_COSTHALO_HELP(hndlr, hndlr.sWrongWayString) ELSE PRINT_COSTHALO_HELP(hndlr, hndlr.sUpsideDownString) ENDIF ENDIF IF IS_PLAYER_OUT_OF_COST_HALO(halo[hndlr.iSelectedHalo]) OR IS_PLAYER_WITHIN_HALO_TOLERANCE(halo[hndlr.iSelectedHalo]) SET_COSTHALO_HANDLER_STATE(hndlr, APPROACH_HALO) RETURN FALSE ENDIF BREAK CASE TRIGGER_HALO SET_INPUT_EXCLUSIVE(FRONTEND_CONTROL, INPUT_CONTEXT) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_ROOF) DISABLE_SELECTOR_THIS_FRAME() IF (GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0) SET_COSTHALO_HANDLER_STATE(hndlr, WANTED_HALO) RETURN FALSE ENDIF IF (halo[hndlr.iSelectedHalo].bCustomCheck) SET_COSTHALO_HANDLER_STATE(hndlr, CUSTOMCHECK_HALO) RETURN FALSE ENDIF IF IS_PLAYER_OUT_OF_COST_HALO(halo[hndlr.iSelectedHalo]) OR NOT IS_COSTHALO_ALLOWED_TO_LAUNCH(hndlr.bAllowOnMission) SET_COSTHALO_HANDLER_STATE(hndlr, APPROACH_HALO) RETURN FALSE ENDIF // don't launch if browser is running IF (g_bBrowserVisible) RETURN FALSE ENDIF // need to add wrong type check here IF (halo[hndlr.iSelectedHalo].haloType = HALO_VEHICLE) IF (NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) OR (GET_SEAT_PED_IS_IN(PLAYER_PED_ID()) <> VS_DRIVER)) SET_COSTHALO_HANDLER_STATE(hndlr, APPROACH_HALO) RETURN FALSE ENDIF ENDIF IF (halo[hndlr.iSelectedHalo].bClosed) OR (GET_MISSION_FLAG() AND (hndlr.bAllowOnMission = FALSE)) SET_COSTHALO_HANDLER_STATE(hndlr, CLOSED_HALO) RETURN FALSE ENDIF IF IS_PLAYER_IN_A_BUST_VEHICLE() SET_COSTHALO_HANDLER_STATE(hndlr, DAMAGED_HALO) RETURN FALSE ENDIF //IF (GET_CARWASH_CURRENT_PLAYER_PED_ACCOUNT_BALANCE() < halo[hndlr.iSelectedHalo].iCost) IF NOT DO_WE_HAVE_ENOUGH_MONEY_FOR(halo[hndlr.iSelectedHalo].iCost) SET_COSTHALO_HANDLER_STATE(hndlr, CANTAFFORD_HALO) RETURN FALSE ENDIF /* IF NOT (CAN_PLAYER_TRIGGER_CARWASH_HALO_IN_CAR(halo[hndlr.iSelectedHalo])) //SET_COSTHALO_HANDLER_STATE(hndlr, DENIED_HALO) //RETURN FALSE DISPLAY_TEXT_WITH_LITERAL_STRING(0.5, 0.5, "STRING", "NO WAY") ENDIF */ IF bNoWay SET_COSTHALO_HANDLER_STATE(hndlr, DENIED_HALO) RETURN FALSE ENDIF IF !bNoWay AND NOT (hndlr.bTriggerHelpShown) PRINT_COSTHALO_HELP_WITH_NUMBER(hndlr, hndlr.sActivateString, halo[hndlr.iSelectedHalo].iCost) ENDIF // don't let player trigger if they are driving straight through it // cant use a vehicle stuck on roof check as i need to add it so check for roll instead IF (halo[hndlr.iSelectedHalo].haloType = HALO_VEHICLE) /* IF (GET_ENTITY_SPEED(PLAYER_PED_ID()) > 5.0) RETURN FALSE ENDIF */ // if ped is getting out of vehicle don't allow launch IF (IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) AND NOT IS_PED_SITTING_IN_ANY_VEHICLE(PLAYER_PED_ID())) RETURN FALSE ENDIF ENDIF IF IS_PAUSE_MENU_ACTIVE() OR IS_SYSTEM_UI_BEING_DISPLAYED() RETURN FALSE ENDIF // don't let a ped this if the player is on foot but on with both feet on the ground IF IS_PED_ON_FOOT(PLAYER_PED_ID()) IF IS_PED_FALLING(PLAYER_PED_ID()) OR IS_PED_JUMPING(PLAYER_PED_ID()) OR IS_PED_JUMPING_OUT_OF_VEHICLE(PLAYER_PED_ID()) RETURN FALSE ENDIF IF IS_PED_RUNNING_RAGDOLL_TASK(PLAYER_PED_ID()) OR IS_PED_RAGDOLL(PLAYER_PED_ID()) OR IS_PED_GETTING_UP(PLAYER_PED_ID()) RETURN FALSE ENDIF IF IS_PED_CLIMBING(PLAYER_PED_ID()) RETURN FALSE ENDIF IF IS_PED_DUCKING(PLAYER_PED_ID()) OR IS_PED_SWIMMING(PLAYER_PED_ID()) RETURN FALSE ENDIF IF (GET_ENTITY_SPEED(PLAYER_PED_ID()) > 0.05) RETURN FALSE ENDIF ENDIF IF IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_CONTEXT) AND (hndlr.bTriggerHelpShown = TRUE) AND bNoWay = FALSE IF NOT IS_PLAYER_WITHIN_HALO_TOLERANCE(halo[hndlr.iSelectedHalo]) SET_COSTHALO_HANDLER_STATE(hndlr, WRONGWAY_HALO) ELSE SET_COSTHALO_HANDLER_STATE(hndlr, LAUNCH_HALO) ENDIF ENDIF BREAK CASE LAUNCH_HALO IF NETWORK_IS_GAME_IN_PROGRESS() IF REQUEST_SCRIPT_AUDIO_BANK("SCRIPT\\CARWASH") PRINTLN("[CARWASH] Audio bank loaded") ENDIF ENDIF CLEAR_COSTHALO_HANDLER_HELP(hndlr) halo[hndlr.iSelectedHalo].bCustomCheck = FALSE IF NOT bAutoLaunch SET_COSTHALO_HANDLER_STATE(hndlr, APPROACH_HALO) RETURN TRUE ENDIF CLEAR_HELP() CLEAR_AREA_OF_PROJECTILES(GET_ENTITY_COORDS(PLAYER_PED_ID()), 20.0) IF NOT IS_STRING_NULL_OR_EMPTY(halo[hndlr.iSelectedHalo].sScriptName) REQUEST_SCRIPT(halo[hndlr.iSelectedHalo].sScriptName) WHILE NOT HAS_SCRIPT_LOADED(halo[hndlr.iSelectedHalo].sScriptName) DISABLE_SELECTOR_THIS_FRAME() IF IS_ENTITY_OK(PLAYER_PED_ID()) IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) AND NOT g_bInMultiplayer BRING_VEHICLE_TO_HALT_AND_DISABLE_VEH_CONTROLS(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), 2) ENDIF ENDIF SET_INPUT_EXCLUSIVE(FRONTEND_CONTROL, INPUT_CONTEXT) REQUEST_SCRIPT(halo[hndlr.iSelectedHalo].sScriptName) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_ROOF) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_EXIT) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_ENTER) WAIT(0) ENDWHILE IF (bFadeLaunch) DO_SCREEN_FADE_OUT(250) ENDIF IF HAS_SCRIPT_LOADED(halo[hndlr.iSelectedHalo].sScriptName) IF (bFadeLaunch) WHILE NOT IS_SCREEN_FADED_OUT() IF IS_ENTITY_OK(PLAYER_PED_ID()) IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) AND NOT g_bInMultiplayer BRING_VEHICLE_TO_HALT_AND_DISABLE_VEH_CONTROLS(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), 2) ENDIF ENDIF SET_INPUT_EXCLUSIVE(FRONTEND_CONTROL, INPUT_CONTEXT) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_ROOF) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_EXIT) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_ENTER) DISABLE_SELECTOR_THIS_FRAME() WAIT(0) ENDWHILE ENDIF START_NEW_SCRIPT(halo[hndlr.iSelectedHalo].sScriptName, iStack) SET_SCRIPT_AS_NO_LONGER_NEEDED(halo[hndlr.iSelectedHalo].sScriptName) RETURN TRUE ENDIF ENDIF BREAK ENDSWITCH RETURN FALSE ENDFUNC //---------------------- // DEBUG FUNCTIONS //---------------------- #IF IS_DEBUG_BUILD /// PURPOSE: /// Initializes Debug Widgets PROC SETUP_DEBUG_CARWASH_HROLLER_WIDGETS(CARWASH_HROLLER &roll, STRING str = NULL) IF IS_STRING_NULL_OR_EMPTY(str) str = "Horizontal Roller" ENDIF START_WIDGET_GROUP(str) ADD_WIDGET_FLOAT_SLIDER("Pivot Angle", roll.fRollerPivotAngle, 0.0, 360.0, 0.25) ADD_WIDGET_FLOAT_SLIDER("Move Rate", roll.fMoveRate, 0.0, 15.0, 1.0) ADD_WIDGET_FLOAT_SLIDER("Spin Rate", roll.fSpinRate, 0.0, 3600.0, 0.025) ADD_WIDGET_FLOAT_SLIDER("Trigger Dist", roll.fTriggerDist, 0.0, 5.0, 0.125) ADD_WIDGET_FLOAT_READ_ONLY("Spin Angle", roll.fRollerSpinAngle) ADD_WIDGET_FLOAT_READ_ONLY("Ground Zero", roll.fGroundZero) ADD_WIDGET_INT_READ_ONLY("Next Check Time", roll.iNextCheckTime) ADD_WIDGET_INT_READ_ONLY("Next Shape Time", roll.iNextShapeTestTime) STOP_WIDGET_GROUP() ENDPROC /// PURPOSE: /// Initializes Debug Widgets PROC SETUP_DEBUG_CARWASH_VERTROLLER_WIDGETS(CARWASH_VROLLER2 &roll, STRING str = NULL) IF IS_STRING_NULL_OR_EMPTY(str) str = "Vert Roller" ENDIF START_WIDGET_GROUP(str) ADD_WIDGET_BOOL("Collision On", roll.bCollisionOn) ADD_WIDGET_BOOL("Front Sensor", roll.bSensorOn[0]) ADD_WIDGET_FLOAT_SLIDER("Front Sensor Offset", roll.fSensorOffset[0], -5.0, 5.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("Front Sensor Radius", roll.fSensorRadius[0], -5.0, 5.0, 0.001) ADD_WIDGET_BOOL("Back Sensor", roll.bSensorOn[1]) ADD_WIDGET_FLOAT_SLIDER("FrontSensor Offset", roll.fSensorOffset[1], -5.0, 5.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("FrontSensor Radius", roll.fSensorRadius[1], -5.0, 5.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("Left Offset", roll.fOffset[0], -5.0, -ROLLER_RADIUS, 0.001) ADD_WIDGET_FLOAT_SLIDER("Right Offset", roll.fOffset[1], ROLLER_RADIUS, 5.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("Left TGT Offset", roll.fTgtOffset[0], -5.0, -ROLLER_RADIUS, 0.001) ADD_WIDGET_FLOAT_SLIDER("Right TGT Offset", roll.fTgtOffset[1], ROLLER_RADIUS, 5.0, 0.001) ADD_WIDGET_FLOAT_SLIDER("Move Rate", roll.fMoveRate, 0.0, 15.0, 1.0) ADD_WIDGET_FLOAT_SLIDER("Shut Down Move Rate", roll.fShutDownMoveRate, 0.0, 15.0, 0.01) ADD_WIDGET_FLOAT_SLIDER("Spin Rate", roll.fSpinRate, 0.0, 3600.0, 10) ADD_WIDGET_FLOAT_READ_ONLY("Spin Angle", roll.fRollerSpinAngle) STOP_WIDGET_GROUP() ENDPROC PROC SETUP_DEBUG_CARWASH_CONSTANT_WIDGETS() START_WIDGET_GROUP("Constants") ADD_WIDGET_BOOL("Use New MP Rollers", bUseNewMPVertRollers) ADD_WIDGET_INT_SLIDER("RollerCheck Interval", ROLLER_CHECK_INTERVAL, 1, 2000, 10) ADD_WIDGET_INT_SLIDER("ShapeCheck Interval", SHAPE_CHECK_INTERVAL, 1, 2000, 10) START_WIDGET_GROUP("Particle Values") ADD_WIDGET_VECTOR_SLIDER("H Spray ROffset", vRollerHorzRotFX, -360, 360.0, 0.01) ADD_WIDGET_VECTOR_SLIDER("V Spray ROffset", vRollerVertRotFX, -360, 360.0, 0.01) ADD_WIDGET_VECTOR_SLIDER("V Spray POffset", vRollerVertPosFX, -5, 5, 0.01) ADD_WIDGET_VECTOR_SLIDER("Jet Spray ROffset", vJetRotFX, -360, 360.0, 0.01) ADD_WIDGET_VECTOR_SLIDER("Steam ROffset", vSteamRotFX, -360, 360.0, 0.01) ADD_WIDGET_VECTOR_SLIDER("Steam POffset", vSteamPosFX, -8, 8, 0.01) STOP_WIDGET_GROUP() STOP_WIDGET_GROUP() ENDPROC /// PURPOSE: /// Initializes Debug Widgets PROC SETUP_DEBUG_CARWASH_JETS_WIDGETS(CARWASH_JETS &roll, STRING str = NULL) IF IS_STRING_NULL_OR_EMPTY(str) str = "Jets" ENDIF START_WIDGET_GROUP(str) ADD_WIDGET_BOOL("Steam", roll.bSteam) ADD_WIDGET_FLOAT_SLIDER("Trigger Dist", roll.fTriggerDist, 0.0, 5.0, 0.125) ADD_WIDGET_FLOAT_SLIDER("Seperation", roll.fSeperation, 0.0, 5.0, 0.0625) ADD_WIDGET_INT_READ_ONLY("Next Check Time", roll.iNextCheckTime) STOP_WIDGET_GROUP() ENDPROC PROC SETUP_DEBUG_CARWASH_HANDLER_WIDGETS(CARWASH_HANDLER &ct) START_WIDGET_GROUP("Carwash") ADD_WIDGET_BOOL("Draw Debug", bDrawDebugCarwash) ADD_WIDGET_BOOL("Use Old Verticle Brush Check", bUseOldVerticleBrushCheck) ADD_WIDGET_BOOL("Use New Shape Test", bUseNewSweptSphereTest) ADD_WIDGET_FLOAT_SLIDER("Sweep Sphere Radius", fSweepSphereRadius, 0.25, 3.0, 0.05) ADD_WIDGET_FLOAT_SLIDER("X Seperation", fShapeTestXSeperation, 0.1, 5.0, 0.125) ADD_WIDGET_BOOL("Aborted", ct.bCarwashAborted) START_WIDGET_GROUP("Tasks") ADD_WIDGET_BOOL("Clear Ped Tasks", bDebugForceClearPedTasks) ADD_WIDGET_BOOL("Restart Ped Tasks", bDebugForceRestartTasks) ADD_WIDGET_BOOL("Is Ped Runing Task", bIsDriverRunningCarwashSequence) ADD_WIDGET_BOOL("Is Ped Done Task", bIsDriverFinishedCarwashSequence) ADD_WIDGET_BOOL("Create Block Car", bCreateBlockCar) ADD_WIDGET_FLOAT_SLIDER("Block Car T", fBlockCarPlaceT, -1.0, 2.0, 0.001) ADD_WIDGET_INT_READ_ONLY("Task Sequence Progress", iDriverCarwashSequenceProgress) ADD_WIDGET_INT_READ_ONLY("Task Sequence Size", ct.iTaskSequenceSize) STOP_WIDGET_GROUP() SETUP_DEBUG_CARWASH_HROLLER_WIDGETS(ct.horzRoller) SETUP_DEBUG_CARWASH_VERTROLLER_WIDGETS(ct.vertRoller, "New Vert Roller") SETUP_DEBUG_CARWASH_JETS_WIDGETS(ct.steamJets, "Steam") SETUP_DEBUG_CARWASH_JETS_WIDGETS(ct.waterJets, "Water") SETUP_DEBUG_CARWASH_JETS_WIDGETS(ct.soapJets, "Soaps") ADD_WIDGET_FLOAT_SLIDER("Roll Shift Factor", ROLLER_SHIFT_FACTOR, 0.0, 2.0, 0.0001) ADD_WIDGET_FLOAT_SLIDER("Forward", ct.fForwardSpeed, 0, 30.0, 0.01) ADD_WIDGET_FLOAT_SLIDER("FCInterpolate", ct.fFinalCameraInterpolate, 0, 1.0, 0.01) ADD_WIDGET_INT_READ_ONLY("Camera State", ct.iCurrentCameraState) ADD_WIDGET_READ_ONLY_VECTOR("Direction", ct.cTrack.vDirection) ADD_WIDGET_FLOAT_READ_ONLY("Car Ratio", fCarDebugRatio) ADD_WIDGET_INT_READ_ONLY("Carwash Timer", iDebugCarWashTimer) STOP_WIDGET_GROUP() ENDPROC PROC DRAW_DEBUG_BOX_WITH_HEADING(VECTOR vPos, VECTOR vDim, FLOAT fHeading) VECTOR vBoxCorner[8] VECTOR vMin = -vDim / 2.0 VECTOR vMax = vDim / 2.0 vBoxCorner[7] = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vPos, fHeading, <>) vBoxCorner[6] = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vPos, fHeading, <>) vBoxCorner[5] = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vPos, fHeading, <>) vBoxCorner[4] = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vPos, fHeading, <>) vBoxCorner[3] = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vPos, fHeading, <>) vBoxCorner[2] = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vPos, fHeading, <>) vBoxCorner[1] = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vPos, fHeading, <>) vBoxCorner[0] = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vPos, fHeading, <>) DRAW_DEBUG_POLY(vBoxCorner[0], vBoxCorner[1], vBoxCorner[5], 200, 100, 0, 100) DRAW_DEBUG_POLY(vBoxCorner[0], vBoxCorner[5], vBoxCorner[4], 200, 100, 0, 100) DRAW_DEBUG_POLY(vBoxCorner[1], vBoxCorner[2], vBoxCorner[6], 200, 200, 0, 100) DRAW_DEBUG_POLY(vBoxCorner[1], vBoxCorner[6], vBoxCorner[5], 200, 200, 0, 100) DRAW_DEBUG_POLY(vBoxCorner[2], vBoxCorner[3], vBoxCorner[7], 200, 100, 0, 100) DRAW_DEBUG_POLY(vBoxCorner[2], vBoxCorner[7], vBoxCorner[6], 200, 100, 0, 100) DRAW_DEBUG_POLY(vBoxCorner[3], vBoxCorner[0], vBoxCorner[4], 200, 200, 0, 100) DRAW_DEBUG_POLY(vBoxCorner[3], vBoxCorner[4], vBoxCorner[7], 200, 200, 0, 100) DRAW_DEBUG_POLY(vBoxCorner[2], vBoxCorner[1], vBoxCorner[0], 200, 150, 0, 100) DRAW_DEBUG_POLY(vBoxCorner[3], vBoxCorner[2], vBoxCorner[0], 200, 150, 0, 100) DRAW_DEBUG_POLY(vBoxCorner[4], vBoxCorner[5], vBoxCorner[6], 200, 150, 0, 100) DRAW_DEBUG_POLY(vBoxCorner[4], vBoxCorner[6], vBoxCorner[7], 200, 150, 0, 100) ENDPROC #ENDIF