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

FREE NWGSkills : 1.0.0 1.0.0

Нет прав для скачивания
C#:
// Forced Recompile: 2026-02-07 11:15
using System;
using System.Collections.Generic;
using System.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Plugins;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using Newtonsoft.Json;

namespace Oxide.Plugins
{
    [Info("NWGSkills", "NWG Team", "1.0.0")]
    [Description("Gathering skill trees and blueprint unlocks.")]
    public class NWGSkills : RustPlugin
    {
#region Data
        private class PlayerData
        {
            public float WoodXP = 0;
            public float StoneXP = 0;
            public float OreXP = 0;
            public float CombatXP = 0;
            public float SurvivalXP = 0;
            public int SkillPoints = 0;
            public int Level = 1;
            public HashSet<string> UnlockedSkills = new HashSet<string>();
        }

#region Config
        private class SkillDef
        {
            public string Name; // Display Name
            public int Cost;
            public string ItemShortname; // Item to unlock BP for
        }

        private class PluginConfig
        {
            public Dictionary<string, SkillDef> Skills = new Dictionary<string, SkillDef>();
        }
        private PluginConfig _config;

        protected override void LoadDefaultConfig()
        {
            _config = new PluginConfig();
            _config.Skills = new Dictionary<string, SkillDef>
            {
                ["unlock.chainsaw"] = new SkillDef { Name = "Chainsaw BP", Cost = 5, ItemShortname = "chainsaw" },
                ["unlock.jackhammer"] = new SkillDef { Name = "Jackhammer BP", Cost = 5, ItemShortname = "jackhammer" },
                ["unlock.quarry"] = new SkillDef { Name = "Quarry BP", Cost = 10, ItemShortname = "mining.quarry" },
                ["unlock.turbine"] = new SkillDef { Name = "Wind Turbine BP", Cost = 15, ItemShortname = "wind.turbine" }
            };
            SaveConfig();
        }

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

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

#region Localization
        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["LevelUp"] = "<color=#b7d092>[NWG]</color> <color=#b7d092>+1 Level!</color> (Level {0}) and +1 Skill Point in <color=#FFA500>{1}</color>!",
                ["UI.Title"] = "SURVIVAL SKILLS",
                ["UI.Points"] = "AVAILABLE POINTS: <color=#b7d092>{0}</color>",
                ["UI.Branch.Gather"] = "GATHERING",
                ["UI.Branch.Build"] = "CONSTRUCTION",
                ["UI.Branch.Adv"] = "ADVANCED",
                ["UI.Locked"] = "Locked...",
                ["Msg.Unlocked"] = "<color=#b7d092>[NWG]</color> Successfully unlocked <color=#FFA500>{0}</color>!",
                ["Msg.NoPoints"] = "<color=#d9534f>[NWG]</color> Not enough skill points.",
                ["Msg.AlreadyUnlocked"] = "<color=#d9534f>[NWG]</color> You already unlocked this skill.",
                ["Msg.Item precise"] = "<color=#b7d092>[NWG]</color> Blueprint for <color=#FFA500>{0}</color> unlocked!"
            }, this);
        }
        private string GetMessage(string key, string userId, params object[] args) => string.Format(lang.GetMessage(key, this, userId), args);
#endregion

        public class UIConstants
        {
            public const string Panel = "0.15 0.15 0.15 0.98"; 
            public const string Header = "0.1 0.1 0.1 1"; 
            public const string Primary = "0.718 0.816 0.573"; // Sage Green (Raw RGB for alpha mixing)
            public const string Accent = "0.851 0.325 0.31"; // Red
            public const string Text = "0.867 0.867 0.867 1";
        }

        private Dictionary<ulong, PlayerData> _playerData = new Dictionary<ulong, PlayerData>();

        private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject("NWG_Skills", _playerData);
        private void LoadData() => _playerData = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, PlayerData>>("NWG_Skills") ?? new Dictionary<ulong, PlayerData>();
#endregion

#region Lifecycle
        private void Init()
        {
            LoadData();
        }

        private void Unload() => SaveData();

        private void OnServerSave() => SaveData();

        private void OnPlayerConnected(BasePlayer player)
        {
            if (!_playerData.ContainsKey(player.userID))
                _playerData[player.userID] = new PlayerData();
        }
#endregion

