C#:
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("EventRF", "skavi", "1.1.1")]
[Description("Broadcasts on RF frequencies while events are active")]
class EventRF : RustPlugin
{
private const int SMALL_OIL_RIG_FREQUENCY = 4765;
private const int LARGE_OIL_RIG_FREQUENCY = 4768;
private const string CONFIG_CARGO_SHIP_ENABLED = "Cargo ship RF enabled";
private const string CONFIG_CARGO_SHIP_FREQ = "Cargo ship RF frequency";
private const string CONFIG_CARGO_PLANE_ENABLED = "Cargo plane RF enabled";
private const string CONFIG_CARGO_PLANE_FREQ = "Cargo plane RF frequency";
private const string CONFIG_CHINOOK_ENABLED = "CH47 helicopter RF enabled";
private const string CONFIG_CHINOOK_FREQ = "CH47 helicopter RF frequency";
private const string CONFIG_BRADLEY_ENABLED = "Bradley APC RF enabled";
private const string CONFIG_BRADLEY_FREQ = "Bradley APC RF frequency";
private const string CONFIG_PATROL_HELI_ENABLED = "Patrol helicopter RF enabled";
private const string CONFIG_PATROL_HELI_FREQ = "Patrol helicopter RF frequency";
private const int DEFAULT_CARGO_SHIP_FREQ = 4785;
private const int DEFAULT_CARGO_PLANE_FREQ = 4786;
private const int DEFAULT_CHINOOK_FREQ = 4787;
private const int DEFAULT_BRADLEY_FREQ = 4788;
private const int DEFAULT_PATROL_HELI_FREQ = 4789;
private const string MSG_INVALID_SYNTAX = "invalid syntax";
private const string MSG_LIST_USAGE = "list usage";
private const string MSG_CARGO_SHIP_FREQ = "cargo ship frequency";
private const string MSG_CARGO_PLANE_FREQ = "cargo plane frequency";
private const string MSG_CHINOOK_FREQ = "ch47 helicopter frequency";
private const string MSG_BRADLEY_FREQ = "bradley apc frequency";
private const string MSG_PATROL_HELI_FREQ = "patrol heli frequency";
private bool cargoShipEnabled;
private int cargoShipFreq;
private bool cargoPlaneEnabled;
private int cargoPlaneFreq;
private bool chinookEnabled;
private int chinookFreq;
private bool bradleyEnabled;
private int bradleyFreq;
private bool patrolHeliEnabled;
private int patrolHeliFreq;
private List<EventRF.EntityRFObject> broadcasters = new List<EntityRFObject>();
private bool timerLooping = false;
#region Hooks
void Init()
{
LoadConfig();
Config[CONFIG_CARGO_PLANE_ENABLED] = cargoPlaneEnabled = GetConfig(CONFIG_CARGO_PLANE_ENABLED, true);
Config[CONFIG_CARGO_PLANE_FREQ] = cargoPlaneFreq = GetConfig(CONFIG_CARGO_PLANE_FREQ, DEFAULT_CARGO_PLANE_FREQ);
Config[CONFIG_CARGO_SHIP_ENABLED] = cargoShipEnabled = GetConfig(CONFIG_CARGO_SHIP_ENABLED, true);
Config[CONFIG_CARGO_SHIP_FREQ] = cargoShipFreq = GetConfig(CONFIG_CARGO_SHIP_FREQ, DEFAULT_CARGO_SHIP_FREQ);
Config[CONFIG_CHINOOK_ENABLED] = chinookEnabled = GetConfig(CONFIG_CHINOOK_ENABLED, true);
Config[CONFIG_CHINOOK_FREQ] = chinookFreq = GetConfig(CONFIG_CHINOOK_FREQ, DEFAULT_CHINOOK_FREQ);
Config[CONFIG_BRADLEY_ENABLED] = bradleyEnabled = GetConfig(CONFIG_BRADLEY_ENABLED, true);
Config[CONFIG_BRADLEY_FREQ] = bradleyFreq = GetConfig(CONFIG_BRADLEY_FREQ, DEFAULT_BRADLEY_FREQ);
Config[CONFIG_PATROL_HELI_ENABLED] = patrolHeliEnabled = GetConfig(CONFIG_PATROL_HELI_ENABLED, true);
Config[CONFIG_PATROL_HELI_FREQ] = patrolHeliFreq = GetConfig(CONFIG_PATROL_HELI_FREQ, DEFAULT_PATROL_HELI_FREQ);
SaveConfig();
if (bradleyEnabled)
{
foreach (BradleyAPC e in UnityEngine.Object.FindObjectsOfType<BradleyAPC>())
{
handleNewBradlayInstance(e);
}
}
if (cargoPlaneEnabled)
{
foreach (CargoPlane e in UnityEngine.Object.FindObjectsOfType<CargoPlane>())
{
handleNewCargoPlaneInstance(e);
}
}
if (cargoShipEnabled)
{
foreach (CargoShip e in UnityEngine.Object.FindObjectsOfType<CargoShip>())
{
handleNewCargoShipInstance(e);
}
}
if (chinookEnabled)
{
foreach (CH47Helicopter e in UnityEngine.Object.FindObjectsOfType<CH47Helicopter>())
{
handleNewChinookInstance(e);
}
}
if (patrolHeliEnabled)
{
foreach (BaseHelicopter e in UnityEngine.Object.FindObjectsOfType<BaseHelicopter>())
{
handleNewPatrolHelicopterInstance(e);
}
}
}
void Unload()
{
DestroyAll<EntityRFObject>();
}
protected override void LoadDefaultConfig()
{
Config.Clear();
Config[CONFIG_CARGO_SHIP_ENABLED] = true;
Config[CONFIG_CARGO_SHIP_FREQ] = DEFAULT_CARGO_SHIP_FREQ;
Config[CONFIG_CARGO_PLANE_ENABLED] = true;
Config[CONFIG_CARGO_PLANE_FREQ] = DEFAULT_CARGO_PLANE_FREQ;
Config[CONFIG_CHINOOK_ENABLED] = true;
Config[CONFIG_CHINOOK_FREQ] = DEFAULT_CHINOOK_FREQ;
Config[CONFIG_BRADLEY_ENABLED] = true;
Config[CONFIG_BRADLEY_FREQ] = DEFAULT_BRADLEY_FREQ;
Config[CONFIG_PATROL_HELI_ENABLED] = true;
Config[CONFIG_PATROL_HELI_FREQ] = DEFAULT_PATROL_HELI_FREQ;
}
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
[MSG_INVALID_SYNTAX] = "Invalid command syntax",
[MSG_LIST_USAGE] = "To list frequencies type: /eventrf list",
[MSG_CARGO_SHIP_FREQ] = "Cargo ship frequency is {0}",
[MSG_CARGO_PLANE_FREQ] = "Cargo plane frequency is {0}",
[MSG_CHINOOK_FREQ] = "CH47 helicopter frequency is {0}",
[MSG_BRADLEY_FREQ] = "Bradley APC frequency is {0}",
[MSG_PATROL_HELI_FREQ] = "Patrol helicopter frequency is {0}"
}, this);
}
void OnEntitySpawned(BaseNetworkable entity)
{
if (entity is CargoShip)
{
if (cargoShipEnabled)
{
handleNewCargoShipInstance(entity as CargoShip);
}
}
else if (entity is CargoPlane)
{
if (cargoPlaneEnabled)
{
handleNewCargoPlaneInstance(entity as CargoPlane);
}
}
else if (entity is CH47Helicopter)
{
if (chinookEnabled)
{
handleNewChinookInstance(entity as CH47Helicopter);
}
}
else if (entity is BradleyAPC)
{
if (bradleyEnabled)
{
handleNewBradlayInstance(entity as BradleyAPC);
}
}
else if (entity is BaseHelicopter)
{
if (patrolHeliEnabled)
{
handleNewPatrolHelicopterInstance(entity as BaseHelicopter);
}
}
}
#endregion
#region Commands
[ChatCommand("eventrf")]
private void eventRfCommand(BasePlayer player, string command, string[] args)
{
if (args.Length != 1)
{
commandSyntaxError(player);
return;
}
if ("list".Equals(args[0]))
{
if (bradleyEnabled)
{
SendReply(player, lang.GetMessage(MSG_BRADLEY_FREQ, this, player.UserIDString), bradleyFreq);
}
if (cargoPlaneEnabled)
{
SendReply(player, lang.GetMessage(MSG_CARGO_PLANE_FREQ, this, player.UserIDString), cargoPlaneFreq);
}
if (cargoShipEnabled)
{
SendReply(player, lang.GetMessage(MSG_CARGO_SHIP_FREQ, this, player.UserIDString), cargoShipFreq);
}
if (chinookEnabled)
{
SendReply(player, lang.GetMessage(MSG_CHINOOK_FREQ, this, player.UserIDString), chinookFreq);
}
if (patrolHeliEnabled)
{
SendReply(player, lang.GetMessage(MSG_PATROL_HELI_FREQ, this, player.UserIDString), patrolHeliFreq);
}
}
else
{
commandSyntaxError(player);
}
}
private void commandSyntaxError(BasePlayer player)
{
SendReply(player, lang.GetMessage(MSG_INVALID_SYNTAX, this, player.UserIDString));
SendReply(player, lang.GetMessage(MSG_LIST_USAGE, this, player.UserIDString));
}
#endregion
#region Helpers
T GetConfig<T>(string name, T value) => Config[name] == null ? value : (T)Convert.ChangeType(Config[name], typeof(T));
private static void DestroyAll<T>()
{
var l = GameObject.FindObjectsOfType(typeof(T));
if (l != null)
{
foreach (var o in l)
{
GameObject.Destroy(o);
}
}
}
#endregion
private void handleNewChinookInstance(CH47Helicopter entity)
{
// If we don't add the first NextTick here, chinooks break. They hang in the air without moving
NextTick(() =>
{
EntityRFObject smallRigListener = entity.gameObject.AddComponent<EntityRFObject>();
smallRigListener.frequency = SMALL_OIL_RIG_FREQUENCY;
smallRigListener.entity = entity;
RFManager.AddListener(smallRigListener.GetFrequency(), smallRigListener);
EntityRFObject largeRigListener = entity.gameObject.AddComponent<EntityRFObject>();
largeRigListener.frequency = LARGE_OIL_RIG_FREQUENCY;
largeRigListener.entity = entity;
RFManager.AddListener(largeRigListener.GetFrequency(), largeRigListener);
// next tick to give listeners a chance to get signal
NextTick(() =>
{
if (!smallRigListener.ReceivingSignal && !largeRigListener.ReceivingSignal)
{
queueAddBroadcaster(entity, chinookFreq);
}
RFManager.RemoveListener(smallRigListener.GetFrequency(), smallRigListener);
RFManager.RemoveListener(largeRigListener.GetFrequency(), largeRigListener);
GameObject.Destroy(smallRigListener);
GameObject.Destroy(largeRigListener);
});
});
}
private void handleNewBradlayInstance(BradleyAPC entity)
{
queueAddBroadcaster(entity, bradleyFreq);
}
private void handleNewCargoShipInstance(CargoShip entity)
{
queueAddBroadcaster(entity, cargoShipFreq);
}
private void handleNewCargoPlaneInstance(CargoPlane entity)
{
queueAddBroadcaster(entity, cargoPlaneFreq);
}
private void handleNewPatrolHelicopterInstance(BaseHelicopter entity)
{
queueAddBroadcaster(entity, patrolHeliFreq);
}
private bool entityIsValid(BaseEntity entity)
{
return entity != null && entity.IsValid() && entity.gameObject.activeInHierarchy;
}
private void queueAddBroadcaster(BaseEntity entity, int frequency)
{
// NextTick here so that if any other plugin kills the entity on spawn we don't broadcast for a single tick
NextTick(() => {
if (entityIsValid(entity))
{
EntityRFObject b = entity.gameObject.AddComponent<EntityRFObject>() as EntityRFObject;
b.frequency = frequency;
b.entity = entity;
RFManager.AddBroadcaster(frequency, b);
broadcasters.Add(b);
if (!timerLooping)
{
timerLooping = true;
timer.In(5, updateBroadcasters);
}
}
});
}
private void updateBroadcasters()
{
List<EntityRFObject> activeBroadcasters = new List<EntityRFObject>();
foreach (EntityRFObject b in broadcasters)
{
if (entityIsValid(b.GetEntity()))
{
activeBroadcasters.Add(b);
}
else
{
RFManager.RemoveBroadcaster(b.GetFrequency(), b);
GameObject.Destroy(b);
}
}
broadcasters = activeBroadcasters;
if (broadcasters.Count == 0)
{
timerLooping = false;
}
else
{
timer.In(5, updateBroadcasters);
}
}
/*
* RFManager requires that IRFObjects are also BaseEntity's (2020-05-16)
*/
private class EntityRFObject : BaseEntity, IRFObject
{
public BaseEntity entity;
public int frequency;
public bool ReceivingSignal { get; private set; } = false;
public override BaseEntity GetEntity()
{
return entity;
}
public Vector3 GetPosition()
{
if (entity == null || entity.ServerPosition == null)
{
return Vector3.zero;
}
else
{
return entity.ServerPosition;
}
}
public float GetMaxRange()
{
return float.MaxValue;
}
public void RFSignalUpdate(bool on)
{
ReceivingSignal = on;
}
public int GetFrequency()
{
return frequency;
}
}
}
}