Иконка ресурса

FREE BikeBunnyhop : 2.0.0 2.0.0

Нет прав для скачивания
C#:
#nullable disable

using System.Collections.Generic;
using HarmonyLib;
using Oxide.Core.Plugins;
using UnityEngine;

namespace Oxide.Plugins;

[Info("Bike Bunnyhop", "Magic Services // crash", "2.0.0")]
internal class BikeBunnyhop : RustPlugin
{
    private const string PermUse = "bikebunnyhop.use";
    private static BikeBunnyhop _instance;

    private ConfigData _config;
    private readonly Dictionary<ulong, float> _lastBunnyhopTime = new();
    private readonly Dictionary<ulong, float> _customEnergy = new();
    private readonly Dictionary<ulong, Rigidbody> _bikeRigidbodies = new();
    private readonly HashSet<ulong> _boostedBikes = new();

    private sealed class ConfigData
    {
        public float CooldownSeconds { get; set; } = 3f;
        public float EnergyCostPercent { get; set; } = 0.1f;
        public float MinimumEnergyRequired { get; set; } = 0.1f;
        public float BaseForce { get; set; } = 2.5f;
        public float SpeedMultiplier { get; set; } = 0.3f;
        public float MaxAdditionalForce { get; set; } = 10f;
        public bool UseCustomEnergy { get; set; } = true;
        public float TopSpeedMultiplier { get; set; } = 1.0f;
        public float AirTurnSpeed { get; set; } = 0.3f;
    }

    protected override void LoadDefaultConfig()
    {
        _config = new ConfigData();
        SaveConfig();
    }

    protected override void LoadConfig()
    {
        base.LoadConfig();
        try
        {
            _config = Config.ReadObject<ConfigData>();
            if (_config == null) LoadDefaultConfig();
            SaveConfig();
        }
        catch
        {
            LoadDefaultConfig();
        }
    }

    protected override void SaveConfig() => Config.WriteObject(_config);

    private void Init()
    {
        _instance = this;
        permission.RegisterPermission(PermUse, this);
    }

    private void Unload()
    {
        _instance = null;
    }

    private void OnServerInitialized()
    {
        foreach (var entity in BaseNetworkable.serverEntities)
        {
            if (entity is Bike bike)
                OnEntitySpawned(bike);
        }
    }

    private void OnEntitySpawned(Bike bike)
    {
        if (bike is null) return;
        var id = bike.net.ID.Value;
        _customEnergy.TryAdd(id, 1f);
        var rb = bike.GetComponent<Rigidbody>();
        if (rb is not null)
            _bikeRigidbodies[id] = rb;
    }

    private void OnEntityKill(Bike bike)
    {
        if (bike is null) return;
        var id = bike.net.ID.Value;
        _lastBunnyhopTime.Remove(id);
        _customEnergy.Remove(id);
        _bikeRigidbodies.Remove(id);
        _boostedBikes.Remove(id);
    }

    private void OnEntityMounted(BaseMountable mountable, BasePlayer player)
    {
        if (player is null || mountable is null) return;
        if (!permission.UserHasPermission(player.UserIDString, PermUse)) return;

        var bike = mountable.VehicleParent() as Bike;
        if (bike is null) return;
        if (!bike.IsDriver(player)) return;

        _boostedBikes.Add(bike.net.ID.Value);
    }

    private void OnEntityDismounted(BaseMountable mountable, BasePlayer player)
    {
        if (mountable is null || player is null) return;

        var bike = mountable.VehicleParent() as Bike;
        if (bike is null) return;

        var bikeId = bike.net.ID.Value;
        if (!_boostedBikes.Contains(bikeId)) return;

        if (!bike.HasDriver())
            _boostedBikes.Remove(bikeId);
    }

    private object OnPlayerInput(BasePlayer player, InputState input)
    {
        if (player is null || input == null) return null;
        if (!input.WasJustPressed(BUTTON.FIRE_SECONDARY)) return null;
        if (!permission.UserHasPermission(player.UserIDString, PermUse)) return null;

        if (player.GetMountedVehicle() is not Bike bike || !bike.HasDriver()) return null;

        var bikeId = bike.net.ID.Value;

        if (!CanBunnyhop(bike, bikeId)) return null;

        ApplyCustomBunnyhop(bike, bikeId);
        return null;
    }

