C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core.Libraries.Covalence;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Endless Cargo", "OG61", "1.1.1")]
[Description("Calls new cargo ship into game as soon as one departs.")]
public class EndlessCargo : CovalencePlugin
{
#region Config
const string cargoPrefab = "assets/content/vehicles/boats/cargoship/cargoshiptest.prefab";
const int MaxShips = 1;
private const string perm = "endlesscargo.admin";
readonly System.Random random = new System.Random();
private class PluginConfig
{
[JsonProperty(PropertyName = "Update Rate (Seconds)")]
public float UpdateRate = 5f;
[JsonProperty(PropertyName = "How far off shore to spawn ship in grid blocks 1-10 (Default 5)")]
public int GridBlocksOffShore = 5;
[JsonProperty(PropertyName = "NPC spawn on ship (Default true)")]
public bool NpcSpawn = true;
[JsonProperty(PropertyName = "Egress duration in minutes (Default 10)")]
public int EgressMin = 10;
[JsonProperty(PropertyName = "Event duration in minutes (Default 50)")]
public int DurationMin = 50;
[JsonProperty(PropertyName = "Loot round spacing in minutes (Default 10)")]
public int LootSpacing = 10;
[JsonProperty(PropertyName = "Loot rounds 1-3 (Default 3)")]
public int LootRounds = 3;
[JsonProperty(PropertyName = "Enable Log file (true/false)")]
public bool LogToFile = true;
[JsonProperty(PropertyName = "Log output to console (true/false)")]
public bool LogToConsole = true;
}
private PluginConfig _config;
protected override void LoadConfig()
{
base.LoadConfig();
try
{
_config = Config.ReadObject<PluginConfig>();
if (_config == null)
{
LoadDefaultConfig();
}
}
catch (Exception e)
{
LoadDefaultConfig();
LogError(e.Message);
}
/* Check for more than 3 loot rounds.Setting loot rounds to more than 3 will work but the ships horn
* will sound everytime the loot round timer triggers and an index out of bounds error will
* print to console.This appears to be a bug in the game.*/
if (_config.LootRounds > 3) _config.LootRounds = 3;
if (_config.GridBlocksOffShore > 10 || _config.GridBlocksOffShore < 1) _config.GridBlocksOffShore = 5; // set to default if outside reasonible range
SaveConfig();
}
protected override void LoadDefaultConfig() => _config = new PluginConfig();
protected override void SaveConfig() => Config.WriteObject(_config);
#endregion //Config
#region Data
private List<CargoShip> _activeCargoShips = new List<CargoShip>();
#endregion //Data
#region uMod Hooks
private void OnServerInitialized()
{
NextTick(() =>
{
_activeCargoShips = UnityEngine.Object.FindObjectsOfType<CargoShip>().ToList();
CheckCargoShip();
});
timer.Every(_config.UpdateRate, CheckCargoShip);
//ConsoleSystem.Run(ConsoleSystem.Option.Server.Quiet(), "cargoship.event_enabled false");
//Setting cargoship.event_enabled to false does not disable the event.For now just kill the new ship
server.Command($"cargoship.egress_duration_minutes {_config.EgressMin}");
server.Command($"ai.npc_spawn_on_cargo_ship {_config.NpcSpawn}");
server.Command($"cargoship.event_duration_minutes {_config.DurationMin}");
server.Command($"cargoship.loot_round_spacing_minutes {_config.LootSpacing}");
server.Command($"cargoship.loot_rounds {_config.LootRounds}");
}
private void OnEntitySpawned(CargoShip ship)
{
if (_activeCargoShips.Count >= MaxShips)
{ // This should never execute if the default event is turned off but it does.ship.Kill();
Logger("NormalGameCall") ;
return;
}
NextTick(() =>
{
_activeCargoShips.Add(ship);
CheckCargoShip();
});
}
#endregion //Oxide Hooks
#region Helpers
private string GetLang(string key, string id = "", params object[] args)
{
return string.Format(lang.GetMessage(key, this, id), args);
}
private void Logger(string key, IPlayer player = null, params object[] args)
{
string s = GetLang(key, player != null ? player.Id : "",args);
string ps = "";
if (player !=null) ps = $"{player.Name} ({player.Id}) ";
s = $"[{DateTime.Now}] {ps} {s}";
if (_config.LogToFile) LogToFile("CargoControl", s, this);
if (_config.LogToConsole) Log(s);
}
private void Message(string key, IPlayer player, params object[] args)
{
player.Reply(GetLang(key, player.Id, args));
}
private void CheckCargoShip()
{
_activeCargoShips.RemoveAll(p => !p.IsValid() || !p.gameObject.activeInHierarchy || p.HasFlag(BaseEntity.Flags.Reserved8));
if (_activeCargoShips.Count < MaxShips) SpawnCargo();
}
private void SpawnCargo()
{
var worldSize = (ConVar.Server.worldsize);
var gridWidth = (worldSize * 0.0066666666666667f);
float step = worldSize / gridWidth;
int steps = (int)(((worldSize / step) / 2) + _config.GridBlocksOffShore);
float posX;
float posZ;
float rotation;
var ranXZ = random.Next(-100, 100); //Randomly choose if we are randomizing x or Z
var ranPN = random.Next(-100, 100); //Randomly choose if we are positive x or z or negative x or z
ranPN = ranPN > 0 ? 1 : -1;
if (ranXZ > 0)
{
posX = random.Next(-steps, steps) * step;
posZ = steps * step * ranPN; //Z will be on the edge of map randomly north or south
rotation = posZ > 0 ? 180 : 0; //Rotate ship to point toward land
}
else
{
posX = steps * step * ranPN; //X will be on the edge of map randomly east or west
posZ = random.Next(-steps, steps) * step;
rotation = posX > 0 ? 270 : 90; //Rotate ship to point toward land
}
Vector3 position = new Vector3(posX, 0f, posZ);
Quaternion myTransform = new Quaternion();
Vector3 rot = myTransform.eulerAngles;
rot = new Vector3(rot.x, rot.y + rotation, rot.z);
myTransform = Quaternion.Euler(rot);
CargoShip cargo = (CargoShip)GameManager.server.CreateEntity(cargoPrefab, position, myTransform);
if (cargo != null)
{
cargo.Spawn();
Logger("ShipSpawned", null, position.x, position.z);
}
else
{
Logger("ShipSpawnError");
}
}
#endregion //Helpers
#region Commands
[Command("KillCargo"), Permission(perm)]
private void KillCargo(IPlayer player)
{
if (_activeCargoShips.Count > 0)
{
foreach (var c in _activeCargoShips)
{
c.Kill();
}
Logger("KillCargo", player);
}
else Logger("NoActiveShips");
}
#endregion
#region Localization
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["NormalGameCall"] = "Normal cargo event triggered.Ship killed.",
["KillcargoRcon"] = "Killcargo issued from RCon",
["NoActiveShips"] = "Killcargo command issued but no active ships",
["KillCargo"] = "Killcargo command executed",
["ShipSpawned"] = "Cargo ship spawned at X={0} Z={1}",
["ConfigError"] = "Error reading config file.Defaut configuration used.",
["ShipSpawnError"] = "Cargo ship spawn error.Spawn failed."
}, this) ;
}
#endregion
}
}