C#:
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using System;
using System.Linq;
using Oxide.Core.Plugins;
namespace Oxide.Plugins {
[Info("Farmilka", "by gey", "0.0.1")]
class Farmilka : RustPlugin {
#region Vars
[PluginReference]
Plugin MonumentFinder;
private Quaternion rot = new Quaternion();
private string strPrefab = "assets/prefabs/visualization/sphere.prefab";
Vector3 outpostPos;
private Dictionary<string, FarmZone> _Farms = new Dictionary<string, FarmZone>();
#endregion
#region Config
private Cfg _Config;
class Cfg {
[JsonProperty("Время сброса фармилки")]
public float frequency = 20;
[JsonProperty("Время файта за фармилку")]
public float timeToOpen = 20;
[JsonProperty("MonumentMarker`ы фармилок")]
public Dictionary<string, string> _MonumentsNames = new Dictionary<string, string>();
}
protected override void LoadDefaultConfig() {
var config = new Cfg() {
frequency = 20, timeToOpen = 20, _MonumentsNames = new Dictionary<string, string>() {
["Farmilka 1"]
= "Фарм зона 1", ["Farmilka 2"] = "Фарм зона 2"
}
}
;
SaveConfig(config);
}
void ReadConfig() {
_Config = Config.ReadObject<Cfg>();
base.Config.Settings.ObjectCreationHandling = ObjectCreationHandling.Replace;
SaveConfig(_Config);
}
void SaveConfig(object config) => Config.WriteObject(config, true);
#endregion
#region Data
void Loaded() {
ReadConfig();
var rtt = GetMonument("compound");
outpostPos = rtt.InverseTransformPoint(rtt.Position);
outpostPos.x += (float)23.8;
outpostPos.y += (float)0.3;
outpostPos.z += (float)15.6;
outpostPos = rtt.TransformPoint(outpostPos);
var bl = false;
foreach(var farm in _Config._MonumentsNames.ToList()) {
var rt = GetMonument(farm.Key);
var sphere = GameManager.server.CreateEntity(strPrefab, rt.Position, rot, true);
;
SpawnSphere(ref sphere);
_Farms.Add(farm.Key, new FarmZone(farm.Value, rt.Position, bl, sphere, (int)_Config.timeToOpen, (int)_Config.frequency));
if(bl) bl = false;
else {
bl = true;
}
}
InvokeHandler.Instance.InvokeRepeating(UpdateTimer, 1f, 1f);
}
void Unload() {
InvokeHandler.Instance.CancelInvoke(UpdateTimer);
foreach(var farm in _Farms.ToList()) {
farm.Value.sphere?.Kill();
}
}
#endregion
#region Classes
class FarmZone {
public string farmName;
public Vector3 pos;
public bool IsOnFighting;
public BaseEntity sphere;
public int _FightTimer;
public int _FarmTimer;
public List<BaseEntity> _BuildingBlocks = new List<BaseEntity>();
public FarmZone(string farmName, Vector3 pos, bool IsOnFighting, BaseEntity sphere, int _FightTimer, int _FarmTimer) {
this.farmName = farmName;
this.pos = pos;
this.IsOnFighting = IsOnFighting;
this.sphere = sphere;
this._FightTimer = _FightTimer;
this._FarmTimer = _FarmTimer;
}
public FarmZone() {
}
}
class MonumentAdapter {
public MonoBehaviour Object => (MonoBehaviour)_monumentInfo["Object"];
public string PrefabName => (string)_monumentInfo["PrefabName"];
public string ShortName => (string)_monumentInfo["ShortName"];
public string Alias => (string)_monumentInfo["Alias"];
public Vector3 Position => (Vector3)_monumentInfo["Position"];
public Quaternion Rotation => (Quaternion)_monumentInfo["Rotation"];
private Dictionary<string, object> _monumentInfo;
public MonumentAdapter(Dictionary<string, object> monumentInfo) {
_monumentInfo = monumentInfo;
}
public Vector3 TransformPoint(Vector3 localPosition) => ((Func<Vector3, Vector3>)_monumentInfo["TransformPoint"]).Invoke(localPosition);
public Vector3 InverseTransformPoint(Vector3 worldPosition) => ((Func<Vector3, Vector3>)_monumentInfo["InverseTransformPoint"]).Invoke(worldPosition);
public Vector3 ClosestPointOnBounds(Vector3 position) => ((Func<Vector3, Vector3>)_monumentInfo["ClosestPointOnBounds"]).Invoke(position);
public bool IsInBounds(Vector3 position) => ((Func<Vector3, bool>)_monumentInfo["IsInBounds"]).Invoke(position);
}
#endregion
#region Functions
MonumentAdapter GetMonument(string filter) {
var temp = "Farmilka";
var dictResult = MonumentFinder?.Call("API_Find", (filter.Contains(temp) ? temp : filter)) as List<Dictionary<string, object>>;
if(filter == "Farmilka 1") {
foreach(var m in dictResult.Take(1).ToList()) {
return new MonumentAdapter(m);
}
}
else if(filter == "Farmilka 2") {
foreach(var m in dictResult.Skip(1).Take(1).ToList()) {
return new MonumentAdapter(m);
}
}
else {
foreach(var m in dictResult.ToList()) {
return new MonumentAdapter(m);
}
}
return null;
}
void UpdateTimer() {
foreach(var farm in _Farms.ToList()) {
if(farm.Value.IsOnFighting && farm.Value._FightTimer <= 0) {
farm.Value.IsOnFighting = false;
farm.Value._FightTimer = (int)_Config.timeToOpen;
farm.Value._FarmTimer = (int)_Config.frequency;
Server.Broadcast($"<color=red>{farm.Value.farmName}</color> доступна для застройки!");
}
else if(farm.Value.IsOnFighting && farm.Value._FightTimer > 0) {
farm.Value._FightTimer--;
continue;
}
else if(!farm.Value.IsOnFighting && farm.Value._FarmTimer <= 0) {
foreach(var ent in farm.Value._BuildingBlocks.ToList()) {
ent?.Kill();
}
foreach(var p in BasePlayer.activePlayerList.ToList()) {
if(Vector3.Distance(p.GetNetworkPosition(), farm.Value.pos) < 100) p.Teleport(outpostPos);
}
farm.Value.IsOnFighting = true;
Server.Broadcast($"<color=green>{farm.Value.farmName}</color> была очищена от игроков и начался файт за фарм!");
}
else if(!farm.Value.IsOnFighting && farm.Value._FarmTimer > 0) {
farm.Value._FarmTimer--;
continue;
}
}
}
void SpawnSphere(ref BaseEntity sphere) {
SphereEntity ball = sphere.GetComponent<SphereEntity>();
ball.currentRadius = 1f;
ball.lerpRadius = 2.0f * 100;
ball.lerpSpeed = 100f;
sphere.Spawn();
}
void DestroySphere(BaseEntity _Sphere) {
_Sphere.Kill();
}
#region API
[HookMethod("GetFarmZonesInfo")]
private string GetFarmZonesInfo() {
string msg = "";
foreach(var farm in _Farms.ToList()) {
var temp = "0" + TimeSpan.FromSeconds(farm.Value._FightTimer).Seconds;
var temp2= "0" + TimeSpan.FromSeconds(farm.Value._FarmTimer).Seconds;
if(farm.Value.IsOnFighting) msg += $"\nИдёт файт за <color=green>{farm.Value.farmName}</color>. Осталось {(int)TimeSpan.FromSeconds(farm.Value._FightTimer).TotalMinutes}:{(TimeSpan.FromSeconds(farm.Value._FightTimer).Seconds < 10 ? temp : TimeSpan.FromSeconds(farm.Value._FightTimer).Seconds.ToString())}";
else {
msg += $"\n<color=red>{farm.Value.farmName}</color> захвачена. Осталось {(int)TimeSpan.FromSeconds(farm.Value._FarmTimer).TotalMinutes}:{(TimeSpan.FromSeconds(farm.Value._FarmTimer).Seconds < 10 ? temp2 : $" {
TimeSpan.FromSeconds(farm.Value._FarmTimer).Seconds
}
")}";
}
}
return msg;
}
#endregion
#region Hooks
object CanBuild(Planner planner, Construction prefab, Construction.Target target) {
if(_Farms.Any(p => Vector3.Distance(p.Value.pos, planner.GetOwnerPlayer().GetNetworkPosition()) < 28 && p.Value.IsOnFighting)) return false;
else if(_Farms.Any(p => Vector3.Distance(p.Value.pos, planner.GetOwnerPlayer().GetNetworkPosition()) >= 28 && Vector3.Distance(p.Value.pos, planner.GetOwnerPlayer().GetNetworkPosition()) <= 100)) return false;
return null;
}
void OnEntityDeath(BaseCombatEntity entity, HitInfo info) {
if(entity == null || !_Farms.Any(p => p.Value._BuildingBlocks.Contains(entity as BaseEntity))) return;
foreach(var f in _Farms.Values.ToList()) {
if(!f._BuildingBlocks.Contains(entity as BaseEntity)) return;
f._BuildingBlocks.Remove(entity);
return;
}
}
void OnEntityBuilt(Planner plan, GameObject go) {
if(plan == null || go == null || go.ToBaseEntity() == null || plan.GetOwnerPlayer() == null || !plan.GetOwnerPlayer().IsConnected || _Farms.Any(p => Vector3.Distance(p.Value.pos, plan.GetOwnerPlayer().GetNetworkPosition()) > 70)) return;
foreach(var f in _Farms.Values.ToList()) {
if(Vector3.Distance(f.pos, plan.GetOwnerPlayer().GetNetworkPosition()) > 100 || f.IsOnFighting) continue;
f._BuildingBlocks.Add(go.ToBaseEntity());
return;
}
}
#endregion
#endregion
#region UI
#endregion
#region UI class
public static class UI {
public static void AddImage(ref CuiElementContainer container, string parrent, string name, string color, string sprite, string mat, string aMin, string aMax, string oMin = "0 0", string oMax = "0 0", string outline = "", string dist = "") {
if (string.IsNullOrEmpty(sprite) && !string.IsNullOrEmpty(mat)) container.Add(new CuiElement() {
Parent = parrent, Name = name, Components = {
new CuiImageComponent {
Color = color, Material = "assets/icons/greyout.mat"
}
, new CuiRectTransformComponent {
AnchorMin = aMin, AnchorMax = aMax, OffsetMin = oMin, OffsetMax = oMax
}
}
}
);
if (string.IsNullOrEmpty(sprite) && string.IsNullOrEmpty(mat)) container.Add(new CuiElement() {
Parent = parrent, Name = name, Components = {
new CuiImageComponent {
Color = color
}
, new CuiRectTransformComponent {
AnchorMin = aMin, AnchorMax = aMax, OffsetMin = oMin, OffsetMax = oMax
}
}
}
);
}
public static void AddRawImage(ref CuiElementContainer container, string parrent, string name, string png, string color, string sprite, string mat, string aMin, string aMax, string oMin = "0 0", string oMax = "0 0") {
if (string.IsNullOrEmpty(sprite) && string.IsNullOrEmpty(mat)) container.Add(new CuiElement() {
Parent = parrent, Name = name, Components = {
new CuiRawImageComponent {
Color = color, Png = png
}
, new CuiOutlineComponent {
Color = "0 0 0 0", Distance = "0 0"
}
, new CuiRectTransformComponent {
AnchorMin = aMin, AnchorMax = aMax, OffsetMin = oMin, OffsetMax = oMax
}
}
}
);
}
public static void AddText(ref CuiElementContainer container, string parrent, string name, string color, string text, TextAnchor align, int size, string aMin, string aMax, string oMin = "0 0", string oMax = "0 0", string outColor = "0 0 0 0", string font = "robotocondensed-bold.ttf", string dist = "0.5 0.5", float FadeIN = 0f, float FadeOut = 0f) {
container.Add(new CuiElement() {
Parent = parrent, Name = name, FadeOut = FadeOut, Components = {
new CuiTextComponent {
Color = color, Text = text, Align = align, FontSize = size, Font = font, FadeIn = FadeIN
}
, new CuiOutlineComponent {
Color = outColor, Distance = dist
}
, new CuiRectTransformComponent {
AnchorMin = aMin, AnchorMax = aMax, OffsetMin = oMin, OffsetMax = oMax
}
}
}
);
}
public static void AddButton(ref CuiElementContainer container, string parrent, string name, string cmd, string close, string color, string sprite, string mat, string aMin, string aMax, string oMin = "0 0", string oMax = "0 0", string outline = "", string dist = "") {
if (!string.IsNullOrEmpty(sprite) && !string.IsNullOrEmpty(mat)) container.Add(new CuiElement() {
Parent = parrent, Name = name, Components = {
new CuiButtonComponent {
Command = cmd, Color = color, Close = close, Sprite = sprite, Material = "assets/icons/greyout.mat",
}
, new CuiRectTransformComponent {
AnchorMin = aMin, AnchorMax = aMax, OffsetMin = oMin, OffsetMax = oMax
}
}
}
);
if (!string.IsNullOrEmpty(sprite) && !string.IsNullOrEmpty(mat) && !string.IsNullOrEmpty(outline)) container.Add(new CuiElement() {
Parent = parrent, Name = name, Components = {
new CuiButtonComponent {
Command = cmd, Color = color, Close = close, Sprite = sprite, Material = "assets/icons/greyout.mat",
}
, new CuiOutlineComponent {
Color = outline, Distance = dist
}
, new CuiRectTransformComponent {
AnchorMin = aMin, AnchorMax = aMax, OffsetMin = oMin, OffsetMax = oMax
}
}
}
);
if (string.IsNullOrEmpty(sprite) && !string.IsNullOrEmpty(mat)) container.Add(new CuiElement() {
Parent = parrent, Name = name, Components = {
new CuiButtonComponent {
Command = cmd, Color = color, Close = close, Material = "assets/icons/greyout.mat",
}
, new CuiRectTransformComponent {
AnchorMin = aMin, AnchorMax = aMax, OffsetMin = oMin, OffsetMax = oMax
}
}
}
);
if (!string.IsNullOrEmpty(sprite) && string.IsNullOrEmpty(mat)) container.Add(new CuiElement() {
Parent = parrent, Name = name, Components = {
new CuiButtonComponent {
Command = cmd, Color = color, Close = close, Sprite = sprite
}
, new CuiRectTransformComponent {
AnchorMin = aMin, AnchorMax = aMax, OffsetMin = oMin, OffsetMax = oMax
}
}
}
);
if (string.IsNullOrEmpty(sprite) && string.IsNullOrEmpty(mat)) container.Add(new CuiElement() {
Parent = parrent, Name = name, Components = {
new CuiButtonComponent {
Command = cmd, Color = color, Close = close,
}
, new CuiRectTransformComponent {
AnchorMin = aMin, AnchorMax = aMax, OffsetMin = oMin, OffsetMax = oMax
}
}
}
);
}
}
#endregion
}
}