This commit is contained in:
2026-07-07 21:08:52 +02:00
commit 4c20cfc716
2613 changed files with 318021 additions and 0 deletions

View File

@@ -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;
}
}
}
}