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

FREE CobaltCase : 1.0.0 1.0.0

Нет прав для скачивания
C#:
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Libraries.Covalence;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace Oxide.Plugins {
  enum CurrencyType { Scrap }

  [Info("Cobalt Case", "Forcet", "1.0.0")]
  class CobaltCase : RustPlugin {
    private const string CaseUI = "CaseUI";
    private const string LootConfigFile = "CobaltCase/lootconfig";

    private Dictionary<string, int> caseCosts = new Dictionary<string, int>();
    private Dictionary<string, List<LootEntry>> lootTables =
        new Dictionary<string, List<LootEntry>>();
    private DynamicConfigFile lootConfig;
    private Dictionary<ulong, bool> playerBuying =
        new Dictionary<ulong, bool>();  
    private Dictionary<ulong, Dictionary<string, bool>> playerLootReady =
        new Dictionary<ulong, Dictionary<string, bool>>();  
    private Dictionary<ulong,
                       Dictionary<string, DateTime>> playerLastPurchaseTime =
        new Dictionary<ulong,
                       Dictionary<string, DateTime>>(); 

    public class LootEntry {
      public string Item { get; set; }
      public int MinAmount { get; set; }
      public int MaxAmount { get; set; }
      public double Chance { get; set; }
      public int DelayMinutes { get; set; }
      public bool IsReady { get; set; }

      public LootEntry(string item, int minAmount, int maxAmount, double chance,
                       int delayMinutes, bool isReady) {
        Item = item;
        MinAmount = minAmount;
        MaxAmount = maxAmount;
        Chance = chance;
        DelayMinutes = delayMinutes;
        IsReady = false; 
      }
    }

    class ConfigData {
      public Dictionary<string, int> CaseCosts { get; set; }
      public Dictionary<string, List<LootEntry>> LootTables { get; set; }
    }

    private void Init() {
      permission.RegisterPermission("cobaltcase.use", this);
      lootConfig = Interface.Oxide.DataFileSystem.GetFile(LootConfigFile);
      LoadConfig();

      var timersData =
          Interface.Oxide.DataFileSystem.GetFile("CobaltCase/timers");
      if (timersData.Exists()) {
        var timerData = timersData.ReadObject<Dictionary<string, DateTime>>();
        foreach (var kvp in timerData) {
          var readyTime = kvp.Value;
          if (readyTime > DateTime.Now) {
            var parts = kvp.Key.Split('_');
            if (parts.Length == 2) {
              var playerID = ulong.Parse(parts[0]);
              var caseOption = parts[1];
              var delayMinutes = (int)(readyTime - DateTime.Now).TotalMinutes;
              timer.Once(delayMinutes * 60, () => {
              });
            }
          }
        }
      }
    }

    private void LoadConfig() {
      try {
        var lootData = lootConfig.ReadObject<ConfigData>();
        caseCosts = lootData.CaseCosts;

        if (caseCosts == null || caseCosts.Count == 0) {
          Puts("Error: Case costs dictionary is null or empty.");
          LoadDefaultConfig(); 
          return;
        }

        lootTables = lootData.LootTables;
      } catch (Exception ex) {
        Puts("Failed to load config: " + ex.Message);
        LoadDefaultConfig(); 
      }
    }

    private void LoadDefaultConfig() {
      var defaultLootConfig = new ConfigData {
        CaseCosts = new Dictionary<string, int> { ["ResourceCase"] = 1000,
                                                  ["MedicCase"] = 1500,
                                                  ["ArmorCase"] = 2000,
                                                  ["WeaponCase"] = 2500,
                                                  ["SmugglersCase"] = 3000 },
        LootTables =
            new Dictionary<string, List<LootEntry>> {
              ["ResourceCase"] =
                  new List<LootEntry> {
                    new LootEntry("gunpowder", 0, 500, 5.0, 20, false),
                    new LootEntry("sulfur", 0, 800, 15.0, 20, false),
                    new LootEntry("scrap", 0, 800, 20.0, 20, false),
                    new LootEntry("stones", 1, 2500, 25.0, 20, false),
                    new LootEntry("metal.ore", 1, 3500, 35.0, 20, false)
                  },
              ["MedicCase"] =
                  new List<LootEntry> {
                    new LootEntry("healingtea.pure", 0, 3, 45.0, 25, false),
                    new LootEntry("maxhealthtea.pure", 0, 2, 45.0, 25, false),
                    new LootEntry("largemedkit", 1, 5, 45.0, 25, false),
                    new LootEntry("syringe.medical", 1, 10, 45.0, 25, false),
                    new LootEntry("bandage", 1, 10, 45.0, 25, false)
                  },
              ["ArmorCase"] =
                  new List<LootEntry> {
                    new LootEntry("metal.facemask", 0, 3, 2.0, 30, false),
                    new LootEntry("metal.plate.torso", 0, 2, 5.0, 30, false),
                    new LootEntry("tactical.gloves", 0, 3, 10.0, 30, false),
                    new LootEntry("scientistsuit_heavy", 0, 1, 10.0, 30, false),
                    new LootEntry("coffeecan.helmet", 0, 2, 15.0, 30, false),
                    new LootEntry("roadsign.jacket", 0, 2, 20.0, 30, false),
                    new LootEntry("roadsign.kilt", 0, 2, 25.0, 30, false),
                    new LootEntry("hat.wolf", 0, 2, 30.0, 30, false),
                    new LootEntry("roadsign.gloves", 0, 2, 35.0, 30, false)
                  },
              ["WeaponCase"] =
                  new List<LootEntry> {
                    new LootEntry("multiplegrenadelauncher", 0, 1, 2.0,
                                  45, false),
                    new LootEntry("rocket.launcher.dragon", 0, 2, 5.0,
                                  45, false),
                    new LootEntry("smg.mp5", 0, 10, 10.0, 45, false),
                    new LootEntry("lmg.m249", 2000, 10000, 10.0, 45, false),
                    new LootEntry("rifle.bolt", 0, 2, 15.0, 45, false),
                    new LootEntry("hmlmg", 0, 2, 20.0, 45, false),
                    new LootEntry("rifle.lr300", 0, 2, 25.0, 45, false),
                    new LootEntry("shotgun.m4", 0, 2, 30.0, 45, false),
                    new LootEntry("rifle.ak", 0, 2, 35.0, 45, false)
                  },
              ["SmugglersCase"] =
                  new List<LootEntry> {
                    new LootEntry("explosive.timed", 0, 10, 2.0, 60, false),
                    new LootEntry("electric.generator.small", 0, 1, 5.0,
                                  60, false),
                    new LootEntry("scraptea.pure", 0, 10, 10.0, 60, false),
                    new LootEntry("gunpowder", 2000, 10000, 10.0, 60, false),
                    new LootEntry("oretea.pure", 0, 10, 15.0, 60, false),
                    new LootEntry("ammo.rocket.basic", 0, 10, 20.0, 60, false),
                    new LootEntry("cctv.camera", 0, 25, 25.0, 60, false),
                    new LootEntry("targeting.computer", 0, 10, 30.0, 60, false),
                    new LootEntry("computerstation", 0, 1, 35.0, 60, false),
                    new LootEntry("rifle.lr300", 1, 2, 35.0, 60, false),
                    new LootEntry("sulfur", 500, 1500, 35.0, 60, false),
                    new LootEntry("shotgun.m4", 0, 1, 40.0, 60, false)
                  }
            }
      };

      lootConfig.WriteObject(defaultLootConfig);
      LoadConfig(); 
    }

    private void SaveConfig() => lootConfig.Save();

    [ChatCommand("case")]
    private void OpenCaseUICommand(BasePlayer player, string cmd,
                                   string[] args) {
      if (!permission.UserHasPermission(player.UserIDString,
                                        "cobaltcase.use")) {
        SendReply(player, "You don't have permission to use this command.");
        return;
      }

      CreateCaseUI(player);
    }

    private void CreateCaseUI(BasePlayer player) {

      DestroyUI(player);

      var elements = new CuiElementContainer();
      var mainPanel = elements.Add(
          new CuiPanel {
            RectTransform = { AnchorMin = "0.2 0.2", AnchorMax = "0.8 0.8" },
            Image = { Color = "0.1 0.1 0.1 0.8" }, CursorEnabled = true
          },
          "Overlay", CaseUI);

      elements.Add(
          new CuiElement { Parent = CaseUI, Components = {
                            new CuiRawImageComponent {
                              Url = "https://imgur.com/SYupr1L.png",
                              Sprite = "assets/content/ui/uibackgroundblur.jpg"
                            },  // Replace with the URL of the background image
                            new CuiRectTransformComponent {
                              AnchorMin = "0 0", AnchorMax = "1 1"
                            }  
                          } });

      elements.Add(
          new CuiButton { RectTransform =
                              {
                                AnchorMin = "0.9 0.95", AnchorMax = "1 1"
                              },  
                          Button = { Command = "case.close",
                                     Color = "0.8 0.1 0.1 1" },  // Red color
                          Text = { Text = "✖", FontSize = 20,
                                   Align = TextAnchor.MiddleCenter } },
          mainPanel);

      float yPos = 0.6f;  


      foreach (var kvp in caseCosts) {

        var caseNameLabel = elements.Add(
            new CuiLabel {
              RectTransform =
                  {
                    AnchorMin = $"0.1 {yPos - 0.05}", AnchorMax = $"0.3 {yPos}"
                  },  
              Text = { Text = kvp.Key, FontSize = 16,
                       Align = TextAnchor.MiddleLeft }
            },
            mainPanel);

        elements.Add(
            new CuiButton { RectTransform = { AnchorMin = $"0.7 {yPos - 0.05}",
                                              AnchorMax = $"0.9 {yPos}" },
                            Button = { Command = $"case.buy {kvp.Key}",
                                       Color = "0.5 0 0 1" },  // Dark red color
                            Text = { Text = $"{kvp.Value} Scrap", FontSize = 16,
                                     Align = TextAnchor.MiddleCenter } },
            mainPanel);


        bool lootIsReady =
            playerLootReady.ContainsKey(player.userID) &&
            playerLootReady[player.userID].ContainsKey(kvp.Key) &&
            playerLootReady[player.userID][kvp.Key] &&
            GetLootEntries(player.userID, kvp.Key).Any(le => le.IsReady);

        var lootEntries = lootTables[kvp.Key];
        var arrivalTimeX =
            0.4f;  
        float delayMinutes =
            lootEntries[0].DelayMinutes;  
        elements.Add(
            new CuiLabel { RectTransform =
                               {
                                 AnchorMin = $"{arrivalTimeX} {yPos - 0.05}",
                                 AnchorMax = $"0.55 {yPos}"
                               }, 
                           Text = { Text = $"Arrival: {delayMinutes} mins",
                                    FontSize = 16,
                                    Align = TextAnchor.MiddleCenter } },
            mainPanel);

        if (lootIsReady) {

          elements.Add(
              new CuiButton {
                RectTransform = { AnchorMin = $"{arrivalTimeX} {yPos - 0.05}",
                                  AnchorMax = $"0.55 {yPos}" },
                Button = { Command = $"case.collect {kvp.Key}",
                           Color = "0.11 0.37 0.03 1" },
                Text = { Text = "Get Loot", FontSize = 16,
                         Align = TextAnchor.MiddleCenter }
              },
              mainPanel);
        }

        yPos -= 0.1f;  
      }

      CuiHelper.AddUi(player, elements);
    }

    [ConsoleCommand("case.collect")]
    private void CollectLoot(ConsoleSystem.Arg arg) {
      var player = arg.Player();
      if (player == null) {
        Puts("Error: Player is null.");
        return;
      }

      if (arg.Args.Length < 1) {
        SendReply(player, "Usage: case.collect <caseOption>");
        return;
      }

      var caseOption = arg.Args[0];
      if (!playerLootReady.ContainsKey(player.userID) ||
          !playerLootReady[player.userID].ContainsKey(caseOption) ||
          !playerLootReady[player.userID][caseOption]) {
        SendReply(
            player,
            "Your loot is not ready yet or you have no loot for this case.");
        return;
      }

      var lootEntries = GetLootEntries(player.userID, caseOption)
                            .Where(entry => entry.IsReady)
                            .ToList();
      if (lootEntries.Count == 0) {
        SendReply(
            player,
            "There seems to be an error with your loot. Please contact an admin.");
        return;
      }

      foreach (var lootEntry in lootEntries) {
        var itemDefinition = ItemManager.FindItemDefinition(lootEntry.Item);
        if (itemDefinition == null) {
          SendReply(
              player,
              $"Error: Item definition not found for item '{lootEntry.Item}'");
          continue;
        }

        var amount = UnityEngine.Random.Range(lootEntry.MinAmount,
                                              lootEntry.MaxAmount + 1);
        var item = ItemManager.Create(itemDefinition, amount, 0uL);
        if (item == null) {
          Puts($"Error: Failed to create item '{lootEntry.Item}'");
          continue;
        }

        if (!player.inventory.GiveItem(item)) {
          item.Drop(player.GetDropPosition(), player.GetDropVelocity());
          SendReply(
              player,
              $"Your inventory was full. Your {item.info.displayName.english} has been dropped at your feet.");
        } else {
          SendReply(
              player,
              $"You have received {amount} x {item.info.displayName.english}.");
        }
        lootEntry.IsReady = false;
      }
      DestroyUI(player);

    }

    private void RefreshCaseUI(BasePlayer player) {
      DestroyUI(player);
      CreateCaseUI(player);
    }

    [ConsoleCommand("case.buy")]
    private void BuyCase(ConsoleSystem.Arg arg) {
      var player = arg.Player();
      if (player == null || arg.Args.Length != 1)
        return;

      var playerID = player.userID;
      if (playerBuying.ContainsKey(playerID) && playerBuying[playerID]) {
        SendReply(
            player,
            "Your guys are still on their way. Please wait until they return.");
        return;
      }

      var caseOption = arg.Args[0];
      if (!caseCosts.ContainsKey(caseOption))
        return;

      var cost = caseCosts[caseOption];
      if (!HasEnoughScrap(player, cost))
        return;  
	
      if (playerLastPurchaseTime.ContainsKey(playerID)) {
        foreach (var kvp in playerLastPurchaseTime[playerID]) {
          var lastPurchaseTime = kvp.Value;
          var caseName = kvp.Key;
          var currentTime = DateTime.Now;
          var purchaseCooldown = TimeSpan.FromMinutes(
              lootTables[caseName][0]
                  .DelayMinutes);  
				  
          var timeRemaining =
              lastPurchaseTime.Add(purchaseCooldown) - currentTime;
          if (timeRemaining.TotalSeconds > 0) {
            SendReply(
                player,
                $"You must wait {timeRemaining.Minutes} minutes and {timeRemaining.Seconds} seconds before sending The Cobalt Scientists out again.");
            return;
          }
        }
      }


      playerBuying[playerID] = true;

      TakeScrap(player, cost);
      DistributeItems(player, caseOption);


      if (!playerLastPurchaseTime.ContainsKey(playerID))
        playerLastPurchaseTime[playerID] = new Dictionary<string, DateTime>();

      playerLastPurchaseTime[playerID][caseOption] = DateTime.Now;

      Effect.server.Run("assets/bundled/prefabs/fx/invite_notice.prefab",
                        player.transform.position);

      SendReply(player, "The CobaltScientists have been dispatched.");

      playerBuying[playerID] = false;

      DestroyUI(player);
    }

    private int GetDelayMinutes(string caseOption) {
      if (lootTables.ContainsKey(caseOption) &&
          lootTables[caseOption].Count > 0) {
        return lootTables[caseOption][0]
            .DelayMinutes;  
                           
      }
      return 0; 
    }

    private bool HasEnoughScrap(BasePlayer player, int amount) {
      var scrapAmount = GetScrapAmount(player);
      if (scrapAmount < amount) {
        SendReply(
            player,
            $"You do not have enough scrap. You need {amount - scrapAmount} more scrap.");
        return false;
      }
      return true;
    }

    [ConsoleCommand("case.close")]
    private void CloseCaseUI(ConsoleSystem.Arg arg) {
      var player = arg.Player();
      if (player == null)
        return;

      DestroyUI(player);
    }

    private void DestroyUI(BasePlayer player) {
      CuiHelper.DestroyUi(player, CaseUI);
    }

    private int GetScrapAmount(BasePlayer player) {
      var inventory = player.inventory;
      if (inventory == null) {
        Puts("Error: Player inventory not found.");
        return 0;
      }

      var scrapItem = ItemManager.FindItemDefinition("scrap");
      if (scrapItem == null) {
        Puts("Error: Scrap item definition not found.");
        return 0;
      }

      return inventory.GetAmount(scrapItem.itemid);
    }

    private void TakeScrap(BasePlayer player, int amount) {
      var inventory = player.inventory;
      if (inventory == null) {
        Puts("Error: Player inventory not found.");
        return;
      }

      var scrapItem = ItemManager.FindItemDefinition("scrap");
      if (scrapItem == null) {
        Puts("Error: Scrap item definition not found.");
        return;
      }

      var scrapAmount = GetScrapAmount(player);
      if (scrapAmount < amount) {
        SendReply(
            player,
            $"You do not have enough scrap. You need {amount - scrapAmount} more scrap.");
        return;
      }

      inventory.Take(null, scrapItem.itemid, amount);
    }

    private void DistributeItems(BasePlayer player, string caseOption) {
      int counter = 1;
      var lootEntries = GetLootEntries(player.userID, caseOption);

      if (!lootTables.ContainsKey(caseOption)) {
        Puts($"Error: Loot table not found for case option '{caseOption}'");
        return;
      }

      var selectedEntries =
          lootTables[caseOption].OrderBy(x => Guid.NewGuid()).Take(4).ToList();

      foreach (var entry in selectedEntries) {

        var delayMinutes = entry.DelayMinutes;


        var readyTime = DateTime.Now.AddMinutes(delayMinutes);
        var key = $"{player.userID}_{caseOption}";
        Interface.Oxide.DataFileSystem.WriteObject($"CobaltCase/timers/{key}",
                                                   readyTime);

        timer.Once(delayMinutes * 60, () => {

          entry.IsReady = true;

          if (!playerLootReady.ContainsKey(player.userID)) {
            playerLootReady[player.userID] = new Dictionary<string, bool>();
          }

          playerLootReady[player.userID][caseOption] = true;

          if (counter == 1) {

            Effect.server.Run("assets/bundled/prefabs/fx/invite_notice.prefab",
                              player.transform.position);
            SendReply(player,
                      $"Your loot for {caseOption} is now ready to collect!");

            counter = 0;
          }
        });
      }
    }

    private List<LootEntry> GetLootEntries(ulong playerId, string caseOption) {
      if (playerLootReady.ContainsKey(playerId) &&
          playerLootReady[playerId].ContainsKey(caseOption)) {
        return lootTables[caseOption];
      }

      return new List<LootEntry>();
    }

    private Dictionary<string, List<LootEntry>> GetLootTables() {
      try {
        var configData = lootConfig.ReadObject<ConfigData>();
        return configData?.LootTables ??
               new Dictionary<string, List<LootEntry>>();
      } catch (Exception ex) {
        Puts("Failed to load loot tables: " + ex.Message);
        return new Dictionary<string, List<LootEntry>>();
      }
    }

    private void SaveLootEntries(ulong playerId, string caseOption,
                                 List<LootEntry> lootEntries) {
      var lootTable = GetLootTables();
      lootTable[caseOption] = lootEntries;
      SaveConfig();  
    }

    private void Unload() {
      foreach (var player in BasePlayer.activePlayerList) {
        CuiHelper.DestroyUi(player, CaseUI);
      }
    }
  }
}

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