private void SituationLeavePeacefully() { GameFiber.StartNew(delegate { try { Game.DisplaySubtitle("~r~Customer~w~: Okay, okay, okay! I am leaving now dude, don't have to be rude!", 7000); karen.Tasks.PlayAnimation("cellphone@", "cellphone_photo_exit", 2f, AnimationFlags.UpperBodyOnly); GameFiber.Wait(2000); karen.Tasks.Clear(); phone.Delete(); karen.Dismiss(); //We will see if just dismissing them is enough to have them leave. GameFiber.Wait(7500); this.calloutStage = Stages.End; } catch (System.Threading.ThreadAbortException e) { Game.LogTrivial(e.ToString()); Game.LogTrivial("Social Justice Callouts handled the exception successfully."); Game.DisplayNotification("~O~Karen~s~ callout crashed, sorry. Please send me your log file <3"); Game.DisplayNotification("Full LSPDFR crash prevented ~g~successfully."); End(); } catch (Exception e) { Game.LogTrivial(e.ToString()); Game.LogTrivial("Social Justice Callouts handled the exception successfully."); Game.DisplayNotification("~O~Karen~s~ callout crashed, sorry. Please send me your log file <3"); Game.DisplayNotification("Full LSPDFR crash prevented ~g~successfully."); End(); } }); }
public static void ToggleMobilePhone(Ped ped, bool toggle) { if (toggle) { if (MobilePhone.Exists()) { MobilePhone.Delete(); } NativeFunction.Natives.SET_PED_CAN_SWITCH_WEAPON(ped, false); ped.Inventory.GiveNewWeapon(new WeaponAsset("WEAPON_UNARMED"), -1, true); MobilePhone = new Rage.Object(new Model("prop_police_phone"), new Vector3(0, 0, 0)); int boneIndex = NativeFunction.Natives.GET_PED_BONE_INDEX <int>(ped, (int)PedBoneId.RightPhHand); NativeFunction.Natives.ATTACH_ENTITY_TO_ENTITY(MobilePhone, ped, boneIndex, 0f, 0f, 0f, 0f, 0f, 0f, true, true, false, false, 2, 1); ped.Tasks.PlayAnimation("cellphone@", "cellphone_call_listen_base", 1.45f, AnimationFlags.Loop | AnimationFlags.UpperBodyOnly | AnimationFlags.SecondaryTask); } else { NativeFunction.Natives.SET_PED_CAN_SWITCH_WEAPON(ped, true); ped.Tasks.Clear(); if (GameFiber.CanSleepNow) { GameFiber.Wait(800); } if (MobilePhone.Exists()) { MobilePhone.Delete(); } } }
public bool AbortCallout() { Game.LogTrivial("[FireyCallouts][Log] Abort 'Dumpster Fire' callout. Locations too far away (> 800)."); // Clean up if not accepted if (locationBlip.Exists()) { locationBlip.Delete(); } if (fireWood.Exists()) { fireWood.Delete(); } foreach (uint f in fireList) { NativeFunction.Natives.RemoveScriptFire(f); } foreach (Ped p in suspects) { if (p.Exists()) { p.Delete(); } } Game.LogTrivial("[FireyCallouts][Log] Cleaned up 'Campfire' callout."); return(false); }
public void CleanUp() { if (Pilot.Exists()) { Pilot.Dismiss(); } if (Paramedic1.Exists()) { Paramedic1.Delete(); } if (Paramedic2.Exists()) { Paramedic2.Delete(); } if (Helicopter.Exists()) { Helicopter.Dismiss(); } if (_heliBlip.Exists()) { _heliBlip.Delete(); } if (_notepad.Exists()) { _notepad.Delete(); } }
public void OnCleanUp(bool isTerminating) { if (saw) { saw.Delete(); } controller.Ped.Tasks.ClearSecondary(); }
/// <summary> /// If you don't accept the callout this will be called, we clear anything we spawned here to prevent it staying in the game /// </summary> public override void OnCalloutNotAccepted() { base.OnCalloutNotAccepted(); if (ped.Exists()) { ped.Delete(); } if (blip.Exists()) { blip.Delete(); } if (pedObj.Exists()) { pedObj.Delete(); } }
/// <summary> /// If you don't accept the callout this will be called, we clear anything we spawned here to prevent it staying in the game /// </summary> public override void OnCalloutNotAccepted() { base.OnCalloutNotAccepted(); if (dead.Exists()) { dead.Delete(); } if (crash.Exists()) { crash.Delete(); } if (heliBlip.Exists()) { heliBlip.Delete(); } }
public static void GiveParkingTicket(GiveParkingTicketEvent parkingTicketEvent) { Vehicle vehicle = parkingTicketEvent.Vehicle; string modelName = vehicle.Model.Name.ToLower(); string licencePlate = vehicle.LicensePlate; string lexemArticle = ParkingTicketsEventHandler.Vowels.Contains <string>(modelName[0].ToString()) ? "an" : "a"; string licencePlateAudioMessage = ""; if (ParkingTicketsEventHandler.Numbers.Contains <string>(modelName.Last().ToString())) { modelName = modelName.Substring(0, modelName.Length - 1); } modelName = char.ToUpper(modelName[0]) + modelName.Substring(1); foreach (char character in licencePlate) { if (!Char.IsWhiteSpace(character)) { licencePlateAudioMessage = licencePlateAudioMessage + " " + character; } } ParkingTicketsEventHandler.Infos.Enabled = true; ParkingTicketsEventHandler.Infos.Text = "Vehicle " + modelName + " (" + licencePlate + ")"; ParkingTicketsEventHandler.Infos.Enabled = false; Game.DisplayNotification("~g~Traffic Officer ~s~is reporting an ~r~illegally parked vehicle."); Game.DisplayNotification("~b~Processing a parking ticket (" + parkingTicketEvent.Amount + ") for " + lexemArticle + " ~r~" + modelName + "~b~ with licence plate: ~r~" + licencePlate + "."); Game.DisplayNotification("~b~The offending ~r~" + modelName + " ~b~is parked on ~o~" + World.GetStreetName(vehicle.Position) + "."); PedsManager.LocalPlayer().Inventory.GiveNewWeapon(new WeaponAsset("WEAPON_UNARMED"), 0, true); Rage.Object notepad = new Rage.Object("prop_notepad_02", PedsManager.LocalPlayer().Position); int boneIndex = NativeFunction.Natives.GET_PED_BONE_INDEX <int>(PedsManager.LocalPlayer(), (int)PedBoneId.LeftThumb2); NativeFunction.Natives.ATTACH_ENTITY_TO_ENTITY(notepad, PedsManager.LocalPlayer(), boneIndex, 0f, 0f, 0f, 0f, 0f, 0f, true, false, false, false, 2, 1); PedsManager.LocalPlayer().Tasks.PlayAnimation("veh@busted_std", "issue_ticket_cop", 1f, AnimationFlags.Loop | AnimationFlags.UpperBodyOnly).WaitForCompletion(8000); notepad.Delete(); vehicle.IsPersistent = false; PedsManager.LocalPlayer().Tasks.PlayAnimation("random@arrests", "generic_radio_enter", 0.7f, AnimationFlags.UpperBodyOnly | AnimationFlags.StayInEndFrame).WaitForCompletion(1500); GameFiber.Sleep(2000); FunctionsLSPDFR.PlayScannerAudioUsingPosition("INTRO_01 OFFICERS_REPORT_02 ILLEGALLY_PARKED_VEHICLE IN_OR_ON_POSITION INTRO_02 OUTRO_03 TARGET_VEHICLE_LICENCE_PLATE UHH" + licencePlateAudioMessage + " NOISE_SHORT CODE4_ADAM OFFICER_INTRO_02 PROCEED_WITH_PATROL NOISE_SHORT OUTRO_02", PedsManager.LocalPlayer().Position); PedsManager.LocalPlayer().Tasks.PlayAnimation("random@arrests", "generic_radio_exit", 1.0f, AnimationFlags.UpperBodyOnly); ParkingTicketsEventHandler.AlreadyGivedTicketsLicencePlateCollection.Add(vehicle.LicensePlate); }
public static void EnableBinoculars() { GameFiber.StartNew(delegate { _isActive = true; Rage.Object binocular = new Rage.Object("prop_binoc_01", Game.LocalPlayer.Character.Position); binocular.AttachToEntity(Game.LocalPlayer.Character, Game.LocalPlayer.Character.GetBoneIndex(PedBoneId.RightPhHand), Vector3.Zero, Rotator.Zero); Game.LocalPlayer.Character.Tasks.PlayAnimation("amb@world_human_binoculars@male@base", "base", 8f, AnimationFlags.UpperBodyOnly | AnimationFlags.SecondaryTask | AnimationFlags.Loop); GameFiber.Sleep(1000); Camera binocCam = new Camera(true); binocCam.AttachToEntity(binocular, new Vector3(0.0f, -0.1f, 0.0f), true); binocCam.Rotation = Game.LocalPlayer.Character.Rotation; _isTextureRenderRunning = true; Game.RawFrameRender += RawFrameRender; while (true) { //float moveSpeed = (binocCam.FOV / 100)/* * 3.0f*/; WildernessCallouts.Common.DisEnableGameControls(false, GameControl.LookUpDown, GameControl.LookLeftRight, GameControl.WeaponWheelPrev, GameControl.WeaponWheelNext, GameControl.SelectWeapon, GameControl.SelectNextWeapon, GameControl.SelectPrevWeapon, GameControl.Sprint); //float leftRight = NativeFunction.CallByName<float>("GET_DISABLED_CONTROL_NORMAL", 0, (int)GameControl.LookLeftRight); //float upDown = NativeFunction.CallByName<float>("GET_DISABLED_CONTROL_NORMAL", 0, (int)GameControl.LookUpDown); if (Controls.ToggleBinoculars.IsJustPressed() || Game.LocalPlayer.Character.IsDead || Game.LocalPlayer.Character.IsInAnyVehicle(false)) { break; } //if (/*wheelBackwards != 0*/Game.IsKeyDownRightNow(Settings.ZoomOutBinocKey) && binocCam.FOV < 75.0f) binocCam.FOV += 0.51225f; //if (/*wheelForwards != 0*/Game.IsKeyDownRightNow(Settings.ZoomInBinocKey) && binocCam.FOV > 1.0f) binocCam.FOV -= 0.51225f; //if (/*leftRight < -0.05f*/Game.IsKeyDownRightNow(Settings.LookLeftBinocKey)) binocCam.SetRotationYaw(binocCam.Rotation.Yaw + moveSpeed); //if (/*leftRight > 0.05f*/Game.IsKeyDownRightNow(Settings.LookRightBinocKey)) binocCam.SetRotationYaw(binocCam.Rotation.Yaw - moveSpeed); //if (/*upDown < -0.05f*/Game.IsKeyDownRightNow(Settings.LookUpBinocKey) && binocCam.Rotation.Pitch <= 85.0f) binocCam.SetRotationPitch(binocCam.Rotation.Pitch + moveSpeed); //if (/*upDown > 0.05f*/Game.IsKeyDownRightNow(Settings.LookDownBinocKey) && binocCam.Rotation.Pitch >= -85.0f) binocCam.SetRotationPitch(binocCam.Rotation.Pitch - moveSpeed); float moveSpeed = (binocCam.FOV / 100) * (WildernessCallouts.Common.IsUsingController() ? 3.5f : 5.25f); float upDown = NativeFunction.Natives.GET_DISABLED_CONTROL_NORMAL <float>(0, (int)GameControl.LookUpDown) * moveSpeed; float leftRight = NativeFunction.Natives.GET_DISABLED_CONTROL_NORMAL <float>(0, (int)GameControl.LookLeftRight) * moveSpeed; binocCam.Rotation = new Rotator(binocCam.Rotation.Pitch - upDown, binocCam.Rotation.Roll, binocCam.Rotation.Yaw - leftRight); if (binocCam.Rotation.Pitch >= 85.0f) { binocCam.SetRotationPitch(84.98f); } else if (binocCam.Rotation.Pitch <= -85.0f) { binocCam.SetRotationPitch(-84.98f); } float wheelForwards = NativeFunction.Natives.GET_DISABLED_CONTROL_NORMAL <float>(0, (int)GameControl.WeaponWheelPrev) * 1.81125f; float wheelBackwards = NativeFunction.Natives.GET_DISABLED_CONTROL_NORMAL <float>(0, (int)GameControl.WeaponWheelNext) * 1.81125f; if (WildernessCallouts.Common.IsUsingController()) { binocCam.FOV -= wheelBackwards - wheelForwards; } else { binocCam.FOV -= wheelForwards - wheelBackwards; } if (binocCam.FOV > 75.0f) { binocCam.FOV = 75.0f; } else if (binocCam.FOV < 1.0f) { binocCam.FOV = 1.0f; } if (Controls.ToggleBinocularsHeliCamNightVision.IsJustPressed() && !WildernessCallouts.Common.IsNightVisionActive() && !WildernessCallouts.Common.IsThermalVisionActive()) { NativeFunction.Natives.PLAY_SOUND_FRONTEND(-1, "THERMAL_VISION_GOGGLES_ON_MASTER", 0, 1); WildernessCallouts.Common.SetNightVision(true); GameFiber.Sleep(25); } else if (Controls.ToggleBinocularsHeliCamNightVision.IsJustPressed() && WildernessCallouts.Common.IsNightVisionActive()) { NativeFunction.Natives.PLAY_SOUND_FRONTEND(-1, "THERMAL_VISION_GOGGLES_OFF_MASTER", 0, 1); WildernessCallouts.Common.SetNightVision(false); GameFiber.Sleep(25); } if (Controls.ToggleBinocularsHeliCamThermalVision.IsJustPressed() && !WildernessCallouts.Common.IsThermalVisionActive() && !WildernessCallouts.Common.IsNightVisionActive()) { NativeFunction.Natives.PLAY_SOUND_FRONTEND(-1, "THERMAL_VISION_GOGGLES_ON_MASTER", 0, 1); WildernessCallouts.Common.SetThermalVision(true); GameFiber.Sleep(25); } else if (Controls.ToggleBinocularsHeliCamThermalVision.IsJustPressed() && WildernessCallouts.Common.IsThermalVisionActive()) { NativeFunction.Natives.PLAY_SOUND_FRONTEND(-1, "THERMAL_VISION_GOGGLES_OFF_MASTER", 0, 1); WildernessCallouts.Common.SetThermalVision(false); GameFiber.Sleep(25); } if (!Game.LocalPlayer.Character.IsPlayingAnimation("amb@world_human_binoculars@male@base", "base")) { Game.LocalPlayer.Character.Tasks.PlayAnimation("amb@world_human_binoculars@male@base", "base", 8f, AnimationFlags.UpperBodyOnly | AnimationFlags.SecondaryTask | AnimationFlags.Loop); } Game.LocalPlayer.Character.Heading = binocCam.Rotation.Yaw; //if (Settings.General.IsDebugBuild) Game.DisplaySubtitle("FOV: " + binocCam.FOV.ToString() + " PITCH: " + binocCam.Rotation.Pitch + " YAW: " + binocCam.Rotation.Yaw + " MOVE SPEED: " + moveSpeed.ToString(), 1000); GameFiber.Yield(); } if (WildernessCallouts.Common.IsNightVisionActive()) { NativeFunction.Natives.PLAY_SOUND_FRONTEND(-1, "THERMAL_VISION_GOGGLES_OFF_MASTER", 0, 1); WildernessCallouts.Common.SetNightVision(false); } if (WildernessCallouts.Common.IsThermalVisionActive()) { NativeFunction.Natives.PLAY_SOUND_FRONTEND(1, "THERMAL_VISION_GOGGLES_OFF_MASTER", 0, 1); WildernessCallouts.Common.SetThermalVision(false); } binocCam.Delete(); _isTextureRenderRunning = false; Game.RawFrameRender -= RawFrameRender; Game.LocalPlayer.Character.Tasks.Clear(); GameFiber.Sleep(250); binocular.Delete(); WildernessCallouts.Common.DisEnableGameControls(true, GameControl.LookUpDown, GameControl.LookLeftRight, GameControl.WeaponWheelPrev, GameControl.WeaponWheelNext, GameControl.SelectWeapon, GameControl.SelectNextWeapon, GameControl.SelectPrevWeapon, GameControl.Sprint); _isActive = false; }); }
private void CheckForDeliverTicketTrigger() { if (!Globals.HasTrafficTicketsInHand() && (ShouldEndPullover.HasValue && ShouldEndPullover.Value) && !Game.LocalPlayer.Character.HasScenario()) { ShouldEndPullover = null; GameFiber.StartNew(() => { if (Game.LocalPlayer.LastVehicle && !Game.LocalPlayer.LastVehicle.HasDriver) { Game.DisplayNotification("The driver will wait until you are back in your vehicle before taking off"); } while (Game.LocalPlayer.LastVehicle && !Game.LocalPlayer.LastVehicle.HasDriver) { GameFiber.Yield(); //Wait for the player to enter their vehicle } Function.Log("Starting Ending pull over wait timer for ped to leave"); var stopAt = DateTime.Now.AddMilliseconds(5000); //have the sadPed drive off in 5 seconds if the traffic stop isnt over while (DateTime.Now < stopAt) { GameFiber.Yield(); } try { lock (mPromptedCitations) mPromptedCitations.Clear(); var handle = Functions.GetCurrentPullover(); if (handle != null) { Functions.ForceEndCurrentPullover(); } } catch (Exception e) { Function.LogCatch(e.Message); } }); } else if (Globals.HasTrafficTicketsInHand() && !Game.LocalPlayer.Character.HasScenario()) //only run when we have tickets and we're not already doing WORLD_HUMAN_CLIPBOARD { var stopped = World.GetEntities(Game.LocalPlayer.Character.Position, 2.5f, GetEntitiesFlags.ConsiderAllPeds); if (stopped != null && stopped.Count() > 0) { var pedsAboutToGetTheSmackDown = stopped.Select(x => x as Ped) .Where(x => x.DistanceTo(Game.LocalPlayer.Character.FrontPosition) < 2f && Globals.GetTrafficCitationsInHandForPed(x) != null); //may have to add ordering by distance foreach (var sadPed in pedsAboutToGetTheSmackDown) { if (Configs.GiveTicketsToPed.Any(x => x.IsPressed)) { //The user wants to give the sad ped the ticket now.. GameFiber.StartNew(() => { var item = new Rage.Object(new Model("prop_cs_documents_01"), Game.LocalPlayer.Character.Position); item.AttachTo(Game.LocalPlayer.Character, Game.LocalPlayer.Character.GetBoneIndex(PedBoneId.RightThumb1), new Vector3(item.Model.Dimensions.Length() * 0.4f, 0, 0), Rotator.Zero); Game.LocalPlayer.Character.Tasks.PlayAnimation("mp_common", "givetake1_b", 3f, AnimationFlags.None).WaitForCompletion(); item.Detach(); item.Delete(); }); ShouldEndPullover = true; Globals.RemoveTrafficCitationsInHandForPed(sadPed); break; } else { //Prompt the user that they can deliver the ticket OnFacingPedWithPendingTickets(null, sadPed, Globals.GetTrafficCitationsInHandForPed(sadPed)); } } } } else if (Functions.GetCurrentPullover() == null && Globals.HasTrafficTicketsInHand()) { Globals.ClearTrafficCitationsInHand(); return; } }
private void DealWithBody(Ped body) { bodiesBeingHandled.Add(body); passenger.Tasks.GoToOffsetFromEntity(body, 10000, -2.0f, -1.0f, 8.0f); driver.Tasks.GoToOffsetFromEntity(body, 10000, 2.4f, 1.0f, 8.0f).WaitForCompletion(); if (Vector3.Distance(driver.Position, Game.LocalPlayer.Character.Position) < 60f) { Rage.Object camera = new Rage.Object("prop_ing_camera_01", driver.GetOffsetPosition(Vector3.RelativeTop * 30)); driver.Tasks.PlayAnimation("anim@mp_player_intupperphotography", "idle_a_fp", 8.0F, AnimationFlags.None); camera.Heading = driver.Heading - 180; camera.Position = driver.GetOffsetPosition(Vector3.RelativeTop * 0.68f + Vector3.RelativeFront * 0.33f); camera.IsPositionFrozen = true; Vector3 dirVect = body.Position - driver.Position; dirVect.Normalize(); GameFiber.Wait(900); NativeFunction.Natives.DRAW_SPOT_LIGHT(driver.GetOffsetPosition(Vector3.RelativeFront * 0.5f).X, driver.GetOffsetPosition(Vector3.RelativeFront * 0.5f).Y, driver.GetOffsetPosition(Vector3.RelativeFront * 0.5f).Z, dirVect.X, dirVect.Y, dirVect.Z, 100, 100, 100, 90.0f, 50.0f, 90.0f, 80.0f, 90.0f); cameraSound.Play(); GameFiber.Wait(1500); NativeFunction.Natives.DRAW_SPOT_LIGHT(driver.GetOffsetPosition(Vector3.RelativeFront * 0.5f).X, driver.GetOffsetPosition(Vector3.RelativeFront * 0.5f).Y, driver.GetOffsetPosition(Vector3.RelativeFront * 0.5f).Z, dirVect.X, dirVect.Y, dirVect.Z, 100, 100, 100, 90.0f, 50.0f, 90.0f, 80.0f, 90.0f); cameraSound.Play(); GameFiber.Wait(1500); NativeFunction.Natives.DRAW_SPOT_LIGHT(driver.GetOffsetPosition(Vector3.RelativeFront * 0.5f).X, driver.GetOffsetPosition(Vector3.RelativeFront * 0.5f).Y, driver.GetOffsetPosition(Vector3.RelativeFront * 0.5f).Z, dirVect.X, dirVect.Y, dirVect.Z, 100, 100, 100, 90.0f, 50.0f, 90.0f, 80.0f, 90.0f); cameraSound.Play(); GameFiber.Wait(1000); camera.Delete(); Game.DisplaySubtitle("~b~Driver~w~: I've got enough pictures, I'll time stamp them.", 4000); passenger.Tasks.PlayAnimation("amb@medic@standing@tendtodead@enter", "enter", 8.0F, AnimationFlags.None); GameFiber.Wait(1000); passenger.Tasks.PlayAnimation("amb@medic@standing@tendtodead@base", "base", 8.0F, AnimationFlags.None); GameFiber.Wait(1000); passenger.Tasks.PlayAnimation("amb@medic@standing@tendtodead@exit", "exit", 8.0F, AnimationFlags.None).WaitForCompletion(); GameFiber.Wait(1000); } Game.DisplaySubtitle("~b~Passenger~w~: " + GetCauseOfDeathPrelude() + GetCauseOfDeathString(body) + "~b~.", 6000); if (body.Exists()) { if (deadBodies.Contains(body)) { deadBodies.Remove(body); } if (bodiesBeingHandled.Contains(body)) { bodiesBeingHandled.Remove(body); } if (!body.IsInAnyVehicle(true)) { bodyBags.Add(new Rage.Object("xm_prop_body_bag", body.Position) { IsPositionFrozen = false, }); } if (body.Exists()) { body.Delete(); } } GameFiber.Wait(2500); }
public ParkingTicket(bool create = true) { if (!create) { return; } Vehicle[] nearbyCars = playerPed.GetNearbyVehicles(1); if (nearbyCars.Length == 0) { return; } if (Functions.IsPlayerPerformingPullover()) { Game.DisplayHelp("Finish your ~b~traffic stop ~s~before reporting a vehicle for a parking offence."); return; } car = nearbyCars[0]; car.IsPersistent = true; if (Vector3.Distance(playerPed.Position, car.Position) > 3.7f) { return; } if (TrafficPolicerHandler.vehiclesTicketedForParking.Contains(car)) { Game.DisplayNotification("You have already given that vehicle a ~b~parking ticket."); Functions.PlayScannerAudio("BEEP"); return; } if (car.IsPoliceVehicle) { Game.DisplayHelp("~b~Police vehicles ~s~are exempt from parking laws.", 5000); Functions.PlayScannerAudio("BEEP"); return; } if (Vector3.Distance(playerPed.Position, car.Position) > 2.3f) { Game.DisplayHelp("You need to be ~b~closer~s~ to the vehicle.", 4000); return; } Vector3 directionFromPedToCar = (car.Position - playerPed.Position); directionFromPedToCar.Normalize(); playerPed.Tasks.AchieveHeading(MathHelper.ConvertDirectionToHeading(directionFromPedToCar)).WaitForCompletion(1800); string modelName = car.Model.Name.ToLower(); if (vowels.Contains <string>(modelName[0].ToString())) { article = "an"; } else { article = "a"; } if (numbers.Contains <string>(modelName.Last().ToString())) { modelName = modelName.Substring(0, modelName.Length - 1); } modelName = char.ToUpper(modelName[0]) + modelName.Substring(1); string licencePlate = car.LicensePlate; foreach (char character in licencePlate) { if (!Char.IsWhiteSpace(character)) { licencePlateAudioMessage = licencePlateAudioMessage + " " + character; licencePlateNotificationMessage = licencePlateNotificationMessage + character; } } Game.DisplayNotification("~g~Traffic Officer ~b~" + TrafficPolicerHandler.DivisionUnitBeat + " ~s~is reporting an ~r~illegally parked vehicle."); Game.DisplayNotification("~b~Processing a parking ticket for " + article + " ~r~" + modelName + "~b~ with licence plate: ~r~" + licencePlateNotificationMessage + "."); Game.DisplayNotification("~b~The offending ~r~" + modelName + " ~b~is parked on ~o~" + World.GetStreetName(car.Position) + "."); if (TrafficPolicerHandler.IsLSPDFRPlusRunning) { API.LSPDFRPlusFunctions.AddCountToStatistic(Main.PluginName, "Parking tickets issued"); } playerPed.Inventory.GiveNewWeapon(new WeaponAsset("WEAPON_UNARMED"), 0, true); Rage.Object notepad = new Rage.Object("prop_notepad_02", playerPed.Position); int boneIndex = NativeFunction.Natives.GET_PED_BONE_INDEX <int>(playerPed, (int)PedBoneId.LeftThumb2); NativeFunction.Natives.ATTACH_ENTITY_TO_ENTITY(notepad, playerPed, boneIndex, 0f, 0f, 0f, 0f, 0f, 0f, true, false, false, false, 2, 1); playerPed.Tasks.PlayAnimation("veh@busted_std", "issue_ticket_cop", 1f, AnimationFlags.Loop | AnimationFlags.UpperBodyOnly).WaitForCompletion(8000); notepad.Delete(); Game.DisplayNotification("~g~Traffic Officer ~b~" + TrafficPolicerHandler.DivisionUnitBeat + " ~s~is reporting an ~r~illegally parked vehicle."); Game.DisplayNotification("~b~Processing a parking ticket for " + article + " ~r~" + modelName + "~b~ with licence plate: ~r~" + licencePlateNotificationMessage + "."); Game.DisplayNotification("~b~The offending ~r~" + modelName + " ~b~is parked on ~o~" + World.GetStreetName(car.Position) + "."); playerPed.Tasks.PlayAnimation("random@arrests", "generic_radio_enter", 0.7f, AnimationFlags.UpperBodyOnly | AnimationFlags.StayInEndFrame).WaitForCompletion(1500); Functions.PlayScannerAudioUsingPosition("WE_HAVE_01 ILLEGALLY_PARKED_VEHICLE IN_OR_ON_POSITION INTRO_02 TARGET_VEHICLE_LICENCE_PLATE UHH" + licencePlateAudioMessage + " OUTRO_03 NOISE_SHORT INTRO_01 CODE4_ADAM PROCEED_WITH_PATROL NOISE_SHORT", playerPed.Position); TrafficPolicerHandler.vehiclesTicketedForParking.Add(car); car.IsPersistent = false; GameFiber.Sleep(5900); Game.DisplayNotification("~g~Traffic Officer ~b~" + TrafficPolicerHandler.DivisionUnitBeat + " ~s~is reporting an ~r~illegally parked vehicle."); Game.DisplayNotification("~b~Processing a parking ticket for " + article + " ~r~" + modelName + "~b~ with licence plate: ~r~" + licencePlateNotificationMessage + "."); Game.DisplayNotification("~b~The offending ~r~" + modelName + " ~b~is parked on ~o~" + World.GetStreetName(car.Position) + "."); playerPed.Tasks.PlayAnimation("random@arrests", "generic_radio_exit", 1.0f, AnimationFlags.UpperBodyOnly); }
private void AdvanceStage() { TimerBars = new TimerBars(); CurrentStage++; CurrentObjectives.Clear(); foreach (var veh in CurrentMission.Vehicles.Where(v => v.SpawnAfter == CurrentStage)) { var newv = new Vehicle(Util.RequestModel(veh.ModelHash), veh.Position) { PrimaryColor = Color.FromArgb((int)veh.PrimaryColor.X, (int)veh.PrimaryColor.Y, (int)veh.PrimaryColor.Z), SecondaryColor = Color.FromArgb((int)veh.SecondaryColor.X, (int)veh.SecondaryColor.Y, (int)veh.SecondaryColor.Z), }; newv.Health = veh.Health; newv.Rotation = veh.Rotation; GameFiber.StartNew(delegate { while (IsMissionPlaying && (veh.RemoveAfter == 0 || veh.RemoveAfter > CurrentStage)) { if (veh.FailMissionOnDeath && newv.IsDead) { FailMission(reason: "The vehicle has been destroyed."); } GameFiber.Yield(); } if (newv.IsValid()) { newv.Delete(); } }); } foreach (var veh in CurrentMission.Objectives.OfType <SerializableVehicleObjective>().Where(v => v.SpawnAfter == CurrentStage)) { var newv = new Vehicle(Util.RequestModel(veh.ModelHash), veh.Position) { PrimaryColor = Color.FromArgb((int)veh.PrimaryColor.X, (int)veh.PrimaryColor.Y, (int)veh.PrimaryColor.Z), SecondaryColor = Color.FromArgb((int)veh.SecondaryColor.X, (int)veh.SecondaryColor.Y, (int)veh.SecondaryColor.Z), }; newv.Health = veh.Health; newv.Rotation = veh.Rotation; var hasActivated = false; if (veh.ActivateAfter == CurrentStage) { CurrentObjectives.Add(veh); hasActivated = true; } GameFiber.StartNew(delegate { if (!hasActivated) { while (CurrentStage != veh.ActivateAfter && IsMissionPlaying) { GameFiber.Yield(); } CurrentObjectives.Add(veh); } var blip = newv.AttachBlip(); if (veh.ObjectiveType == 0) { blip.Color = Color.DarkRed; while (!newv.IsDead && IsMissionPlaying) { if (veh.ShowHealthBar) { TimerBars.UpdateValue(newv.Handle.Value.ToString(), veh.Name, true, (100f * newv.Health / veh.Health).ToString("###") + "%"); } GameFiber.Yield(); } TimerBars.UpdateValue(newv.Handle.Value.ToString(), veh.Name, true, "0%"); } if (veh.ObjectiveType == 1) { blip.Color = Color.CornflowerBlue; while (!Game.LocalPlayer.Character.IsInVehicle(newv, false) && IsMissionPlaying) { GameFiber.Yield(); } } CurrentObjectives.Remove(veh); if (blip.IsValid()) { blip.Delete(); } while (IsMissionPlaying) { GameFiber.Yield(); } if (newv.IsValid()) { newv.Delete(); } }); } if (CurrentMission.Spawnpoints.Any(s => s.SpawnAfter == CurrentStage)) { var sp = CurrentMission.Spawnpoints.First(s => s.SpawnAfter == CurrentStage); Game.FadeScreenOut(100, true); Game.LocalPlayer.Character.Position = sp.Position - new Vector3(0, 0, 1); Game.LocalPlayer.Character.Rotation = sp.Rotation; Game.LocalPlayer.Model = Util.RequestModel(sp.ModelHash); if (sp.WeaponHash != 0) { Game.LocalPlayer.Character.GiveNewWeapon(sp.WeaponHash, sp.WeaponAmmo, true); } Game.LocalPlayer.Character.Health = sp.Health; Game.LocalPlayer.Character.Armor = sp.Armor; if (sp.SpawnInVehicle) { var vehList = Game.LocalPlayer.Character.GetNearbyVehicles(15).OrderBy(v => (Game.LocalPlayer.Character.Position - v.Position).Length()); Game.LocalPlayer.Character.WarpIntoVehicle(vehList.ToList()[0], sp.VehicleSeat); } Game.FadeScreenIn(500, false); } foreach (var actor in CurrentMission.Actors.Where(v => v.SpawnAfter == CurrentStage)) { GameFiber.StartNew(delegate { var ped = new Ped(Util.RequestModel(actor.ModelHash), actor.Position - new Vector3(0, 0, 1f), actor.Rotation.Yaw); ped.Rotation = actor.Rotation; ped.Accuracy = actor.Accuracy; var blip = ped.AttachBlip(); blip.Scale = 0.6f; if (actor.WeaponHash != 0) { ped.GiveNewWeapon(actor.WeaponHash, actor.WeaponAmmo, true); } ped.Health = actor.Health; ped.Armor = actor.Armor; if (actor.RelationshipGroup == 0) { ped.RelationshipGroup = StaticData.RelationshipGroups.Groups[1]; blip.Color = Color.DodgerBlue; NativeFunction.CallByName <uint>("REMOVE_PED_FROM_GROUP", ped.Handle.Value); NativeFunction.CallByName <uint>("SET_PED_AS_GROUP_MEMBER", ped.Handle.Value, NativeFunction.CallByName <int>("GET_PED_GROUP_INDEX", Game.LocalPlayer.Character.Handle.Value)); } else { ped.RelationshipGroup = StaticData.RelationshipGroups.Groups[actor.RelationshipGroup]; if (actor.RelationshipGroup == 4 || actor.RelationshipGroup == 5) { blip.Color = Color.DarkRed; } } if (actor.SpawnInVehicle) { var vehList = ped.GetNearbyVehicles(15).OrderBy(v => (ped.Position - v.Position).Length()); ped.WarpIntoVehicle(vehList.ToList()[0], actor.VehicleSeat); } ped.BlockPermanentEvents = false; NativeFunction.CallByName <uint>("SET_PED_FIRING_PATTERN", ped.Handle.Value, 0xC6EE6B4C); if (actor.Behaviour == 3) { ped.Tasks.FightAgainstClosestHatedTarget(100f); } else if (actor.Behaviour == 2) { NativeFunction.CallByName <uint>("TASK_GUARD_CURRENT_POSITION", ped.Handle.Value, 15f, 10f, true); } else if (actor.Behaviour == 0) { ped.Tasks.Clear(); } else if (actor.Behaviour == 4) { GameFiber.StartNew(delegate { var wpyList = new List <SerializableWaypoint>(actor.Waypoints); SerializableWaypoint currentWaypoint; if (wpyList.Count > 0) { currentWaypoint = wpyList[0]; } while (ped.IsValid() && ped.Exists() && ped.IsAlive && IsMissionPlaying && wpyList.Count > 0) { if (wpyList.Count == 0) { break; } currentWaypoint = wpyList[0]; Task pedTask = null; switch (currentWaypoint.Type) { case WaypointTypes.Drive: if (ped.IsInAnyVehicle(true)) { pedTask = ped.Tasks.DriveToPosition(currentWaypoint.Position, currentWaypoint.VehicleSpeed, (DriveToPositionFlags)currentWaypoint.DrivingStyle); } break; case WaypointTypes.Run: { var heading = 0f; if (wpyList.Count >= 2) { heading = Util.DirectionToRotation(wpyList[1].Position - currentWaypoint.Position) .Z; } pedTask = ped.Tasks.FollowNavigationMeshToPosition(currentWaypoint.Position, heading, 2f, 0.3f, currentWaypoint.Duration == 0 ? -1 : (int)currentWaypoint.Duration); } break; case WaypointTypes.Walk: { var heading = 0f; if (wpyList.Count >= 2) { heading = Util.DirectionToRotation(wpyList[1].Position - currentWaypoint.Position) .Z; } pedTask = ped.Tasks.FollowNavigationMeshToPosition(currentWaypoint.Position, heading, 1f, 0.3f, currentWaypoint.Duration == 0 ? -1 : (int)currentWaypoint.Duration); } break; case WaypointTypes.ExitVehicle: if (ped.IsInAnyVehicle(true)) { pedTask = ped.Tasks.LeaveVehicle(LeaveVehicleFlags.None); } break; case WaypointTypes.EnterVehicle: Vehicle[] vehs = World.GetAllVehicles().Where(v => { if (v != null && v.IsValid()) { return(v.Model.Hash == currentWaypoint.VehicleTargetModel); } return(false); }).OrderBy(v => (v.Position - ped.Position).Length()).ToArray(); if (vehs.Any()) { if ((vehs[0].Position - ped.Position).Length() > 10f) { pedTask = ped.Tasks.FollowNavigationMeshToPosition(vehs[0].Position, 0f, 3f, 5f); pedTask.WaitForCompletion(10000); } var seat = vehs[0].GetFreeSeatIndex(); if (seat.HasValue) { pedTask = ped.Tasks.EnterVehicle(vehs[0], seat.Value); } } break; case WaypointTypes.Wait: pedTask = ped.Tasks.StandStill(currentWaypoint.Duration); break; case WaypointTypes.Wander: pedTask = ped.Tasks.Wander(); break; case WaypointTypes.Shoot: pedTask = null; NativeFunction.CallByName <uint>("TASK_SHOOT_AT_COORD", ped.Handle.Value, currentWaypoint.Position.X, currentWaypoint.Position.Y, currentWaypoint.Position.Z, currentWaypoint.Duration, 0xC6EE6B4C); GameFiber.Sleep(currentWaypoint.Duration); break; case WaypointTypes.Animation: pedTask = ped.Tasks.PlayAnimation(currentWaypoint.AnimDict, currentWaypoint.AnimName, 8f, AnimationFlags.None); break; } pedTask?.WaitForCompletion(currentWaypoint.Duration == 0 ? -1 : currentWaypoint.Duration); if (wpyList.Count > 0) { wpyList.RemoveAt(0); } GameFiber.Yield(); } }); } while (IsMissionPlaying && (actor.RemoveAfter == 0 || actor.RemoveAfter > CurrentStage) && !ped.IsDead) { GameFiber.Yield(); } if (actor.FailMissionOnDeath && ped.IsDead) { FailMission(reason: "An ally has died."); } if (blip.IsValid()) { blip.Delete(); } while (IsMissionPlaying && (actor.RemoveAfter == 0 || actor.RemoveAfter > CurrentStage)) { GameFiber.Yield(); } if (ped.IsValid()) { ped.Delete(); } }); } foreach (var o in CurrentMission.Objects.Where(v => v.SpawnAfter == CurrentStage)) { GameFiber.StartNew(delegate { var prop = new Rage.Object(Util.RequestModel(o.ModelHash), o.Position); prop.Position = o.Position; prop.Rotation = o.Rotation; while (IsMissionPlaying && (o.RemoveAfter == 0 || o.RemoveAfter > CurrentStage)) { GameFiber.Yield(); } if (prop.IsValid()) { prop.Delete(); } }); } foreach (var pickup in CurrentMission.Pickups.Where(v => v.SpawnAfter == CurrentStage)) { GameFiber.StartNew(delegate { var obj = NativeFunction.CallByName <uint>("CREATE_PICKUP_ROTATE", pickup.PickupHash, pickup.Position.X, pickup.Position.Y, pickup.Position.Z, pickup.Rotation.Pitch, pickup.Rotation.Roll, pickup.Rotation.Yaw, 1, pickup.Ammo, 2, 1, 0); int counter = 0; while (IsMissionPlaying && (pickup.RemoveAfter == 0 || pickup.RemoveAfter > CurrentStage)) { var alpha = 40 * (Math.Sin(Util.DegToRad(counter % 180))); Util.DrawMarker(28, pickup.Position, new Vector3(), new Vector3(0.75f, 0.75f, 0.75f), Color.FromArgb((int)alpha, 10, 10, 230)); counter += 5; if (counter >= 360) { counter = 0; } if ((pickup.Position - Game.LocalPlayer.Character.Position).Length() < 1f && pickup.Respawn) { NativeFunction.CallByName <uint>("REMOVE_PICKUP", obj); while ((pickup.Position - Game.LocalPlayer.Character.Position).Length() < 3f) { GameFiber.Yield(); } obj = NativeFunction.CallByName <uint>("CREATE_PICKUP_ROTATE", pickup.PickupHash, pickup.Position.X, pickup.Position.Y, pickup.Position.Z, pickup.Rotation.Pitch, pickup.Rotation.Roll, pickup.Rotation.Yaw, 1, pickup.Ammo, 2, 1, 0); } else if ((pickup.Position - Game.LocalPlayer.Character.Position).Length() < 1f && !pickup.Respawn) { break; } GameFiber.Yield(); } NativeFunction.CallByName <uint>("REMOVE_PICKUP", obj); }); } foreach (var actor in CurrentMission.Objectives.OfType <SerializableActorObjective>().Where(v => v.SpawnAfter == CurrentStage)) { var ped = new Ped(Util.RequestModel(actor.ModelHash), actor.Position - new Vector3(0, 0, 1f), actor.Rotation.Yaw); ped.Rotation = actor.Rotation; ped.Accuracy = actor.Accuracy; if (actor.WeaponHash != 0) { ped.GiveNewWeapon(actor.WeaponHash, actor.WeaponAmmo, true); } NativeFunction.CallByName <uint>("SET_PED_FIRING_PATTERN", ped.Handle.Value, 0xC6EE6B4C); ped.Health = actor.Health; ped.MaxHealth = actor.Health; ped.Armor = actor.Armor; if (actor.RelationshipGroup == 0) { NativeFunction.CallByName <uint>("REMOVE_PED_FROM_GROUP", ped.Handle.Value); NativeFunction.CallByName <uint>("SET_PED_AS_GROUP_MEMBER", ped.Handle.Value, NativeFunction.CallByName <int>("GET_PED_GROUP_INDEX", Game.LocalPlayer.Character.Handle.Value)); ped.RelationshipGroup = StaticData.RelationshipGroups.Groups[1]; } else { ped.RelationshipGroup = StaticData.RelationshipGroups.Groups[actor.RelationshipGroup]; } if (actor.SpawnInVehicle) { var vehList = ped.GetNearbyVehicles(15).OrderBy(v => (ped.Position - v.Position).Length()); ped.WarpIntoVehicle(vehList.ToList()[0], actor.VehicleSeat); } var hasActivated = false; if (actor.ActivateAfter == CurrentStage) { CurrentObjectives.Add(actor); hasActivated = true; } GameFiber.StartNew(delegate { if (!hasActivated) { while (CurrentStage != actor.ActivateAfter && IsMissionPlaying) { GameFiber.Yield(); } CurrentObjectives.Add(actor); } var blip = ped.AttachBlip(); blip.Scale = 0.6f; blip.Color = Color.DarkRed; ped.BlockPermanentEvents = false; if (actor.Behaviour == 3) { ped.Tasks.FightAgainstClosestHatedTarget(100f); } else if (actor.Behaviour == 2) { NativeFunction.CallByName <uint>("TASK_GUARD_CURRENT_POSITION", ped.Handle.Value, 15f, 10f, true); } else if (actor.Behaviour == 0) { ped.Tasks.Clear(); } else if (actor.Behaviour == 4) { GameFiber.StartNew(delegate { var wpyList = new List <SerializableWaypoint>(actor.Waypoints); SerializableWaypoint currentWaypoint; if (wpyList.Count > 0) { currentWaypoint = wpyList[0]; } while (ped.IsValid() && ped.Exists() && ped.IsAlive && IsMissionPlaying && wpyList.Count > 0) { if (wpyList.Count == 0) { break; } currentWaypoint = wpyList[0]; Task pedTask = null; switch (currentWaypoint.Type) { case WaypointTypes.Drive: if (ped.IsInAnyVehicle(true)) { pedTask = ped.Tasks.DriveToPosition(currentWaypoint.Position, currentWaypoint.VehicleSpeed, (DriveToPositionFlags)currentWaypoint.DrivingStyle); } break; case WaypointTypes.Run: { var heading = 0f; if (wpyList.Count >= 2) { heading = Util.DirectionToRotation(wpyList[1].Position - currentWaypoint.Position) .Z; } pedTask = ped.Tasks.FollowNavigationMeshToPosition(currentWaypoint.Position, heading, 2f, 0.3f, currentWaypoint.Duration == 0 ? -1 : (int)currentWaypoint.Duration); } break; case WaypointTypes.Walk: { var heading = 0f; if (wpyList.Count >= 2) { heading = Util.DirectionToRotation(wpyList[1].Position - currentWaypoint.Position) .Z; } pedTask = ped.Tasks.FollowNavigationMeshToPosition(currentWaypoint.Position, heading, 1f, 0.3f, currentWaypoint.Duration == 0 ? -1 : (int)currentWaypoint.Duration); } break; case WaypointTypes.ExitVehicle: if (ped.IsInAnyVehicle(true)) { pedTask = ped.Tasks.LeaveVehicle(LeaveVehicleFlags.None); } break; case WaypointTypes.EnterVehicle: Vehicle[] vehs = World.GetAllVehicles().Where(v => { if (v != null && v.IsValid()) { return(v.Model.Hash == currentWaypoint.VehicleTargetModel); } return(false); }).OrderBy(v => (v.Position - ped.Position).Length()).ToArray(); if (vehs.Any()) { if ((vehs[0].Position - ped.Position).Length() > 10f) { pedTask = ped.Tasks.FollowNavigationMeshToPosition(vehs[0].Position, 0f, 3f, 5f); pedTask.WaitForCompletion(10000); } var seat = vehs[0].GetFreeSeatIndex(); if (seat.HasValue) { pedTask = ped.Tasks.EnterVehicle(vehs[0], seat.Value); } } break; case WaypointTypes.Wait: pedTask = ped.Tasks.StandStill(currentWaypoint.Duration); break; case WaypointTypes.Wander: pedTask = ped.Tasks.Wander(); break; case WaypointTypes.Shoot: pedTask = null; NativeFunction.CallByName <uint>("TASK_SHOOT_AT_COORD", ped.Handle.Value, currentWaypoint.Position.X, currentWaypoint.Position.Y, currentWaypoint.Position.Z, currentWaypoint.Duration, 0xC6EE6B4C); GameFiber.Sleep(currentWaypoint.Duration); break; case WaypointTypes.Animation: pedTask = ped.Tasks.PlayAnimation(currentWaypoint.AnimDict, currentWaypoint.AnimName, 8f, AnimationFlags.None); break; } pedTask?.WaitForCompletion(currentWaypoint.Duration == 0 ? -1 : currentWaypoint.Duration); if (wpyList.Count > 0) { wpyList.RemoveAt(0); } GameFiber.Yield(); } }); } while (!ped.IsDead && IsMissionPlaying) { if (actor.ShowHealthBar) { TimerBars.UpdateValue(ped.Handle.Value.ToString(), actor.Name, true, (100f * ped.Health / actor.Health).ToString("###") + "%"); } GameFiber.Yield(); } if (actor.ShowHealthBar) { TimerBars.UpdateValue(ped.Handle.Value.ToString(), actor.Name, true, "0%"); } CurrentObjectives.Remove(actor); if (blip.IsValid()) { blip.Delete(); } while (IsMissionPlaying) { GameFiber.Yield(); } if (ped.IsValid()) { ped.Delete(); } }); } foreach (var pickup in CurrentMission.Objectives.OfType <SerializablePickupObjective>().Where(v => v.ActivateAfter == CurrentStage)) { CurrentObjectives.Add(pickup); GameFiber.StartNew(delegate { var obj = NativeFunction.CallByName <uint>("CREATE_PICKUP_ROTATE", pickup.PickupHash, pickup.Position.X, pickup.Position.Y, pickup.Position.Z, pickup.Rotation.Pitch, pickup.Rotation.Roll, pickup.Rotation.Yaw, 1, pickup.Ammo, 2, 1, 0); var blip = new Blip(pickup.Position); blip.Scale = 0.7f; blip.Color = Color.DodgerBlue; var counter = 0; while ((pickup.Position - Game.LocalPlayer.Character.Position).Length() > 1f && IsMissionPlaying) { var alpha = 40 * (Math.Sin(Util.DegToRad(counter % 180))); Util.DrawMarker(28, pickup.Position, new Vector3(), new Vector3(0.75f, 0.75f, 0.75f), Color.FromArgb((int)alpha, 230, 10, 10)); counter += 5; if (counter >= 360) { counter = 0; } GameFiber.Yield(); } if (blip != null && blip.IsValid()) { blip.Delete(); } NativeFunction.CallByName <uint>("REMOVE_PICKUP", obj); CurrentObjectives.Remove(pickup); }); } foreach (var mark in CurrentMission.Objectives.OfType <SerializableMarker>().Where(v => v.ActivateAfter == CurrentStage)) { CurrentObjectives.Add(mark); GameFiber.StartNew(delegate { var bColor = Color.FromArgb(mark.Alpha, (int)mark.Color.X, (int)mark.Color.Y, (int)mark.Color.Z); var blip = new Blip(mark.Position); blip.Color = bColor; blip.EnableRoute(bColor); while ((mark.Position - Game.LocalPlayer.Character.Position).Length() > 1.5f && IsMissionPlaying) { Util.DrawMarker(mark.Type, mark.Position, new Vector3(mark.Rotation.Pitch, mark.Rotation.Roll, mark.Rotation.Yaw), mark.Scale, bColor); GameFiber.Yield(); } if (blip.IsValid()) { blip.Delete(); } CurrentObjectives.Remove(mark); }); } if (CurrentMission.Cutscenes.Any(c => c.PlayAt == CurrentStage)) { var origPos = Game.LocalPlayer.Character.Position; var origRot = Game.LocalPlayer.Character.Rotation; Game.FadeScreenIn(100, true); Game.LocalPlayer.Character.Opacity = 0f; Game.LocalPlayer.Character.IsPositionFrozen = true; var cutscene = CurrentMission.Cutscenes.First(c => c.PlayAt == CurrentStage); var camLeft = new List <SerializableCamera>(cutscene.Cameras); var subLeft = new List <SerializableSubtitle>(cutscene.Subtitles); var startTime = Game.GameTime; Camera mainCam = null; SerializableCamera currentCam = null; uint lerpStart = 0; while ((Game.GameTime - startTime) < cutscene.Length) { var ct = (Game.GameTime - startTime); if (camLeft.Any()) { if (camLeft[0].PositionInTime <= ct) { if (mainCam == null || !mainCam.IsValid()) { Camera.DeleteAllCameras(); mainCam = new Camera(true); } Game.LocalPlayer.HasControl = false; mainCam.Position = cutscene.Cameras[0].Position; mainCam.Rotation = cutscene.Cameras[0].Rotation; currentCam = camLeft[0]; camLeft.RemoveAt(0); lerpStart = Game.GameTime; Game.LocalPlayer.Character.Position = mainCam.Position; } else if (currentCam != null) { // Advance cam pos if (currentCam.InterpolationStyle == InterpolationStyle.Linear) { mainCam.Position = Util.LerpVector(currentCam.Position, camLeft[0].Position, Util.LinearLerp, Game.GameTime - lerpStart, camLeft[0].PositionInTime - currentCam.PositionInTime); mainCam.Rotation = Util.LerpVector(currentCam.Rotation.ToVector(), camLeft[0].Rotation.ToVector(), Util.LinearLerp, Game.GameTime - lerpStart, camLeft[0].PositionInTime - currentCam.PositionInTime).ToRotator(); Game.LocalPlayer.Character.Position = mainCam.Position; } else if (currentCam.InterpolationStyle == InterpolationStyle.Smooth) { mainCam.Position = Util.LerpVector(currentCam.Position, camLeft[0].Position, Util.QuadraticLerp, Game.GameTime - lerpStart, camLeft[0].PositionInTime - currentCam.PositionInTime); mainCam.Rotation = Util.LerpVector(currentCam.Rotation.ToVector(), camLeft[0].Rotation.ToVector(), Util.QuadraticLerp, Game.GameTime - lerpStart, camLeft[0].PositionInTime - currentCam.PositionInTime).ToRotator(); Game.LocalPlayer.Character.Position = mainCam.Position; } } } else if (currentCam != null && mainCam != null) { mainCam.Position = currentCam.Position; mainCam.Rotation = currentCam.Rotation; Game.LocalPlayer.Character.Position = mainCam.Position; } if (subLeft.Any()) { if (subLeft[0].PositionInTime <= ct) { Game.DisplaySubtitle(subLeft[0].Content, subLeft[0].DurationInMs); subLeft.RemoveAt(0); } } GameFiber.Yield(); } mainCam.Active = false; Game.LocalPlayer.HasControl = true; Game.LocalPlayer.Character.IsPositionFrozen = false; Game.LocalPlayer.Character.Position = origPos; Game.LocalPlayer.Character.Rotation = origRot; Game.LocalPlayer.Character.Opacity = 1f; Game.FadeScreenOut(100); } if (!string.IsNullOrEmpty(CurrentMission.ObjectiveNames[CurrentStage])) { Game.DisplaySubtitle(CurrentMission.ObjectiveNames[CurrentStage], 10000); } Game.FadeScreenIn(1); }
private void AdvanceStage() { TimerBars = new TimerBars(); CurrentStage++; CurrentObjectives.Clear(); foreach (var veh in CurrentMission.Vehicles.Where(v => v.SpawnAfter == CurrentStage)) { var newv = new Vehicle(Util.RequestModel(veh.ModelHash), veh.Position) { PrimaryColor = Color.FromArgb((int)veh.PrimaryColor.X, (int)veh.PrimaryColor.Y, (int)veh.PrimaryColor.Z), SecondaryColor = Color.FromArgb((int)veh.SecondaryColor.X, (int)veh.SecondaryColor.Y, (int)veh.SecondaryColor.Z), }; newv.Health = veh.Health; newv.Rotation = veh.Rotation; GameFiber.StartNew(delegate { while (IsMissionPlaying && (veh.RemoveAfter == 0 || veh.RemoveAfter > CurrentStage)) { if (veh.FailMissionOnDeath && newv.IsDead) { FailMission(reason: "The vehicle has been destroyed."); } GameFiber.Yield(); } if(newv.IsValid()) newv.Delete(); }); } foreach (var veh in CurrentMission.Objectives.OfType<SerializableVehicleObjective>().Where(v => v.SpawnAfter == CurrentStage)) { var newv = new Vehicle(Util.RequestModel(veh.ModelHash), veh.Position) { PrimaryColor = Color.FromArgb((int)veh.PrimaryColor.X, (int)veh.PrimaryColor.Y, (int)veh.PrimaryColor.Z), SecondaryColor = Color.FromArgb((int)veh.SecondaryColor.X, (int)veh.SecondaryColor.Y, (int)veh.SecondaryColor.Z), }; newv.Health = veh.Health; newv.Rotation = veh.Rotation; var hasActivated = false; if (veh.ActivateAfter == CurrentStage) { CurrentObjectives.Add(veh); hasActivated = true; } GameFiber.StartNew(delegate { if(!hasActivated) { while (CurrentStage != veh.ActivateAfter && IsMissionPlaying) { GameFiber.Yield(); } CurrentObjectives.Add(veh); } var blip = newv.AttachBlip(); if(veh.ObjectiveType == 0) { blip.Color = Color.DarkRed; while (!newv.IsDead && IsMissionPlaying) { if (veh.ShowHealthBar) { TimerBars.UpdateValue(newv.Handle.Value.ToString(), veh.Name, true, (100f*newv.Health / veh.Health).ToString("###") + "%"); } GameFiber.Yield(); } TimerBars.UpdateValue(newv.Handle.Value.ToString(), veh.Name, true, "0%"); } if (veh.ObjectiveType == 1) { blip.Color = Color.CornflowerBlue; while (!Game.LocalPlayer.Character.IsInVehicle(newv, false) && IsMissionPlaying) { GameFiber.Yield(); } } CurrentObjectives.Remove(veh); if(blip.IsValid()) blip.Delete(); while (IsMissionPlaying) GameFiber.Yield(); if (newv.IsValid()) newv.Delete(); }); } if (CurrentMission.Spawnpoints.Any(s => s.SpawnAfter == CurrentStage)) { var sp = CurrentMission.Spawnpoints.First(s => s.SpawnAfter == CurrentStage); Game.FadeScreenOut(100, true); Game.LocalPlayer.Character.Position = sp.Position - new Vector3(0,0,1); Game.LocalPlayer.Character.Rotation = sp.Rotation; Game.LocalPlayer.Model = Util.RequestModel(sp.ModelHash); if (sp.WeaponHash != 0) Game.LocalPlayer.Character.GiveNewWeapon(sp.WeaponHash, sp.WeaponAmmo, true); Game.LocalPlayer.Character.Health = sp.Health; Game.LocalPlayer.Character.Armor = sp.Armor; if (sp.SpawnInVehicle) { var vehList = Game.LocalPlayer.Character.GetNearbyVehicles(15).OrderBy(v => (Game.LocalPlayer.Character.Position - v.Position).Length()); Game.LocalPlayer.Character.WarpIntoVehicle(vehList.ToList()[0], sp.VehicleSeat); } Game.FadeScreenIn(500, false); } foreach (var actor in CurrentMission.Actors.Where(v => v.SpawnAfter == CurrentStage)) { GameFiber.StartNew(delegate { var ped = new Ped(Util.RequestModel(actor.ModelHash), actor.Position - new Vector3(0,0,1f), actor.Rotation.Yaw); ped.Rotation = actor.Rotation; ped.Accuracy = actor.Accuracy; var blip = ped.AttachBlip(); blip.Scale = 0.6f; if (actor.WeaponHash != 0) ped.GiveNewWeapon(actor.WeaponHash, actor.WeaponAmmo, true); ped.Health = actor.Health; ped.Armor = actor.Armor; if (actor.RelationshipGroup == 0) { ped.RelationshipGroup = StaticData.RelationshipGroups.Groups[1]; blip.Color = Color.DodgerBlue; NativeFunction.CallByName<uint>("REMOVE_PED_FROM_GROUP", ped.Handle.Value); NativeFunction.CallByName<uint>("SET_PED_AS_GROUP_MEMBER", ped.Handle.Value, NativeFunction.CallByName<int>("GET_PED_GROUP_INDEX", Game.LocalPlayer.Character.Handle.Value)); } else { ped.RelationshipGroup = StaticData.RelationshipGroups.Groups[actor.RelationshipGroup]; if(actor.RelationshipGroup == 4 || actor.RelationshipGroup == 5) blip.Color = Color.DarkRed; } if (actor.SpawnInVehicle) { var vehList = ped.GetNearbyVehicles(15).OrderBy(v => (ped.Position - v.Position).Length()); ped.WarpIntoVehicle(vehList.ToList()[0], actor.VehicleSeat); } ped.BlockPermanentEvents = false; NativeFunction.CallByName<uint>("SET_PED_FIRING_PATTERN", ped.Handle.Value, 0xC6EE6B4C); if (actor.Behaviour == 3) ped.Tasks.FightAgainstClosestHatedTarget(100f); else if (actor.Behaviour == 2) NativeFunction.CallByName<uint>("TASK_GUARD_CURRENT_POSITION", ped.Handle.Value, 15f, 10f, true); else if (actor.Behaviour == 0) ped.Tasks.Clear(); else if (actor.Behaviour == 4) { GameFiber.StartNew(delegate { var wpyList = new List<SerializableWaypoint>(actor.Waypoints); SerializableWaypoint currentWaypoint; if (wpyList.Count > 0) currentWaypoint = wpyList[0]; while (ped.IsValid() && ped.Exists() && ped.IsAlive && IsMissionPlaying && wpyList.Count > 0) { if (wpyList.Count == 0) break; currentWaypoint = wpyList[0]; Task pedTask = null; switch (currentWaypoint.Type) { case WaypointTypes.Drive: if (ped.IsInAnyVehicle(true)) { pedTask = ped.Tasks.DriveToPosition(currentWaypoint.Position, currentWaypoint.VehicleSpeed, (DriveToPositionFlags)currentWaypoint.DrivingStyle); } break; case WaypointTypes.Run: { var heading = 0f; if (wpyList.Count >= 2) { heading = Util.DirectionToRotation(wpyList[1].Position - currentWaypoint.Position) .Z; } pedTask = ped.Tasks.FollowNavigationMeshToPosition(currentWaypoint.Position, heading, 2f, 0.3f, currentWaypoint.Duration == 0 ? -1 : (int)currentWaypoint.Duration); } break; case WaypointTypes.Walk: { var heading = 0f; if (wpyList.Count >= 2) { heading = Util.DirectionToRotation(wpyList[1].Position - currentWaypoint.Position) .Z; } pedTask = ped.Tasks.FollowNavigationMeshToPosition(currentWaypoint.Position, heading, 1f, 0.3f, currentWaypoint.Duration == 0 ? -1 : (int)currentWaypoint.Duration); } break; case WaypointTypes.ExitVehicle: if (ped.IsInAnyVehicle(true)) pedTask = ped.Tasks.LeaveVehicle(LeaveVehicleFlags.None); break; case WaypointTypes.EnterVehicle: Vehicle[] vehs = World.GetAllVehicles().Where(v => { if (v != null && v.IsValid()) return v.Model.Hash == currentWaypoint.VehicleTargetModel; return false; }).OrderBy(v => (v.Position - ped.Position).Length()).ToArray(); if (vehs.Any()) { if ((vehs[0].Position - ped.Position).Length() > 10f) { pedTask = ped.Tasks.FollowNavigationMeshToPosition(vehs[0].Position, 0f, 3f, 5f); pedTask.WaitForCompletion(10000); } var seat = vehs[0].GetFreeSeatIndex(); if (seat.HasValue) pedTask = ped.Tasks.EnterVehicle(vehs[0], seat.Value); } break; case WaypointTypes.Wait: pedTask = ped.Tasks.StandStill(currentWaypoint.Duration); break; case WaypointTypes.Wander: pedTask = ped.Tasks.Wander(); break; case WaypointTypes.Shoot: pedTask = null; NativeFunction.CallByName<uint>("TASK_SHOOT_AT_COORD", ped.Handle.Value, currentWaypoint.Position.X, currentWaypoint.Position.Y, currentWaypoint.Position.Z, currentWaypoint.Duration, 0xC6EE6B4C); GameFiber.Sleep(currentWaypoint.Duration); break; case WaypointTypes.Animation: pedTask = ped.Tasks.PlayAnimation(currentWaypoint.AnimDict, currentWaypoint.AnimName, 8f, AnimationFlags.None); break; } pedTask?.WaitForCompletion(currentWaypoint.Duration == 0 ? -1 : currentWaypoint.Duration); if (wpyList.Count > 0) wpyList.RemoveAt(0); GameFiber.Yield(); } }); } while (IsMissionPlaying && (actor.RemoveAfter == 0 || actor.RemoveAfter > CurrentStage) && !ped.IsDead) { GameFiber.Yield(); } if (actor.FailMissionOnDeath && ped.IsDead) { FailMission(reason: "An ally has died."); } if (blip.IsValid()) blip.Delete(); while(IsMissionPlaying && (actor.RemoveAfter == 0 || actor.RemoveAfter > CurrentStage)) GameFiber.Yield(); if(ped.IsValid()) ped.Delete(); }); } foreach (var o in CurrentMission.Objects.Where(v => v.SpawnAfter == CurrentStage)) { GameFiber.StartNew(delegate { var prop = new Rage.Object(Util.RequestModel(o.ModelHash), o.Position); prop.Position = o.Position; prop.Rotation = o.Rotation; while (IsMissionPlaying && (o.RemoveAfter == 0 || o.RemoveAfter > CurrentStage)) { GameFiber.Yield(); } if(prop.IsValid()) prop.Delete(); }); } foreach (var pickup in CurrentMission.Pickups.Where(v => v.SpawnAfter == CurrentStage)) { GameFiber.StartNew(delegate { var obj = NativeFunction.CallByName<uint>("CREATE_PICKUP_ROTATE", pickup.PickupHash, pickup.Position.X, pickup.Position.Y, pickup.Position.Z, pickup.Rotation.Pitch, pickup.Rotation.Roll, pickup.Rotation.Yaw, 1, pickup.Ammo, 2, 1, 0); int counter = 0; while (IsMissionPlaying && (pickup.RemoveAfter == 0 || pickup.RemoveAfter > CurrentStage)) { var alpha = 40 * (Math.Sin(Util.DegToRad(counter % 180))); Util.DrawMarker(28, pickup.Position, new Vector3(), new Vector3(0.75f, 0.75f, 0.75f), Color.FromArgb((int)alpha, 10, 10, 230)); counter += 5; if (counter >= 360) counter = 0; if ((pickup.Position - Game.LocalPlayer.Character.Position).Length() < 1f && pickup.Respawn) { NativeFunction.CallByName<uint>("REMOVE_PICKUP", obj); while((pickup.Position - Game.LocalPlayer.Character.Position).Length() < 3f) { GameFiber.Yield();} obj = NativeFunction.CallByName<uint>("CREATE_PICKUP_ROTATE", pickup.PickupHash, pickup.Position.X, pickup.Position.Y, pickup.Position.Z, pickup.Rotation.Pitch, pickup.Rotation.Roll, pickup.Rotation.Yaw, 1, pickup.Ammo, 2, 1, 0); } else if ((pickup.Position - Game.LocalPlayer.Character.Position).Length() < 1f && !pickup.Respawn) break; GameFiber.Yield(); } NativeFunction.CallByName<uint>("REMOVE_PICKUP", obj); }); } foreach (var actor in CurrentMission.Objectives.OfType<SerializableActorObjective>().Where(v => v.SpawnAfter == CurrentStage)) { var ped = new Ped(Util.RequestModel(actor.ModelHash), actor.Position - new Vector3(0, 0, 1f), actor.Rotation.Yaw); ped.Rotation = actor.Rotation; ped.Accuracy = actor.Accuracy; if (actor.WeaponHash != 0) ped.GiveNewWeapon(actor.WeaponHash, actor.WeaponAmmo, true); NativeFunction.CallByName<uint>("SET_PED_FIRING_PATTERN", ped.Handle.Value, 0xC6EE6B4C); ped.Health = actor.Health; ped.MaxHealth = actor.Health; ped.Armor = actor.Armor; if (actor.RelationshipGroup == 0) { NativeFunction.CallByName<uint>("REMOVE_PED_FROM_GROUP", ped.Handle.Value); NativeFunction.CallByName<uint>("SET_PED_AS_GROUP_MEMBER", ped.Handle.Value, NativeFunction.CallByName<int>("GET_PED_GROUP_INDEX", Game.LocalPlayer.Character.Handle.Value)); ped.RelationshipGroup = StaticData.RelationshipGroups.Groups[1]; } else { ped.RelationshipGroup = StaticData.RelationshipGroups.Groups[actor.RelationshipGroup]; } if (actor.SpawnInVehicle) { var vehList = ped.GetNearbyVehicles(15).OrderBy(v => (ped.Position - v.Position).Length()); ped.WarpIntoVehicle(vehList.ToList()[0], actor.VehicleSeat); } var hasActivated = false; if (actor.ActivateAfter == CurrentStage) { CurrentObjectives.Add(actor); hasActivated = true; } GameFiber.StartNew(delegate { if(!hasActivated) { while (CurrentStage != actor.ActivateAfter && IsMissionPlaying) { GameFiber.Yield(); } CurrentObjectives.Add(actor); } var blip = ped.AttachBlip(); blip.Scale = 0.6f; blip.Color = Color.DarkRed; ped.BlockPermanentEvents = false; if (actor.Behaviour == 3) ped.Tasks.FightAgainstClosestHatedTarget(100f); else if (actor.Behaviour == 2) NativeFunction.CallByName<uint>("TASK_GUARD_CURRENT_POSITION", ped.Handle.Value, 15f, 10f, true); else if(actor.Behaviour == 0) ped.Tasks.Clear(); else if (actor.Behaviour == 4) { GameFiber.StartNew(delegate { var wpyList = new List<SerializableWaypoint>(actor.Waypoints); SerializableWaypoint currentWaypoint; if(wpyList.Count > 0) currentWaypoint = wpyList[0]; while (ped.IsValid() && ped.Exists() && ped.IsAlive && IsMissionPlaying && wpyList.Count > 0) { if (wpyList.Count == 0) break; currentWaypoint = wpyList[0]; Task pedTask = null; switch (currentWaypoint.Type) { case WaypointTypes.Drive: if (ped.IsInAnyVehicle(true)) { pedTask = ped.Tasks.DriveToPosition(currentWaypoint.Position, currentWaypoint.VehicleSpeed, (DriveToPositionFlags)currentWaypoint.DrivingStyle); } break; case WaypointTypes.Run: { var heading = 0f; if (wpyList.Count >= 2) { heading = Util.DirectionToRotation(wpyList[1].Position - currentWaypoint.Position) .Z; } pedTask = ped.Tasks.FollowNavigationMeshToPosition(currentWaypoint.Position, heading, 2f, 0.3f, currentWaypoint.Duration == 0 ? -1 : (int)currentWaypoint.Duration); } break; case WaypointTypes.Walk: { var heading = 0f; if (wpyList.Count >= 2) { heading = Util.DirectionToRotation(wpyList[1].Position - currentWaypoint.Position) .Z; } pedTask = ped.Tasks.FollowNavigationMeshToPosition(currentWaypoint.Position, heading, 1f, 0.3f, currentWaypoint.Duration == 0 ? -1 : (int)currentWaypoint.Duration); } break; case WaypointTypes.ExitVehicle: if (ped.IsInAnyVehicle(true)) pedTask = ped.Tasks.LeaveVehicle(LeaveVehicleFlags.None); break; case WaypointTypes.EnterVehicle: Vehicle[] vehs = World.GetAllVehicles().Where(v => { if (v != null && v.IsValid()) return v.Model.Hash == currentWaypoint.VehicleTargetModel; return false; }).OrderBy(v => (v.Position - ped.Position).Length()).ToArray(); if (vehs.Any()) { if ((vehs[0].Position - ped.Position).Length() > 10f) { pedTask = ped.Tasks.FollowNavigationMeshToPosition(vehs[0].Position, 0f, 3f, 5f); pedTask.WaitForCompletion(10000); } var seat = vehs[0].GetFreeSeatIndex(); if (seat.HasValue) pedTask = ped.Tasks.EnterVehicle(vehs[0], seat.Value); } break; case WaypointTypes.Wait: pedTask = ped.Tasks.StandStill(currentWaypoint.Duration); break; case WaypointTypes.Wander: pedTask = ped.Tasks.Wander(); break; case WaypointTypes.Shoot: pedTask = null; NativeFunction.CallByName<uint>("TASK_SHOOT_AT_COORD", ped.Handle.Value, currentWaypoint.Position.X, currentWaypoint.Position.Y, currentWaypoint.Position.Z, currentWaypoint.Duration, 0xC6EE6B4C); GameFiber.Sleep(currentWaypoint.Duration); break; case WaypointTypes.Animation: pedTask = ped.Tasks.PlayAnimation(currentWaypoint.AnimDict, currentWaypoint.AnimName, 8f, AnimationFlags.None); break; } pedTask?.WaitForCompletion(currentWaypoint.Duration == 0 ? -1 : currentWaypoint.Duration); if(wpyList.Count > 0) wpyList.RemoveAt(0); GameFiber.Yield(); } }); } while (!ped.IsDead && IsMissionPlaying) { if (actor.ShowHealthBar) { TimerBars.UpdateValue(ped.Handle.Value.ToString(), actor.Name, true, (100f*ped.Health/actor.Health).ToString("###") + "%"); } GameFiber.Yield(); } if (actor.ShowHealthBar) { TimerBars.UpdateValue(ped.Handle.Value.ToString(), actor.Name, true, "0%"); } CurrentObjectives.Remove(actor); if(blip.IsValid()) blip.Delete(); while(IsMissionPlaying) GameFiber.Yield(); if (ped.IsValid()) ped.Delete(); }); } foreach (var pickup in CurrentMission.Objectives.OfType<SerializablePickupObjective>().Where(v => v.ActivateAfter == CurrentStage)) { CurrentObjectives.Add(pickup); GameFiber.StartNew(delegate { var obj = NativeFunction.CallByName<uint>("CREATE_PICKUP_ROTATE", pickup.PickupHash, pickup.Position.X, pickup.Position.Y, pickup.Position.Z, pickup.Rotation.Pitch, pickup.Rotation.Roll, pickup.Rotation.Yaw, 1, pickup.Ammo, 2, 1, 0); var blip = new Blip(pickup.Position); blip.Scale = 0.7f; blip.Color = Color.DodgerBlue; var counter = 0; while ((pickup.Position - Game.LocalPlayer.Character.Position).Length() > 1f && IsMissionPlaying) { var alpha = 40 * (Math.Sin(Util.DegToRad(counter % 180))); Util.DrawMarker(28, pickup.Position, new Vector3(), new Vector3(0.75f, 0.75f, 0.75f), Color.FromArgb((int)alpha, 230, 10, 10)); counter += 5; if (counter >= 360) counter = 0; GameFiber.Yield(); } if(blip != null && blip.IsValid()) blip.Delete(); NativeFunction.CallByName<uint>("REMOVE_PICKUP", obj); CurrentObjectives.Remove(pickup); }); } foreach (var mark in CurrentMission.Objectives.OfType<SerializableMarker>().Where(v => v.ActivateAfter == CurrentStage)) { CurrentObjectives.Add(mark); GameFiber.StartNew(delegate { var bColor = Color.FromArgb(mark.Alpha, (int) mark.Color.X, (int) mark.Color.Y, (int) mark.Color.Z); var blip = new Blip(mark.Position); blip.Color = bColor; blip.EnableRoute(bColor); while ((mark.Position - Game.LocalPlayer.Character.Position).Length() > 1.5f && IsMissionPlaying) { Util.DrawMarker(mark.Type, mark.Position, new Vector3(mark.Rotation.Pitch, mark.Rotation.Roll, mark.Rotation.Yaw), mark.Scale, bColor); GameFiber.Yield(); } if(blip.IsValid()) blip.Delete(); CurrentObjectives.Remove(mark); }); } if (CurrentMission.Cutscenes.Any(c => c.PlayAt == CurrentStage)) { var origPos = Game.LocalPlayer.Character.Position; var origRot = Game.LocalPlayer.Character.Rotation; Game.FadeScreenIn(100, true); Game.LocalPlayer.Character.Opacity = 0f; Game.LocalPlayer.Character.IsPositionFrozen = true; var cutscene = CurrentMission.Cutscenes.First(c => c.PlayAt == CurrentStage); var camLeft = new List<SerializableCamera>(cutscene.Cameras); var subLeft = new List<SerializableSubtitle>(cutscene.Subtitles); var startTime = Game.GameTime; Camera mainCam = null; SerializableCamera currentCam = null; uint lerpStart = 0; while ((Game.GameTime - startTime) < cutscene.Length) { var ct = (Game.GameTime - startTime); if (camLeft.Any()) { if (camLeft[0].PositionInTime <= ct) { if (mainCam == null || !mainCam.IsValid()) { Camera.DeleteAllCameras(); mainCam = new Camera(true); } Game.LocalPlayer.HasControl = false; mainCam.Position = cutscene.Cameras[0].Position; mainCam.Rotation = cutscene.Cameras[0].Rotation; currentCam = camLeft[0]; camLeft.RemoveAt(0); lerpStart = Game.GameTime; Game.LocalPlayer.Character.Position = mainCam.Position; } else if (currentCam != null) { // Advance cam pos if (currentCam.InterpolationStyle == InterpolationStyle.Linear) { mainCam.Position = Util.LerpVector(currentCam.Position, camLeft[0].Position, Util.LinearLerp, Game.GameTime - lerpStart, camLeft[0].PositionInTime - currentCam.PositionInTime); mainCam.Rotation = Util.LerpVector(currentCam.Rotation.ToVector(), camLeft[0].Rotation.ToVector(), Util.LinearLerp, Game.GameTime - lerpStart, camLeft[0].PositionInTime - currentCam.PositionInTime).ToRotator(); Game.LocalPlayer.Character.Position = mainCam.Position; } else if (currentCam.InterpolationStyle == InterpolationStyle.Smooth) { mainCam.Position = Util.LerpVector(currentCam.Position, camLeft[0].Position, Util.QuadraticLerp, Game.GameTime - lerpStart, camLeft[0].PositionInTime - currentCam.PositionInTime); mainCam.Rotation = Util.LerpVector(currentCam.Rotation.ToVector(), camLeft[0].Rotation.ToVector(), Util.QuadraticLerp, Game.GameTime - lerpStart, camLeft[0].PositionInTime - currentCam.PositionInTime).ToRotator(); Game.LocalPlayer.Character.Position = mainCam.Position; } } } else if(currentCam != null && mainCam != null) { mainCam.Position = currentCam.Position; mainCam.Rotation = currentCam.Rotation; Game.LocalPlayer.Character.Position = mainCam.Position; } if (subLeft.Any()) { if (subLeft[0].PositionInTime <= ct) { Game.DisplaySubtitle(subLeft[0].Content, subLeft[0].DurationInMs); subLeft.RemoveAt(0); } } GameFiber.Yield(); } mainCam.Active = false; Game.LocalPlayer.HasControl = true; Game.LocalPlayer.Character.IsPositionFrozen = false; Game.LocalPlayer.Character.Position = origPos; Game.LocalPlayer.Character.Rotation = origRot; Game.LocalPlayer.Character.Opacity = 1f; Game.FadeScreenOut(100); } if (!string.IsNullOrEmpty(CurrentMission.ObjectiveNames[CurrentStage])) { Game.DisplaySubtitle(CurrentMission.ObjectiveNames[CurrentStage], 10000); } Game.FadeScreenIn(1); }