    private bool CanBunnyhop(Bike bike, ulong bikeId)
    {
        if (_lastBunnyhopTime.TryGetValue(bikeId, out float lastTime))
        {
            if (Time.time - lastTime < _config.CooldownSeconds)
                return false;
        }

        if (!IsGrounded(bike)) return false;

        if (bike.engineController?.IsWaterlogged() == true) return false;

        if (!_config.UseCustomEnergy) return true;
        if (_customEnergy.TryGetValue(bikeId, out var energy)) return !(energy < _config.MinimumEnergyRequired);
        _customEnergy[bikeId] = 1f;
        energy = 1f;
        return !(energy < _config.MinimumEnergyRequired);
    }

    private void ApplyCustomBunnyhop(Bike bike, ulong bikeId)
    {
        if (!_bikeRigidbodies.TryGetValue(bikeId, out var rigidBody) || rigidBody is null)
            return;

        var force = _config.BaseForce;

        if (_config.SpeedMultiplier > 0f)
        {
            var speed = bike.GetSpeed();
            var energyMult = 1f;

            if (_config.UseCustomEnergy && _customEnergy.TryGetValue(bikeId, out var energy))
                energyMult = energy;

            var speedBonus = Mathf.Min(Mathf.Abs(speed * _config.SpeedMultiplier) * energyMult, _config.MaxAdditionalForce);
            force += speedBonus;
        }

        rigidBody.AddRelativeForce(Vector3.up * force, ForceMode.VelocityChange);

        _lastBunnyhopTime[bikeId] = Time.time;

        if (!_config.UseCustomEnergy || !_customEnergy.ContainsKey(bikeId)) return;
        _customEnergy[bikeId] = Mathf.Clamp01(_customEnergy[bikeId] - _config.EnergyCostPercent);
        timer.Once(_config.CooldownSeconds * 2f, () =>
        {
            if (_customEnergy.ContainsKey(bikeId))
                _customEnergy[bikeId] = Mathf.Clamp01(_customEnergy[bikeId] + 0.05f);
        });
    }

    private static bool IsGrounded(Bike bike)
    {
        var transform = bike.transform;
        return Physics.Raycast(transform.position, Vector3.down, 0.5f, LayerMask.GetMask("Terrain", "World", "Construction"));
    }

    #region Harmony Patches
    
    [AutoPatch]
    [HarmonyPatch(typeof(Bike), nameof(Bike.GetMaxDriveForce))]
    internal static class Bike_GetMaxDriveForce_Patch
    {
        [HarmonyPostfix]
        private static void Postfix(Bike __instance, ref float __result)
        {
            if (_instance is null) return;
            if (_instance._config.TopSpeedMultiplier <= 1f) return;
            if (!_instance._boostedBikes.Contains(__instance.net.ID.Value)) return;

            __result *= _instance._config.TopSpeedMultiplier;
        }
    }
    
    [AutoPatch]
    [HarmonyPatch(typeof(Bike), "PDDirectionStab")]
    internal static class Bike_PDDirectionStab_Patch
    {
        [HarmonyPrefix]
        private static bool Prefix(Bike __instance)
        {
            if (_instance is null) return true;
            if (_instance._config.AirTurnSpeed <= 0f) return true;
            if (__instance.carPhysics.IsGrounded()) return true;

            var bikeId = __instance.net.ID.Value;
            if (!_instance._boostedBikes.Contains(bikeId)) return true;
            if (!_instance._bikeRigidbodies.TryGetValue(bikeId, out var rb) || rb is null) return true;
            
            var angularVelocity = rb.angularVelocity;
            var max = _instance._config.AirTurnSpeed * 10f;
            angularVelocity.y = Mathf.Clamp(angularVelocity.y, -max, max);
            rb.angularVelocity = angularVelocity;
            return false;
        }
    }
    
    [AutoPatch]
    [HarmonyPatch(typeof(Bike), "AwakeBikePhysicsTick")]
    internal static class Bike_AwakeBikePhysicsTick_Patch
    {
        [HarmonyPostfix]
        private static void Postfix(Bike __instance)
        {
            if (_instance is null) return;
            if (_instance._config.AirTurnSpeed <= 0f) return;
            if (__instance.carPhysics.IsGrounded()) return;

            var bikeId = __instance.net.ID.Value;
            if (!_instance._boostedBikes.Contains(bikeId)) return;
            if (!_instance._bikeRigidbodies.TryGetValue(bikeId, out var rb) || rb is null) return;
            if (rb.isKinematic) return;

            var steerInput = __instance.GetSteerInput();
            if (steerInput == 0f) return;

            rb.AddRelativeTorque(0f, steerInput * _instance._config.AirTurnSpeed, 0f, ForceMode.VelocityChange);
        }
    }

    #endregion
}

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху