C#:
using Facepunch.Extend;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("LightRPG", "Frizen", "1.0.0")]
internal class LightRPG : RustPlugin
{
#region Vars and sub classes
[PluginReference]
private Plugin ImageLibrary;
private const float _fadeout = 0.25f;
private const float _fadein = 1f;
private static LightRPG _ins;
public class Level
{
[JsonProperty("Уникальный идентификатор уровня")]
public string UniqueIdentify { get; set; }
[JsonProperty("Количество опыта необходимое для открытия данного уровня")]
public int ExpNeed { get; set; }
[JsonProperty("Предмет открывающийся при достижении")]
public RewardItem Item { get; set; }
public void TakeItem(BasePlayer player)
{
var data = PluginData.DataObject.GetOrAdd(player);
if (data == null) return;
if (data.TakedLevels.Contains(UniqueIdentify)) return;
Item.TakeItem(player);
data.TakedLevels.Add(UniqueIdentify);
_ins.MainUI(player);
}
}
public class RewardItem
{
[JsonProperty("Количество выдаваемого предмета")]
public float Amount { get; set; }
[JsonProperty("Шортнейм")]
public string ShortName { get; set; }
public RewardItem(float amount, string shortName)
{
Amount = amount;
ShortName = shortName;
}
public void TakeItem(BasePlayer player)
{
var loot = ItemManager.CreateByName(ShortName, (int)Amount);
player.GiveItem(loot, BaseEntity.GiveItemReason.PickedUp);
}
}
#endregion
#region Config
private PluginConfig _config;
protected override void LoadDefaultConfig()
{
_config = PluginConfig.DefaultConfig();
}
protected override void LoadConfig()
{
base.LoadConfig();
_config = Config.ReadObject<PluginConfig>();
if (_config.PluginVersion < Version)
UpdateConfigValues();
Config.WriteObject(_config, true);
}
private void UpdateConfigValues()
{
PluginConfig baseConfig = PluginConfig.DefaultConfig();
if (_config.PluginVersion < Version)
{
_config.PluginVersion = Version;
PrintWarning("Config checked completed!");
}
_config.PluginVersion = Version;
}
protected override void SaveConfig()
{
Config.WriteObject(_config);
}
private class PluginConfig
{
[JsonProperty("Награда за убийство игрока")]
public float PlayerKillAward { get; set; }
[JsonProperty("Награда за убийство нпс")]
public float NpcKillAward { get; set; }
[JsonProperty("Награда за ящики/бочки")]
public float ContainerAward { get; set; }
[JsonProperty("Награда за фарм")]
public Dictionary<string, float> FarmAwards { get; set; }
[JsonProperty("Список уровней")]
public List<Level> Levels { get; set; }
[JsonProperty("Config version")]
public VersionNumber PluginVersion = new VersionNumber();
public static PluginConfig DefaultConfig()
{
return new PluginConfig()
{
PlayerKillAward = 20,
NpcKillAward = 20,
ContainerAward = 20,
FarmAwards = new Dictionary<string, float>()
{
["stones"] = 20,
["sulfur.ore"] = 15,
["metal.ore"] = 15,
["wood"] = 15
},
Levels = new List<Level>()
{
new Level
{
ExpNeed = 250,
Item = new RewardItem(10, "metal.refined"),
UniqueIdentify = CuiHelper.GetGuid()
},
new Level
{
ExpNeed = 500,
Item = new RewardItem(20, "hammer"),
UniqueIdentify = CuiHelper.GetGuid()
},
new Level
{
ExpNeed = 600,
Item = new RewardItem(20, "hammer"),
UniqueIdentify = CuiHelper.GetGuid()
},
new Level
{
ExpNeed = 700,
Item = new RewardItem(20, "hammer"),
UniqueIdentify = CuiHelper.GetGuid()
},
new Level
{
ExpNeed = 289,
Item = new RewardItem(20, "hammer"),
UniqueIdentify = CuiHelper.GetGuid()
},
new Level
{
ExpNeed = 384,
Item = new RewardItem(20, "hammer"),
UniqueIdentify = CuiHelper.GetGuid()
},
new Level
{
ExpNeed = 565,
Item = new RewardItem(20, "hammer"),
UniqueIdentify = CuiHelper.GetGuid()
},
new Level
{
ExpNeed = 900,
Item = new RewardItem(20, "hammer"),
UniqueIdentify = CuiHelper.GetGuid()
},
},
PluginVersion = new VersionNumber()
};
}
}
#endregion
#region Data
private static PluginData _data;
private void LoadData()
{
try
{
_data = Interface.Oxide.DataFileSystem.ReadObject<PluginData>(this.Name);
}
catch (Exception e)
{
PrintError(e.ToString());
}
if (_data == null) _data = new PluginData();
}
private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject(this.Name, _data);
private class PluginData
{
public Dictionary<ulong, DataObject> PlayerData = new Dictionary<ulong, DataObject>();
internal class DataObject
{
[JsonProperty("Текущий уровень")]
public int CurrentLevel { get; set; }
[JsonProperty("Текущий опыт")]
public float CurrentExp { get; set; }
[JsonProperty("Полученные награды")]
public List<string> TakedLevels { get; set; }
public static DataObject GetOrAdd(BasePlayer player)
{
return GetOrAdd(player.userID);
}
public static DataObject GetOrAdd(ulong userId)
{
if (!_data.PlayerData.ContainsKey(userId))
_data.PlayerData.Add(userId, new DataObject
{
CurrentExp = 0,
CurrentLevel = 0,
TakedLevels = new List<string>()
{
"0"
}
});
return _data.PlayerData[userId];
}
}
}
#endregion
#region Methods
private void AddExp(BasePlayer player, float amount)
{
var data = PluginData.DataObject.GetOrAdd(player);
if (data == null) return;
data.CurrentExp += amount;
if (data.CurrentLevel < _config.Levels.Count && data.CurrentExp >= _config.Levels[data.CurrentLevel].ExpNeed)
{
data.CurrentExp -= _config.Levels[data.CurrentLevel].ExpNeed;
data.CurrentLevel += 1;
}
DrawExp(player);
DrawNotify(player, amount);
}
#region ImageLibrary
public bool AddImage(string url, string imageName, ulong imageId = 0) => (bool)ImageLibrary.Call("AddImage", url, imageName, imageId);
public string GetImage(string shortname) => (string)ImageLibrary.Call("GetImage", shortname);
#endregion
#region Helpers
private static string HexToRustFormat(string hex)
{
if (string.IsNullOrEmpty(hex)) hex = "#FFFFFFFF";
var str = hex.Trim('#');
if (str.Length == 6) str += "FF";
if (str.Length != 8)
{
throw new Exception(hex);
throw new InvalidOperationException("Cannot convert a wrong format.");
}
var r = byte.Parse(str.Substring(0, 2), NumberStyles.HexNumber);
var g = byte.Parse(str.Substring(2, 2), NumberStyles.HexNumber);
var b = byte.Parse(str.Substring(4, 2), NumberStyles.HexNumber);
var a = byte.Parse(str.Substring(6, 2), NumberStyles.HexNumber);
Color color = new Color32(r, g, b, a);
return string.Format("{0:F2} {1:F2} {2:F2} {3:F2}", color.r, color.g, color.b, color.a);
}
#endregion
#endregion
#region Hooks
private void OnServerInitialized()
{
AddImage("https://i.imgur.com/KWaH1Ko.png", "UpgradeSprite");
AddImage("https://i.imgur.com/6d0TEvT.png", "BGTaked");
AddImage("https://i.imgur.com/TSbN6ID.png", "BGCanTake");
AddImage("https://i.imgur.com/MIFMJmp.png", "BGUnavaible");
AddImage("https://i.imgur.com/v4Ix05O.png", "Viniette");
LoadData();
foreach (var player in BasePlayer.activePlayerList)
{
OnPlayerConnected(player);
}
_ins = this;
}
private void Unload()
{
foreach (var item in BasePlayer.activePlayerList)
{
CuiHelper.DestroyUi(item, "ExpPanel");
}
SaveData();
_ins = null;
}
private void OnServerSave()
{
SaveData();
}
private void OnPlayerConnected(BasePlayer player)
{
PluginData.DataObject.GetOrAdd(player);
DrawExp(player);
}
object OnPlayerDeath(BasePlayer player, HitInfo info)
{
if (player == null || info == null || info.InitiatorPlayer == null) return null;
if(info.InitiatorPlayer.userID != player.userID)
{
AddExp(info.InitiatorPlayer, _config.PlayerKillAward);
}
return null;
}
void OnDispenserBonus(ResourceDispenser dispenser, BasePlayer player, Item item)
{
if (player == null || item == null || dispenser == null) return;
if (_config.FarmAwards.ContainsKey(item.info.shortname))
{
AddExp(player, _config.FarmAwards[item.info.shortname]);
}
return;
}
private void OnEntityDeath(LootContainer entity, HitInfo info)
{
if (entity == null) return;
if (info == null) return;
if (!entity.ShortPrefabName.Contains("barrel")) return;
if (info.InitiatorPlayer == null) return;
var player = info.InitiatorPlayer;
AddExp(player, _config.ContainerAward);
}
private void OnLootEntityEnd(BasePlayer player, BaseCombatEntity entity)
{
if (player == null) return;
if (entity == null) return;
if (entity.OwnerID != 0) return;
if (entity.GetComponentInChildren<LootContainer>() == null) return;
if(entity.GetComponentInChildren<LootContainer>().inventory.IsEmpty())
{
AddExp(player, _config.ContainerAward);
}
}
#endregion
#region UI
private void MainUI(BasePlayer player, int page = 0)
{
var container = new CuiElementContainer();
var data = PluginData.DataObject.GetOrAdd(player);
if (data == null) return;
container.Add(new CuiPanel
{
CursorEnabled = true,
RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" },
Image = { Color = "0 0 0 0.5", Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat" }
}, "Overlay", "MainBG");
container.Add(new CuiElement
{
Parent = "MainBG",
Name = "Viniette",
Components =
{
new CuiRawImageComponent{Color = "1 1 1 1", Png = ImageLibrary.Call<string>("GetImage", "Viniette")},
new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1" }
}
});
container.Add(new CuiElement
{
Parent = "MainBG",
Name = "BG",
Components =
{
new CuiRawImageComponent{Color = "1 1 1 0"},
new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1" }
}
});
container.Add(new CuiButton
{
RectTransform =
{
AnchorMin = "0 0",
AnchorMax= "1 1"
},
Text =
{
Text = "",
},
Button =
{
Color = "0 0 0 0",
Close = "MainBG",
}
}, "BG");
container.Add(new CuiPanel
{
CursorEnabled = false,
Image = { Color = "1 1 1 0" },
RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-385.441 -130.108", OffsetMax = "385.415 129.964" }
}, "BG", "MainUI");
container.Add(new CuiPanel
{
CursorEnabled = false,
Image = { Color = $"{HexToRustFormat("#29222259")}" },
RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-385.423 39.864", OffsetMax = "385.426 130.038" }
}, "MainUI", "TitlePanel");
container.Add(new CuiPanel
{
CursorEnabled = false,
Image = { Color = "0 0 0 0.6", Material = "assets/content/ui/uibackgroundblur-notice.mat" },
RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" }
}, "TitlePanel", "BlurTitle");
container.Add(new CuiElement
{
Name = "Title",
Parent = "TitlePanel",
Components = {
new CuiTextComponent { Text = "МЕНЮ УРОВНЕЙ MAGIX RUST", Font = "robotocondensed-bold.ttf", FontSize = 25, Align = TextAnchor.MiddleLeft, Color = "1 1 1 0.6" },
new CuiRectTransformComponent { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-361.569 -5.974", OffsetMax = "385.425 27.174" }
}
});
container.Add(new CuiElement
{
Name = "Desc",
Parent = "TitlePanel",
Components = {
new CuiTextComponent { Text = "Прокачивай свой уровень и получай крутые награды!", Font = "robotocondensed-bold.ttf", FontSize = 15, Align = TextAnchor.MiddleLeft, Color = "1 1 1 0.4" },
new CuiRectTransformComponent { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-361.569 -28.174", OffsetMax = "385.425 4.974" }
}
});
var dict = _config.Levels.ToList();
int CountPage = dict.Skip(8 * (page + 1)).Take(8).Count();
container.Add(new CuiButton
{
Button = { Color = $"{HexToRustFormat("#29222259")}", Command = page != 0 ? $"rpg.skip {page - 1}" : "", Sprite = "Assets/Content/UI/UI.Background.Tile.psd" },
Text = { Text = "<", Font = "robotocondensed-bold.ttf", FontSize = 25, Align = TextAnchor.MiddleCenter, Color = "1 1 1 0.6" },
RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-385.421 -130.039", OffsetMax = "-340.123 -84.461" }
}, "MainUI", "Left");
container.Add(new CuiButton
{
Button = { Color = $"{HexToRustFormat("#29222259")}", Command = CountPage != 0 ? $"rpg.skip {page + 1}" : "", Sprite = "Assets/Content/UI/UI.Background.Tile.psd" },
Text = { Text = ">", Font = "robotocondensed-bold.ttf", FontSize = 25, Align = TextAnchor.MiddleCenter, Color = "1 1 1 0.6" },
RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "340.131 -130.039", OffsetMax = "385.429 -84.461" }
}, "MainUI", "Right");
double offsetminx = -385.43, offsetmaxx = -295.776, margin = 97.273;
int i = 0;
foreach (var item in dict.Skip(page * 8).Take(8))
{
container.Add(new CuiPanel
{
CursorEnabled = false,
Image = { Color = "1 1 1 0" },
RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = $"{offsetminx} -76.721", OffsetMax = $"{offsetmaxx} 33.042" }
}, "MainUI", "Level");
container.Add(new CuiPanel
{
CursorEnabled = false,
Image = { Color = $"{HexToRustFormat("#29222259")}" },
RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-44.827 -54.882", OffsetMax = "44.827 34.777" }
}, "Level", "PanelBG");
container.Add(new CuiElement
{
Name = "ItemIcon",
Parent = "PanelBG",
Components = {
new CuiRawImageComponent { Color = "1 1 1 1", Png = GetImage(item.Item.ShortName + 512) },
new CuiRectTransformComponent { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-24.541 -24.541", OffsetMax = "25.459 25.459" }
}
});
container.Add(new CuiElement
{
Name = "Amount",
Parent = "PanelBG",
Components = {
new CuiTextComponent { Text = $"x{item.Item.Amount}", Font = "robotocondensed-bold.ttf", FontSize = 9, Align = TextAnchor.MiddleRight, Color = "1 1 1 1" },
new CuiRectTransformComponent { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-4.206 -44.829", OffsetMax = "37.548 -25.853" }
}
});
var itemIndex = (page * 8) + (i + 1);
var statustext = (data.TakedLevels != null && data.TakedLevels.Contains(item.UniqueIdentify))
? "ПОЛУЧЕНО!"
: data.CurrentLevel < itemIndex
? "НЕДОСТУПНО!"
: "ЗАБРАТЬ!";
var color = statustext == "ПОЛУЧЕНО!" || statustext == "ЗАБРАТЬ!" ? "#26520070" : "#52150070";
var BGImage = statustext == "ПОЛУЧЕНО!" ? "BGTaked" : statustext == "ЗАБРАТЬ!" ? "BGCanTake" : "BGUnavaible";
container.Add(new CuiElement
{
Name = "BGGradient",
Parent = "PanelBG",
Components = {
new CuiRawImageComponent { Color = "1 1 1 0.35", Png = GetImage(BGImage), FadeIn = _fadein },
new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1" }
}
});
container.Add(new CuiPanel
{
CursorEnabled = false,
Image = { Color = "0 0 0 0.3", Material = "assets/content/ui/uibackgroundblur-notice.mat" },
RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" }
}, "PanelBG", "Blur");
container.Add(new CuiElement
{
Name = "Status",
Parent = "PanelBG",
Components = {
new CuiTextComponent { Text = $"{statustext}", Font = "robotocondensed-bold.ttf", FontSize = 10, Align = TextAnchor.MiddleCenter, Color = "1 1 1 0.6", FadeIn = _fadein},
new CuiRectTransformComponent { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-44.827 -44.829", OffsetMax = "44.827 44.829" }
}
});
container.Add(new CuiPanel
{
CursorEnabled = false,
Image = { Color = $"{HexToRustFormat(color)}" },
RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-44.827 48.653", OffsetMax = "44.827 64.42" }
}, "PanelBG", "LevelTextPanel");
var text = (page * 8) + (i + 1);
container.Add(new CuiElement
{
Name = "Level",
Parent = "LevelTextPanel",
Components = {
new CuiTextComponent { Text = $"{text} Уровень", Font = "robotocondensed-bold.ttf", FontSize = 10, Align = TextAnchor.MiddleCenter, Color = "1 1 1 0.6" },
new CuiRectTransformComponent { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-44.827 -7.883", OffsetMax = "44.827 7.884" }
}
});
var command = statustext == "ЗАБРАТЬ!" ? $"rpg.take {item.UniqueIdentify}" : "";
container.Add(new CuiButton
{
RectTransform =
{
AnchorMin = $"0 0",
AnchorMax = $"1 1"
},
Button =
{
Color = "0 0 0 0",
Command = $"{command}",
},
Text =
{
Text = ""
}
}, "PanelBG", $"BTN");
offsetminx += margin;
offsetmaxx += margin;
i++;
}
CuiHelper.DestroyUi(player, "MainBG");
CuiHelper.AddUi(player, container);
}
private void DrawExp(BasePlayer player)
{
var container = new CuiElementContainer();
var data = PluginData.DataObject.GetOrAdd(player);
if (data == null) return;
container.Add(new CuiPanel
{
CursorEnabled = false,
Image = { Color = "0.7137255 0.7137255 0.7137255 0.2431373" },
RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "304.892 -346.51", OffsetMax = "464.788 -325.478" }
}, "Hud", "ExpPanel");
container.Add(new CuiElement
{
Name = "CurrentLevel",
Parent = "ExpPanel",
Components = {
new CuiTextComponent { Text = $"УРОВЕНЬ: {data.CurrentLevel}", Font = "robotocondensed-bold.ttf", FontSize = 10, Align = TextAnchor.MiddleCenter, Color = "1 1 1 0.6" },
new CuiRectTransformComponent { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "3.728 -10.516", OffsetMax = "79.95 10.516" }
}
});
container.Add(new CuiPanel
{
CursorEnabled = false,
Image = { Color = "0 0 0 0" },
RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-57.875 -9.65", OffsetMax = "3.728 8.65" }
}, "ExpPanel", "ProgressPanel");
var anchor = data.CurrentExp / _config.Levels[data.CurrentLevel].ExpNeed > 1 ? 1 : data.CurrentExp / _config.Levels[data.CurrentLevel].ExpNeed;
container.Add(new CuiPanel
{
CursorEnabled = false,
Image = { Color = "0.03301889 0.6080197 1 1" },
RectTransform = { AnchorMin = "0 0", AnchorMax = $"{anchor} 1"}
}, "ProgressPanel", "Progress");
container.Add(new CuiElement
{
Name = "CurrentExp",
Parent = "ProgressPanel",
Components = {
new CuiTextComponent { Text = $" XP: {data.CurrentExp}", Font = "robotocondensed-bold.ttf", FontSize = 10, Align = TextAnchor.MiddleLeft, Color = "1 1 1 0.8" },
new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1"}
}
});
container.Add(new CuiElement
{
Name = "UpgradeIcon",
Parent = "ExpPanel",
Components = {
new CuiRawImageComponent { Color = "1 1 1 1", Png = GetImage("UpgradeSprite") },
new CuiRectTransformComponent { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-77.225 -6.885", OffsetMax = "-62.775 6.885" }
}
});
CuiHelper.DestroyUi(player, "ExpPanel");
CuiHelper.AddUi(player, container);
}
private void DrawNotify(BasePlayer player, float amount)
{
var container = new CuiElementContainer();
container.Add(new CuiPanel
{
CursorEnabled = false,
FadeOut = _fadeout,
Image = { Color = "0.7137255 0.7137255 0.7137255 0.2431373", FadeIn = _fadein},
RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-102.828 -10.5", OffsetMax = "-81.828 10.5" }
}, "ExpPanel", "Notify");
container.Add(new CuiElement
{
Name = "NotifyText",
Parent = "Notify",
FadeOut = _fadeout,
Components = {
new CuiTextComponent { Text = $"+{amount}", Font = "robotocondensed-bold.ttf", FontSize = 10, Align = TextAnchor.MiddleCenter, Color = "1 1 1 0.8", FadeIn = _fadein },
new CuiRectTransformComponent { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-10.5 -10.5", OffsetMax = "10.5 10.5" }
}
});
CuiHelper.DestroyUi(player, "NotifyText");
CuiHelper.DestroyUi(player, "Notify");
CuiHelper.AddUi(player, container);
timer.Once(2f, () =>
{
CuiHelper.DestroyUi(player, "NotifyText");
CuiHelper.DestroyUi(player, "Notify");
});
}
#endregion
#region Commands
[ChatCommand("rpg")]
private void RpgChatCommand(BasePlayer player)
{
MainUI(player);
}
[ConsoleCommand("rpg.take")]
private void CmdRpgTake(ConsoleSystem.Arg args)
{
var player = args.Player();
if (player == null) return;
if (args.Args.Length == 0) return;
var identify = args.Args[0];
var Level = _config.Levels.FirstOrDefault(x => x.UniqueIdentify == identify);
if (Level == null) return;
Level.TakeItem(player);
}
[ConsoleCommand("rpg.skip")]
private void CmdRpgSkip(ConsoleSystem.Arg args)
{
var player = args.Player();
if (player == null) return;
int page = Convert.ToInt32(args.Args[0]);
MainUI(player, page);
}
#endregion
}
}