diff --git a/SharedClasses/ConfigManager.cs b/SharedClasses/ConfigManager.cs
index c8b07fe7..5f212c2d 100644
--- a/SharedClasses/ConfigManager.cs
+++ b/SharedClasses/ConfigManager.cs
@@ -34,8 +34,10 @@ public enum Setting
vmenu_disable_entity_outlines_tool,
vmenu_disable_player_stats_setup,
- // Vehicle Chameleon Colours
+ // Vehicle Settings
vmenu_using_chameleon_colours,
+ vmenu_vehicle_spawn_delay,
+ vmenu_delete_vehicle_distance,
// Prevent Extras Abuse
vmenu_prevent_extras_when_damaged,
@@ -61,6 +63,7 @@ public enum Setting
vmenu_vehicle_blackout_enabled,
vmenu_weather_change_duration,
vmenu_enable_snow,
+ vmenu_smooth_time_transitions,
// Time settings
vmenu_enable_time_sync,
@@ -92,12 +95,12 @@ public static bool GetSettingsBool(Setting setting)
///
///
///
- public static int GetSettingsInt(Setting setting)
+ public static int GetSettingsInt(Setting setting, int defaultValue = -1)
{
- var convarInt = GetConvarInt(setting.ToString(), -1);
- if (convarInt == -1)
+ var convarInt = GetConvarInt(setting.ToString(), defaultValue);
+ if (convarInt == defaultValue)
{
- if (int.TryParse(GetConvar(setting.ToString(), "-1"), out var convarIntAlt))
+ if (int.TryParse(GetConvar(setting.ToString(), defaultValue.ToString()), out var convarIntAlt))
{
return convarIntAlt;
}
@@ -110,13 +113,13 @@ public static int GetSettingsInt(Setting setting)
///
///
///
- public static float GetSettingsFloat(Setting setting)
+ public static float GetSettingsFloat(Setting setting, float defaultValue = -1f)
{
- if (float.TryParse(GetConvar(setting.ToString(), "-1.0"), out var result))
+ if (float.TryParse(GetConvar(setting.ToString(), defaultValue.ToString()), out var result))
{
return result;
}
- return -1f;
+ return defaultValue;
}
///
diff --git a/SharedClasses/PermissionsManager.cs b/SharedClasses/PermissionsManager.cs
index f3240bc6..d5826c73 100644
--- a/SharedClasses/PermissionsManager.cs
+++ b/SharedClasses/PermissionsManager.cs
@@ -113,6 +113,7 @@ public enum Permission
#region vehicle spawner
VSMenu,
VSAll,
+ VSBypassRateLimit,
VSDisableReplacePrevious,
VSSpawnByName,
VSAddon,
@@ -481,8 +482,7 @@ private static bool IsAllowedServer(Permission permission, string playerHandle)
{
return false;
}
-
- return IsPlayerAceAllowed(playerHandle, GetAceName(permission));
+ return GetPermissionAndParentPermissions(permission).Any(p => IsPlayerAceAllowed(playerHandle, GetAceName(p)));
}
#endif
diff --git a/SharedClasses/SupplementaryPermissionManager.cs b/SharedClasses/SupplementaryPermissionManager.cs
index 2c94e769..8ef9944c 100644
--- a/SharedClasses/SupplementaryPermissionManager.cs
+++ b/SharedClasses/SupplementaryPermissionManager.cs
@@ -124,7 +124,7 @@ private static bool IsAllowedServer(string permission, string playerHandle)
return false;
}
- return IsPlayerAceAllowed(playerHandle, GetAceName(permission));
+ return GetPermissionAndParentPermissions(permission).Any(p => IsPlayerAceAllowed(playerHandle, GetAceName(p)));
}
#endif
diff --git a/vMenu/CommonFunctions.cs b/vMenu/CommonFunctions.cs
index 78b40f4e..4234228f 100644
--- a/vMenu/CommonFunctions.cs
+++ b/vMenu/CommonFunctions.cs
@@ -15,6 +15,7 @@
using static CitizenFX.Core.UI.Screen;
using static vMenuShared.PermissionsManager;
+using vMenuShared;
namespace vMenuClient
{
@@ -1225,6 +1226,8 @@ public static async Task SpawnVehicle(string vehicleName = "custom", bool s
#endregion
#region Main Spawn Vehicle Function
+ public static int lastSpawnTime = 0;
+ public static int spawnTime = ConfigManager.GetSettingsInt(ConfigManager.Setting.vmenu_vehicle_spawn_delay, 5) * 1000; // make convar
///
/// Spawns a vehicle.
///
@@ -1260,8 +1263,19 @@ public static async Task SpawnVehicle(uint vehicleHash, bool spawnInside, b
return 0;
}
}
-
-
+
+ int gameTime = GetGameTimer();
+ if (!IsAllowed(Permission.VSBypassRateLimit))
+ {
+ if (lastSpawnTime + spawnTime > gameTime)
+ {
+ Notify.Error($"You are spawning vehicles too quickly. Please wait {Math.Ceiling((double)(lastSpawnTime + spawnTime - gameTime)/1000)} second(s) before trying again.");
+ return 0;
+ }
+ }
+
+ lastSpawnTime = gameTime;
+
if (!skipLoad)
{
var successFull = await LoadModel(vehicleHash);
@@ -1375,6 +1389,12 @@ public static async Task SpawnVehicle(uint vehicleHash, bool spawnInside, b
{
vehicle.PlaceOnGround();
}
+
+ if (!vehicle.Model.IsTrain) // to be extra fucking safe
+ {
+ // workaround of retarded feature above:
+ SetVehicleForwardSpeed(vehicle.Handle, speed);
+ }
}
// If mod info about the vehicle was specified, check if it's not null.
@@ -1386,11 +1406,6 @@ public static async Task SpawnVehicle(uint vehicleHash, bool spawnInside, b
// Set the previous vehicle to the new vehicle.
_previousVehicle = vehicle;
//vehicle.Speed = speed; // retarded feature that randomly breaks for no fucking reason
- if (!vehicle.Model.IsTrain) // to be extra fucking safe
- {
- // workaround of retarded feature above:
- SetVehicleForwardSpeed(vehicle.Handle, speed);
- }
vehicle.CurrentRPM = rpm;
int vehicleDefaultRadio = UserDefaults.VehicleDefaultRadio;
@@ -2141,7 +2156,7 @@ public static void UpdateServerTime(int hours, int minutes)
{
realMinutes = 0;
}
- TriggerServerEvent("vMenu:UpdateServerTime", realHours, realMinutes);
+ TriggerServerEvent("vMenu:UpdateServerTime", realHours, realMinutes, EventManager.IsServerTimeFrozen);
}
///
diff --git a/vMenu/MainMenu.cs b/vMenu/MainMenu.cs
index 7087f4d7..bad66d2b 100644
--- a/vMenu/MainMenu.cs
+++ b/vMenu/MainMenu.cs
@@ -147,6 +147,80 @@ public MainMenu()
}
}
}), false);
+
+ RegisterCommand("vMenu:DV", new Action, string>(async (source, args, rawCommand) =>
+ {
+ if (IsAllowed(Permission.VODelete))
+ {
+ var player = Game.PlayerPed;
+
+ if (!player.IsAlive)
+ return;
+
+ if (player.IsInVehicle())
+ {
+ var veh = GetVehicle();
+
+ if (veh != null && veh.Exists() && veh.Driver == player)
+ {
+ SetVehicleHasBeenOwnedByPlayer(veh.Handle, false);
+ SetEntityAsMissionEntity(veh.Handle, false, false);
+ veh.Delete();
+ }
+ else
+ {
+ Notify.Error("This vehicle does not exist (somehow) or you need to be the driver of this vehicle to delete it!");
+ }
+
+ return;
+ }
+
+ float distance = GetSettingsFloat(Setting.vmenu_delete_vehicle_distance, 5.0f);
+ int maxDeleteTries = 5;
+ int maxHitTries = 5;
+
+ var forward = GetOffsetFromEntityInWorldCoords(player.Handle, 0f, distance, 0f);
+ var ray = StartShapeTestCapsule(player.Position.X, player.Position.Y, player.Position.Z, forward.X, forward.Y, forward.Z, 5f, 10, player.Handle, 7);
+
+ bool hit = false;
+ Vector3 endCoords = Vector3.Zero;
+ Vector3 surfaceNormal = Vector3.Zero;
+ int entity = 0;
+
+ for (int i = 0; i < maxHitTries; i++)
+ {
+ GetShapeTestResult(ray, ref hit, ref endCoords, ref surfaceNormal, ref entity);
+ if (hit) break;
+ await Task.FromResult(0);
+ }
+
+ if (!hit || !DoesEntityExist(entity) || !IsEntityAVehicle(entity))
+ {
+ Notify.Error("No vehicle found in front of you to delete!");
+ return;
+ }
+
+ var hitVeh = new Vehicle(entity);
+
+ for (int i = 0; i <= maxDeleteTries && DoesEntityExist(entity); i++)
+ {
+ NetworkRequestControlOfEntity(entity);
+ SetVehicleHasBeenOwnedByPlayer(entity, false);
+ SetEntityAsMissionEntity(entity, false, false);
+ hitVeh.Delete();
+ await Task.FromResult(0);
+ }
+
+ if (DoesEntityExist(entity))
+ {
+ Notify.Error("Failed to delete the vehicle in front of you. Try again or ask an admin for help.");
+ }
+ else
+ {
+ Notify.Success("Vehicle deleted successfully.");
+ }
+ }
+ }), false);
if (!(GetSettingsString(Setting.vmenu_noclip_toggle_key) == null))
{
diff --git a/vMenu/vMenuClient.csproj b/vMenu/vMenuClient.csproj
index 10eb93a6..7c974cb9 100644
--- a/vMenu/vMenuClient.csproj
+++ b/vMenu/vMenuClient.csproj
@@ -50,7 +50,7 @@
-
+
diff --git a/vMenuServer/MainServer.cs b/vMenuServer/MainServer.cs
index 8b351ba1..c6fd8d0a 100644
--- a/vMenuServer/MainServer.cs
+++ b/vMenuServer/MainServer.cs
@@ -547,7 +547,7 @@ internal void ServerCommandHandler(int source, List
///
///
+ ///
[EventHandler("vMenu:UpdateServerTime")]
- internal void UpdateTime([FromSource] Player source, int newHours, int newMinutes)
+ internal async void UpdateTime([FromSource] Player source, int newHours, int newMinutes, bool newFreezeTime)
{
- if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.TOSetTime, source) && !PermissionsManager.IsAllowed(PermissionsManager.Permission.TOAll, source))
+ if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.TOSetTime, source))
{
BanManager.BanCheater(source);
return;
}
+ if (GetSettingsBool(Setting.vmenu_smooth_time_transitions))
+ {
+ CurrentHours = CurrentHours;
+ CurrentMinutes = CurrentMinutes;
+ FreezeTime = true;
+ while (newHours != CurrentHours)
+ {
+ if ((CurrentMinutes + 1) > 59)
+ {
+ CurrentMinutes = 0;
+ if ((CurrentHours + 1) > 23)
+ {
+ CurrentHours = 0;
+ }
+ else
+ {
+ CurrentHours++;
+ }
+ }
+ else
+ {
+ CurrentMinutes = CurrentMinutes + 5;
+ }
+ await Delay(0);
+ }
+ FreezeTime = newFreezeTime;
+ }
CurrentHours = newHours;
CurrentMinutes = newMinutes;
}
@@ -830,7 +857,7 @@ internal void UpdateTime([FromSource] Player source, int newHours, int newMinute
[EventHandler("vMenu:FreezeServerTime")]
internal void FreezeServerTime([FromSource] Player source, bool freezeTime)
{
- if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.TOFreezeTime, source) && !PermissionsManager.IsAllowed(PermissionsManager.Permission.TOAll, source))
+ if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.TOFreezeTime, source))
{
BanManager.BanCheater(source);
return;
@@ -850,7 +877,7 @@ internal void FreezeServerTime([FromSource] Player source, bool freezeTime)
[EventHandler("vMenu:KickPlayer")]
internal void KickPlayer([FromSource] Player source, int target, string kickReason = "You have been kicked from the server.")
{
- if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.OPKick, source) && !PermissionsManager.IsAllowed(PermissionsManager.Permission.OPAll, source))
+ if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.OPKick, source))
{
BanManager.BanCheater(source);
return;
@@ -885,7 +912,7 @@ internal void KickPlayer([FromSource] Player source, int target, string kickReas
[EventHandler("vMenu:KillPlayer")]
internal void KillPlayer([FromSource] Player source, int target)
{
- if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.OPKill, source) && !PermissionsManager.IsAllowed(PermissionsManager.Permission.OPAll, source))
+ if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.OPKill, source))
{
BanManager.BanCheater(source);
return;
@@ -909,7 +936,7 @@ internal void KillPlayer([FromSource] Player source, int target)
[EventHandler("vMenu:SummonPlayer")]
internal async void SummonPlayer([FromSource] Player source, int target, int numberOfSeats)
{
- if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.OPSummon, source) && !PermissionsManager.IsAllowed(PermissionsManager.Permission.OPAll, source))
+ if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.OPSummon, source))
{
BanManager.BanCheater(source);
return;
@@ -987,7 +1014,7 @@ internal async void SummonPlayer([FromSource] Player source, int target, int num
[EventHandler("vMenu:SendMessageToPlayer")]
internal void SendPrivateMessage([FromSource] Player source, int target, string message)
{
- if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.OPSendMessage, source) && !PermissionsManager.IsAllowed(PermissionsManager.Permission.OPAll, source))
+ if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.OPSendMessage, source))
{
BanManager.BanCheater(source);
return;
@@ -1021,7 +1048,7 @@ internal void SendPrivateMessage([FromSource] Player source, int target, string
foreach (string playerHandle in joinedPlayers)
{
- if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.OPSeePrivateMessages, playerHandle) && !PermissionsManager.IsAllowed(PermissionsManager.Permission.OPAll, playerHandle))
+ if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.OPSeePrivateMessages, playerHandle))
{
continue;
}
@@ -1063,7 +1090,7 @@ private static void KickLog(string kickLogMesage)
[EventHandler("vMenu:SaveTeleportLocation")]
internal void AddTeleportLocation([FromSource] Player source, string locationJson)
{
- if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.MSTeleportSaveLocation, source) && !PermissionsManager.IsAllowed(PermissionsManager.Permission.MSAll, source))
+ if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.MSTeleportSaveLocation, source))
{
BanManager.BanCheater(source);
return;
@@ -1113,7 +1140,7 @@ internal void GetPlayerCoords([FromSource] Player source, long rpcId, int player
{
var coords = Vector3.Zero;
- if (PermissionsManager.IsAllowed(PermissionsManager.Permission.OPTeleport, source) || PermissionsManager.IsAllowed(PermissionsManager.Permission.OPAll, source))
+ if (PermissionsManager.IsAllowed(PermissionsManager.Permission.OPTeleport, source))
{
Player targetPlayer = GetPlayerFromServerId(playerId);
@@ -1141,7 +1168,7 @@ private IEnumerable GetJoinQuitNotifPlayers()
foreach (string playerHandle in joinedPlayers)
{
- if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.MSJoinQuitNotifs, playerHandle) && !PermissionsManager.IsAllowed(PermissionsManager.Permission.MSAll, playerHandle))
+ if (!PermissionsManager.IsAllowed(PermissionsManager.Permission.MSJoinQuitNotifs, playerHandle))
{
continue;
}
diff --git a/vMenuServer/config/permissions.cfg b/vMenuServer/config/permissions.cfg
index 6c6df4a6..aebb7ec7 100644
--- a/vMenuServer/config/permissions.cfg
+++ b/vMenuServer/config/permissions.cfg
@@ -114,6 +114,8 @@ setr vmenu_enable_snow false
setr vmenu_enable_time_sync true
# Set this to true if you want time to be frozen by default.
setr vmenu_freeze_time false
+# Enables smooth time transitions.
+setr vmenu_smooth_time_transitions true
# This setting determines how long one in-game minute lasts in real time.
# By default, one GTA V minute, takes 2 seconds (2000 miliseconds).
# The value here is measured in miliseconds, and must be a positive number at least greater than 100.
@@ -136,6 +138,11 @@ setr vmenu_prevent_extras_when_damaged false
setr vmenu_allowed_engine_damage_for_extra_change 800
# This is the amount of body damage before the extras will be blocked. Value must be between 0 and 1000 (inclusive)
setr vmenu_allowed_body_damage_for_extra_change 800
+# This setting adjusts the vehicle spawning ratelimit in seconds. Value must be between 0 and infinity
+setr vmenu_vehicle_spawn_rate_limit 5
+# This setting adjusts the "vMenu:DV" command delete distance.
+setr vmenu_delete_vehicle_distance 5.0
+
### MP Ped options ###
# Setting this to true will enable a 3D ped preview when viewing saved MP Peds.
@@ -296,6 +303,7 @@ add_ace builtin.everyone "vMenu.VehicleOptions.All" allow
####################################
add_ace builtin.everyone "vMenu.VehicleSpawner.Menu" allow
add_ace builtin.everyone "vMenu.VehicleSpawner.All" allow
+#add_ace builtin.everyone "vMenu.VehicleSpawner.BypassRateLimit" allow
#add_ace builtin.everyone "vMenu.VehicleSpawner.DisableReplacePrevious" allow
#add_ace builtin.everyone "vMenu.VehicleSpawner.SpawnByName" allow
#add_ace builtin.everyone "vMenu.VehicleSpawner.Addon" allow # allows you to spawn an addon car from the Addon Vehicles list.