C#:
#region _Main.cs
namespace Oxide.Plugins {
using System;
using System.IO;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Core.Configuration;
using Oxide.Core.Libraries.Covalence;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using Network;
[Info("Imperium", "chucklenugget/evict", "2.4.4")]
[Description("Land Claims for Rust")]
public partial class Imperium : RustPlugin {
//Optional Dependencies
[PluginReference]
private Plugin BetterChat, Clans, RaidableBases, NpcSpawn ;
//Hook Deferrals
private void InitDeferList() {
}
private static Imperium Instance;
private bool Ready;
public static string dataDirectory = $"file://{Interface.Oxide.DataDirectory}{Path.DirectorySeparatorChar}ImperiumImages{Path.DirectorySeparatorChar}";
private DynamicConfigFile AreasFile;
private DynamicConfigFile FactionsFile;
private DynamicConfigFile PinsFile;
private DynamicConfigFile WarsFile;
private GameObject GO;
private ImperiumOptions Options;
private Timer UpkeepCollectionTimer;
private AreaManager Areas;
private FactionManager Factions;
private HudManager Hud;
private PinManager Pins;
private UserManager Users;
private WarManager Wars;
private ZoneManager Zones;
private void Init() {
AreasFile = GetDataFile("areas");
FactionsFile = GetDataFile("factions");
PinsFile = GetDataFile("pins");
WarsFile = GetDataFile("wars");
}
private void Loaded() {
InitLang();
InitDeferList();
Permission.RegisterAll(this);
try {
Options = Config.ReadObject<ImperiumOptions>();
}
catch (Exception ex) {
PrintError($"Error while loading configuration: {ex.ToString()}");
}
Puts("Area claims are " + (Options.Claims.Enabled ? "enabled" : "disabled"));
Puts("Taxation is " + (Options.Taxes.Enabled ? "enabled" : "disabled"));
Puts("Badlands are " + (Options.Badlands.Enabled ? "enabled" : "disabled"));
Puts("Map pins are " + (Options.Map.PinsEnabled ? "enabled" : "disabled"));
Puts("War is " + (Options.War.Enabled ? "enabled" : "disabled"));
Puts("Decay reduction is " + (Options.Decay.Enabled ? "enabled" : "disabled"));
Puts("Claim upkeep is " + (Options.Upkeep.Enabled ? "enabled" : "disabled"));
Puts("Zones are " + (Options.Zones.Enabled ? "enabled" : "disabled"));
if (Options.Upgrading.Enabled) {
PrintWarning("Land upgrading is not available in this Imperium version yet! Disabling it");
Options.Upgrading.Enabled = false;
}
if (Options.Recruiting.Enabled) {
PrintWarning("Recruiting is not available in this Imperium version yet! Disabling it");
Options.Recruiting.Enabled = false;
}
if (BetterChat != null) {
Puts("Using " + BetterChat.Name + " by " + BetterChat.Author);
Interface.CallHook("API_RegisterThirdPartyTitle", this, new Func<IPlayer, string>(BetterChat_FormattedFactionTag));
}
Instance = this;
//Puts("Recruiting is " + (Options.Recruiting.Enabled ? "enabled" : "disabled"));
// If the map has already been initialized, we can set up now; otherwise,
// we need to wait until the savefile has been loaded.
if (TerrainMeta.Size.x > 0) Setup();
}
private void OnServerInitialized(bool initial) {
if (initial) Setup();
}
private void Setup() {
GO = new GameObject();
Areas = new AreaManager();
Factions = new FactionManager();
Hud = new HudManager();
Pins = new PinManager();
Users = new UserManager();
Wars = new WarManager();
Zones = new ZoneManager();
Factions.Init(TryLoad<FactionInfo>(FactionsFile));
Areas.Init(TryLoad<AreaInfo>(AreasFile));
Pins.Init(TryLoad<PinInfo>(PinsFile));
Users.Init();
Wars.Init(TryLoad<WarInfo>(WarsFile));
Zones.Init();
Hud.Init();
Hud.GenerateMapOverlayImage();
if (Options.Factions.OverrideInGameTeamSystem) {
RelationshipManager.maxTeamSize = 128;
RelationshipManager.maxTeamSize_Internal = 128;
}
if (Instance.Options.Factions.UseClansPlugin) {
Factions.SyncAllWithClans();
}
if (Options.Upkeep.Enabled) UpkeepCollectionTimer = timer.Every(Options.Upkeep.CheckIntervalMinutes * 60, Upkeep.CollectForAllFactions);
PrintToChat($"{Title} v{Version} initialized.");
Ready = true;
}
private void Unload() {
SaveData();
Hud.Destroy();
Zones.Destroy();
Users.Destroy();
Wars.Destroy();
Pins.Destroy();
Areas.Destroy();
Factions.Destroy();
for (int i = recruitInstancesList.Count - 1; i >= 0; i--) {
Recruit recruit = recruitInstancesList[i];
UnregisterRecruitInstance(recruit.npc);
recruit.npc.AdminKill();
}
ClearRecruitRegister();
if (UpkeepCollectionTimer != null && !UpkeepCollectionTimer.Destroyed) UpkeepCollectionTimer.Destroy();
if (GO != null) UnityEngine.Object.Destroy(GO);
Instance = null;
}
private void OnServerSave() {
timer.Once(Core.Random.Range(10, 30), SaveData);
}
private void SaveData() {
AreasFile.WriteObject(Areas.Serialize());
FactionsFile.WriteObject(Factions.Serialize());
PinsFile.WriteObject(Pins.Serialize());
WarsFile.WriteObject(Wars.Serialize());
}
private DynamicConfigFile GetDataFile(string name) {
return Interface.Oxide.DataFileSystem.GetFile(Name + Path.DirectorySeparatorChar + name);
}
private IEnumerable<T> TryLoad<T>(DynamicConfigFile file) {
List<T> items;
try {
items = file.ReadObject<List<T>>();
}
catch (Exception ex) {
PrintWarning($"Error reading data from {file.Filename}: ${ex.ToString()}");
items = new List<T>();
}
return items;
}
private void Log(string message, params object[] args) {
LogToFile("log", String.Format(message, args), this, true);
}
//SHOULD MOVE THIS TO FACTION MANAGER
//SHOULD MOVE THIS TO AREA MANAGER
private bool EnsureFactionCanClaimArea(User user, Faction faction, Area area) {
if (area.Type == AreaType.Badlands) {
user.SendChatMessage(nameof(Messages.AreaIsBadlands), area.Id);
return false;
}
if (faction.MemberCount < Instance.Options.Claims.MinFactionMembers) {
user.SendChatMessage(nameof(Messages.FactionTooSmallToOwnLand), Instance.Options.Claims.MinFactionMembers);
return false;
}
Area[] claimedAreas = Areas.GetAllClaimedByFaction(faction);
if (Instance.Options.Claims.RequireContiguousClaims && !area.IsClaimed && claimedAreas.Length > 0) {
int contiguousClaims = Areas.GetNumberOfContiguousClaimedAreas(area, faction);
if (contiguousClaims == 0) {
user.SendChatMessage(nameof(Messages.AreaNotContiguous), area.Id, faction.Id);
return false;
}
}
int? maxClaims = Instance.Options.Claims.MaxClaims;
if (maxClaims != null && claimedAreas.Length >= maxClaims) {
user.SendChatMessage(nameof(Messages.FactionOwnsTooMuchLand), faction.Id, maxClaims);
return false;
}
return true;
}
//SHOULD MOVE THIS TO AREA MANAGER
private bool EnsureCupboardCanBeUsedForClaim(User user, BuildingPrivlidge cupboard) {
if (cupboard == null) {
user.SendChatMessage(nameof(Messages.SelectingCupboardFailedInvalidTarget));
return false;
}
if (!cupboard.IsAuthed(user.Player)) {
user.SendChatMessage(nameof(Messages.SelectingCupboardFailedNotAuthorized));
return false;
}
return true;
}
//SHOULD MOVE THIS TO RECRUIT MANAGER
private bool EnsureLockerCanBeUsedForArmory(User user, Locker locker, Area area) {
if (area == null || area.FactionId != user.Faction.Id) {
user.SendChatMessage(nameof(Messages.AreaNotOwnedByYourFaction));
return false;
}
return true;
}
//SHOULD MOVE THIS TO RECRUIT MANAGER
private bool EnsureSleepingBagCanBeUsedForRecruit(User user, SleepingBag sleepingBag, Area area) {
Area areaHere = Areas.GetByEntityPosition(sleepingBag);
if (areaHere == null || areaHere.FactionId != user.Faction.Id) {
user.SendChatMessage(nameof(Messages.AreaNotOwnedByYourFaction));
return false;
}
if (sleepingBag.deployerUserID != (ulong)user.Player.userID) {
user.SendChatMessage(nameof(Messages.UserIsNotSleepingBagOwner));
return false;
}
return true;
}
//SHOULD MOVE THIS TO WAR MANAGER
private bool EnsureUserAndFactionCanEngageInDiplomacy(User user, Faction faction) {
if (faction == null) {
user.SendChatMessage(nameof(Messages.NotMemberOfFaction));
return false;
}
if (faction.MemberCount < Options.Claims.MinFactionMembers) {
user.SendChatMessage(nameof(Messages.FactionTooSmallToOwnLand));
return false;
}
if (Areas.GetAllClaimedByFaction(faction).Length == 0) {
user.SendChatMessage(nameof(Messages.FactionDoesNotOwnLand));
return false;
}
return true;
}
private bool EnforceCommandCooldown(User user, string command, int cooldownSeconds) {
int secondsRemaining = user.GetSecondsLeftOnCooldown(command);
if (secondsRemaining > 0) {
user.SendChatMessage(nameof(Messages.CommandIsOnCooldown), secondsRemaining);
return false;
}
user.SetCooldownExpiration(command, DateTime.UtcNow.AddSeconds(cooldownSeconds));
return true;
}
private bool TryCollectFromStacks(ItemDefinition itemDef, IEnumerable<Item> stacks, int amount) {
if (stacks.Sum(item => item.amount) < amount) return false;
int amountRemaining = amount;
var dirtyContainers = new HashSet<ItemContainer>();
foreach (Item stack in stacks) {
var amountToTake = Math.Min(stack.amount, amountRemaining);
stack.amount -= amountToTake;
amountRemaining -= amountToTake;
dirtyContainers.Add(stack.GetRootContainer());
if (stack.amount == 0) stack.RemoveFromContainer();
if (amountRemaining == 0) break;
}
foreach (ItemContainer container in dirtyContainers) container.MarkDirty();
return true;
}
}
}
#endregion
#region API.Hooks.cs
namespace Oxide.Plugins {
using Oxide.Core;
public partial class Imperium : RustPlugin {
private static class Events {
public static void OnAreaChanged(Area area) {
Interface.CallHook(nameof(OnAreaChanged), area);
}
public static void OnUserEnteredArea(User user, Area area) {
Interface.CallHook(nameof(OnUserEnteredArea), user, area);
}
public static void OnUserLeftArea(User user, Area area) {
Interface.CallHook(nameof(OnUserLeftArea), user, area);
}
public static void OnUserEnteredZone(User user, Zone zone) {
Interface.CallHook(nameof(OnUserEnteredZone), user, zone);
}
public static void OnUserLeftZone(User user, Zone zone) {
Interface.CallHook(nameof(OnUserLeftZone), user, zone);
}
public static void OnFactionCreated(Faction faction) {
Interface.CallHook(nameof(OnFactionCreated), faction);
}
public static void OnFactionDisbanded(Faction faction) {
Interface.CallHook(nameof(OnFactionDisbanded), faction);
}
public static void OnFactionTaxesChanged(Faction faction) {
Interface.CallHook(nameof(OnFactionTaxesChanged), faction);
}
public static void OnFactionArmoryChanged(Faction faction) {
Interface.CallHook(nameof(OnFactionArmoryChanged), faction);
}
public static void OnFactionBadlandsChanged(Faction faction) {
Interface.CallHook(nameof(OnFactionBadlandsChanged), faction);
}
public static void OnPlayerJoinedFaction(Faction faction, User user) {
Interface.CallHook(nameof(OnPlayerJoinedFaction), faction, user);
}
public static void OnPlayerLeftFaction(Faction faction, User user) {
Interface.CallHook(nameof(OnPlayerLeftFaction), faction, user);
}
public static void OnPlayerInvitedToFaction(Faction faction, User user) {
Interface.CallHook(nameof(OnPlayerInvitedToFaction), faction, user);
}
public static void OnPlayerUninvitedFromFaction(Faction faction, User user) {
Interface.CallHook(nameof(OnPlayerUninvitedFromFaction), faction, user);
}
public static void OnPlayerPromoted(Faction faction, User user) {
Interface.CallHook(nameof(OnPlayerPromoted), faction, user);
}
public static void OnPlayerDemoted(Faction faction, User user) {
Interface.CallHook(nameof(OnPlayerDemoted), faction, user);
}
public static void OnPinCreated(Pin pin) {
Interface.CallHook(nameof(OnPinCreated), pin);
}
public static void OnPinRemoved(Pin pin) {
Interface.CallHook(nameof(OnPinRemoved), pin);
}
}
}
}
#endregion
#region API.Methods.cs
namespace Oxide.Plugins {
using Oxide.Core.Plugins;
public partial class Imperium {
[HookMethod(nameof(GetFactionName))]
public object GetFactionName(BasePlayer player) {
User user = Users.Get(player);
if (user == null || user.Faction == null) return null;
else return user.Faction.Id;
}
}
}
#endregion
#region Area.cs
namespace Oxide.Plugins {
using Rust;
using Rust.UI;
using UnityEngine;
public partial class Imperium {
private class Area : MonoBehaviour {
public Vector3 Position {
get;
private set;
}
public Vector3 Size {
get;
private set;
}
public string Id {
get;
private set;
}
public int Row {
get;
private set;
}
public int Col {
get;
private set;
}
public AreaType Type {
get;
set;
}
public string Name {
get;
set;
}
public string FactionId {
get;
set;
}
public string ClaimantId {
get;
set;
}
public BuildingPrivlidge ClaimCupboard {
get;
set;
}
public BasePlayer ClaimReskinningPlayer {
get;
set;
}
public Vector3 ReskinnedCupboardLastPosition {
get;
set;
}
public bool IsCupboardChangingSkin {
get;
set;
}
public Locker ArmoryLocker {
get;
set;
}
public int Level {
get;
set;
}
public SleepingBag RecruitSleepingBag {
get;
set;
}
public BasePlayer recruitInstance = null;
public Recruit recruitInfo = null;
public int recruitRespawnCooldown = 5;
public MapMarkerGenericRadius mapMarker;
public VendingMachineMapMarker headquartersMarker;
public MapMarkerGenericRadius hqMarkerColor;
public BaseEntity textMarker;
public bool IsClaimed {
get {
return FactionId != null;
}
}
public bool IsTaxableClaim {
get {
return Type == AreaType.Claimed || Type == AreaType.Headquarters;
}
}
public bool IsWarZone {
get {
return GetActiveWars().Length > 0;
}
}
public bool IsHostile {
get {
if (FactionId != null) {
if (Instance.Factions.Get(FactionId) != null) {
return Instance.Factions.Get(FactionId).IsBadlands;
}
}
return false;
}
}
public int UpgradeCost {
get {
var costs = Instance.Options.Upgrading.Costs;
return costs[Mathf.Clamp(Level, 0, costs.Count - 1) ];
}
}
public void Init(string id, int row, int col, Vector3 position, Vector3 size, AreaInfo info) {
Id = id;
Row = row;
Col = col;
Position = position;
Size = size;
if (info != null) TryLoadInfo(info);
gameObject.layer = (int)Layer.Reserved1;
gameObject.name = $"imperium_area_{id}";
transform.position = position;
transform.rotation = Quaternion.Euler(new Vector3(0, 0, 0));
var collider = gameObject.AddComponent<BoxCollider>();
collider.size = Size;
collider.isTrigger = true;
collider.enabled = true;
gameObject.SetActive(true);
enabled = true;
}
private void Awake() {
InvokeRepeating("CheckClaimCupboard", 60f, 60f);
InvokeRepeating("CheckArmoryLocker", 60f, 60f);
InvokeRepeating("CheckRecruitRespawn", 5f, 5f);
}
private void OnDestroy() {
if (recruitInstance != null) recruitInstance.AdminKill();
var collider = GetComponent<BoxCollider>();
if (collider != null) Destroy(collider);
if (IsInvoking("CheckClaimCupboard")) CancelInvoke("CheckClaimCupboard");
if (IsInvoking("CheckArmoryLocker")) CancelInvoke("CheckArmoryLocker");
if (IsInvoking("CheckRecruitRespawn")) CancelInvoke("CheckRecruitRespawn");
}
private void TryLoadInfo(AreaInfo info) {
BuildingPrivlidge cupboard = null;
Locker locker = null;
SleepingBag bag = null;
if (info.CupboardId != null) {
cupboard = BaseNetworkable.serverEntities.Find(new NetworkableId((ulong)info.CupboardId)) as BuildingPrivlidge;
if (cupboard == null) {
Instance.Log($"[LOAD] Area {Id}: Cupboard entity {info.CupboardId} not found, treating as unclaimed");
return;
}
}
if (info.FactionId != null) {
Faction faction = Instance.Factions.Get(info.FactionId);
if (faction == null) {
Instance.Log($"[LOAD] Area {Id}: Claimed by unknown faction {info.FactionId}, treating as unclaimed");
return;
}
}
Name = info.Name;
Type = info.Type;
FactionId = info.FactionId;
ClaimantId = info.ClaimantId;
ClaimCupboard = cupboard;
Level = info.Level;
if (info.ArmoryId != null) {
locker = BaseNetworkable.serverEntities.Find(new NetworkableId((ulong)info.ArmoryId)) as Locker;
if (locker == null) {
Instance.Log($"[LOAD] Area {Id}: Locker entity {info.ArmoryId} not found");
}
}
ArmoryLocker = locker;
if (info.RecruitSleepingBagId != null) {
bag = BaseNetworkable.serverEntities.Find(new NetworkableId((ulong)info.RecruitSleepingBagId)) as SleepingBag;
if (bag == null) {
Instance.Log($"[LOAD] Area {Id}: Locker entity {info.ArmoryId} not found");
}
}
RecruitSleepingBag = bag;
if (FactionId != null) Instance.Log($"[LOAD] Area {Id}: Claimed by {FactionId}, type = {Type}, cupboard = {Util.Format(ClaimCupboard)}");
}
private void CheckClaimCupboard() {
if (ClaimCupboard == null || !ClaimCupboard.IsDestroyed) return;
Instance.Log($"{FactionId} lost their claim on {Id} because the tool cupboard was destroyed (periodic check)");
Util.PrintToChat(nameof(Messages.AreaClaimLostCupboardDestroyedAnnouncement), FactionId, Id);
Instance.Areas.Unclaim(this);
}
private void CheckArmoryLocker() {
if (ArmoryLocker == null || !ArmoryLocker.IsDestroyed) return;
Instance.Log($"{FactionId} lost their armory on {Id} because the locker was destroyed (periodic check)");
Util.PrintToChat(nameof(Messages.AreaClaimLostArmoryDestroyedAnnouncement), FactionId, Id);
Instance.Areas.RemoveArmory(this);
}
private void CheckRecruitRespawn() {
if (RecruitSleepingBag == null) return;
if (ArmoryLocker == null) {
return;
}
if (recruitInstance != null) return;
if (recruitRespawnCooldown > 0) {
recruitRespawnCooldown -= 5;
return;
}
NpcConfig config = Instance.GetAreaNpcConfig(this);
if (config == null) return;
Instance.SpawnRecruit(this, RecruitSleepingBag.transform.position, config);
recruitRespawnCooldown = 5;
}
private void CheckRecruitForgetAggressors() {
}
private void OnTriggerEnter(Collider collider) {
if (collider.gameObject.layer != (int)Layer.Player_Server) return;
var user = collider.GetComponentInParent<User>();
if (user != null) {
if (user.CurrentArea != this) {
Events.OnUserEnteredArea(user, this);
}
}
}
private void OnTriggerExit(Collider collider) {
if (collider.gameObject.layer != (int)Layer.Player_Server) return;
var user = collider.GetComponentInParent<User>();
if (user != null) {
Events.OnUserLeftArea(user, this);
}
}
public void UpdateAreaMarker(FactionColorPicker colorPicker) {
bool markerExists = true;
if (Type != AreaType.Headquarters) {
if (headquartersMarker != null) {
headquartersMarker.Kill();
headquartersMarker = null;
}
if (hqMarkerColor != null) {
hqMarkerColor.Kill();
hqMarkerColor = null;
}
}
if (Type == AreaType.Wilderness) {
if (mapMarker != null) mapMarker.Kill();
}
else {
if (mapMarker == null) {
markerExists = false;
var markerRadius = ((4000 / Instance.Areas.MapGrid.MapSize) * 0.5f);
var marker = GameManager.server.CreateEntity("assets/prefabs/tools/map/genericradiusmarker.prefab", transform.position) as MapMarkerGenericRadius;
marker.radius = markerRadius;
marker.enableSaving = false;
mapMarker = marker;
}
if (Type == AreaType.Claimed) {
mapMarker.alpha = 0.3f;
mapMarker.color1 = Util.ConvertSystemToUnityColor(colorPicker.GetColorForFaction(FactionId));
mapMarker.color2 = Color.black;
if (!markerExists) mapMarker.Spawn();
mapMarker.SendUpdate();
}
if (Type == AreaType.Headquarters) {
mapMarker.alpha = 0.3f;
mapMarker.color1 = Util.ConvertSystemToUnityColor(colorPicker.GetColorForFaction(FactionId));
mapMarker.color2 = Color.black;
if (!markerExists) mapMarker.Spawn();
mapMarker.SendUpdate();
if (headquartersMarker == null) {
if (ClaimCupboard) {
Vector3 tcPosition = ClaimCupboard.transform.position;
var marker = GameManager.server.CreateEntity("assets/prefabs/deployable/vendingmachine/vending_mapmarker.prefab", tcPosition) as VendingMachineMapMarker;
marker.markerShopName = FactionId + " Headquarters";
marker.transform.position.Set(marker.transform.position.x, -100f, marker.transform.position.z);
headquartersMarker = marker;
headquartersMarker.enableSaving = false;
headquartersMarker.appType = ProtoBuf.AppMarkerType.Player;
headquartersMarker.Spawn();
var markerTop = GameManager.server.CreateEntity("assets/prefabs/tools/map/genericradiusmarker.prefab") as MapMarkerGenericRadius;
markerTop.radius = 0.2f;
markerTop.enableSaving = false;
markerTop.color1 = Util.ConvertSystemToUnityColor(colorPicker.GetColorForFaction(FactionId));
markerTop.color2 = Color.black;
markerTop.alpha = 0.5f;
markerTop.SetParent(headquartersMarker);
markerTop.Spawn();
hqMarkerColor = markerTop;
headquartersMarker.SendNetworkUpdate();
markerTop.SendUpdate();
}
}
}
if (Type == AreaType.Badlands) {
mapMarker.alpha = 0.2f;
mapMarker.color1 = Color.black;
mapMarker.color2 = Color.black;
if (!markerExists) mapMarker.Spawn();
mapMarker.SendUpdate();
}
}
}
public float GetDistanceFromEntity(BaseEntity entity) {
return Vector3.Distance(entity.transform.position, transform.position);
}
public int GetClaimCost(Faction faction) {
var costs = Instance.Options.Claims.Costs;
int numberOfAreasOwned = Instance.Areas.GetAllClaimedByFaction(faction).Length;
int index = Mathf.Clamp(numberOfAreasOwned, 0, costs.Count - 1);
return costs[index];
}
public float GetDefensiveBonus() {
var bonuses = Instance.Options.War.DefensiveBonuses;
var depth = Instance.Areas.GetDepthInsideFriendlyTerritory(this);
int index = Mathf.Clamp(depth, 0, bonuses.Count - 1);
float bonus = bonuses[index];
if (Instance.Options.Upgrading.Enabled && Instance.Options.Upgrading.MaxRaidDefenseBonus > 0) {
bonus = Mathf.Clamp(bonus + GetLevelDefensiveBonus(), 0, 1);
bonus = Mathf.Floor((bonus * 100) / 100);
}
return bonus;
}
public float GetTaxRate() {
if (!IsTaxableClaim) return 0;
Faction faction = Instance.Factions.Get(FactionId);
if (!faction.CanCollectTaxes) return 0;
return faction.TaxRate;
}
public War[] GetActiveWars() {
if (FactionId == null) return new War[0];
return Instance.Wars.GetAllActiveWarsByFaction(FactionId);
}
private float GetRatio(int level, int maxLevel, float maxBonus) {
return (level / maxLevel) * maxBonus;
}
//TODO: Remove all logic about levels (land upgrading) as this was a terrible idea
public float GetLevelDefensiveBonus() {
return GetRatio(Level, Instance.Options.Upgrading.MaxUpgradeLevel, Instance.Options.Upgrading.MaxRaidDefenseBonus);
}
public float GetLevelDecayReduction() {
return GetRatio(Level, Instance.Options.Upgrading.MaxUpgradeLevel, Instance.Options.Upgrading.MaxDecayExtraReduction);
}
public float GetLevelTaxBonus() {
return GetRatio(Level, Instance.Options.Upgrading.MaxUpgradeLevel, Instance.Options.Upgrading.MaxTaxChestBonus);
}
public AreaInfo Serialize() {
return new AreaInfo {
Id = Id, Name = Name, Type = Type, FactionId = FactionId, ClaimantId = ClaimantId, CupboardId = ClaimCupboard?.net?.ID.Value, ArmoryId = ArmoryLocker?.net?.ID.Value, RecruitSleepingBagId = RecruitSleepingBag?.net?.ID.Value, Level = Level
}
;
}
}
}
}
#endregion
#region AreaInfo.cs
namespace Oxide.Plugins {
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public partial class Imperium : RustPlugin {
public class AreaInfo {
[JsonProperty("id")]
public string Id;
[JsonProperty("name")]
public string Name;
[JsonProperty("type"), JsonConverter(typeof(StringEnumConverter))]
public AreaType Type;
[JsonProperty("factionId")]
public string FactionId;
[JsonProperty("claimantId")]
public string ClaimantId;
[JsonProperty("cupboardId")]
public ulong? CupboardId;
[JsonProperty("armoryId")]
public ulong? ArmoryId;
[JsonProperty("recruitBagId")]
public ulong? RecruitSleepingBagId;
[JsonProperty("level")]
public int Level;
[JsonProperty("hasRecruit")]
public bool HasRecruit;
[JsonProperty("recruitSpawnPosition")]
public string RecruitSpawnPosition;
}
}
}
#endregion
#region AreaManager.cs
namespace Oxide.Plugins {
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public partial class Imperium {
private class AreaManager {
private Dictionary<string, Area> Areas;
private Area[, ] Layout;
private float areaHeight = 0f;
private float topHeight = 500f;
private float bottomHeight = -500f;
public MapGrid MapGrid {
get;
}
public float AreaHeight {
get {
return areaHeight;
}
}
public float Topheight {
get {
return topHeight;
}
}
public float Bottomheight {
get {
return bottomHeight;
}
}
public int Count {
get {
return Areas.Count;
}
}
public AreaManager() {
MapGrid = new MapGrid();
Areas = new Dictionary<string, Area>();
Layout = new Area[MapGrid.NumberOfColumns, MapGrid.NumberOfRows];
}
public Area Get(string areaId) {
Area area;
if (Areas.TryGetValue(areaId, out area)) return area;
else return null;
}
public Area Get(int row, int col) {
return Layout[row, col];
}
public Area[] GetAll() {
return Areas.Values.ToArray();
}
public Area[] GetAllByType(AreaType type) {
return Areas.Values.Where(a => a.Type == type).ToArray();
}
public Area[] GetAllClaimedByFaction(Faction faction) {
return GetAllClaimedByFaction(faction.Id);
}
public Area[] GetAllClaimedByFaction(string factionId) {
return Areas.Values.Where(a => a.FactionId == factionId).ToArray();
}
public Area[] GetAllTaxableClaimsByFaction(Faction faction) {
return GetAllTaxableClaimsByFaction(faction.Id);
}
public Area[] GetAllTaxableClaimsByFaction(string factionId) {
return Areas.Values.Where(a => a.FactionId == factionId && a.IsTaxableClaim).ToArray();
}
public Area GetByClaimCupboard(BuildingPrivlidge cupboard) {
return GetByClaimCupboard(cupboard.net.ID.Value);
}
public Area GetByClaimReskinningPlayer(BasePlayer player) {
if (player == null) return null;
return Areas.Values.FirstOrDefault(a => a.ClaimCupboard != null && a.ClaimReskinningPlayer == player);
}
public Area GetByReskinnedCupboardLastPosition(Vector3 testPosition) {
return Areas.Values.FirstOrDefault(a => IsApproximatedly(a.ReskinnedCupboardLastPosition, testPosition));
}
private Vector3 Abs(Vector3 v) {
return new Vector3(Mathf.Abs(v.x), Mathf.Abs(v.y), Mathf.Abs(v.z));
}
private bool IsApproximatedly(Vector3 v1, Vector3 v2) {
Vector3 diff = Abs(v1 - v2);
return (diff.x < 0.1f) && (diff.y < 0.1f) && (diff.z < 0.1f);
}
public Area GetByClaimCupboard(ulong cupboardId) {
return Areas.Values.FirstOrDefault(a => a.ClaimCupboard != null && a.ClaimCupboard.net.ID.Value == cupboardId);
}
public Area GetByArmoryLocker(Locker locker) {
return GetByArmoryLocker(locker.net.ID.Value);
}
public Area GetByArmoryLocker(ulong lockerId) {
return Areas.Values.FirstOrDefault(a => a.ArmoryLocker != null && a.ArmoryLocker.net.ID.Value == lockerId);
}
public Area GetByRecruitSleepingBag(SleepingBag bag) {
return GetByRecruitSleepingBag(bag.net.ID.Value);
}
public Area GetByRecruitSleepingBag(ulong bagId) {
return Areas.Values.FirstOrDefault(a => a.RecruitSleepingBag != null && a.RecruitSleepingBag.net.ID.Value == bagId);
}
public Area GetByEntityPosition(BaseEntity entity) {
Vector3 position = entity.transform.position;
int row = Mathf.FloorToInt((MapGrid.MapHeight / 2 - (position.z + (MapGrid.MapOffsetZ / 2))) / MapGrid.CellSize) + Instance.Options.Map.MapGridYOffset;
int col = Mathf.FloorToInt((MapGrid.MapWidth / 2 + (position.x + (MapGrid.MapOffsetX) / 2)) / MapGrid.CellSize);
if (position.y < bottomHeight) return null;
if(position.y > topHeight) return null;
if (row < 0 || col < 0 || row >= MapGrid.NumberOfRows || col >= MapGrid.NumberOfColumns) return null;
return Layout[row, col];
}
public Area GetByWorldPosition(Vector3 position) {
int row = Mathf.FloorToInt((MapGrid.MapHeight / 2 - (position.z + (MapGrid.MapOffsetZ / 2))) / MapGrid.CellSize) + Instance.Options.Map.MapGridYOffset;
int col = Mathf.FloorToInt((MapGrid.MapWidth / 2 + (position.x + (MapGrid.MapOffsetX) / 2)) / MapGrid.CellSize);
if (Instance.Options.Pvp.AllowedUnderground && position.y < -20f) return null;
if (row < 0 || col < 0 || row >= MapGrid.NumberOfRows || col >= MapGrid.NumberOfColumns) return null;
return Layout[row, col];
}
public void Claim(Area area, AreaType type, Faction faction, User claimant, BuildingPrivlidge cupboard) {
area.Type = type;
area.FactionId = faction.Id;
area.ClaimantId = claimant.Id;
area.ClaimCupboard = cupboard;
Events.OnAreaChanged(area);
}
public void SetHeadquarters(Area area, Faction faction) {
// Ensure that no other areas are considered headquarters.
foreach (Area otherArea in GetAllClaimedByFaction(faction).Where(a => a.Type == AreaType.Headquarters)) {
otherArea.Type = AreaType.Claimed;
Events.OnAreaChanged(otherArea);
}
area.Type = AreaType.Headquarters;
Events.OnAreaChanged(area);
}
public void Unclaim(IEnumerable<Area> areas) {
Unclaim(areas.ToArray());
}
public void Unclaim(params Area[] areas) {
foreach (Area area in areas) {
area.Type = AreaType.Wilderness;
area.FactionId = null;
area.ClaimantId = null;
area.ClaimCupboard = null;
area.RecruitSleepingBag = null;
if (area.recruitInstance != null) {
area.recruitInstance.AdminKill();
}
area.recruitInstance = null;
area.recruitInfo = null;
Events.OnAreaChanged(area);
}
}
//TODO: Move all Recruit logic to Recruit Manager?
public void SetArmory(Area area, Locker locker) {
area.ArmoryLocker = locker;
Events.OnAreaChanged(area);
}
public void SetRecruitSpawnPoint(Area area, SleepingBag sleepingBag) {
ulong ownerId = sleepingBag.deployerUserID;
SleepingBag.RemoveBagForPlayer(sleepingBag, ownerId);
sleepingBag.deployerUserID = 0L;
sleepingBag.SendNetworkUpdate();
BasePlayer owner = BasePlayer.FindByID(ownerId);
if (owner != null) {
owner.SendRespawnOptions();
}
area.RecruitSleepingBag = sleepingBag;
area.recruitRespawnCooldown = 30;
if (area.recruitInstance) {
area.recruitInstance.AdminKill();
}
}
public void RemoveArmory(Area area) {
area.ArmoryLocker = null;
if (area.recruitInstance != null) {
area.recruitInstance.AdminKill();
}
area.RecruitSleepingBag = null;
area.recruitInstance = null;
area.recruitInfo = null;
Events.OnAreaChanged(area);
}
public void RemoveRecruitSpawnPoint(Area area) {
area.RecruitSleepingBag = null;
if (area.recruitInstance != null) {
area.recruitInstance.AdminKill();
}
area.recruitInstance = null;
area.recruitInfo = null;
Events.OnAreaChanged(area);
}
public void AddBadlands(params Area[] areas) {
foreach (Area area in areas) {
area.Type = AreaType.Badlands;
area.FactionId = null;
area.ClaimantId = null;
area.ClaimCupboard = null;
Events.OnAreaChanged(area);
}
}
public void AddBadlands(IEnumerable<Area> areas) {
AddBadlands(areas.ToArray());
}
public int GetNumberOfContiguousClaimedAreas(Area area, Faction owner) {
int count = 0;
// North
if (area.Row > 0 && Layout[area.Row - 1, area.Col].FactionId == owner.Id) count++;
// South
if (area.Row < MapGrid.NumberOfRows - 1 && Layout[area.Row + 1, area.Col].FactionId == owner.Id) count++;
// West
if (area.Col > 0 && Layout[area.Row, area.Col - 1].FactionId == owner.Id) count++;
// East
if (area.Col < MapGrid.NumberOfColumns - 1 && Layout[area.Row, area.Col + 1].FactionId == owner.Id) count++;
return count;
}
public int GetDepthInsideFriendlyTerritory(Area area) {
if (!area.IsClaimed) return 0;
var depth = new int[4];
// North
for (var row = area.Row; row >= 0; row--) {
if (Layout[row, area.Col].FactionId != area.FactionId) break;
depth[0]++;
}
// South
for (var row = area.Row; row < MapGrid.NumberOfRows; row++) {
if (Layout[row, area.Col].FactionId != area.FactionId) break;
depth[1]++;
}
// West
for (var col = area.Col; col >= 0; col--) {
if (Layout[area.Row, col].FactionId != area.FactionId) break;
depth[2]++;
}
// East
for (var col = area.Col; col < MapGrid.NumberOfColumns; col++) {
if (Layout[area.Row, col].FactionId != area.FactionId) break;
depth[3]++;
}
return depth.Min() - 1;
}
public void Init(IEnumerable<AreaInfo> areaInfos) {
Instance.Puts("Creating area objects...");
topHeight = Instance.Options.Claims.MaxAreaHeight;
bottomHeight = -500f;
areaHeight = topHeight - bottomHeight;
Dictionary<string, AreaInfo> lookup;
if (areaInfos != null) lookup = areaInfos.ToDictionary(a => a.Id);
else lookup = new Dictionary<string, AreaInfo>();
for (var row = 0; row < MapGrid.NumberOfRows; row++) {
for (var col = 0; col < MapGrid.NumberOfColumns; col++) {
string areaId = MapGrid.GetAreaId(row, col);
Vector3 position = MapGrid.GetPosition(row, col);
if (Instance.Options.Pvp.AllowedUnderground) {
bottomHeight = -18f;
}
position.y = Mathf.Lerp(bottomHeight, topHeight, 0.5f);
Vector3 size = new Vector3(MapGrid.CellSize / 2, areaHeight, MapGrid.CellSize / 2);
AreaInfo info = null;
lookup.TryGetValue(areaId, out info);
var area = new GameObject().AddComponent<Area>();
area.Init(areaId, row, col, position, size, info);
Areas[areaId] = area;
Layout[row, col] = area;
}
}
Instance.Areas.UpdateAreaMarkers();
Instance.Puts($"Created {Areas.Values.Count} area objects.");
}
public void Destroy() {
DestroyAreaMarkers();
Area[] areas = UnityEngine.Object.FindObjectsOfType<Area>();
if (areas != null) {
Instance.Puts($"Destroying {areas.Length} area objects...");
foreach (Area area in areas) UnityEngine.Object.Destroy(area);
}
Areas.Clear();
Array.Clear(Layout, 0, Layout.Length);
Instance.Puts("Area objects destroyed.");
}
public AreaInfo[] Serialize() {
return Areas.Values.Select(area => area.Serialize()).ToArray();
}
public void UpdateAreaMarkers() {
FactionColorPicker colorPicker = new FactionColorPicker();
Area[] AllAreas = GetAll();
foreach (Area area in AllAreas) {
area.UpdateAreaMarker(colorPicker);
}
}
public void DestroyAreaMarkers() {
Area[] AllAreas = GetAll();
foreach (Area area in AllAreas) {
if (area.mapMarker != null) {
area.mapMarker.Kill();
// ... [Code preview truncated due to length. Full source in attached file] ...