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

FREE Gamble : 2.0.0 2.0.0

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
/*           ________               __
           / ____/ /_  ____  _____/ /___  __
          / / __/ __ \/ __ \/ ___/ __/ / / /
         / /_/ / / / / /_/ (__  ) /_/ /_/ /
         \____/_/ /_/\____/____/\__/\__, /
                                   /____/

This plugin is exclusively licensed to Enchanted.gg and may not be edited or sold without explicit permission.© 2025 Ghosty & Enchanted.gg
*/
using System;
using System.Collections.Generic;
using System.Linq;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("Gamble", "Ghosty", "2.0.0")]
    public class Gamble : RustPlugin {
        private ConfigData _config;
        private bool _roundInProgress;
        private readonly Dictionary<string, int> _participants = new Dictionary<string, int>();
        private readonly List<string> _participantOrder = new List<string>();
        private Timer _countdownTimer;
        private Timer _autoStartTimer;
        private System.Random _random = new System.Random();
        private float _timeLeft;
#region Config
        private class ConfigData {
            public float CountdownTime {
                get;
                set;
            }
            = 600f;
            public string CurrencyShortName {
                get;
                set;
            }
            = "scrap";
            public bool BroadcastToAll {
                get;
                set;
            }
            = true;
            public string BroadcastPrefix {
                get;
                set;
            }
            = "<color=#dbb403><b>[Gamble]</b></color> ";
            public float AutoStartInterval {
                get;
                set;
            }
            = 1800f;
        }
        protected override void LoadDefaultConfig() {
            _config = new ConfigData();
            SaveConfig(_config);
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                _config = Config.ReadObject<ConfigData>();
                if (_config == null) throw new Exception();
            }
            catch {
                PrintError("Invalid configuration file, creating a new one!");
                LoadDefaultConfig();
            }
            SaveConfig(_config);
        }
        protected override void SaveConfig() => SaveConfig(_config);
        private void SaveConfig(ConfigData config) => Config.WriteObject(config);
