C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Core.Libraries.Covalence;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using Newtonsoft.Json;
using Rust;
namespace Oxide.Plugins
{
[Info("ZLevels Remastered", "nivex", "3.2.2")]
[Description("Lets players level up as they harvest different resources and when crafting")]
class ZLevelsRemastered : RustPlugin
{
[PluginReference]
Plugin EventManager, CraftingController, ZoneManager, Economics, IQEconomic, ServerRewards, SkillTree;
private StoredData data = new();
private Dictionary<string, ItemDefinition> CraftItems;
private CraftData _craftData = new();
private StringBuilder _sb = new();
private bool newSaveDetected;
private bool bonusOn;
private int MaxB = 10001;
private int MinB = 10;
public enum Skills
{
ACQUIRE,
CRAFTING,
MINING,
SKINNING,
WOODCUTTING,
ALL
}
private Skills[] AllSkills = new Skills[] { Skills.ACQUIRE, Skills.CRAFTING, Skills.MINING, Skills.SKINNING, Skills.WOODCUTTING };
private class CraftData
{
public Dictionary<string, CraftInfo> CraftList = new();
public CraftData() { }
}
private class CraftInfo
{
public int MaxBulkCraft;
public int MinBulkCraft;
public string shortName;
public bool Enabled;
public CraftInfo() { }
}
private class StoredData
{
public Hash<ulong, PlayerInfo> PlayerInfo = new();
public StoredData() { }
}
private enum LevelType
{
ACQUIRE_LEVEL,
ACQUIRE_POINTS,
CRAFTING_LEVEL,
CRAFTING_POINTS,
MINING_LEVEL,
MINING_POINTS,
WOODCUTTING_LEVEL,
WOODCUTTING_POINTS,
SKINNING_LEVEL,
SKINNING_POINTS,
LAST_DEATH,
XP_MULTIPLIER,
}
private class PlayerInfo : IEquatable<PlayerInfo>
{
private double _acquireLevel = 1.0;
private double _acquirePoints = 10.0;
private double _craftingLevel = 1.0;
private double _craftingPoints = 10.0;
private double _miningLevel = 1.0;
private double _miningPoints = 10.0;
private double _skinningLevel = 1.0;
private double _skinningPoints = 10.0;
private double _woodcuttingLevel = 1.0;
private double _woodcuttingPoints = 10.0;
private double _lastDeath = 0.0;
private double _xpMultiplier = 100.0;
private double RoundValue(double value) => Math.Round(value, 2, MidpointRounding.AwayFromZero);
[JsonProperty(PropertyName = "AL")]
public double ACQUIRE_LEVEL
{
get => RoundValue(_acquireLevel);
set => _acquireLevel = RoundValue(value);
}
[JsonProperty(PropertyName = "AP")]
public double ACQUIRE_POINTS
{
get => RoundValue(_acquirePoints);
set => _acquirePoints = RoundValue(value);
}
[JsonProperty(PropertyName = "CL")]
public double CRAFTING_LEVEL
{
get => RoundValue(_craftingLevel);
set => _craftingLevel = RoundValue(value);
}
[JsonProperty(PropertyName = "CP")]
public double CRAFTING_POINTS
{
get => RoundValue(_craftingPoints);
set => _craftingPoints = RoundValue(value);
}
[JsonProperty(PropertyName = "ML")]
public double MINING_LEVEL
{
get => RoundValue(_miningLevel);
set => _miningLevel = RoundValue(value);
}
[JsonProperty(PropertyName = "MP")]
public double MINING_POINTS
{
get => RoundValue(_miningPoints);
set => _miningPoints = RoundValue(value);
}
[JsonProperty(PropertyName = "SL")]
public double SKINNING_LEVEL
{
get => RoundValue(_skinningLevel);
set => _skinningLevel = RoundValue(value);
}
[JsonProperty(PropertyName = "SP")]
public double SKINNING_POINTS
{
get => RoundValue(_skinningPoints);
set => _skinningPoints = RoundValue(value);
}
[JsonProperty(PropertyName = "WCL")]
public double WOODCUTTING_LEVEL
{
get => RoundValue(_woodcuttingLevel);
set => _woodcuttingLevel = RoundValue(value);
}
[JsonProperty(PropertyName = "WCP")]
public double WOODCUTTING_POINTS
{
get => RoundValue(_woodcuttingPoints);
set => _woodcuttingPoints = RoundValue(value);
}
[JsonProperty(PropertyName = "LD")]
public double LAST_DEATH
{
get => RoundValue(_lastDeath);
set => _lastDeath = RoundValue(value);
}
[JsonProperty(PropertyName = "XPM")]
public double XP_MULTIPLIER
{
get => RoundValue(_xpMultiplier);
set => _xpMultiplier = RoundValue(value);
}
[JsonProperty(PropertyName = "CUI")]
public bool CUI { get; set; } = true;
[JsonProperty(PropertyName = "ONOFF")]
public bool ENABLED { get; set; } = true;
public PlayerInfo() { }
public bool Equals(PlayerInfo other)
{
if (other == null)
return false;
return ACQUIRE_LEVEL == other.ACQUIRE_LEVEL &&
ACQUIRE_POINTS == other.ACQUIRE_POINTS &&
CRAFTING_LEVEL == other.CRAFTING_LEVEL &&
CRAFTING_POINTS == other.CRAFTING_POINTS &&
MINING_LEVEL == other.MINING_LEVEL &&
MINING_POINTS == other.MINING_POINTS &&
SKINNING_LEVEL == other.SKINNING_LEVEL &&
SKINNING_POINTS == other.SKINNING_POINTS &&
WOODCUTTING_LEVEL == other.WOODCUTTING_LEVEL &&
WOODCUTTING_POINTS == other.WOODCUTTING_POINTS &&
XP_MULTIPLIER == other.XP_MULTIPLIER &&
CUI == other.CUI &&
ENABLED == other.ENABLED;
}
public override bool Equals(object obj)
{
return obj is PlayerInfo other && Equals(other);
}
public override int GetHashCode()
{
HashCode hash = new();
hash.Add(ACQUIRE_LEVEL);
hash.Add(ACQUIRE_POINTS);
hash.Add(CRAFTING_LEVEL);
hash.Add(CRAFTING_POINTS);
hash.Add(MINING_LEVEL);
hash.Add(MINING_POINTS);
hash.Add(SKINNING_LEVEL);
hash.Add(SKINNING_POINTS);
hash.Add(WOODCUTTING_LEVEL);
hash.Add(WOODCUTTING_POINTS);
hash.Add(XP_MULTIPLIER);
hash.Add(CUI);
hash.Add(ENABLED);
return hash.ToHashCode();
}
public static bool operator ==(PlayerInfo left, PlayerInfo right)
{
if (ReferenceEquals(left, right))
return true;
if (left is null)
return false;
return left.Equals(right);
}
public static bool operator !=(PlayerInfo left, PlayerInfo right)
{
return !(left == right);
}
internal bool IsDefault(PlayerInfo other) => Equals(other);
}
#region Main
private void Init()
{
Unsubscribe();
RegisterPermissions();
int index = 0;
foreach (Skills skill in AllSkills)
{
if (IsSkillEnabled(skill))
{
skillIndex.Add(skill, ++index);
}
}
}
private void Unload()
{
Clean();
SaveData();
foreach (var player in BasePlayer.activePlayerList)
{
DestroyGUI(player);
}
if (TOD_Sky.Instance?.Components?.Time != null)
{
TOD_Sky.Instance.Components.Time.OnSunrise -= OnTimeSunrise;
TOD_Sky.Instance.Components.Time.OnSunset -= OnTimeSunset;
}
}
private void OnNewSave(string strFilename)
{
if (config.generic.wipeDataOnNewSave)
{
Puts("New save detected...");
newSaveDetected = true;
}
}
private void OnServerInitialized()
{
LoadData();
if (config.nightbonus.enableNightBonus && TOD_Sky.Instance.IsNight)
{
pointsPerHitCurrent = config.nightbonus.pointsPerHitAtNight;
resourceMultipliersCurrent = config.nightbonus.resourceMultipliersAtNight;
pointsPerHitPowerToolCurrent = config.nightbonus.pointsPerPowerToolAtNight;
bonusOn = true;
}
else
{
pointsPerHitCurrent = config.settings.pointsPerHit;
resourceMultipliersCurrent = config.settings.resourceMultipliers;
pointsPerHitPowerToolCurrent = config.settings.pointsPerPowerTool;
}
foreach (var player in BasePlayer.allPlayerList)
{
var pi = GetPlayerInfo(player);
if (player.IsConnected) CreateGUI(player, pi);
}
Puts("Stats can be reset by > zl.reset <");
Subscribe();
SaveData();
RegisterCommands();
}
private void OnPlayerConnected(BasePlayer player) => OnPlayerSleepEnded(player);
private void OnPlayerDisconnected(BasePlayer player) => GetPlayerInfo(player);
private void OnEntityKill(BasePlayer player) => OnPlayerSleep(player);
private void OnPlayerRespawned(BasePlayer player) => OnPlayerSleepEnded(player);
private void OnPlayerSleepEnded(BasePlayer player) => CreateGUI(player, GetPlayerInfo(player));
private void OnPlayerSleep(BasePlayer player) => DestroyGUI(player);
private void OnEntityDeath(BasePlayer player, HitInfo hitInfo)
{
if (hitInfo == null || !IsValid(player) || isZoneExcluded(player))
{
return;
}
DestroyGUI(player);
if (!hasRights(player.UserIDString))
{
return;
}
var pi = GetPlayerInfo(player);
if (!pi.ENABLED || permission.UserHasPermission(player.UserIDString, config.generic.permissionNameXP))
{
return;
}
bool isSuicide = hitInfo.damageTypes.Has(DamageType.Suicide) && (player.IsAdmin || player.IsDeveloper || !player.CanSuicide());
if (!config.generic.penaltyOnSuicide && isSuicide) return;
if (!config.generic.penaltyOnDeath && !isSuicide) return;
if (EventManager?.Call("IsEventPlayer", player) != null)
{
return;
}
if (Interface.CallHook("CanBePenalized", player) != null)
{
return;
}
_sb.Clear();
foreach (Skills skill in AllSkills)
{
if (IsSkillEnabled(skill))
{
var penalty = GetPenalty(player, pi, skill, isSuicide);
if (penalty > 0)
{
_sb.AppendLine("* -" + penalty + " " + _(skill + "Skill") + " XP.");
removePoints(pi, skill, penalty);
}
}
}
if (_sb.Length > 0)
{
Message(player, "PenaltyText", _sb.ToString());
}
pi.LAST_DEATH = ToEpochTime(DateTime.UtcNow);
}
private void OnDispenserGather(ResourceDispenser dispenser, BasePlayer player, Item item)
{
if (item == null || dispenser == null || !IsValid(player) || !hasRights(player.UserIDString))
{
return;
}
Skills? skill = dispenser.gatherType switch
{
ResourceDispenser.GatherType.Tree => Skills.WOODCUTTING,
ResourceDispenser.GatherType.Flesh => Skills.SKINNING,
ResourceDispenser.GatherType.Ore => Skills.MINING,
_ => null
};
if (skill == null || !IsSkillEnabled(skill.Value))
{
return;
}
var pi = GetPlayerInfo(player);
if (!pi.ENABLED)
{
return;
}
Item activeItem = player.GetActiveItem();
if (permission.UserHasPermission(player.UserIDString, config.generic.BlockWeaponsGather) && activeItem?.info.category == ItemCategory.Weapon)
{
return;
}
if (!config.functions.ShouldAllowGather(item.info.shortname, out bool grantXPOnly))
{
return;
}
int prevAmount = item.amount;
bool isPowerTool = false;
if (skill != Skills.SKINNING && activeItem != null)
{
HeldEntity heldEntity = activeItem.GetHeldEntity() as HeldEntity;
if (heldEntity is Jackhammer || heldEntity is Chainsaw)
{
if (skill == Skills.WOODCUTTING && !CanUseChainsaw(player))
{
return;
}
if (skill == Skills.MINING && !CanUseJackhammer(player))
{
return;
}
if (!config.functions.gibs && dispenser.GetComponent<ServerGib>() != null)
{
return;
}
isPowerTool = true;
}
}
if (!config.functions.gibs && skill == Skills.MINING && dispenser.GetComponent<ServerGib>() != null)
{
return;
}
int amount = levelHandler(pi, player, item.amount, skill.Value, dispenser.baseEntity, isPowerTool);
if (!grantXPOnly)
{
item.amount = amount;
}
if (item.amount != prevAmount)
{
Interface.CallHook("OnZLevelDispenserGather", dispenser, player, item, prevAmount, item.amount, isPowerTool);
}
}
private bool CanUseJackhammer(BasePlayer player) => permission.UserHasPermission(player.UserIDString, config.generic.AllowJackhammerGather);
private bool CanUseChainsaw(BasePlayer player) => permission.UserHasPermission(player.UserIDString, config.generic.AllowChainsawGather);
private void OnDispenserBonus(ResourceDispenser dispenser, BasePlayer player, Item item) => OnDispenserGather(dispenser, player, item);
private List<string> _warnings = new();
private object OnCollectiblePickup(CollectibleEntity collectible, BasePlayer player)
{
if (collectible == null || collectible.itemList.IsNullOrEmpty() || !IsValid(player) || !hasRights(player.UserIDString))
return null;
var pi = GetPlayerInfo(player);
if (pi == null || !pi.ENABLED)
return null;
if (config.functions.enabledCollectibleEntity.TryGetValue(collectible.ShortPrefabName, out var enabled) && !enabled)
return null;
Skills skill;
for (int i = 0; i < collectible.itemList.Length; i++)
{
ItemAmount itemAmount = collectible.itemList[i];
if (itemAmount == null) continue;
if (itemAmount.itemDef == null) continue;
switch (itemAmount.itemDef.shortname)
{
case "black.berry":
case "blue.berry":
case "bone.fragments":
case "clone.seed":
case "clone.orchid":
case "clone.rose":
case "clone.sunflower":
case "cloth":
case "corn":
case "diesel_barrel":
case "green.berry":
case "mushroom":
case "orchid":
case "potato":
case "pumpkin":
case "red.berry":
case "rose":
case "seed.black.berry":
case "seed.blue.berry":
case "seed.corn":
case "seed.green.berry":
case "seed.hemp":
case "seed.orchid":
case "seed.potato":
case "seed.pumpkin":
case "seed.red.berry":
case "seed.rose":
case "seed.sunflower":
case "seed.wheat":
case "seed.white.berry":
case "seed.yellow.berry":
case "sunflower":
case "wheat":
case "white.berry":
case "yellow.berry":
skill = IsSkillEnabled(Skills.ACQUIRE) ? Skills.ACQUIRE : Skills.SKINNING;
break;
case "metal.ore":
case "sulfur.ore":
case "stones":
skill = config.settings.MiningStonesOre ? Skills.MINING : Skills.ACQUIRE;
break;
case "wood":
skill = config.settings.AcquireWood ? Skills.ACQUIRE : Skills.WOODCUTTING;
break;
default:
if (IsSkillEnabled(Skills.ACQUIRE)) skill = Skills.ACQUIRE;
else if (IsSkillEnabled(Skills.SKINNING)) skill = Skills.SKINNING;
else return null;
if (!_warnings.Contains(itemAmount.itemDef.shortname))
{
PrintWarning($"WARNING: {player} picked up undefined item: {itemAmount.itemDef.shortname}.Defaulting to {skill} skill.");
_warnings.Add(itemAmount.itemDef.shortname);
}
break;
}
if (IsSkillEnabled(skill))
{
int prevAmount = (int)itemAmount.amount;
itemAmount.amount = levelHandler(pi, player, prevAmount, skill, collectible);
if (Interface.CallHook("OnZLevelCollectiblePickup", itemAmount, player, collectible, prevAmount, itemAmount.amount) != null)
{
return true;
}
}
}
return null;
}
private void OnTimeSunset()
{
if (!config.nightbonus.enableNightBonus || bonusOn)
{
return;
}
bonusOn = true;
pointsPerHitCurrent = config.nightbonus.pointsPerHitAtNight;
resourceMultipliersCurrent = config.nightbonus.resourceMultipliersAtNight;
pointsPerHitPowerToolCurrent = config.nightbonus.pointsPerPowerToolAtNight;
if (config.nightbonus.broadcastEnabledBonus)
{
foreach (var player in BasePlayer.activePlayerList)
Message(player, "NightBonusOn");
}
if (config.nightbonus.logEnabledBonusConsole)
Puts("Nightbonus points enabled");
}
private void OnTimeSunrise()
{
if (!config.nightbonus.enableNightBonus || !bonusOn)
{
return;
}
bonusOn = false;
pointsPerHitCurrent = config.settings.pointsPerHit;
resourceMultipliersCurrent = config.settings.resourceMultipliers;
pointsPerHitPowerToolCurrent = config.settings.pointsPerPowerTool;
if (config.nightbonus.broadcastEnabledBonus)
{
foreach (var player in BasePlayer.activePlayerList)
Message(player, "NightBonusOff");
}
if (config.nightbonus.logEnabledBonusConsole)
Puts("Nightbonus points disabled");
}
private object OnGrowableGathered(GrowableEntity plant, Item item, BasePlayer player)
{
if (item == null || player == null || !hasRights(player.UserIDString))
{
return true;
}
var pi = GetPlayerInfo(player);
if (!pi.ENABLED)
{
return true;
}
Skills skill;
if (IsSkillEnabled(Skills.ACQUIRE))
skill = Skills.ACQUIRE;
else skill = Skills.SKINNING;
var prevAmount = item.amount;
item.amount = levelHandler(pi, player, item.amount, skill, plant);
Interface.CallHook("OnZLevelGrowableGathered", plant, item, player, prevAmount, item.amount);
return null;
}
private object OnItemCraft(ItemCraftTask task, BasePlayer crafter, Item fromTempBlueprint)
{
if (!hasRights(crafter.UserIDString)) return null;
var pi = GetPlayerInfo(crafter);
if (!pi.ENABLED) return null;
var bypassCraftLevelRequirement = CanInstantCraftNoLevelRequirement(crafter);
var craftingTime = task.blueprint.time;
if (bypassCraftLevelRequirement)
{
craftingTime = 0;
}
else if (IsSkillEnabled(Skills.CRAFTING))
{
if (pi.CRAFTING_LEVEL > 1)
craftingTime -= task.blueprint.time * (float)((pi.CRAFTING_LEVEL * config.settings.craftingDetails.percent) / 100);
}
else return null;
if (craftingTime <= 0)
{
craftingTime = 0;
foreach (var craftInfo in _craftData.CraftList.Values)
{
if (!craftInfo.Enabled || craftInfo.shortName != task.blueprint.targetItem.shortname)
{
continue;
}
if (task.amount >= craftInfo.MinBulkCraft && task.amount <= craftInfo.MaxBulkCraft && task.amount > 0)
{
var stacks = GetStacks(task.amount * task.blueprint.amountToCreate, task.blueprint.targetItem.stackable);
if (!HasPlace(crafter, stacks))
{
ReturnCraft(task, crafter);
return true;
}
if (bypassCraftLevelRequirement || CanInstantCraft(crafter))
{
if (!task.blueprint.name.Contains("(Clone)"))
task.blueprint = UnityEngine.Object.Instantiate(task.blueprint);
task.blueprint.amountToCreate *= task.amount;
crafter.inventory.crafting.FinishCrafting(task);
task.cancelled = true;
return true;
}
}
}
}
if (!task.blueprint.name.Contains("(Clone)"))
task.blueprint = UnityEngine.Object.Instantiate(task.blueprint);
task.blueprint.time = craftingTime;
return null;
}
private List<int> GetStacks(int amount, int maxStack)
{
List<int> stacks = new();
while (amount > maxStack && amount > 0)
{
amount -= maxStack;
stacks.Add(maxStack);
}
if (amount > 0)
{
stacks.Add(amount);
}
return stacks;
}
private bool HasPlace(BasePlayer crafter, List<int> stacks)
{
if (!config.settings.craftingDetails.slots)
{
return true;
}
var capacity = crafter.inventory.containerMain.capacity + crafter.inventory.containerBelt.capacity;
var taken = crafter.inventory.containerMain.itemList.Count + crafter.inventory.containerBelt.itemList.Count;
var slots = capacity - taken;
if (slots - stacks.Count < 0)
{
return false;
}
return slots > 0;
}
private bool CanInstantCraftNoLevelRequirement(BasePlayer crafter)
{
return config.settings.craftingDetails.noLevelRequirement && permission.UserHasPermission(crafter.UserIDString, config.settings.craftingDetails.Permission);
}
private bool CanInstantCraft(BasePlayer crafter)
{
if (config.settings.craftingDetails.usePermission)
{
return permission.UserHasPermission(crafter.UserIDString, config.settings.craftingDetails.Permission);
}
return true;
}
private void ReturnCraft(ItemCraftTask task, BasePlayer crafter)
{
task.cancelled = true;
Message(crafter, "NoSlots");
foreach (var item in task.takenItems)
{
if (item.amount > 0)
crafter.GiveItem(item);
}
}
private object OnItemCraftFinished(ItemCraftTask task, Item item, ItemCrafter craft)
{
if (task == null) return null;
var crafter = craft?.owner;
if (crafter == null || !hasRights(crafter.UserIDString)) return null;
var bypassLevelRequirement = CanInstantCraftNoLevelRequirement(crafter);
if (!bypassLevelRequirement && !IsSkillEnabled(Skills.CRAFTING)) return null;
var pi = GetPlayerInfo(crafter);
var xpPercentBefore = getExperiencePercent(pi, Skills.CRAFTING);
if (task.blueprint == null)
{
Puts("There is problem obtaining task.blueprint on 'OnItemCraftFinished' hook! This is usually caused by some incompatable plugins.");
return null;
}
var experienceGain = (task.blueprint.time + 0.99f) / config.settings.craftingDetails.time;
if (experienceGain == 0)
return null;
double Level = pi.CRAFTING_LEVEL;
double Points = pi.CRAFTING_POINTS;
Points += experienceGain * config.settings.craftingDetails.xp;
if (Points >= getLevelPoints(Level + 1))
{
var levelCap = config.settings.levelCaps.CRAFTING;
var maxLevel = levelCap > 0 && Level + 1 > levelCap;
if (!maxLevel)
{
Level = getPointsLevel(Points, Skills.CRAFTING);
string format = $"<color={config.settings.colors.CRAFTING}>{_("LevelUpText", crafter.UserIDString)}</color>";
string message = string.Format(format, _("CRAFTINGSkill", crafter.UserIDString), Level, Points, getLevelPoints(Level + 1), pi.CRAFTING_LEVEL * Convert.ToDouble(config.settings.craftingDetails.percent));
Player.Message(crafter, message, string.IsNullOrEmpty(config.generic.pluginPrefix) ? string.Empty : config.generic.pluginPrefix, config.generic.steamIDIcon);
GiveReward(crafter, Skills.CRAFTING, Level);
if (config.generic.enableLevelupBroadcast)
{
foreach (var target in BasePlayer.activePlayerList)
{
if (target != null && target.userID != crafter.userID && hasRights(target.UserIDString) && GetPlayerInfo(target).ENABLED)
{
Message(target, "LevelUpTextBroadcast", crafter.displayName, Level, config.settings.colors.CRAFTING, _("CRAFTINGSkill", crafter.UserIDString));
}
}
}
}
}
try
{
if (item.info.shortname != "lantern_a" && item.info.shortname != "lantern_b")
setPointsAndLevel(pi, Skills.CRAFTING, Points, Level);
}
catch { }
try
{
var xpPercentAfter = getExperiencePercent(pi, Skills.CRAFTING);
if (xpPercentAfter != xpPercentBefore)
GUIUpdateSkill(crafter, Skills.CRAFTING);
}
catch { }
if (task.amount > 0) return null;
if (task.blueprint != null && task.blueprint.name.Contains("(Clone)"))
{
var behaviours = task.blueprint.GetComponents<MonoBehaviour>();
foreach (var behaviour in behaviours)
{
if (behaviour.name.Contains("(Clone)")) UnityEngine.Object.Destroy(behaviour);
}
}
return null;
}
#endregion Serverhooks
#region Commands
[HookMethod("SendHelpText"), ChatCommand("stathelp")]
private void SendHelpText(BasePlayer player)
{
_sb.Clear();
_sb.AppendLine("<size=18><color=orange>ZLevels</color></size><size=14><color=#ce422b>REMASTERED</color></size>");
_sb.AppendLine("/stats - Displays your stats.");
_sb.AppendLine("/statsui - Enable/Disable stats UI.");
_sb.AppendLine("/statsonoff - Enable/Disable whole leveling.");
_sb.AppendLine("/statinfo - Displays information about skills.");
_sb.AppendLine("/stathelp - Displays the help.");
//sb.AppendLine("/topskills - Display max levels reached so far.");
SendReply(player, _sb.ToString());
}
private void PointsPerHitCommand(IPlayer user, string command, string[] args)
{
if (!user.IsAdmin) return;
if (args.Length < 2)
{
user.Reply("Syntax: zl.pointsperhit skill number");
user.Reply("Possible skills are: WC, M, S, A, C, *(All skills)");
_sb.Clear();
_sb.Append("Current points per hit:");
foreach (var currSkill in AllSkills)
{
if (!IsSkillEnabled(currSkill)) continue;
_sb.Append($" {currSkill} > {pointsPerHitCurrent.Get(currSkill)} |");
}
user.Reply(_sb.ToString().TrimEnd('|'));
return;
}
if (!double.TryParse(args[1], out var points) || points < 1)
{
user.Reply("Incorrect number.Must be greater than or equal to 1");
return;
}
var skillName = args[0].ToUpper();
Skills skill;
if (skillName == "*") skill = Skills.ALL;
else if (skillName.Equals("C")) skill = Skills.CRAFTING;
else if (skillName.Equals("WC")) skill = Skills.WOODCUTTING;
else if (skillName.Equals("M")) skill = Skills.MINING;
else if (skillName.Equals("A")) skill = Skills.ACQUIRE;
else if (skillName.Equals("S")) skill = Skills.SKINNING;
else { user.Reply("Incorrect skill.Possible skills are: WC, M, S, A, C, *(All skills)."); return; }
if (skill == Skills.ALL)
{
foreach (var currSkill in AllSkills)
{
if (!IsSkillEnabled(currSkill)) continue;
pointsPerHitCurrent.Set(currSkill, points);
}
_sb.Clear();
_sb.Append("New points per hit:");
foreach (var currSkill in AllSkills)
{
if (!IsSkillEnabled(currSkill)) continue;
_sb.Append($" {currSkill} > {pointsPerHitCurrent.Get(currSkill)} |");
}
user.Reply(_sb.ToString().TrimEnd('|'));
}
else
{
pointsPerHitCurrent.Set(skill, points);
_sb.Clear();
_sb.Append("New points per hit:");
foreach (var currSkill in AllSkills)
{
if (!IsSkillEnabled(currSkill)) continue;
_sb.Append($" {currSkill} > {pointsPerHitCurrent.Get(currSkill)} |");
}
user.Reply(_sb.ToString().TrimEnd('|'));
}
}
private void PlayerXpmCommand(IPlayer user, string command, string[] args)
{
if (!user.IsAdmin) return;
if (args.Length < 1)
{
user.Reply(_("XPM USE 1", user.Id));
user.Reply(_("XPM USE 2", user.Id));
return;
}
IPlayer target = covalence.Players.FindPlayer(args[0]);
if (target == null)
{
user.Reply(_("PLAYER NOT FOUND", user.Id));
return;
}
if (!data.PlayerInfo.TryGetValue(Convert.ToUInt64(target.Id), out var playerData))
{
user.Reply("PlayerData is NULL!");
return;
}
if (args.Length < 2)
{
var bonus1 = getXpMulti(playerData, target.Id);
var baseMultiplier = playerData.XP_MULTIPLIER;
if (baseMultiplier != bonus1)
{
user.Reply($"Current XP multiplier for player '{target.Name}' is {baseMultiplier}% with vip raising total to {bonus1}%");
}
else user.Reply($"Current XP multiplier for player '{target.Name}' is {baseMultiplier}%");
return;
}
double multiplier = -1;
if (double.TryParse(args[1], out multiplier))
{
if (multiplier <= 0)
{
user.Reply("Incorrect number.Must be greater than 0");
return;
}
}
playerData.XP_MULTIPLIER = multiplier;
var bonus2 = getXpMulti(playerData, target.Id);
if (multiplier != bonus2)
{
user.Reply($"New XP multiplier for player '{target.Name}' is {getXpMulti(playerData, target.Id)}% with vip raising total to {bonus2}%");
}
else user.Reply($"New XP multiplier for player '{target.Name}' is {getXpMulti(playerData, target.Id)}%");
}
private void InfoCommand(IPlayer user, string command, string[] args)
{
if (!user.IsAdmin)
{
return;
}
if (args.Length < 1)
{
if (!GetLookingAtPlayer(user))
{
user.Reply(_("INFO USE", user.Id));
}
return;
}
IPlayer target = covalence.Players.FindPlayer(args[0]);
if (target == null)
{
user.Reply(_("PLAYER NOT FOUND", user.Id));
return;
}
if (!data.PlayerInfo.TryGetValue(Convert.ToUInt64(target.Id), out var playerData))
{
user.Reply("PlayerData is NULL!");
return;
}
PrintInfo(user, target.Id, target.Name, playerData);
}
private bool GetLookingAtPlayer(IPlayer user)
{
BasePlayer player = user.Object as BasePlayer;
if (player == null) return false;
BasePlayer target = RelationshipManager.GetLookingAtPlayer(player);
if (target == null) return false;
if (!data.PlayerInfo.TryGetValue(target.userID, out var playerData)) return false;
PrintInfo(user, target.UserIDString, target.displayName, playerData);
return true;
}
private void PrintInfo(IPlayer user, string targetId, string targetName, PlayerInfo playerData)
{
TextTable textTable = new();
textTable.AddColumn("FieldInfo");
textTable.AddColumn("Level");
textTable.AddColumn("Points");
textTable.AddRow(new string[] { _("ACQUIRESkill", targetId), $"{playerData.ACQUIRE_LEVEL:#0.##}", $"{playerData.ACQUIRE_POINTS:#0.##}" });
textTable.AddRow(new string[] { _("CRAFTINGSkill", targetId), $"{playerData.CRAFTING_LEVEL:#0.##}", $"{playerData.CRAFTING_POINTS:#0.##}" });
textTable.AddRow(new string[] { _("MININGSkill", targetId), $"{playerData.MINING_LEVEL:#0.##}", $"{playerData.MINING_POINTS:#0.##}" });
textTable.AddRow(new string[] { _("SKINNINGSkill", targetId), $"{playerData.SKINNING_LEVEL:#0.##}", $"{playerData.SKINNING_POINTS:#0.##}" });
textTable.AddRow(new string[] { _("WOODCUTTINGSkill", targetId), $"{playerData.WOODCUTTING_LEVEL:#0.##}", $"{playerData.WOODCUTTING_POINTS:#0.##}" });
textTable.AddRow(new string[] { _("XPM", targetId), $"{getXpMulti(playerData, targetId):#0.##}%", string.Empty });
user.Reply($"\n{_("STATS", targetId)}{targetName}\n{textTable}");
}
private void ResetCommand(IPlayer user, string command, string[] args)
{
if (!user.IsAdmin) return;
if (args.Length != 1 || args[0] != "true")
{
user.Reply(_("RESET USE", user.Id));
return;
}
WipeData();
SaveData();
foreach (var player in BasePlayer.activePlayerList)
{
DestroyGUI(player);
CreateGUI(player, GetPlayerInfo(player));
}
user.Reply("Userdata was successfully reset to zero");
Puts("{0} ({1}) reset userdata to zero", user.Name, user.Id);
}
private void ZlvlCommand(IPlayer user, string command, string[] args)
{
if (!user.IsAdmin) return;
if (args.Length < 3)
{
_sb.Clear();
_sb.AppendLine("Syntax: zl.lvl name|steamid skill [OPERATOR]NUMBER");
_sb.AppendLine("Example: zl.lvl Player WC /2 -- Player gets his WC level divided by 2.");
_sb.AppendLine("Example: zl.lvl * * +3 -- Everyone currently playing in the server gets +3 for all skills.");
_sb.AppendLine("Example: zl.lvl ** * /2 -- Everyone (including offline players) gets their level divided by 2.");
_sb.AppendLine("Instead of names you can use wildcard(*): * - affects online players, ** - affects all players");
_sb.AppendLine("Possible operators: *(XP Modified %), +(Adds level), -(Removes level), /(Divides level)").AppendLine();
user.Reply(_sb.ToString());
return;
}
var playerName = args[0];
IPlayer target = covalence.Players.FindPlayer(playerName);
if (playerName != "*" && playerName != "**" && target == null)
{
user.Reply(_("PLAYER NOT FOUND", user.Id));
return;
}
if (playerName != "*" && playerName != "**" && !data.PlayerInfo.ContainsKey(Convert.ToUInt64(target.Id)))
{
user.Reply("PlayerData is NULL!");
return;
}
if (target != null || playerName == "*" || playerName == "**")
{
var playerMode = 0; // Exact player
if (playerName == "*")
playerMode = 1; // Online players
else if (playerName == "**")
playerMode = 2; // All players
var skillName = args[1].ToUpper();
Skills skill;
if (skillName == "*") skill = Skills.ALL;
else if (skillName.Equals("C")) skill = Skills.CRAFTING;
else if (skillName.Equals("WC")) skill = Skills.WOODCUTTING;
else if (skillName.Equals("M")) skill = Skills.MINING;
else if (skillName.Equals("A")) skill = Skills.ACQUIRE;
else if (skillName.Equals("S")) skill = Skills.SKINNING;
else { user.Reply("Incorrect skill.Possible skills are: WC, M, S, A, C, *(All skills)."); return; }
var mode = 0; // 0 = SET, 1 = ADD, 2 = SUBTRACT, 3 = multiplier, 4 = divide
int value;
bool correct;
if (args[2][0] == '+')
{
mode = 1;
correct = int.TryParse(args[2].Replace("+", string.Empty), out value);
}
else if (args[2][0] == '-')
{
mode = 2;
correct = int.TryParse(args[2].Replace("-", string.Empty), out value);
}
else if (args[2][0] == '*')
{
mode = 3;
correct = int.TryParse(args[2].Replace("*", string.Empty), out value);
}
else if (args[2][0] == '/')
{
mode = 4;
correct = int.TryParse(args[2].Replace("/", string.Empty), out value);
}
else
{
correct = int.TryParse(args[2], out value);
}
if (correct)
{
if (mode == 3) // Change XP Multiplier.{
if (skill != Skills.ALL)
{
user.Reply("XPMultiplier is changeable for all skills! Use * instead of " + skill + ".");
return;
}
if (playerMode == 1)
{
foreach (var currPlayer in BasePlayer.activePlayerList)
editMultiplierForPlayer(value, currPlayer.userID);
}
else if (playerMode == 2)
editMultiplierForPlayer(value);
else if (target != null)
editMultiplierForPlayer(value, Convert.ToUInt64(target.Id));
var whom = playerMode == 1 ? "ALL ONLINE PLAYERS" : playerMode == 2 ? "ALL PLAYERS" : target.Name;
user.Reply($"XP rates has changed to {value}% of normal XP for {whom}");
return;
}
if (playerMode == 1)
{
foreach (var connPlayer in covalence.Players.Connected)
{
adminModifyPlayerStats(user, skill, value, mode, connPlayer);
}
}
else if (playerMode == 2)
{
foreach (var other in covalence.Players.All)
{
if (data.PlayerInfo.ContainsKey(Convert.ToUInt64(other.Id)))
{
adminModifyPlayerStats(user, skill, value, mode, other);
}
}
}
else
{
adminModifyPlayerStats(user, skill, value, mode, target);
}
}
}
}
private void CheckCommand(IPlayer user, string command, string[] args)
{
if (!user.IsAdmin) return;
int count = 0;
var pi = CreatePlayerInfo();
foreach (var info in data.PlayerInfo)
{
if (info.Value.IsDefault(pi))
{
count++;
}
}
user.Reply($"{count} / {data.PlayerInfo.Count} entries in datafile can be removed");
}
private void CleanCommand(IPlayer user, string command, string[] args)
{
if (!user.IsAdmin) return;
int count = data.PlayerInfo.Count;
int cleaned = Clean();
user.Reply($"{cleaned} / {count} entries in datafile have been removed");
SaveData();
}
private int Clean()
{
int count = 0;
if (data == null)
{
return count;
}
var pi = CreatePlayerInfo();
foreach (var info in data.PlayerInfo.ToList())
{
if (info.Value.IsDefault(pi))
{
count++;
data.PlayerInfo.Remove(info.Key);
}
}
return count;
}
private void PenaltyCommand(IPlayer user, string command, string[] args)
{
if (!user.IsAdmin) return;
if (args.Length == 1 && args[0] == "status")
{
user.Reply(config.generic.penaltyOnDeath ? "Penalty is currently enabled." : "Penalty is currently disabled.");
return;
}
if (args.Length == 0) config.generic.penaltyOnDeath = !config.generic.penaltyOnDeath;
else config.generic.penaltyOnSuicide = !config.generic.penaltyOnSuicide;
if (config.generic.penaltyOnDeath || config.generic.penaltyOnSuicide)
{
Subscribe(nameof(OnEntityDeath));
user.Reply("Penalty is now enabled.");
}
else
{
Unsubscribe(nameof(OnEntityDeath));
user.Reply("Penalty is now disabled.");
}
SaveConfig();
}
[ChatCommand("stats")]
private void StatsCommand(BasePlayer player, string command, string[] args)
{
if (!hasRights(player.UserIDString))
{
Message(player, "NoPermission");
return;
}
_sb.Clear();
_sb.AppendLine("<size=18><color=orange>ZLevels</color></size><size=14><color=#ce422b>REMASTERED</color></size>");
foreach (Skills skill in AllSkills) _sb.Append(getStatPrint(player, skill));
var pi = GetPlayerInfo(player.userID);
var alive = ReadableTimeSpan(DateTime.UtcNow - ToDateTimeFromEpoch(pi.LAST_DEATH));
_sb.AppendLine().AppendLine($"Time alive: {alive}");
_sb.AppendLine($"XP rates for you are {getXpMulti(pi, player.UserIDString)}
// ... [Code preview truncated due to length. Full source in attached file] ...