0.0.1
This commit is contained in:
@@ -0,0 +1,415 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
using CitizenFX.Core;
|
||||
using static CitizenFX.Core.Native.API;
|
||||
|
||||
namespace RvWorldCleanup.Client
|
||||
{
|
||||
public class WorldCleanupClient : BaseScript
|
||||
{
|
||||
private static readonly string[] BlockedScenarioTypes =
|
||||
{
|
||||
"WORLD_HUMAN_AA_COFFEE",
|
||||
"WORLD_HUMAN_AA_SMOKE",
|
||||
"WORLD_HUMAN_BINOCULARS",
|
||||
"WORLD_HUMAN_CLIPBOARD",
|
||||
"WORLD_HUMAN_DRINKING",
|
||||
"WORLD_HUMAN_GUARD_STAND",
|
||||
"WORLD_HUMAN_HANG_OUT_STREET",
|
||||
"WORLD_HUMAN_SMOKING",
|
||||
"WORLD_HUMAN_STAND_IMPATIENT",
|
||||
"PROP_HUMAN_SEAT_BENCH",
|
||||
"PROP_HUMAN_SEAT_CHAIR",
|
||||
"WORLD_VEHICLE_ATTRACTOR",
|
||||
"WORLD_VEHICLE_BICYCLE_BMX",
|
||||
"WORLD_VEHICLE_EMPTY",
|
||||
"WORLD_VEHICLE_POLICE_CAR",
|
||||
"WORLD_VEHICLE_POLICE_NEXT_TO_CAR"
|
||||
};
|
||||
|
||||
private CleanupSettings _settings;
|
||||
private int _nextConfigRefreshAt;
|
||||
private int _nextCleanupAt;
|
||||
|
||||
public WorldCleanupClient()
|
||||
{
|
||||
_settings = CleanupSettings.Load();
|
||||
ApplyPersistentToggles();
|
||||
|
||||
EventHandlers["onClientResourceStart"] += new Action<string>(OnClientResourceStart);
|
||||
EventHandlers["onClientResourceStop"] += new Action<string>(OnClientResourceStop);
|
||||
|
||||
Tick += OnTick;
|
||||
}
|
||||
|
||||
private void OnClientResourceStart(string resourceName)
|
||||
{
|
||||
if (resourceName != GetCurrentResourceName())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_settings = CleanupSettings.Load();
|
||||
ApplyPersistentToggles();
|
||||
|
||||
Debug.WriteLine(string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"[{0}] Ambient cleanup aktiv. Radius={1:0.##}, Intervall={2}ms",
|
||||
GetCurrentResourceName(),
|
||||
_settings.ClearRadius,
|
||||
_settings.ClearIntervalMs));
|
||||
}
|
||||
|
||||
private void OnClientResourceStop(string resourceName)
|
||||
{
|
||||
if (resourceName != GetCurrentResourceName())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RestorePersistentToggles();
|
||||
}
|
||||
|
||||
private async Task OnTick()
|
||||
{
|
||||
var now = GetGameTimer();
|
||||
|
||||
if (now >= _nextConfigRefreshAt)
|
||||
{
|
||||
_settings = CleanupSettings.Load();
|
||||
ApplyPersistentToggles();
|
||||
_nextConfigRefreshAt = now + _settings.ConfigRefreshMs;
|
||||
}
|
||||
|
||||
if (!_settings.Enabled)
|
||||
{
|
||||
await Delay(1000);
|
||||
return;
|
||||
}
|
||||
|
||||
ApplyFrameSuppression();
|
||||
|
||||
if (_settings.DisableScenarioActions)
|
||||
{
|
||||
ApplyScenarioSuppression();
|
||||
}
|
||||
|
||||
if (now >= _nextCleanupAt)
|
||||
{
|
||||
CleanupNearbyWorld();
|
||||
_nextCleanupAt = now + _settings.ClearIntervalMs;
|
||||
}
|
||||
|
||||
await Delay(0);
|
||||
}
|
||||
|
||||
private void ApplyPersistentToggles()
|
||||
{
|
||||
SetRandomBoats(!_settings.DisableRandomBoats);
|
||||
SetGarbageTrucks(!_settings.DisableGarbageTrucks);
|
||||
|
||||
var allowRandomCops = !_settings.DisableRandomCops;
|
||||
SetCreateRandomCops(allowRandomCops);
|
||||
SetCreateRandomCopsOnScenarios(allowRandomCops);
|
||||
SetCreateRandomCopsNotOnScenarios(allowRandomCops);
|
||||
|
||||
var allowDispatch = !_settings.DisableDispatchServices;
|
||||
|
||||
for (var service = 1; service <= 15; service++)
|
||||
{
|
||||
EnableDispatchService(service, allowDispatch);
|
||||
}
|
||||
|
||||
SetMaxWantedLevel(_settings.DisableDispatchServices ? 0 : 5);
|
||||
}
|
||||
|
||||
private void RestorePersistentToggles()
|
||||
{
|
||||
SetRandomBoats(true);
|
||||
SetGarbageTrucks(true);
|
||||
SetCreateRandomCops(true);
|
||||
SetCreateRandomCopsOnScenarios(true);
|
||||
SetCreateRandomCopsNotOnScenarios(true);
|
||||
|
||||
for (var service = 1; service <= 15; service++)
|
||||
{
|
||||
EnableDispatchService(service, true);
|
||||
}
|
||||
|
||||
SetMaxWantedLevel(5);
|
||||
}
|
||||
|
||||
private void ApplyFrameSuppression()
|
||||
{
|
||||
SetPedPopulationBudget(_settings.DisableAmbientPeds ? 0 : 3);
|
||||
SetVehiclePopulationBudget(_settings.DisableAmbientVehicles ? 0 : 3);
|
||||
|
||||
SetPedDensityMultiplierThisFrame(_settings.DisableAmbientPeds ? 0.0f : 1.0f);
|
||||
SetScenarioPedDensityMultiplierThisFrame(
|
||||
_settings.DisableScenarioPeds ? 0.0f : 1.0f,
|
||||
_settings.DisableScenarioPeds ? 0.0f : 1.0f);
|
||||
SetVehicleDensityMultiplierThisFrame(_settings.DisableAmbientVehicles ? 0.0f : 1.0f);
|
||||
SetRandomVehicleDensityMultiplierThisFrame(_settings.DisableAmbientVehicles ? 0.0f : 1.0f);
|
||||
SetParkedVehicleDensityMultiplierThisFrame(_settings.DisableParkedVehicles ? 0.0f : 1.0f);
|
||||
}
|
||||
|
||||
private void ApplyScenarioSuppression()
|
||||
{
|
||||
SuppressShockingEventsNextFrame();
|
||||
|
||||
foreach (var scenarioType in BlockedScenarioTypes)
|
||||
{
|
||||
SetScenarioTypeEnabled(scenarioType, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void CleanupNearbyWorld()
|
||||
{
|
||||
var playerPed = PlayerPedId();
|
||||
|
||||
if (playerPed == 0 || !DoesEntityExist(playerPed))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var playerCoords = GetEntityCoords(playerPed, true);
|
||||
var radius = _settings.ClearRadius;
|
||||
|
||||
if (_settings.DisableAmbientVehicles || _settings.DisableParkedVehicles)
|
||||
{
|
||||
RemoveVehiclesFromGeneratorsInArea(
|
||||
playerCoords.X - radius,
|
||||
playerCoords.Y - radius,
|
||||
playerCoords.Z - 10.0f,
|
||||
playerCoords.X + radius,
|
||||
playerCoords.Y + radius,
|
||||
playerCoords.Z + 10.0f);
|
||||
}
|
||||
|
||||
if (_settings.DeleteExistingPeds)
|
||||
{
|
||||
CleanupPeds(playerCoords, radius, playerPed);
|
||||
}
|
||||
|
||||
if (_settings.DeleteExistingVehicles)
|
||||
{
|
||||
CleanupVehicles(playerCoords, radius, playerPed);
|
||||
}
|
||||
}
|
||||
|
||||
private void CleanupPeds(Vector3 origin, float radius, int playerPed)
|
||||
{
|
||||
var iterator = FindFirstPed(ref playerPed);
|
||||
|
||||
try
|
||||
{
|
||||
if (iterator == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var ped = playerPed;
|
||||
|
||||
do
|
||||
{
|
||||
if (!CanDeletePed(ped, playerPed, origin, radius))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
SetEntityAsMissionEntity(ped, true, true);
|
||||
DeletePed(ref ped);
|
||||
}
|
||||
while (FindNextPed(iterator, ref ped));
|
||||
}
|
||||
finally
|
||||
{
|
||||
EndFindPed(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
private void CleanupVehicles(Vector3 origin, float radius, int playerPed)
|
||||
{
|
||||
var vehicle = 0;
|
||||
var iterator = FindFirstVehicle(ref vehicle);
|
||||
|
||||
try
|
||||
{
|
||||
if (iterator == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (!CanDeleteVehicle(vehicle, playerPed, origin, radius))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
SetEntityAsMissionEntity(vehicle, true, true);
|
||||
DeleteVehicle(ref vehicle);
|
||||
}
|
||||
while (FindNextVehicle(iterator, ref vehicle));
|
||||
}
|
||||
finally
|
||||
{
|
||||
EndFindVehicle(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanDeletePed(int ped, int playerPed, Vector3 origin, float radius)
|
||||
{
|
||||
if (ped == 0 || ped == playerPed || !DoesEntityExist(ped))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsPedAPlayer(ped))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_settings.PreserveMissionEntities && IsEntityAMissionEntity(ped))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_settings.PreserveNetworkedEntities && NetworkGetEntityIsNetworked(ped))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsPedInAnyVehicle(ped, false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsInsideRadius(origin, GetEntityCoords(ped, true), radius);
|
||||
}
|
||||
|
||||
private bool CanDeleteVehicle(int vehicle, int playerPed, Vector3 origin, float radius)
|
||||
{
|
||||
if (vehicle == 0 || !DoesEntityExist(vehicle))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var currentPlayerVehicle = GetVehiclePedIsIn(playerPed, false);
|
||||
|
||||
if (vehicle == currentPlayerVehicle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_settings.PreserveMissionEntities && IsEntityAMissionEntity(vehicle))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_settings.PreserveNetworkedEntities && NetworkGetEntityIsNetworked(vehicle))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_settings.PreserveOccupiedVehicles && !IsVehicleSeatFree(vehicle, -1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsInsideRadius(origin, GetEntityCoords(vehicle, true), radius);
|
||||
}
|
||||
|
||||
private static bool IsInsideRadius(Vector3 origin, Vector3 target, float radius)
|
||||
{
|
||||
var distanceX = origin.X - target.X;
|
||||
var distanceY = origin.Y - target.Y;
|
||||
var distanceZ = origin.Z - target.Z;
|
||||
|
||||
return (distanceX * distanceX) + (distanceY * distanceY) + (distanceZ * distanceZ) <= radius * radius;
|
||||
}
|
||||
|
||||
private sealed class CleanupSettings
|
||||
{
|
||||
public bool Enabled { get; private set; }
|
||||
public bool DisableAmbientPeds { get; private set; }
|
||||
public bool DisableScenarioPeds { get; private set; }
|
||||
public bool DisableAmbientVehicles { get; private set; }
|
||||
public bool DisableParkedVehicles { get; private set; }
|
||||
public bool DisableDispatchServices { get; private set; }
|
||||
public bool DisableRandomCops { get; private set; }
|
||||
public bool DisableGarbageTrucks { get; private set; }
|
||||
public bool DisableRandomBoats { get; private set; }
|
||||
public bool DisableScenarioActions { get; private set; }
|
||||
public bool DeleteExistingPeds { get; private set; }
|
||||
public bool DeleteExistingVehicles { get; private set; }
|
||||
public bool PreserveMissionEntities { get; private set; }
|
||||
public bool PreserveNetworkedEntities { get; private set; }
|
||||
public bool PreserveOccupiedVehicles { get; private set; }
|
||||
public float ClearRadius { get; private set; }
|
||||
public int ClearIntervalMs { get; private set; }
|
||||
public int ConfigRefreshMs { get; private set; }
|
||||
|
||||
public static CleanupSettings Load()
|
||||
{
|
||||
return new CleanupSettings
|
||||
{
|
||||
Enabled = ReadBool("rv_cleanup_enable", true),
|
||||
DisableAmbientPeds = ReadBool("rv_cleanup_disable_ambient_peds", true),
|
||||
DisableScenarioPeds = ReadBool("rv_cleanup_disable_scenario_peds", true),
|
||||
DisableAmbientVehicles = ReadBool("rv_cleanup_disable_ambient_vehicles", true),
|
||||
DisableParkedVehicles = ReadBool("rv_cleanup_disable_parked_vehicles", true),
|
||||
DisableDispatchServices = ReadBool("rv_cleanup_disable_dispatch_services", true),
|
||||
DisableRandomCops = ReadBool("rv_cleanup_disable_random_cops", true),
|
||||
DisableGarbageTrucks = ReadBool("rv_cleanup_disable_garbage_trucks", true),
|
||||
DisableRandomBoats = ReadBool("rv_cleanup_disable_random_boats", true),
|
||||
DisableScenarioActions = ReadBool("rv_cleanup_disable_scenario_actions", true),
|
||||
DeleteExistingPeds = ReadBool("rv_cleanup_delete_existing_peds", true),
|
||||
DeleteExistingVehicles = ReadBool("rv_cleanup_delete_existing_vehicles", true),
|
||||
PreserveMissionEntities = ReadBool("rv_cleanup_preserve_mission_entities", true),
|
||||
PreserveNetworkedEntities = ReadBool("rv_cleanup_preserve_networked_entities", true),
|
||||
PreserveOccupiedVehicles = ReadBool("rv_cleanup_preserve_occupied_vehicles", true),
|
||||
ClearRadius = ReadFloat("rv_cleanup_clear_radius", 175.0f),
|
||||
ClearIntervalMs = ReadInt("rv_cleanup_clear_interval_ms", 10000),
|
||||
ConfigRefreshMs = ReadInt("rv_cleanup_config_refresh_ms", 5000)
|
||||
};
|
||||
}
|
||||
|
||||
private static bool ReadBool(string convarName, bool defaultValue)
|
||||
{
|
||||
var defaultText = defaultValue ? "true" : "false";
|
||||
var value = GetConvar(convarName, defaultText);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
value = value.Trim().ToLowerInvariant();
|
||||
|
||||
return value == "1" || value == "true" || value == "yes" || value == "on";
|
||||
}
|
||||
|
||||
private static int ReadInt(string convarName, int defaultValue)
|
||||
{
|
||||
var value = GetConvarInt(convarName, defaultValue);
|
||||
return value > 0 ? value : defaultValue;
|
||||
}
|
||||
|
||||
private static float ReadFloat(string convarName, float defaultValue)
|
||||
{
|
||||
var rawValue = GetConvar(convarName, defaultValue.ToString(CultureInfo.InvariantCulture));
|
||||
float parsedValue;
|
||||
|
||||
if (float.TryParse(rawValue, NumberStyles.Float, CultureInfo.InvariantCulture, out parsedValue) && parsedValue > 0.0f)
|
||||
{
|
||||
return parsedValue;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user