using System;
using System.Collections.Generic;
using Oxide.Core;
using UnityEngine;
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System.Collections;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Rust;
using VLB;
using System.Threading;
namespace Oxide.Plugins
{
[Info("TopTurret", "Sempai#3239", "1.1.1")]
class TopTurret : RustPlugin
{
static TopTurret ins;
PluginConfig config;
public class PluginConfig
{
[JsonProperty("Максимум хп турели")]
public float MaxHealth;
[JsonProperty("Радиус агра турели (100 стандарт)")]
public float aggroRange;
[JsonProperty("Угол разлета пуль (4 - стандарт (чем меньше тем точнее))")]
public float AimCone;
[JsonProperty("Интервал между запусками ракет")]
public float FireRate;
[JsonProperty("Перезарядка между залпами")]
public float ReloadTime;
[JsonProperty("Множитель урона наносимый ракетами (1 - стандарт)")]
public float damage;
[JsonProperty("Радиус взрыва от ракеты (3 дефолт)")]
public float radius;
[JsonProperty("Максимум турелей у игрока (0 - безлимит)")]
public int MaxCount;
}
protected override void LoadDefaultConfig()
{
config = new PluginConfig
{
MaxHealth = 1500,
AimCone = 4,
aggroRange = 100,
FireRate = 0.3f,
ReloadTime = 15f,
damage = 0.6f,
radius = 3f,
MaxCount = 4
};
}
protected override void LoadConfig()
{
base.LoadConfig();
config = Config.ReadObject<PluginConfig>();
}
protected override void SaveConfig()
{
Config.WriteObject(config);
}
public DataStorage dataStorage;
public class DataStorage
{
public List<ulong> netID = new List<ulong>();
public Dictionary<ulong, int> turrentID = new Dictionary<ulong, int>();
}
void LoadData()
{
dataStorage = new DataStorage() { netID = new List<ulong>(), turrentID = new Dictionary<ulong, int>() };
if (Interface.Oxide.DataFileSystem.ExistsDatafile("TopTurret"))
{
dataStorage = Interface.Oxide.DataFileSystem.ReadObject<DataStorage>("TopTurret");
}
else
{
Interface.Oxide.DataFileSystem.WriteObject("TopTurret", dataStorage);
}
}
private void OnServerInitialized()
{
ins = this;
LoadConfig();
LoadData();
timer.Once(10f, () => RestoreTurret());
}
void Unload()
{
Interface.Oxide.DataFileSystem.WriteObject("TopTurret", dataStorage);
var objects = UnityEngine.Object.FindObjectsOfType<TurretComponent>();
foreach (var obj in objects)
if (obj != null)
UnityEngine.Object.Destroy(obj);
}
void OnServerSave()
{
Interface.Oxide.DataFileSystem.WriteObject("TopTurret", dataStorage);
}
private bool TryGetPlayerView(BasePlayer player, out Quaternion viewAngle)
{
viewAngle = new Quaternion(0f, 0f, 0f, 0f);
if (player.serverInput?.current == null) return false;
viewAngle = Quaternion.Euler(player.serverInput.current.aimAngles);
return true;
}
private void OnPlayerInput(BasePlayer player, InputState input)
{
if (!input.WasJustPressed(BUTTON.RELOAD)) return;
new Thread(new ThreadStart(delegate
{
Vector3 eyesPosition = new Vector3(0f, 0.9f, 0f);
Quaternion currentRot;
TryGetPlayerView(player, out currentRot);
var hitpoints = Physics.RaycastAll(new Ray(player.transform.position + eyesPosition, currentRot * Vector3.forward), 5f);
Array.Sort(hitpoints, (a, b) => a.distance == b.distance ? 0 : a.distance > b.distance ? 1 : -1);
for (var i = 0; i < hitpoints.Length; i++)
{
var turret = hitpoints[i].collider.GetComponentInParent<NPCAutoTurret>();
if (turret != null && turret.GetComponent<TurretComponent>() != null)
{
if (turret.authorizedPlayers.Any(x => x.userid == player.userID))
{
if (Vector3.Distance(turret.transform.position, player.transform.position) > 2) return;
turret.GetComponent<TurretComponent>().ToggleTurret();
break;
}
}
}
})).Start();
}
object OnCupboardAuthorize(BuildingPrivlidge privilege, BasePlayer player)
{
if (privilege == null || player == null)
return null;
if (privilege.GetBuilding().decayEntities.Any(x => x.ShortPrefabName.Contains("sentry.scientist.static")))
{
var turret = privilege.GetBuilding().decayEntities.Where(x => x.ShortPrefabName.Contains("sentry.scientist.static"));
foreach (var it in turret)
{
if (it.GetComponent<AutoTurret>().authorizedPlayers.Any(x => x.userid == player.userID)) continue;
it.GetComponent<AutoTurret>().authorizedPlayers.Add(new ProtoBuf.PlayerNameID() { userid = player.userID, username = player.displayName, ShouldPool = true });
it.GetComponent<AutoTurret>().SendNetworkUpdate();
}
}
return null;
}
object OnCupboardDeauthorize(BuildingPrivlidge privilege, BasePlayer player)
{
if (privilege == null || player == null)
return null;
if (privilege.GetBuilding().decayEntities.Any(x => (x as BaseEntity).ShortPrefabName.Contains("sentry.scientist.static")))
{
var turret = privilege.GetBuilding().decayEntities.Where(x => x.ShortPrefabName == "sentry.scientist.static");
foreach (var it in turret)
{
if (it.GetComponent<AutoTurret>().authorizedPlayers.Any(x => x.userid != player.userID)) continue;
it.GetComponent<AutoTurret>().authorizedPlayers.Remove(it.GetComponent<AutoTurret>().authorizedPlayers.First(x => x.userid == player.userID));
it.GetComponent<AutoTurret>().SendNetworkUpdate();
}
}
return null;
}
void RestoreTurret()
{
var ents = UnityEngine.Object.FindObjectsOfType<NPCAutoTurret>().Where(x => x.OwnerID != 0);
foreach (var turret in ents)
{
if (dataStorage.netID.Contains(turret.net.ID.Value))
{
if (turret.IsDestroyed)
{
dataStorage.netID.Remove(turret.net.ID.Value);
continue;
}
turret.GetOrAddComponent<TurretComponent>();
SetupProtection(turret);
turret.InitializeHealth(turret.health < 1000 ? turret.health : config.MaxHealth, config.MaxHealth);
turret.SendNetworkUpdate();
}
}
}
void SpawnTurret(Vector3 pos, Quaternion rot, ulong owner, float health)
{
NPCAutoTurret turret = GameManager.server.CreateEntity("assets/content/props/sentry_scientists/sentry.scientist.static.prefab", pos, rot) as NPCAutoTurret;
turret.OwnerID = owner;
turret.Spawn();
turret.InitializeHealth(health < 1000 ? health : config.MaxHealth, config.MaxHealth);
turret.gameObject.AddComponent<TurretComponent>();
turret.enableSaving = true;
turret.SetIsOnline(false);
turret.SetPeacekeepermode(false);
SetupProtection(turret);
turret.SendNetworkUpdate();
dataStorage.netID.Add(turret.net.ID.Value);
OnServerSave();
}
private void SetupProtection(BaseCombatEntity turret)
{
turret.baseProtection = ScriptableObject.CreateInstance<ProtectionProperties>();
turret.baseProtection.amounts = new float[]
{
1,1,1,1,1,0.8f,1,1,1,0.9f,0.5f,
0.5f,1,1,0,0.5f,0,1,1,0,1,0.9f
};
}
[ConsoleCommand("TopTurret")]
void SetTurret(ConsoleSystem.Arg arg)
{
if (arg.Connection != null && arg.Connection.authLevel < 2)
return;
if (arg.Args == null || arg.Args.Length < 2)
{
Puts("Use: TopTurret STEAMID amount");
return;
}
ulong uid = arg.GetUInt64(0);
int amount = arg.GetInt(1);
BasePlayer player = BasePlayer.FindByID(uid);
var item = ItemManager.CreateByName("autoturret", amount, 1756027229);
item.name = "TopTurret";
player.GiveItem(item, BaseEntity.GiveItemReason.PickedUp);
SendReply(player, "Вы получили TopTurret");
}
object OnEntityBuilt(Planner plan, GameObject obj)
{
var entity = obj.GetComponent<BaseEntity>();
if (plan == null) return null;
if (entity != null && entity.PrefabName == "assets/prefabs/npc/autoturret/autoturret_deployed.prefab" && entity.skinID == 1756027229)
{
BasePlayer player = plan.GetOwnerPlayer();
if (player == null) return null;
if (config.MaxCount > 0 && !player.IsAdmin)
{
if (!dataStorage.turrentID.ContainsKey(player.userID))
dataStorage.turrentID.Add(player.userID, 1);
else if (dataStorage.turrentID.ContainsKey(player.userID) && dataStorage.turrentID[player.userID] < config.MaxCount)
dataStorage.turrentID[player.userID]++;
else if (dataStorage.turrentID.ContainsKey(player.userID) && dataStorage.turrentID[player.userID] >= config.MaxCount)
{
SendReply(player, "Достигнут лимит установку TopTurret");
var item = ItemManager.CreateByName("autoturret", 1, 1756027229);
item.name = "TopTurret";
item.condition = entity.Health() / entity.MaxHealth() * 100;
player.GiveItem(item, BaseEntity.GiveItemReason.PickedUp);
entity.Kill();
return false;
}
}
var pos = entity.transform.position;
var rot = entity.transform.rotation;
try
{
SpawnTurret(pos, rot, player.userID, entity.Health());
}
catch (Exception ex)
{
Puts(ex.Message);
//SpawnTurret(pos, rot, player.userID, 100f);
}
NextTick(() => entity.Kill());
//SendReply(player, $"Вы установили TopTurret. Вы можете установить еще {dataStorage.turrentID[player.userID] - config.MaxCount}");
}
return null;
}
object CanPickupEntity(BasePlayer player, BaseCombatEntity entity)
{
if (entity.ShortPrefabName.Contains("sentry.scientist"))
{
if (dataStorage.turrentID.ContainsKey(entity.OwnerID) && dataStorage.turrentID[entity.OwnerID] > 0)
dataStorage.turrentID[entity.OwnerID]--;
if (dataStorage.netID.Contains(entity.net.ID.Value)) dataStorage.netID.Remove(entity.net.ID.Value);
entity.skinID = 1756027229;
}
return true;
}
void OnEntityDeath(BaseCombatEntity entity, HitInfo info)
{
try
{
if (entity?.net?.ID == null) return;
if (dataStorage.netID.Contains(entity.net.ID.Value))
dataStorage.netID.Remove(entity.net.ID.Value);
}
catch { }
}
void OnEntityKill(BaseNetworkable entity)
{
try
{
if (entity == null) return;
if (entity.net == null) return;
if (dataStorage == null) return;
if (dataStorage.netID.Contains(entity.net.ID.Value))
dataStorage.netID.Remove(entity.net.ID.Value);
}
catch { }
}
public class TurretComponent : FacepunchBehaviour
{
AutoTurret turret;
private DestroyOnGroundMissing destroyOnGroundMissing;
private GroundWatch groundWatch;
private SphereCollider sphereCollider;
Dictionary<BasePlayer, bool> ColliderPlayersList = new Dictionary<BasePlayer, bool>();
ulong netID;
ulong ownerid;
private void Awake()
{
turret = gameObject.GetComponent<AutoTurret>();
netID = turret.net.ID.Value;
ownerid = turret.OwnerID;
destroyOnGroundMissing = gameObject.GetComponent<DestroyOnGroundMissing>();
if (destroyOnGroundMissing == null)
{
gameObject.AddComponent<DestroyOnGroundMissing>();
destroyOnGroundMissing = gameObject.GetComponent<DestroyOnGroundMissing>();
}
groundWatch = gameObject.GetComponent<GroundWatch>();
if (groundWatch == null)
{
gameObject.AddComponent<GroundWatch>();
groundWatch = gameObject.GetComponent<GroundWatch>();
}
groundWatch.CancelInvoke("OnPhysicsNeighbourChanged");
groundWatch.InvokeRepeating("OnPhysicsNeighbourChanged", 0, 0.5f);
turret.sightRange = ins.config.aggroRange;
turret.aimCone = ins.config.AimCone;
this.sphereCollider = gameObject.AddComponent<SphereCollider>();
this.sphereCollider.name = $"ArtefactRadZone.{turret.net.ID}";
this.sphereCollider.transform.position = turret.transform.position;
this.sphereCollider.gameObject.layer = (int)Rust.Layer.Reserved1;
this.sphereCollider.isTrigger = true;
this.sphereCollider.radius = 3f;
InvokeRepeating("DrawInfoPlayer", 0f, 1f);
InvokeRepeating("ChectTarget", 0, 0.2f);
}
public void ToggleTurret()
{
if (turret.IsOnline())
{
turret.SetIsOnline(false);
}
else
turret.SetOnline();
}
private void OnTriggerEnter(Collider other)
{
var target = other.GetComponentInParent<BasePlayer>();
if (target != null && !ColliderPlayersList.ContainsKey(target))
ColliderPlayersList.Add(target, !target.IsAdmin);
}
private void OnTriggerExit(Collider other)
{
var target = other.GetComponentInParent<BasePlayer>();
if (target != null && ColliderPlayersList.ContainsKey(target))
ColliderPlayersList.Remove(target);
}
void DrawInfoPlayer()
{
foreach (var player in ColliderPlayersList)
{
if (!turret.authorizedPlayers.Any(x => x.userid == player.Key.userID)) continue;
if (player.Value) SetPlayerFlag(player.Key, BasePlayer.PlayerFlags.IsAdmin, true);
player.Key.SendConsoleCommand("ddraw.text", 1.01f, UnityEngine.Color.white, turret.transform.position + Vector3.up, $"<size=16>{(turret.IsOnline() ? "Нажмите R чтобы <color=red>ВЫКЛЮЧИТЬ</color> турель" : "Нажмите R чтобы <color=green>ВКЛЮЧИТЬ</color> турель")}</size>");
if (player.Value) SetPlayerFlag(player.Key, BasePlayer.PlayerFlags.IsAdmin, false);
}
}
private float lastFireMG;
private int LaunchPos = 1;
void ChectTarget()
{
if (turret.HasTarget())
{
var Distance = Vector3.Distance(turret.transform.position, turret.target.transform.position);
if (Distance < 5) return;
if (Time.realtimeSinceStartup >= lastFireMG)
{
var targetPos = turret.aimDir;
if (LaunchPos == 1)
{
Vector3 pos = turret.gun_yaw.transform.position;
CreateRocket(pos, targetPos, 3.0f / Distance);
lastFireMG = Time.realtimeSinceStartup + ins.config.FireRate;
LaunchPos++;
}
else if (LaunchPos == 2)
{
Vector3 pos2 = turret.gun_yaw.transform.position;
CreateRocket(pos2, targetPos, 3.0f / Distance);
lastFireMG = Time.realtimeSinceStartup + ins.config.FireRate;
LaunchPos++;
}
else if (LaunchPos == 3)
{
Vector3 pos2 = turret.gun_yaw.transform.position;
CreateRocket(pos2, targetPos, 3.0f / Distance);
lastFireMG = Time.realtimeSinceStartup + ins.config.FireRate;
LaunchPos++;
}
else if (LaunchPos == 4)
{
Vector3 pos2 = turret.gun_yaw.transform.position;
CreateRocket(pos2, targetPos, 3.0f / Distance);
lastFireMG = Time.realtimeSinceStartup + ins.config.ReloadTime;
LaunchPos = 1;
}
}
}
}
private void CreateRocket(Vector3 startPoint, Vector3 direction, float gravity)
{
ItemDefinition projectileItem = ItemManager.FindItemDefinition("ammo.rocket.hv");
ItemModProjectile component = projectileItem.GetComponent<ItemModProjectile>();
BaseEntity entity = GameManager.server.CreateEntity(component.projectileObject.resourcePath, startPoint, new Quaternion(), true);
TimedExplosive timedExplosive = entity.GetComponent<TimedExplosive>();
ServerProjectile serverProjectile = entity.GetComponent<ServerProjectile>();
serverProjectile.gravityModifier = gravity;
serverProjectile.speed = 200;
timedExplosive.explosionRadius = ins.config.radius;
timedExplosive.timerAmountMin = 30;
timedExplosive.timerAmountMax = 30;
ScaleAllDamage(timedExplosive.damageTypes, ins.config.damage);
entity.SendMessage("InitializeVelocity", (object)(direction * 30f));
entity.Spawn();
}
private void ScaleAllDamage(List<DamageTypeEntry> damageTypes, float scale)
{
for (int i = 0; i < damageTypes.Count; i++)
damageTypes[i].amount *= scale;
}
void SetPlayerFlag(BasePlayer player, BasePlayer.PlayerFlags f, bool b)
{
if (b)
{
if (player.HasPlayerFlag(f)) return;
player.playerFlags |= f;
}
else
{
if (!player.HasPlayerFlag(f)) return;
player.playerFlags &= ~f;
}
player.SendNetworkUpdateImmediate(false);
}
void Update()
{
CheckTarget();
}
void CheckTarget()
{
if (turret.target is SamSite)
turret.target = null;
}
private void OnDestroy()
{
if (ins.dataStorage.turrentID.ContainsKey(ownerid) && ins.dataStorage.turrentID[ownerid] > 0)
ins.dataStorage.turrentID[ownerid]--;
if (ins.dataStorage.netID.Contains(netID))
ins.dataStorage.netID.Remove(netID);
Destroy(this);
}
}
}
}