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

269 lines
11 KiB
Python
Executable File

//
// Author: Ben Rollinson Date: 10/04/13
//
//
// Lester Handler
//
// Manages Lester when he hangs around on his laptop after missions.
//
//
//Compile out Title Update changes to header functions.
//Must be before includes.
//CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R.
USING "globals.sch"
USING "rage_builtins.sch"
USING "dialogue_public.sch"
USING "random_events_public.sch"
USING "brains.sch"
CONST_INT BIT_LESTER_OWNED 0
CONST_INT BIT_PLAYER_LEFT_AREA 1
PED_INDEX pedLester
OBJECT_INDEX objLesterStick
OBJECT_INDEX objLaptop
SEQUENCE_INDEX seqLesterUseLaptop
REL_GROUP_HASH rghLester
structPedsForConversation sPedForConversation
TWEAK_FLOAT f_Hacking_Render_Target_x 0.080
TWEAK_FLOAT f_Hacking_Render_Target_y 0.170
TWEAK_FLOAT f_Hacking_Render_Target_width 0.270
TWEAK_FLOAT f_Hacking_Render_Target_height 0.450
//WIDGET_GROUP_ID widget_debug
INT iState = 0
INT iLesterChatTimer = 0
INT rt_laptop
SCALEFORM_INDEX sflaptop
// release the rendertarget for the LAPTOP
PROC RELEASE_LAPTOP_RENDERTARGET()
IF IS_NAMED_RENDERTARGET_REGISTERED("tvscreen")
RELEASE_NAMED_RENDERTARGET("tvscreen")
ENDIF
ENDPROC
PROC RELEASE_FAKE_LAPTOP_MOVIE()
RELEASE_LAPTOP_RENDERTARGET()
SET_SCALEFORM_MOVIE_AS_NO_LONGER_NEEDED(sflaptop)
ENDPROC
PROC Cleanup_Handler()
CPRINTLN(DEBUG_HEIST, "<LESTER-HANDLER> Handler cleaning up Lester.")
SET_PED_AS_NO_LONGER_NEEDED(pedLester)
SET_MODEL_AS_NO_LONGER_NEEDED(PROP_CS_WALKING_STICK)
SET_OBJECT_AS_NO_LONGER_NEEDED(objLesterStick)
SET_MODEL_AS_NO_LONGER_NEEDED(PROP_CS_WALKING_STICK)
SET_OBJECT_AS_NO_LONGER_NEEDED(objLaptop)
SET_MODEL_AS_NO_LONGER_NEEDED(PROP_LAPTOP_LESTER2)
SET_SCRIPT_AS_NO_LONGER_NEEDED("re_lured")
REMOVE_ANIM_DICT("MISSHEIST_JEWEL@HACKING")
REMOVE_MODEL_HIDE(<<707.3041, -967.6456, 30.3760>>, 1.00, PROP_LAPTOP_LESTER2, FALSE)
REMOVE_RELATIONSHIP_GROUP(rghLester)
RELEASE_FAKE_LAPTOP_MOVIE()
CPRINTLN(DEBUG_HEIST, "<LESTER-HANDLER> Handler terminated.")
TERMINATE_THIS_THREAD()
ENDPROC
// request the fake LAPTOP movie
FUNC BOOL HAVE_LAPTOP_ASSETS_LOADED()
sflaptop = REQUEST_SCALEFORM_MOVIE("JHPB_02_Laptop")
IF HAS_SCALEFORM_MOVIE_LOADED(sflaptop)
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
// draw fake LAPTOP
PROC DRAW_FAKE_LAPTOP_SCREEN()
if HAVE_LAPTOP_ASSETS_LOADED()
IF DOES_ENTITY_EXIST(objlaptop)
SET_TEXT_RENDER_ID(rt_laptop)
DRAW_SCALEFORM_MOVIE(sflaptop, f_Hacking_Render_Target_x, f_Hacking_Render_Target_y,f_Hacking_Render_Target_width,f_Hacking_Render_Target_height, 255, 255, 255, 255)
SET_TEXT_RENDER_ID(GET_DEFAULT_SCRIPT_RENDERTARGET_RENDER_ID())
ENDIF
endif
ENDPROC
SCRIPT(StructLesterHandover sLesterHandover)
CPRINTLN(DEBUG_HEIST, "<LESTER-HANDLER> Lester handler started.")
IF HAS_FORCE_CLEANUP_OCCURRED(DEFAULT_FORCE_CLEANUP_FLAGS|FORCE_CLEANUP_FLAG_SP_TO_MP|FORCE_CLEANUP_FLAG_DEBUG_MENU|FORCE_CLEANUP_FLAG_REPEAT_PLAY)
CPRINTLN(DEBUG_HEIST, "<LESTER-HANDLER> Handler was forced to clean up.")
Cleanup_Handler()
ENDIF
IF IS_REPEAT_PLAY_ACTIVE()
CPRINTLN(DEBUG_HEIST, "<LESTER-HANDLER> Cleaning up as a repeat play is running.")
Cleanup_Handler()
ENDIF
pedLester = sLesterHandover.pedHandover
//Load handler assets.
CPRINTLN(DEBUG_HEIST, "<LESTER-HANDLER> Starting assets loading...")
REQUEST_ANIM_DICT("MISSHEIST_JEWEL@HACKING")
REQUEST_MODEL(PROP_CS_WALKING_STICK)
REQUEST_MODEL(PROP_LAPTOP_LESTER2)
WHILE NOT HAS_ANIM_DICT_LOADED("MISSHEIST_JEWEL@HACKING")
OR NOT HAS_MODEL_LOADED(PROP_CS_WALKING_STICK)
OR NOT HAS_MODEL_LOADED(PROP_LAPTOP_LESTER2)
WAIT(0)
ENDWHILE
//--------------- Setup the render target for the screen ---------------------
IF NOT IS_NAMED_RENDERTARGET_REGISTERED("tvscreen")
REGISTER_NAMED_RENDERTARGET("tvscreen")
ENDIF
IF NOT IS_NAMED_RENDERTARGET_LINKED(PROP_LAPTOP_LESTER2)
LINK_NAMED_RENDERTARGET(PROP_LAPTOP_LESTER2)
ENDIF
rt_laptop = GET_NAMED_RENDERTARGET_RENDER_ID("tvscreen")
CPRINTLN(DEBUG_HEIST, "<LESTER-HANDLER> ...Assets loaded.")
//#if IS_DEBUG_BUILD
// widget_debug = START_WIDGET_GROUP("LESTER-HANDLER")
// ADD_WIDGET_FLOAT_SLIDER("PosX", f_Hacking_Render_Target_x, -1.0, 1.0, 0.01)
// ADD_WIDGET_FLOAT_SLIDER("PosY", f_Hacking_Render_Target_y, -1.0, 1.0, 0.01)
// ADD_WIDGET_FLOAT_SLIDER("Width", f_Hacking_Render_Target_width, -1.0, 1.0, 0.01)
// ADD_WIDGET_FLOAT_SLIDER("Height", f_Hacking_Render_Target_height, -1.0, 1.0, 0.01)
// STOP_WIDGET_GROUP()
// SET_LOCATES_HEADER_WIDGET_GROUP(widget_debug)
//#endif
WHILE NOT IS_BIT_SET(iState, BIT_PLAYER_LEFT_AREA)
//Wait for global Lester ped to exist and grab ownership of it.
IF NOT IS_BIT_SET(iState, BIT_LESTER_OWNED)
IF DOES_ENTITY_EXIST(pedLester)
IF NOT IS_PED_INJURED(pedLester)
//Take ownership of Lester.
SET_ENTITY_AS_MISSION_ENTITY(pedLester, FALSE, TRUE)
CPRINTLN(DEBUG_HEIST, "<LESTER-HANDLER> Handler took ownership of global Lester ped index.")
//Configure Lester to be as non interactable as possible.
ADD_RELATIONSHIP_GROUP("Lester Group", rghLester)
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, rghLester, RELGROUPHASH_PLAYER)
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, RELGROUPHASH_PLAYER, rghLester)
SET_PED_RELATIONSHIP_GROUP_HASH(pedLester, rghLester)
SET_PED_DIES_WHEN_INJURED(pedLester, FALSE)
SET_PED_CAN_BE_TARGETTED(pedLester, FALSE)
SET_PED_SUFFERS_CRITICAL_HITS(pedLester, FALSE)
SET_PED_CAN_EVASIVE_DIVE(pedLester, FALSE)
SET_ENTITY_IS_TARGET_PRIORITY(pedLester, FALSE)
SET_PED_CAN_RAGDOLL(pedLester, FALSE)
SET_PED_ID_RANGE(pedLester, 250.00)
SET_PED_TARGET_LOSS_RESPONSE(pedLester, TLR_NEVER_LOSE_TARGET)
SET_ENTITY_IS_TARGET_PRIORITY(pedLester, FALSE)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(pedLester, TRUE)
SET_PED_CONFIG_FLAG(pedLester, PCF_KeepRelationshipGroupAfterCleanUp, TRUE)
SET_PED_CONFIG_FLAG(pedLester, PCF_WillFlyThroughWindscreen, FALSE)
SET_PED_CONFIG_FLAG(pedLester, PCF_DisableExplosionReactions, TRUE)
SET_PED_CONFIG_FLAG(pedLester, PCF_RunFromFiresAndExplosions, FALSE)
SET_PED_CONFIG_FLAG(pedLester, PCF_OnlyAttackLawIfPlayerIsWanted, TRUE)
SET_PED_CONFIG_FLAG(pedLester, PCF_CannotBeTargeted, TRUE)
SET_ENTITY_PROOFS(pedLester, TRUE, TRUE, TRUE, TRUE, TRUE)
//Set Lester to use his laptop.
VECTOR vLesterPos = << 707.320, -966.830, 30.413 >>
VECTOR vLesterRot = << 0.000, 0.000, -171.500 >>
OPEN_SEQUENCE_TASK(seqLesterUseLaptop)
TASK_PLAY_ANIM_ADVANCED(NULL, "MISSHEIST_JEWEL@HACKING", "HACK_INTRO", vLesterPos, vLesterRot, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_NOT_INTERRUPTABLE|AF_USE_KINEMATIC_PHYSICS)
TASK_PLAY_ANIM_ADVANCED(NULL, "MISSHEIST_JEWEL@HACKING", "HACK_LOOP", vLesterPos, vLesterRot, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING|AF_NOT_INTERRUPTABLE|AF_USE_KINEMATIC_PHYSICS)
CLOSE_SEQUENCE_TASK(seqLesterUseLaptop)
TASK_PERFORM_SEQUENCE(pedLester, seqLesterUseLaptop)
FORCE_PED_AI_AND_ANIMATION_UPDATE(pedLester)
FREEZE_ENTITY_POSITION(pedLester, TRUE)
ADD_PED_FOR_DIALOGUE(sPedForConversation, 3, pedLester, "LESTER")
CPRINTLN(DEBUG_HEIST, "<LESTER-HANDLER> Lester state configured.")
//Create Lester's stick.
objLesterStick = CREATE_OBJECT(PROP_CS_WALKING_STICK, <<706.987366,-967.094543,30.400000>>, FALSE, FALSE, FALSE)
SET_ENTITY_COORDS (objLesterStick, <<706.987366,-967.094543,30.400000>>)
SET_ENTITY_ROTATION (objLesterStick, <<90.00, 0.00, 160.00>>)
SET_ENTITY_INVINCIBLE(objLesterStick, TRUE)
SET_ENTITY_PROOFS(objLesterStick, TRUE, TRUE, TRUE, TRUE, TRUE)
FREEZE_ENTITY_POSITION(objLesterStick, TRUE)
SET_MODEL_AS_NO_LONGER_NEEDED(PROP_CS_WALKING_STICK)
CPRINTLN(DEBUG_HEIST, "<LESTER-HANDLER> Walking stick created.")
//Create dummy laptop and proof it.
CREATE_MODEL_HIDE(<<707.3041, -967.6456, 30.3760>>, 1.00, PROP_LAPTOP_01A, FALSE)///
objLaptop = CREATE_OBJECT(PROP_LAPTOP_LESTER2, <<707.3041, -967.6456, 30.3760>>)
SET_ENTITY_HEADING(objLaptop, 183.14)
FREEZE_ENTITY_POSITION(objLaptop, TRUE)
SET_ENTITY_INVINCIBLE(objLaptop, TRUE)
SET_ENTITY_PROOFS(objLaptop, TRUE, TRUE, TRUE, TRUE, TRUE)
SET_MODEL_AS_NO_LONGER_NEEDED(PROP_LAPTOP_LESTER2)
CPRINTLN(DEBUG_HEIST, "Lester's dummy laptop created.")
SET_BIT(iState, BIT_LESTER_OWNED)
ENDIF
ENDIF
//Lester owned. Trigger dialogue and wait for cleanup conditions.
ELIF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
IF NOT IS_ENTITY_DEAD(pedLester)
FLOAT fDistanceSquaredFromLester = VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(pedLester))
//CPRINTLN(DEBUG_HEIST, "<LESTER-HANDLER> Distance from Lester is ", fDistanceSquaredFromLester)
//Play dialogue every 20 seconds if Michael gets close to Lester.
IF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_MICHAEL
IF fDistanceSquaredFromLester < 4
IF GET_GAME_TIMER() > iLesterChatTimer
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF CREATE_CONVERSATION(sPedForConversation, "JHFAUD", "JHF_LEAVE", CONV_PRIORITY_AMBIENT_MEDIUM)
CPRINTLN(DEBUG_HEIST, "<LESTER-HANDLER> Michael triggered Lester dialogue.")
iLesterChatTimer = GET_GAME_TIMER() + 25000
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
//Check for player leaving area so we can clean up.
IF g_eLastMissionPassed = SP_HEIST_JEWELRY_1
IF NOT g_bForceNextLuredEvent = TRUE
AND IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<718.074890,-976.047180,22.914824>>, <<718.059265,-979.454956,27.119097>>, 5.750000)
//unlock lured
SET_RANDOM_EVENT_AVAILABLE(RE_LURED, TRUE)
g_iLastRandomEventLaunch = 0
g_bForceNextLuredEvent = TRUE
//Reactivate the worldpoint
//this needs to be set to use REACTIVATE_NAMED_WORLD_BRAINS_WAITING_TILL_OUT_OF_RANGE() in v341
REACTIVATE_ALL_WORLD_BRAINS_THAT_ARE_WAITING_TILL_OUT_OF_RANGE()
ENDIF
ENDIF
DRAW_FAKE_LAPTOP_SCREEN()
IF fDistanceSquaredFromLester > 2500
CPRINTLN(DEBUG_HEIST, "<LESTER-HANDLER> The player has left the area.")
SET_BIT(iState, BIT_PLAYER_LEFT_AREA)
ENDIF
ENDIF
ENDIF
WAIT(0)
ENDWHILE
Cleanup_Handler()
ENDSCRIPT