#region Gathering & Combat Hooks
        private void OnDispenserGather(ResourceDispenser dispenser, BaseEntity entity, Item item)
        {
            var player = entity as BasePlayer;
            if (player == null) return;

            string category = dispenser.gatherType.ToString();
            float xpGain = item.amount * 0.15f; // Buffed XP slightly

            var data = GetPlayerData(player.userID);
            string label = "";

            if (category == "Tree") { data.WoodXP += xpGain; label = "Woodcutting"; }
            else if (category == "Ore") { data.OreXP += xpGain; label = "Mining"; }
            else if (category == "Stone") { data.StoneXP += xpGain; label = "Quarrying"; }
            
            CheckLevelUp(player, data, label);
        }

        private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
        {
            var attacker = info?.Initiator as BasePlayer;
            if (attacker == null || entity == null) return;

            var data = GetPlayerData(attacker.userID);

            // Combat XP for hitting hostile NPCs or other players
            if (entity is BaseNpc || entity is BasePlayer && entity != attacker)
            {
                float xpGain = info.damageTypes.Total() * 0.5f;
                data.CombatXP += xpGain;
                CheckLevelUp(attacker, data, "Combat");
            }
            // Survival XP for hitting barrels, crates, etc.
            else if (entity is LootContainer || (entity.ShortPrefabName.Contains("barrel") || entity.ShortPrefabName.Contains("crate")))
            {
                float xpGain = info.damageTypes.Total() * 0.2f;
                data.SurvivalXP += xpGain;
                CheckLevelUp(attacker, data, "Survival");
            }
        }

        private void CheckLevelUp(BasePlayer player, PlayerData data, string label)
        {
            const float XP_PER_POINT = 1000f;
            bool leveled = false;

            if (data.WoodXP >= XP_PER_POINT) { data.WoodXP -= XP_PER_POINT; leveled = true; }
            if (data.StoneXP >= XP_PER_POINT) { data.StoneXP -= XP_PER_POINT; leveled = true; }
            if (data.OreXP >= XP_PER_POINT) { data.OreXP -= XP_PER_POINT; leveled = true; }
            if (data.CombatXP >= XP_PER_POINT) { data.CombatXP -= XP_PER_POINT; leveled = true; }
            if (data.SurvivalXP >= XP_PER_POINT) { data.SurvivalXP -= XP_PER_POINT; leveled = true; }

            if (leveled)
            {
                data.SkillPoints++;
                data.Level++;
                data.SkillPoints++;
                data.Level++;
                player.ChatMessage(GetMessage("LevelUp", player.UserIDString, data.Level, label));
            }
        }

        private PlayerData GetPlayerData(ulong uid)
        {
            if (!_playerData.TryGetValue(uid, out var data))
                _playerData[uid] = data = new PlayerData();
            return data;
        }
#endregion