#endregion
        void OnServerInitialized() {
            _roundInProgress = false;
            _participants.Clear();
            _participantOrder.Clear();
            _countdownTimer?.Destroy();
            _autoStartTimer?.Destroy();
            _autoStartTimer = timer.Every(_config.AutoStartInterval, CheckAndStartRoundAutomatically);
        }
        [ChatCommand("gamble")]
        private void GambleCommand(BasePlayer player, string command, string[] args) {
            if (!_roundInProgress) {
                SendReply(player, Prefix() + "No gamble round is running! Wait for the next round to open.");
                return;
            }
            if (args.Length < 1) {
                SendReply(player, Prefix() + "Usage: <color=#ffb400>/gamble <scrap amount></color>");
                return;
            }
            if (!int.TryParse(args[0], out int amount) || amount <= 0) {
                SendReply(player, Prefix() + "Please enter a valid positive amount.");
                return;
            }
            if (_participants.ContainsKey(player.UserIDString)) {
                SendReply(player, Prefix() + "You've already entered this round! Wait for the next round to try again.");
                return;
            }
            var def = ItemManager.FindItemDefinition(_config.CurrencyShortName);
            if (def == null) {
                SendReply(player, Prefix() + "Internal error: configured currency not found.");
                return;
            }
            int playerScrap = (int)player.inventory.GetAmount(def.itemid);
            if (playerScrap < amount) {
                SendReply(player, Prefix() + $"You don't have enough <color=#dbb403>{_config.CurrencyShortName}</color>.");
                return;
            }
            int removed = RemoveItems(player, _config.CurrencyShortName, amount);
            if (removed < amount) {
                SendReply(player, Prefix() + $"Failed to remove required {_config.CurrencyShortName}.");
                return;
            }
            AddParticipant(player.UserIDString, amount);
            float playerChance = 100f * amount / GetTotalPot();
            SendReply(player, Prefix() + $"You entered with <color=#dbb403>{amount} {def.displayName.translated}</color> | Your odds: <color=#5cb85c>{playerChance:0.0}%</color>.");
            BroadcastToAll(Prefix() + $"<color=#b6e2ff>{player.displayName}</color> joined the gamble.({_participants.Count} participants, pot: <color=#dbb403>{GetTotalPot()} {def.displayName.translated}</color>)\nUse /pot to check the current pot.");
        }
        [ChatCommand("pot")]
        private void PotCommand(BasePlayer player, string command, string[] args) {
            if (!_roundInProgress) {
                SendReply(player, Prefix() + "No round is running currently.");
                return;
            }
            var def = ItemManager.FindItemDefinition(_config.CurrencyShortName);
            int pot = GetTotalPot();
            string msg = $"{Prefix()}<color=#dbb403>POT:</color> <color=#dbb403>{pot} {def.displayName.translated}</color> | <color=#b6e2ff>{_participants.Count}</color> participants";
            if (_participants.ContainsKey(player.UserIDString)) {
                int you = _participants[player.UserIDString];
                float odds = 100f * you / pot;
                msg += $" | <color=#5cb85c>Your odds: {odds:0.0}%</color>";
            }
            if (_timeLeft > 0) msg += $" | <color=#ababab>Time left: {FormatTime(_timeLeft)}</color>";
            SendReply(player, msg);
        }
        [ChatCommand("startgamble")]
        private void StartGambleCommand(BasePlayer player, string command, string[] args) {
            if (player != null && player.net?.connection != null && player.net.connection.authLevel < 1) {
                SendReply(player, Prefix() + "You don't have permission to use this command.");
                return;
            }
            if (_roundInProgress) {
                SendReply(player, Prefix() + "A gamble round is already running!");
                return;
            }
            StartCountdown();
            BroadcastToAll(Prefix() + $"<color=#e3ffb6>Admin started a new gamble round!</color> Use <color=#ffb400>/gamble <scrap amount></color> to join.");
        }
        private void CheckAndStartRoundAutomatically() {
            if (!_roundInProgress) StartCountdown();
        }
        private void AddParticipant(string playerId, int amount) {
            _participants[playerId] = amount;
            _participantOrder.Add(playerId);
        }
        private void StartCountdown() {
            _roundInProgress = true;
            _timeLeft = _config.CountdownTime;
            BroadcastToAll(Prefix() + $"<color=#fff6b0>Gamble round started!</color> Use <color=#ffb400>/gamble <scrap amount></color> to enter.Winner in <color=#5cb85c>{FormatTime(_config.CountdownTime)}</color>.");
            _countdownTimer = timer.Every(1f, OnCountdownTick);
        }
        private void OnCountdownTick() {
            _timeLeft -= 1f;
            if (_timeLeft <= 0) {
                _countdownTimer.Destroy();
                EndRound();
                return;
            }
            if (_timeLeft == 60 || _timeLeft == 30 || _timeLeft == 10 || (_timeLeft <= 5 && _timeLeft > 0)) {
                BroadcastToAll(Prefix() + $"Gamble ends in <color=#dbb403>{(int)_timeLeft}</color> seconds! Use <color=#ffb400>/gamble <scrap amount></color> to join!");
            }
        }
        private void EndRound() {
            if (_participants.Count == 0) {
                _roundInProgress = false;
                BroadcastToAll(Prefix() + "<color=#ff9f9f>No one joined.No winner this round.</color>");
                return;
            }
            string winnerId = PickWinner();
            int totalPot = GetTotalPot();
            int winnerAmount = _participants[winnerId];
            float winnerChance = 100f * winnerAmount / totalPot;
            var winnerPlayer = BasePlayer.FindByID(Convert.ToUInt64(winnerId));
            var def = ItemManager.FindItemDefinition(_config.CurrencyShortName);
            if (winnerPlayer != null && winnerPlayer.IsConnected && winnerPlayer.inventory != null) {
                GiveItems(winnerPlayer, _config.CurrencyShortName, totalPot);
                BroadcastToAll(Prefix() + $"<color=#b6e2ff>{winnerPlayer.displayName}</color> wins <color=#dbb403>{totalPot} {def.displayName.translated}</color> with <color=#5cb85c>{winnerChance:0.0}%</color> odds! 🎉");
            }
            else {
                BroadcastToAll(Prefix() + $"The winner (ID: {winnerId}) is offline and did not receive the winnings.Their odds: {winnerChance:0.0}%.");
            }
            _roundInProgress = false;
            _participants.Clear();
            _participantOrder.Clear();
        }
        private string PickWinner() {
            int totalPot = GetTotalPot();
            int roll = _random.Next(1, totalPot + 1);
            int sum = 0;
            foreach (var entry in _participantOrder) {
                sum += _participants[entry];
                if (roll <= sum) return entry;
            }
            return _participantOrder[_random.Next(_participantOrder.Count)];
        }
        private int GetTotalPot() => _participants.Values.Sum();
        private void BroadcastToAll(string message) {
            if (_config.BroadcastToAll) PrintToChat(message);
            else Puts(message);
        }
        private string Prefix() => _config.BroadcastPrefix;
        private int RemoveItems(BasePlayer player, string shortname, int amount) {
            var def = ItemManager.FindItemDefinition(shortname);
            if (def == null || player?.inventory == null) return 0;
            int removed = 0;
            removed += TakeFromContainer(player.inventory.containerMain, def.itemid, amount - removed);
            if (removed < amount) removed += TakeFromContainer(player.inventory.containerBelt, def.itemid, amount - removed);
            if (removed < amount) removed += TakeFromContainer(player.inventory.containerWear, def.itemid, amount - removed);
            player.SendNetworkUpdate();
            return removed;
        }
        private int TakeFromContainer(ItemContainer container, int itemId, int amount) {
            int removed = 0;
            if (container == null || amount <= 0) return 0;
            foreach (var item in container.itemList.ToArray()) {
                if (item.info.itemid == itemId) {
                    int take = Math.Min(item.amount, amount - removed);
                    item.amount -= take;
                    removed += take;
                    item.MarkDirty();
                    if (item.amount <= 0) item.Remove();
                    if (removed >= amount) break;
                }
            }
            return removed;
        }
        private void GiveItems(BasePlayer player, string shortname, int amount) {
            var def = ItemManager.FindItemDefinition(shortname);
            if (def == null) return;
            var item = ItemManager.Create(def, amount);
            if (!item.MoveToContainer(player.inventory.containerMain)) if (!item.MoveToContainer(player.inventory.containerBelt)) if (!item.MoveToContainer(player.inventory.containerWear)) item.Drop(player.transform.position, Vector3.up);
            player.SendNetworkUpdate();
        }
        private string FormatTime(float seconds) {
            if (seconds >= 60f) return $"{Mathf.FloorToInt(seconds / 60f)} minute{(seconds >= 120f ? "s" : "")}";
            return $"{(int)seconds} seconds";
        }
    }
}

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