C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using Rust;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
/* TODO:
- Finish anti-air turrets MonoBehviour ✓
- Heat seeking rockets? ✓
- Give the anti-air turrets a different aesthetic ✓
- Handle the data for anti air turrets (loading / unloading) ✓
- Return items on pickup / downgrade back to normal turret ✓
- upgrades / different tiers for the rocket turret (increased rocket speed / shot speed / heatseeking rockets)
- Grenade turrets?
- Make custom permissions at least for per player limits, please.- Stop turrets from shooting animals
BUGS:
1.anti-air turrets don't lose their health on projectile impact/splash damage.(idk if this is (efficently) possible)
2.make custom permissions at least for per player limits, please.(WIP)
3.heat seeking rocket feature don't work or i don't understand how it should to work =] ✓
UPDATE LOG:
- Optimized plugin loading (using CoRoutine to initialize all rocket turrets)
*/
namespace Oxide.Plugins
{
[Info("RocketTurrets", "redBDGR", "1.3.7")]
[Description("Create rocket shooting turrets")]
class RocketTurrets : RustPlugin
{
private bool changed;
private List<AutoTurret> rocketTurrets = new List<AutoTurret>();
private List<AutoTurret> antiairTurrets = new List<AutoTurret>();
private List<AutoTurret> javelinTurrets = new List<AutoTurret>();
private Dictionary<string, PlayerData> turretNumbers = new Dictionary<string, PlayerData>();
private List<ulong> turretIDs = new List<ulong>();
private List<ulong> antiAirIDs = new List<ulong>();
private List<ulong> javelinIDs = new List<ulong>();
private static RocketTurrets plugin;
public static LayerMask collLayers = LayerMask.GetMask("Construction", "Deployed", "Tree", "Terrain", "Resource", "World", "Water", "Default", "AI");
#region Config Variables
// Rocket turrets
private float rocketFireRate = 1.2f;
private float rocketLockonTime = 5f;
private float minHitDistance = 10f;
private float rocketLockonRadius = 40f;
private float rocketSpeed = 20f;
private uint rocketLauncherSkin;
private float explosionRadius = 4f;
private bool explodeAtTarget = true;
private int lockonSoundEveryxUpdate = 100;
private bool requiresAmmo = true;
private int maxNumberAllowed = 5;
private bool rocketHeatSeeking;
// AA turrets
private float aaFireRate = 1.2f;
private float aaLockonTime = 5f;
private float aaminHitDistance = 5f;
private float aaLockonRadius = 150f;
private float aarocketSpeed = 40f;
private uint aaLauncherSkin;
private float aaexplosionRadius = 4f;
private int aalockonSoundEveryxUpdate = 100;
private float damageToHeli = 500f;
private bool aaRequiresAmmo = true;
private int aaMaxNumberAllowed = 5;
private bool aaRequireBuildingRightsToAccessInventory = true;
// Javelin Turrets
private float jrocketFireRate = 1.2f;
private float jrocketLockonTime = 5f;
private float jminHitDistance = 10f;
private float jrocketLockonRadius = 40f;
private float jrocketSpeed = 20f;
private uint jrocketLauncherSkin;
private float jexplosionRadius = 4f;
private int jlockonSoundEveryxUpdate = 100;
private bool jrequiresAmmo = true;
private int jmaxNumberAllowed = 5;
private bool jSeekTarget = true;
private float jHeightBeforeCurve = 40f;
// Global vars
private bool returnCostOnPickup;
private bool returnCostOnDowngrade;
#region Config Lists
private static Dictionary<string, object> RocketUpgradeCost()
{
var at = new Dictionary<string, object> { { "rocket.launcher", 1 } };
return at;
}
private static Dictionary<string, object> AntiAirUpgradeCost()
{
var at = new Dictionary<string, object> { { "targeting.computer", 1 }, { "cctv.camera", 2 }, { "rocket.launcher", 1 } };
return at;
}
private static Dictionary<string, object> JavelinUpgradeCost()
{
var at = new Dictionary<string, object> { { "rocket.launcher", 1 } };
return at;
}
private Dictionary<string, object> rocketUpgradeCost;
private Dictionary<string, object> antiAirUpgradeCost;
private Dictionary<string, object> javelinUpgradeCost;
#endregion
#endregion
#region Permissions
private const string permissionName = "rocketturrets.use";
private const string permissionNameROCKET = "rocketturrets.rocket";
private const string permissionNameANTIAIR = "rocketturrets.antiair";
private const string permissionNameJAVELIN = "rocketturrets.javelin";
private const string permissionNameUNLIMITED = "rocketturrets.unlimited";
#endregion
#region Classes
private class StoredData
{
public List<ulong> turretIDs = new List<ulong>();
public List<ulong> antiAirIDs = new List<ulong>();
public List<ulong> javelinIDs = new List<ulong>();
}
private class StoredData2
{
public Dictionary<string, PlayerData> turretNumbers = new Dictionary<string, PlayerData>();
}
private class PlayerData
{
public int RocketTurrets;
public int AntiAirTurrets;
public int JavelinTurrets;
}
#endregion
#region Data Handling
private DynamicConfigFile data;
private DynamicConfigFile data2;
private StoredData storedData;
private StoredData2 storedData2;
private void OnServerSave() => SaveData();
private void SaveData()
{
storedData.turretIDs = turretIDs;
storedData.antiAirIDs = antiAirIDs;
storedData.javelinIDs = javelinIDs;
storedData2.turretNumbers = turretNumbers;
data.WriteObject(storedData);
data2.WriteObject(storedData2);
}
private void LoadData()
{
try
{
storedData = data.ReadObject<StoredData>();
storedData2 = data2.ReadObject<StoredData2>();
turretNumbers = storedData2.turretNumbers;
turretIDs = storedData.turretIDs;
antiAirIDs = storedData.antiAirIDs;
javelinIDs = storedData.javelinIDs;
}
catch
{
Puts("Failed to load data, creating new file");
storedData = new StoredData();
}
}
#endregion
#region Config Loading
protected override void LoadDefaultConfig()
{
Config.Clear();
LoadVariables();
}
private void LoadVariables()
{
// Rocket turret settings
rocketFireRate = Convert.ToSingle(GetConfig("Turret Settings", "Rocket fire rate", 2f));
rocketLockonTime = Convert.ToSingle(GetConfig("Turret Settings", "Lockon length", 5f));
minHitDistance = Convert.ToSingle(GetConfig("Turret Settings", "Min shoot distance", 4f));
rocketLockonRadius = Convert.ToSingle(GetConfig("Turret Settings", "Rocket lockon radius", 40f));
rocketSpeed = Convert.ToSingle(GetConfig("Turret Settings", "Rocket speed", 20f));
rocketLauncherSkin = Convert.ToUInt32(GetConfig("Turret Settings", "Default rocket model skin", 0));
explosionRadius = Convert.ToSingle(GetConfig("Turret Settings", "Explosion radius", 4f));
explodeAtTarget = Convert.ToBoolean(GetConfig("Turret Settings", "Explode at target pos", true));
lockonSoundEveryxUpdate = Convert.ToInt32(GetConfig("Turret Settings", "Lockon sound every x updates", 100));
requiresAmmo = Convert.ToBoolean(GetConfig("Turret Settings", "Requires Ammo", true));
maxNumberAllowed = Convert.ToInt16(GetConfig("Turret Settings", "Maximum Allowed Per Player", 5));
rocketHeatSeeking = Convert.ToBoolean(GetConfig("Turret Settings", "Heatseeking Rockets", false));
// AntiAir turret settings
aaFireRate = Convert.ToSingle(GetConfig("AntiAir Settings", "Rocket fire rate", 2f));
aaLockonTime = Convert.ToSingle(GetConfig("AntiAir Settings", "Lockon length", 5f));
aaminHitDistance = Convert.ToSingle(GetConfig("AntiAir Settings", "Min shoot distance", 4f));
aaLockonRadius = Convert.ToSingle(GetConfig("AntiAir Settings", "Lockon radius", 80f));
aarocketSpeed = Convert.ToSingle(GetConfig("AntiAir Settings", "Rocket speed", 30f));
aaLauncherSkin = Convert.ToUInt32(GetConfig("AntiAir Settings", "Default rocket model skin", 0));
aaexplosionRadius = Convert.ToSingle(GetConfig("AntiAir Settings", "Explosion radius", 4f));
aalockonSoundEveryxUpdate = Convert.ToInt32(GetConfig("AntiAir Settings", "Lockon sound every x updates", 100));
damageToHeli = Convert.ToSingle(GetConfig("AntiAir Settings", "Damage to heli", 500f));
aaRequiresAmmo = Convert.ToBoolean(GetConfig("AntiAir Settings", "Requires Ammo", true));
aaMaxNumberAllowed = Convert.ToInt16(GetConfig("AntiAir Settings", "Maximum Allowed Per Player", 5));
aaRequireBuildingRightsToAccessInventory = Convert.ToBoolean(GetConfig("AntiAir Settings", "Require Build Acces to Loot", true));
// Javelin turret settings
jrocketFireRate = Convert.ToSingle(GetConfig("Javelin Settings", "Rocket fire rate", 2f));
jrocketLockonTime = Convert.ToSingle(GetConfig("Javelin Settings", "Lockon Length", 5f));
jminHitDistance = Convert.ToSingle(GetConfig("Javelin Settings", "Min lockon distance", 10f));
jrocketLockonRadius = Convert.ToSingle(GetConfig("Javelin Settings", "Lockon radius", 80f));
jrocketSpeed = Convert.ToSingle(GetConfig("Javelin Settings", "Rocket speed", 15f));
jrocketLauncherSkin = Convert.ToUInt32(GetConfig("Javelin Settings", "Default rocket model skin", 0));
jexplosionRadius = Convert.ToSingle(GetConfig("Javelin Settings", "Explosion radius", 4f));
jlockonSoundEveryxUpdate = Convert.ToInt16(GetConfig("Javelin Settings", "Lockon sound every x updates", 100));
jrequiresAmmo = Convert.ToBoolean(GetConfig("Javelin Settings", "Requires ammo", true));
jmaxNumberAllowed = Convert.ToInt16(GetConfig("Javelin Settings", "Max number allowed per player", 5));
jSeekTarget = Convert.ToBoolean(GetConfig("Javelin Settings", "Seek target", true));
jHeightBeforeCurve = Convert.ToSingle(GetConfig("Javelin Settings", "Height before curve starts", 40f));
// Costs
rocketUpgradeCost = (Dictionary<string, object>) GetConfig("Turret Settings", "[ Cost to upgrade - Rocket tier ]", RocketUpgradeCost());
antiAirUpgradeCost = (Dictionary<string, object>) GetConfig("AntiAir Settings", "[Cost to Upgrade - AntiAir Tier ]", AntiAirUpgradeCost());
javelinUpgradeCost = (Dictionary<string, object>) GetConfig("Javelin Settings", "[ Cost to upgrade - Javelin Tier ]", JavelinUpgradeCost());
returnCostOnPickup = Convert.ToBoolean(GetConfig("General Settings", "Return upgrade cost on turret pickup", false));
returnCostOnDowngrade = Convert.ToBoolean(GetConfig("General Settings", "Return upgrade cost on turret downgrade", false));
if (!changed) return;
SaveConfig();
changed = false;
}
#endregion
#region API
[HookMethod("IsRocketTurret")]
public bool IsRocketTurret(AutoTurret turret) => turret.GetComponent<RocketTurret>();
[HookMethod("ToggleTurretAutomation")]
public void ToggleTurretAutomation(AutoTurret turret, bool enabled)
{
if (turret.GetComponent<RocketTurret>())
turret.GetComponent<RocketTurret>().enabled = true;
}
[HookMethod("TryFireRocket")]
public void TryFireRocket(AutoTurret turret)
{
if (turret.GetComponent<RocketTurret>())
turret.GetComponent<RocketTurret>().TryFireRocket();
}
#endregion
#region MonoBehaviour Classes
#region Turret Classes
private class RocketTurret : MonoBehaviour
{
private float aimRadius = plugin.rocketLockonRadius;
private float fireRate = plugin.rocketFireRate;
private float rocketSpeed = plugin.rocketSpeed;
private float minHitDistance = plugin.minHitDistance;
private float lockonTime = plugin.rocketLockonTime;
private uint rocketLauncherSkin = plugin.rocketLauncherSkin;
private float explosionRadius = plugin.explosionRadius;
private bool explodeOnTargetPos = plugin.explodeAtTarget;
private int soundEveryxUpdates = plugin.lockonSoundEveryxUpdate;
private bool requiresAmmo = plugin.requiresAmmo;
private bool heatSeek = plugin.rocketHeatSeeking;
private int updateCounter;
private bool isLockedOn;
private bool isLockingOn;
private float lockonFinish;
private float nextShoot;
private AutoTurret turret;
private BaseCombatEntity target;
private DroppedItem launcher_1;
private DroppedItem rocket_1;
private DroppedItem rocket_2;
private DestroyOnGroundMissing desGround;
private GroundWatch groundWatch;
private void Awake()
{
turret = gameObject.GetComponent<AutoTurret>();
InitAesthetics();
if (!plugin.rocketTurrets.Contains(turret))
plugin.rocketTurrets.Add(turret);
turret.sightRange = aimRadius;
if (!plugin.turretIDs.Contains(turret.net.ID))
plugin.turretIDs.Add(turret.net.ID);
desGround = GetComponent<DestroyOnGroundMissing>();
if (!desGround)
gameObject.AddComponent<DestroyOnGroundMissing>();
groundWatch = GetComponent<GroundWatch>();
if (!groundWatch)
gameObject.AddComponent<GroundWatch>();
groundWatch.CancelInvoke("OnPhysicsNeighbourChanged");
groundWatch.InvokeRepeating("OnPhysicsNeighbourChanged", 0, 0.5f);
}
private void Update()
{
if (!turret.HasTarget())
{
if (isLockedOn)
isLockedOn = false;
if (isLockingOn)
isLockingOn = false;
return;
}
if (!isLockedOn)
{
if (!isLockingOn)
{
lockonFinish = Time.time + lockonTime;
isLockingOn = true;
}
else if (isLockingOn && Time.time > lockonFinish)
LockToTarget(turret.target);
else if (isLockingOn)
{
if (updateCounter == soundEveryxUpdates)
{
Effect.server.Run("assets/prefabs/locks/keypad/effects/lock.code.unlock.prefab", turret.transform.position);
updateCounter = 0;
return;
}
updateCounter++;
}
}
else
{
if (Time.time < nextShoot)
return;
if (Vector3.Distance(turret.muzzlePos.transform.position, turret.target.transform.position) < minHitDistance)
return;
var rocketItem = HasAmmo();
if (rocketItem == null)
return;
FireRocket(rocketItem);
nextShoot = Time.time + fireRate;
}
}
private void OnDestroy()
{
if (!launcher_1.IsDestroyed)
launcher_1.Kill();
if (!rocket_1.IsDestroyed)
rocket_1.Kill();
if (!rocket_2.IsDestroyed)
rocket_2.Kill();
}
public void Destroy()
{
if (plugin.rocketTurrets.Contains(turret))
plugin.rocketTurrets.Remove(turret);
if (plugin.turretIDs.Contains(turret.net.ID))
plugin.turretIDs.Remove(turret.net.ID);
OnDestroy();
//turret.Kill(BaseNetworkable.DestroyMode.Gib);
if (this)
Destroy(this);
}
private void DestroyTurret()
{
if (turret != null)
turret.Kill(BaseNetworkable.DestroyMode.Gib);
}
public void UnloadDestroy()
{
if (plugin.rocketTurrets.Contains(turret))
plugin.rocketTurrets.Remove(turret);
OnDestroy();
Destroy(this);
}
private Item HasAmmo()
{
return !requiresAmmo ? ItemManager.CreateByItemID(-742865266) : turret.inventory.itemList.FirstOrDefault(item => item.info.itemid == -742865266 || item.info.itemid == 1638322904 || item.info.itemid == -1841918730);
}
private void LockToTarget(BaseCombatEntity entity)
{
isLockedOn = true;
isLockingOn = false;
nextShoot = Time.time + 0.3f;
target = entity;
}
private void InitAesthetics()
{
// Rocket Launcher
launcher_1 = ItemManager.CreateByItemID(442886268, 1, rocketLauncherSkin).Drop(turret.transform.position, Vector3.zero).GetComponent<DroppedItem>();
launcher_1.GetComponent<Rigidbody>().isKinematic = true;
launcher_1.GetComponent<Rigidbody>().useGravity = false;
launcher_1.allowPickup = false;
launcher_1.CancelInvoke((Action)Delegate.CreateDelegate(typeof(Action), launcher_1, "IdleDestroy"));
// rocket_1
rocket_1 = ItemManager.CreateByItemID(-742865266).Drop(turret.transform.position, Vector3.zero).GetComponent<DroppedItem>();
rocket_1.GetComponent<Rigidbody>().isKinematic = true;
rocket_1.GetComponent<Rigidbody>().useGravity = false;
rocket_1.allowPickup = false;
rocket_1.CancelInvoke((Action)Delegate.CreateDelegate(typeof(Action), rocket_1, "IdleDestroy"));
// rocket_2
rocket_2 = ItemManager.CreateByItemID(-742865266).Drop(turret.transform.position, Vector3.zero).GetComponent<DroppedItem>();
rocket_2.GetComponent<Rigidbody>().isKinematic = true;
rocket_2.GetComponent<Rigidbody>().useGravity = false;
rocket_2.allowPickup = false;
rocket_2.CancelInvoke((Action)Delegate.CreateDelegate(typeof(Action), rocket_2, "IdleDestroy"));
var launcherRot = new Vector3();
var rocketRot = new Vector3();
foreach (var entry in turret.gameObject.transform.GetAllChildren())
{
if (entry.name != "weapon_socket") continue;
// launcher rot
launcherRot = entry.gameObject.transform.localRotation.eulerAngles;
launcherRot = new Vector3(launcherRot.x, launcherRot.y + 180, launcherRot.z);
// rocket rot
rocketRot = entry.gameObject.transform.localRotation.eulerAngles;
rocketRot = new Vector3(rocketRot.x, rocketRot.y + 270, rocketRot.z);
}
// launcher_1
launcher_1.SetParent(turret, "weapon_socket");
launcher_1.transform.localPosition = new Vector3(0, 0, 0);
launcher_1.transform.localRotation = Quaternion.Euler(launcherRot);
// rocket_1
rocket_1.SetParent(turret, "weapon_socket");
rocket_1.transform.localPosition = new Vector3(0, -0.05f, 0.17f);
rocket_1.transform.localRotation = Quaternion.Euler(rocketRot);
// rocket_2
rocket_2.SetParent(turret, "weapon_socket");
rocket_2.transform.localPosition = new Vector3(0, -0.05f, -0.17f);
rocket_2.transform.localRotation = Quaternion.Euler(rocketRot);
}
public void TryFireRocket()
{
if (Time.time < nextShoot)
return;
var rocketItem = HasAmmo();
if (rocketItem == null)
return;
FireRocket(rocketItem);
nextShoot = Time.time + fireRate;
}
private void FireRocket(Item rocketItem)
{
ServerProjectile rocket = CreateRocket(turret.muzzlePos.transform.position, rocketItem);
if (rocket == null)
return;
TimedExplosive expl = rocket.gameObject.GetComponent<TimedExplosive>();
// Explosion settings
if (enabled && explodeOnTargetPos)
{
float dist = Vector3.Distance(turret.muzzlePos.position, turret.target.transform.position);
float time = dist / rocketSpeed;
expl.SetFuse(time);
}
expl.explosionRadius = explosionRadius;
// Rocket settings
rocket.gravityModifier = 0f;
rocket.speed = rocketSpeed;
rocket.InitializeVelocity(turret.muzzlePos.transform.forward);
Effect.server.Run("assets/prefabs/npc/patrol helicopter/effects/rocket_fire.prefab", turret.muzzlePos.position);
if (heatSeek)
if (this.target != null)
rocket.gameObject.AddComponent<HeatRocket>().target = target;
}
private ServerProjectile CreateRocket(Vector3 launchPos, Item rocketItem)
{
if (requiresAmmo)
{
if (rocketItem == null)
return null;
if (rocketItem.amount == 1)
rocketItem.RemoveFromContainer();
else
rocketItem.UseItem();
}
else
rocketItem.RemoveFromContainer();
BaseEntity rocket;
switch (rocketItem.info.shortname)
{
case "ammo.rocket.basic":
rocket = GameManager.server.CreateEntity("assets/prefabs/ammo/rocket/rocket_basic.prefab", launchPos);
break;
case "ammo.rocket.fire":
rocket = GameManager.server.CreateEntity("assets/prefabs/ammo/rocket/rocket_fire.prefab", launchPos);
break;
case "ammo.rocket.hv":
rocket = GameManager.server.CreateEntity("assets/prefabs/ammo/rocket/rocket_hv.prefab", launchPos);
break;
default:
return null;
}
if (rocket == null) return null;
rocket.creatorEntity = turret;
rocket.Spawn();
if (target != null)
{
rocket.transform.LookAt(target.transform);
rocket.GetComponent<ServerProjectile>()?.InitializeVelocity(target.transform.position);
}
else
{
rocket.transform.LookAt(turret.muzzlePos.position + turret.muzzlePos.forward.normalized * 10);
rocket.GetComponent<ServerProjectile>()?.InitializeVelocity(turret.muzzlePos.position + turret.muzzlePos.forward * 10);
}
return rocket.GetComponent<ServerProjectile>();
}
}
private class AntiAirTurret : MonoBehaviour
{
private float aimRadius = plugin.aaLockonRadius;
private float fireRate = plugin.aaFireRate;
private float rocketSpeed = plugin.aarocketSpeed;
private float minHitDistance = plugin.aaminHitDistance;
private float lockonTime = plugin.aaLockonTime;
private uint rocketLauncherSkin = plugin.aaLauncherSkin;
private float explosionRadius = plugin.aaexplosionRadius;
private int soundEveryxUpdates = plugin.aalockonSoundEveryxUpdate;
private float damage = plugin.damageToHeli;
private bool requiresAmmo = plugin.aaRequiresAmmo;
private int updateCounter;
private bool isLockedOn;
private bool isLockingOn;
private float lockonFinish;
private float nextShoot;
private AutoTurret turret;
private BaseEntity entity;
private BaseCombatEntity target;
private DestroyOnGroundMissing desGround;
private GroundWatch groundWatch;
// Models
private DroppedItem launcher_1;
private DroppedItem rocket_1;
private DroppedItem rocket_2;
private DroppedItem computer;
private DroppedItem camera_1;
private DroppedItem camera_2;
private void Awake()
{
turret = gameObject.GetComponent<AutoTurret>();
InitAesthetics();
turret.SetIsOnline(false);
if (!plugin.antiairTurrets.Contains(turret))
plugin.antiairTurrets.Add(turret);
turret.sightRange = 0.1f;
if (!plugin.antiAirIDs.Contains(turret.net.ID))
plugin.antiAirIDs.Add(turret.net.ID);
entity = gameObject.GetComponent<BaseEntity>();
var collider = entity.gameObject.AddComponent<SphereCollider>();
collider.gameObject.layer = (int)Layer.Reserved1;
collider.radius = aimRadius;
collider.isTrigger = true;
desGround = GetComponent<DestroyOnGroundMissing>();
if (!desGround)
gameObject.AddComponent<DestroyOnGroundMissing>();
groundWatch = GetComponent<GroundWatch>();
if (!groundWatch)
gameObject.AddComponent<GroundWatch>();
groundWatch.CancelInvoke("OnPhysicsNeighbourChanged");
groundWatch.InvokeRepeating("OnPhysicsNeighbourChanged", 0, 0.5f);
}
private void Update()
{
if (target == null)
{
if (isLockedOn)
isLockedOn = false;
if (isLockingOn)
isLockingOn = false;
return;
}
if (!isLockedOn)
{
turret.target = target;
turret.UpdateFacingToTarget();
if (!isLockingOn)
{
lockonFinish = Time.time + lockonTime;
isLockingOn = true;
}
else if (isLockingOn && Time.time > lockonFinish)
LockToTarget(turret.target);
else if (isLockingOn)
{
if (updateCounter == soundEveryxUpdates)
{
Effect.server.Run("assets/prefabs/locks/keypad/effects/lock.code.unlock.prefab", turret.transform.position);
updateCounter = 0;
return;
}
updateCounter++;
}
}
else
{
if (Time.time < nextShoot)
return;
if (Vector3.Distance(turret.muzzlePos.transform.position, turret.target.transform.position) < minHitDistance)
return;
var rocketItem = HasAmmo();
if (rocketItem == null)
return;
FireRocket(rocketItem);
nextShoot = Time.time + fireRate;
}
}
private void OnTriggerEnter(Collider col)
{
if (col.name != "patrol_helicopter")
return;
BaseCombatEntity heli = col.GetComponentInParent<BaseCombatEntity>();
target = heli;
}
private void OnTriggerExit(Collider col)
{
if (col.name != "patrol_helicopter")
return;
turret.target = null;
turret.SetTarget(null);
target = null;
}
/*
private void OnTriggerExit(Collider col)
{
if (col.name != "patrol_helicopter")
return;
turret.target = null;
target = null;
}
*/
private void OnDestroy()
{
if (!launcher_1.IsDestroyed)
launcher_1.Kill();
if (!rocket_1.IsDestroyed)
rocket_1.Kill();
if (!rocket_2.IsDestroyed)
rocket_2.Kill();
if (!computer.IsDestroyed)
computer.Kill();
if (!camera_1.IsDestroyed)
camera_1.Kill();
if (!camera_2.IsDestroyed)
camera_2.Kill();
}
public void Destroy()
{
if (plugin.antiairTurrets.Contains(turret))
plugin.antiairTurrets.Remove(turret);
if (plugin.turretIDs.Contains(turret.net.ID))
plugin.turretIDs.Remove(turret.net.ID);
OnDestroy();
Destroy(this);
}
private void DestroyTurret()
{
if (turret != null)
turret.Kill(BaseNetworkable.DestroyMode.Gib);
}
public void UnloadDestroy()
{
if (plugin.antiairTurrets.Contains(turret))
plugin.antiairTurrets.Remove(turret);
OnDestroy();
Destroy(this);
}
private Item HasAmmo()
{
return !requiresAmmo ? ItemManager.CreateByItemID(-742865266) : turret.inventory.itemList.FirstOrDefault(item => item.info.itemid == -742865266 || item.info.itemid == 1638322904 || item.info.itemid == -1841918730);
}
private void LockToTarget(BaseCombatEntity _entity)
{
isLockedOn = true;
isLockingOn = false;
nextShoot = Time.time + 0.3f;
target = _entity;
}
private void InitAesthetics()
{
// Rocket Launcher
launcher_1 = ItemManager.CreateByItemID(442886268, 1, rocketLauncherSkin).Drop(turret.transform.position, Vector3.zero).GetComponent<DroppedItem>();
launcher_1.GetComponent<Rigidbody>().isKinematic = true;
launcher_1.GetComponent<Rigidbody>().useGravity = false;
launcher_1.allowPickup = false;
launcher_1.CancelInvoke((Action)Delegate.CreateDelegate(typeof(Action), launcher_1, "IdleDestroy"));
// rocket_1
rocket_1 = ItemManager.CreateByItemID(-742865266).Drop(turret.transform.position, Vector3.zero).GetComponent<DroppedItem>();
rocket_1.GetComponent<Rigidbody>().isKinematic = true;
rocket_1.GetComponent<Rigidbody>().useGravity = false;
rocket_1.allowPickup = false;
rocket_1.CancelInvoke((Action)Delegate.CreateDelegate(typeof(Action), rocket_1, "IdleDestroy"));
// rocket_2
rocket_2 = ItemManager.CreateByItemID(-742865266).Drop(turret.transform.position, Vector3.zero).GetComponent<DroppedItem>();
rocket_2.GetComponent<Rigidbody>().isKinematic = true;
rocket_2.GetComponent<Rigidbody>().useGravity = false;
rocket_2.allowPickup = false;
rocket_2.CancelInvoke((Action)Delegate.CreateDelegate(typeof(Action), rocket_2, "IdleDestroy"));
// computer
computer = ItemManager.CreateByItemID(1523195708).Drop(turret.transform.position, Vector3.zero).GetComponent<DroppedItem>();
computer.GetComponent<Rigidbody>().isKinematic = true;
computer.GetComponent<Rigidbody>().useGravity = false;
computer.allowPickup = false;
computer.CancelInvoke((Action)Delegate.CreateDelegate(typeof(Action), computer, "IdleDestroy"));
// camera_1
camera_1 = ItemManager.CreateByItemID(634478325).Drop(turret.transform.position, Vector3.zero).GetComponent<DroppedItem>();
camera_1.GetComponent<Rigidbody>().isKinematic = true;
camera_1.GetComponent<Rigidbody>().useGravity = false;
camera_1.allowPickup = false;
camera_1.CancelInvoke((Action)Delegate.CreateDelegate(typeof(Action), camera_1, "IdleDestroy"));
// camera_2
camera_2 = ItemManager.CreateByItemID(634478325).Drop(turret.transform.position, Vector3.zero).GetComponent<DroppedItem>();
camera_2.GetComponent<Rigidbody>().isKinematic = true;
camera_2.GetComponent<Rigidbody>().useGravity = false;
camera_2.allowPickup = false;
camera_2.CancelInvoke((Action)Delegate.CreateDelegate(typeof(Action), camera_2, "IdleDestroy"));
Vector3 computerRot = turret.gameObject.transform.localRotation.eulerAngles;
computerRot = new Vector3(computerRot.x, computerRot.y + 240, computerRot.z);
computer.SetParent(turret);
computer.transform.localPosition = new Vector3(0.45f, 0, 0.25f);
computer.transform.rotation = Quaternion.Euler(computerRot);
Vector3 launcherRot = new Vector3();
Vector3 rocketRot = new Vector3();
foreach (var entry in turret.gameObject.transform.GetAllChildren())
{
if (entry.name != "weapon_socket") continue;
// launcher rot
launcherRot = entry.gameObject.transform.localRotation.eulerAngles;
launcherRot = new Vector3(launcherRot.x, launcherRot.y + 180, launcherRot.z);
// rocket rot
rocketRot = entry.gameObject.transform.localRotation.eulerAngles;
rocketRot = new Vector3(rocketRot.x, rocketRot.y + 270, rocketRot.z);
}
// launcher_1
launcher_1.SetParent(turret, "weapon_socket");
launcher_1.transform.localPosition = new Vector3(0, 0, 0);
launcher_1.transform.localRotation = Quaternion.Euler(launcherRot);
// rocket_1
rocket_1.SetParent(turret, "weapon_socket");
rocket_1.transform.localPosition = new Vector3(0, -0.05f, 0.17f);
rocket_1.transform.localRotation = Quaternion.Euler(rocketRot);
// rocket_2
rocket_2.SetParent(turret, "weapon_socket");
rocket_2.transform.localPosition = new Vector3(0, -0.05f, -0.17f);
rocket_2.transform.localRotation = Quaternion.Euler(rocketRot);
// camera_1
camera_1.SetParent(turret, "weapon_socket");
camera_1.transform.localPosition = new Vector3(0, 0.05f, -0.17f);
camera_1.transform.localRotation = Quaternion.Euler(rocketRot);
// camera_2
camera_2.SetParent(turret, "weapon_socket");
camera_2.transform.localPosition = new Vector3(0, 0.05f, 0.17f);
camera_2.transform.localRotation = Quaternion.Euler(rocketRot);
}
private void FireRocket(Item rocketItem)
{
ServerProjectile rocket = CreateRocket(turret.muzzlePos.transform.position, rocketItem);
if (rocket == null)
return;
TimedExplosive expl = rocket.gameObject.GetComponent<TimedExplosive>();
// Explosion settings
float dist = Vector3.Distance(turret.muzzlePos.position, turret.target.transform.position);
float time = dist / rocketSpeed;
//expl.SetFuse(time);
plugin.timer.Once(time - 4f, () =>
{
if (target)
target.Hurt(damage);
});
expl.explosionRadius = explosionRadius;
// Rocket settings
rocket.gravityModifier = 0f;
rocket.speed = rocketSpeed;
rocket.InitializeVelocity(turret.muzzlePos.transform.forward);
Effect.server.Run("assets/prefabs/npc/patrol helicopter/effects/rocket_fire.prefab", turret.muzzlePos.position);
rocket.gameObject.AddComponent<HeatRocket>().target = turret.target;
}
private ServerProjectile CreateRocket(Vector3 launchPos, Item rocketItem)
{
if (requiresAmmo)
{
if (rocketItem == null)
return null;
if (rocketItem.amount == 1)
rocketItem.RemoveFromContainer();
else
rocketItem.UseItem();
}
BaseEntity rocket;
switch (rocketItem.info.shortname)
{
case "ammo.rocket.basic":
rocket = GameManager.server.CreateEntity("assets/prefabs/ammo/rocket/rocket_basic.prefab", launchPos);
break;
case "ammo.rocket.fire":
rocket = GameManager.server.CreateEntity("assets/prefabs/ammo/rocket/rocket_fire.prefab", launchPos);
break;
case "ammo.rocket.hv":
rocket = GameManager.server.CreateEntity("assets/prefabs/ammo/rocket/rocket_hv.prefab", launchPos);
break;
default:
return null;
}
if (rocket == null) return null;
rocket.Spawn();
rocket.transform.LookAt(target.transform);
return rocket.GetComponent<ServerProjectile>();
}
}
private class JavelinTurret : MonoBehaviour
{
private float aimRadius = plugin.jrocketLockonRadius;
private float fireRate = plugin.jrocketFireRate;
private float rocketSpeed = plugin.jrocketSpeed;
private float minHitDistance = plugin.jminHitDistance;
private float lockonTime = plugin.jrocketLockonTime;
private uint rocketLauncherSkin = plugin.jrocketLauncherSkin;
private float explosionRadius = plugin.jexplosionRadius;
private int soundEveryxUpdates = plugin.jlockonSoundEveryxUpdate;
private bool requiresAmmo = plugin.jrequiresAmmo;
private bool seekTarget = plugin.jSeekTarget;
private int updateCounter;
private bool isLockedOn;
private bool isLockingOn;
private float lockonFinish;
private float nextShoot;
private AutoTurret turret;
private BaseCombatEntity target;
private BaseCombatEntity externalTarget;
private DroppedItem launcher_1;
private DroppedItem rocket_1;
private DroppedItem rocket_2;
private DestroyOnGroundMissing desGround;
private GroundWatch groundWatch;
private void Awake()
{
turret = gameObject.GetComponent<AutoTurret>();
InitAesthetics();
if (!plugin.javelinTurrets.Contains(turret))
plugin.javelinTurrets.Add(turret);
turret.sightRange = aimRadius;
if (!plugin.javelinIDs.Contains(turret.net.ID))
plugin.javelinIDs.Add(turret.net.ID);
desGround = GetComponent<DestroyOnGroundMissing>();
if (!desGround)
gameObject.AddComponent<DestroyOnGroundMissing>();
groundWatch = GetComponent<GroundWatch>();
if (!groundWatch)
gameObject.AddComponent<GroundWatch>();
groundWatch.CancelInvoke("OnPhysicsNeighbourChanged");
groundWatch.InvokeRepeating("OnPhysicsNeighbourChanged", 0, 0.5f);
// Collider add
SphereCollider collider = turret.gameObject.AddComponent<SphereCollider>();
collider.gameObject.layer = (int)Layer.Reserved1;
collider.radius = aimRadius;
collider.isTrigger = true;
}
private void Update()
{
if (externalTarget)
{
turret.SetTarget(externalTarget);
turret.UpdateAiming();
}
if (!turret.HasTarget())
{
if (isLockedOn)
isLockedOn = false;
if (isLockingOn)
isLockingOn = false;
return;
}
if (!isLockedOn)
{
if (!isLockingOn)
{
lockonFinish = Time.time + lockonTime;
isLockingOn = true;
}
else if (isLockingOn && Time.time > lockonFinish)
LockToTarget(turret.target);
else if (isLockingOn)
{
if (updateCounter == soundEveryxUpdates)
{
Effect.server.Run("assets/prefabs/locks/keypad/effects/lock.code.unlock.prefab", turret.transform.position);
updateCounter = 0;
return;
}
updateCounter++;
}
}
else
{
if (Time.time < nextShoot)
return;
if (Vector3.Distance(turret.muzzlePos.transform.position, turret.target.transform.position) < minHitDistance)
return;
var rocketItem = HasAmmo();
if (rocketItem == null)
return;
FireRocket(rocketItem);
nextShoot = Time.time + fireRate;
}
}
private void OnTriggerEnter(Collider col)
{
if (col.name != "assets/prefabs/npc/m2bradley/bradleyapc.prefab")
return;
turret.SetTarget(col.GetComponent<BaseCombatEntity>());
externalTarget = col.GetComponent<BaseCombatEntity>();
turret.UpdateAiming();
}
private void OnTriggerExit(Collider col)
{
if (col.name != "assets/prefabs/npc/m2bradley/bradleyapc.prefab")
return;
turret.SetTarget(null);
turret.TargetScan();
externalTarget = null;
turret.UpdateAiming();
isLockedOn = false;
isLockingOn = false;
}
private void OnDestroy()
{
if (!launcher_1.IsDestroyed)
launcher_1.Kill();
if (!rocket_1.IsDestroyed)
rocket_1.Kill();
if (!rocket_2.IsDestroyed)
rocket_2.Kill();
}
public void Destroy()
{
if (plugin.rocketTurrets.Contains(turret))
plugin.rocketTurrets.Remove(turret);
if (plugin.turretIDs.Contains(turret.net.ID))
plugin.turretIDs.Remove(turret.net.ID);
OnDestroy();
//turret.Kill(BaseNetworkable.DestroyMode.Gib);
if (this)
Destroy(this);
}
private void DestroyTurret()
{
if (turret != null)
turret.Kill(BaseNetworkable.DestroyMode.Gib);
}
public void UnloadDestroy()
{
if (plugin.rocketTurrets.Contains(turret))
plugin.rocketTurrets.Remove(turret);
OnDestroy();
Destroy(this);
}
private Item HasAmmo()
{
return !requiresAmmo ? ItemManager.CreateByItemID(-742865266) : turret.inventory.itemList.FirstOrDefault(item => item.info.itemid == -742865266 || item.info.itemid == 1638322904 || item.info.itemid == -1841918730);
}
private void LockToTarget(BaseCombatEntity entity)
{
isLockedOn = true;
isLockingOn = false;
nextShoot = Time.time + 0.3f;
target = entity;
}
private void InitAesthetics()
{
// Rocket Launcher
launcher_1 = ItemManager.CreateByItemID(442886268, 1, rocketLauncherSkin).Drop(turret.transform.position, Vector3.zero).GetComponent<DroppedItem>();
launcher_1.GetComponent<Rigidbody>().isKinematic = true;
launcher_1.GetComponent<Rigidbod
// ... [Code preview truncated due to length. Full source in attached file] ...