#region UI
        [ChatCommand("skills")]
        private void CmdSkills(BasePlayer player)
        {
            ShowSkillsUI(player);
        }

        [ConsoleCommand("skills.close")]
        private void ConsoleClose(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player != null) CuiHelper.DestroyUi(player, "NWG_Skills_UI");
        }

        private void ShowSkillsUI(BasePlayer player)
        {
            CuiHelper.DestroyUi(player, "NWG_Skills_UI");
            var elements = new CuiElementContainer();
            var data = GetPlayerData(player.userID);

            var root = elements.Add(new CuiPanel {
                Image = { Color = UIConstants.Panel },
                RectTransform = { AnchorMin = "0.1 0.1", AnchorMax = "0.9 0.9" },
                CursorEnabled = true
            }, "Overlay", "NWG_Skills_UI");

            // Header
            elements.Add(new CuiPanel {
                Image = { Color = UIConstants.Header },
                RectTransform = { AnchorMin = "0 0.92", AnchorMax = "1 1" }
            }, root);

            elements.Add(new CuiLabel {
                Text = { Text = GetMessage("UI.Title", player.UserIDString), FontSize = 24, Align = TextAnchor.MiddleLeft, Font = "robotocondensed-bold.ttf", Color = UIConstants.Text },
                RectTransform = { AnchorMin = "0.02 0.92", AnchorMax = "0.5 1" }
            }, root);

            elements.Add(new CuiLabel {
                Text = { Text = GetMessage("UI.Points", player.UserIDString, data.SkillPoints), FontSize = 18, Align = TextAnchor.MiddleRight, Font = "robotocondensed-bold.ttf", Color = UIConstants.Text },
                RectTransform = { AnchorMin = "0.5 0.92", AnchorMax = "0.98 1" }
            }, root);

            // Close Button
            elements.Add(new CuiButton {
                Button = { Command = "skills.close", Color = $"{UIConstants.Accent} 0.9" },
                RectTransform = { AnchorMin = "0.96 0.94", AnchorMax = "0.99 0.98" },
                Text = { Text = "✕", FontSize = 16, Align = TextAnchor.MiddleCenter }
            }, root);

            // --- BRANCHED TREE LAYOUT ---
            
            // Branch 1: Gathering (Left)
            float gatherX = 0.15f;
            AddBranchHeader(elements, root, GetMessage("UI.Branch.Gather", player.UserIDString), gatherX, 0.85f);
            AddSkillNodeTree(elements, root, "unlock.chainsaw", gatherX, 0.70f, player);
            AddSkillTreeLink(elements, root, gatherX, 0.65f, gatherX, 0.58f);
            AddSkillNodeTree(elements, root, "unlock.jackhammer", gatherX, 0.53f, player);

            // Branch 2: Construction (Center)
            float constrX = 0.50f;
            AddBranchHeader(elements, root, GetMessage("UI.Branch.Build", player.UserIDString), constrX, 0.85f);
            AddSkillNodeTree(elements, root, "unlock.quarry", constrX, 0.70f, player);
            AddSkillTreeLink(elements, root, constrX, 0.65f, constrX, 0.58f);
            AddSkillNodeTree(elements, root, "unlock.turbine", constrX, 0.53f, player);

            // Branch 3: Coming Soon (Right)
            float soonX = 0.85f;
            AddBranchHeader(elements, root, GetMessage("UI.Branch.Adv", player.UserIDString), soonX, 0.85f);
            // Example placeholder
            
            CuiHelper.AddUi(player, elements);
        }

        private void AddBranchHeader(CuiElementContainer container, string parent, string text, float x, float y)
        {
            container.Add(new CuiLabel {
                Text = { Text = text, Align = TextAnchor.MiddleCenter, FontSize = 14, Font = "robotocondensed-bold.ttf", Color = $"{UIConstants.Primary} 1" },
                RectTransform = { AnchorMin = $"{x - 0.12f} {y - 0.05f}", AnchorMax = $"{x + 0.12f} {y}" }
            }, parent);
        }

        private void AddSkillTreeLink(CuiElementContainer container, string parent, float x1, float y1, float x2, float y2)
        {
            container.Add(new CuiPanel {
                Image = { Color = "0.3 0.3 0.3 0.5" },
                RectTransform = { AnchorMin = $"{x1 - 0.002f} {y2}", AnchorMax = $"{x1 + 0.002f} {y1}" }
            }, parent);
        }

        private void AddSkillNodeTree(CuiElementContainer container, string parent, string id, float x, float y, BasePlayer player)
        {
            var data = GetPlayerData(player.userID);
            bool unlocked = data.UnlockedSkills.Contains(id);
            
            string name = id;
            int cost = 0;
            if (_config.Skills.TryGetValue(id, out var def))
            {
                name = def.Name;
                cost = def.Cost;
            }
            else
            {
                // Fallback for missing config or locked placeholders
                name = GetMessage("UI.Locked", player.UserIDString);
                cost = 999;
            }
            
            string color = unlocked ? $"{UIConstants.Primary} 0.8" : (data.SkillPoints >= cost ? "0.15 0.15 0.15 0.8" : "0.3 0.1 0.1 0.8");
            string btnText = unlocked ? $"<color=#b7d092>✓</color> {name}" : $"{name}\n<color=#999>{cost} pts</color>";
            string cmd = (unlocked || cost > 999) ? "" : $"skills.unlock {id} {cost}";

            container.Add(new CuiButton {
                Button = { Command = cmd, Color = color },
                RectTransform = { AnchorMin = $"{x - 0.1f} {y - 0.06f}", AnchorMax = $"{x + 0.1f} {y + 0.06f}" },
                Text = { Text = btnText, Align = TextAnchor.MiddleCenter, FontSize = 12, Font = "robotocondensed-bold.ttf", Color = UIConstants.Text }
            }, parent);
        }

        [ConsoleCommand("skills.unlock")]
        private void ConsoleUnlock(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null) return;

            string id = arg.GetString(0);

            var data = GetPlayerData(player.userID);
            if (data.UnlockedSkills.Contains(id)) 
            {
                player.ChatMessage(GetMessage("Msg.AlreadyUnlocked", player.UserIDString));
                return;
            }

            if (!_config.Skills.TryGetValue(id, out var def)) return;
            
            if (data.SkillPoints >= def.Cost)
            {
                data.SkillPoints -= def.Cost;
                data.UnlockedSkills.Add(id);
                UnlockBlueprint(player, def);
                player.ChatMessage(GetMessage("Msg.Unlocked", player.UserIDString, def.Name));
                ShowSkillsUI(player);
            }
            else
            {
                player.ChatMessage(GetMessage("Msg.NoPoints", player.UserIDString));
            }
        }

        private void UnlockBlueprint(BasePlayer player, SkillDef skill)
        {
            if (string.IsNullOrEmpty(skill.ItemShortname)) return;
            var itemDef = ItemManager.FindItemDefinition(skill.ItemShortname);
            if (itemDef != null)
            {
                 player.blueprints.Unlock(itemDef);
            }
        }

        [HookMethod("GetLevel")]
        public int API_GetLevel(ulong uid) => GetPlayerData(uid).Level;
#endregion
    }
}

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