C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using UnityEngine;
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using System.Collections.Generic;
namespace Oxide.Plugins {
[Info("CargoPlaneCrash", "Fruster", "1.2.8")]
[Description("CargoPlaneCrash")]
class CargoPlaneCrash : CovalencePlugin {
private List<Vector3> spawnItems = new List<Vector3>();
private float remainToEvent;
private float remain;
private string prefabstr = "assets/prefabs/npc/cargo plane/cargo_plane.prefab";
private BaseEntity entity;
private Vector3 target = new Vector3(0, 0, 0);
private float mapSize;
private float speed;
private Vector3 direction;
private float crashRadius = 10f;
private bool expMarker;
private bool signalSmoke;
private int cratesAmount;
private int airdropsAmount;
private int fireballsAmount;
private int passengersAmount;
private RaycastHit check;
private LayerMask layerS = LayerMask.GetMask("Construction", "Terrain", "Water", "World");
private string message;
private string kitName;
private string passengerName;
private Vector3 crashZoneCenter;
private Vector3 crashPosition;
[PluginReference]
Plugin Kits, SimpleLootTable;
private float altitude;
private int lifeTimeExpMarker;
private int lifeTimeCrates;
private int lifeTimeAirdrops;
private bool smokeFlag = false;
private int lifeTimeSignalSmoke;
private const string botPrefab = "assets/rust.ai/agents/npcplayer/npcplayertest.prefab";
private int typeNpcs;
private string npcPrefab;
private int lifeTimeNpcs;
private int npcsAmount;
private float npcDamageMultiplier;
private int npcHealth;
private const string npcName = "cpcguardnpc";
private bool randomEventTime;
private int minimumRemainToEvent;
private int maximumRemainToEvent;
private int minOnline;
private bool buildingBlock;
private int buildingBlockTime;
private int buildingBlockTimer;
private string npcKit;
private float npcAttackRange;
private ConfigData Configuration;
private List<Vector3> wayPoints = new List<Vector3>();
private List<BaseEntity> botList = new List<BaseEntity>();
private List<BaseEntity> entityList = new List<BaseEntity>();
private int chaseRadius = 50;
private int coolDownTime = 7;
private int homeRadius = 20;
private int attackRadius = 75;
private MapMarkerGenericRadius marker;
private VendingMachineMapMarker vending;
private class NpcBrain : FacepunchBehaviour {
public Vector3 homePosition;
public Vector3 targetPosition;
public BaseEntity target;
public int stateTimer;
public int moveChance;
}
private class MultipleZones {
public string name {
get;
set;
}
public int radius {
get;
set;
}
public Vector3 center {
get;
set;
}
}
private int zoneSequence = 0;
private class TimerForCrate : FacepunchBehaviour {
public Timer timer;
}
private float serverHackSeconds = HackableLockedCrate.requiredHackSeconds;
private List<Vector3> monumentsList = new List<Vector3>();
private int monumentsRadius;
class ConfigData {
[JsonProperty("Triggering an event by timer (disable if you want to trigger the event only manually)")]
public bool timerStart = true;
[JsonProperty("Time to event start(in seconds)")]
public float remainToEvent = 3600f;
[JsonProperty("Random time to event start")]
public bool randomEventTime = false;
[JsonProperty("Minimum time to event start(in seconds)")]
public int minimumRemainToEvent = 600;
[JsonProperty("Maximum time to event start(in seconds)")]
public int maximumRemainToEvent = 10800;
[JsonProperty("CargoPlane speed(recommended 4 to 6)")]
public float speed = 5f;
[JsonProperty("Minimum amount of online players to trigger the event")]
public int minOnline = 1;
[JsonProperty("Crates amount(spawn after crash)")]
public int cratesAmount = 1;
[JsonProperty("Crate simple loot table name(plugin SimpleLootTable is required)")]
public string crateTableName = "";
[JsonProperty("Minimum number of items in a crate(plugin SimpleLootTable is required)")]
public int crateMinItems = 0;
[JsonProperty("Maximum number of items in a crate(plugin SimpleLootTable is required)")]
public int crateMaxItems = 0;
[JsonProperty("Crates lifetime(in seconds).The crate will not be destroyed if it has been activated")]
public int lifeTimeCrates = 3600;
[JsonProperty("Crates timer(in seconds)")]
public int timerCrates = 900;
[JsonProperty("Airdrops amount(spawn after crash)")]
public int airdropsAmount = 1;
[JsonProperty("Airdrop simple loot table name(plugin SimpleLootTable is required)")]
public string airdropTableName = "";
[JsonProperty("Minimum number of items in an airdrop(plugin SimpleLootTable is required)")]
public int airdropMinItems = 0;
[JsonProperty("Maximum number of items in an airdrop(plugin SimpleLootTable is required)")]
public int airdropMaxItems = 0;
[JsonProperty("Airdrops lifetime(in seconds)")]
public int lifeTimeAirdrops = 3600;
[JsonProperty("Fireballs amount(spawn after crash)")]
public int fireballsAmount = 5;
[JsonProperty("Passengers amount(spawn after crash)")]
public int passengersAmount = 2;
[JsonProperty("Explosion marker on the map(spawn after crash)")]
public bool expMarker = true;
[JsonProperty("Explosion marker lifetime(in seconds)")]
public int lifeTimeExpMarker = 300;
[JsonProperty("Enable signal smoke(spawn after crash)")]
public bool signalSmoke = true;
[JsonProperty("Signal smoke lifetime(in seconds, max 214)")]
public int lifeTimeSignalSmoke = 214;
[JsonProperty("Map size(crash zone size), you can see the zone, use the chat command /showcrashzone")]
public float mapSize = 4500;
[JsonProperty("Starting altitude, defaults to map size, can be increased if cargo plane hits high ground(no more than 10000 recommended)")]
public float altitude = 4500;
[JsonProperty("Crash zone center.Use chat command /setcrashzonecenter to set to player position.You can check crash zone center, use the chat command /showcrashzone")]
public Vector3 crashZoneCenter = new Vector3(0, 0, 0);
[JsonProperty("Use multiple zones")]
public bool useMultipleZones = false;
[JsonProperty("Select a zone from the list sequentially(if false, then the crash zone will be chosen randomly)")]
public bool selectZoneSequentially = false;
[JsonProperty("Zones list")]
public List<MultipleZones> zonesList = new List<MultipleZones>() {
new MultipleZones {
name = "0", radius = 300, center = new Vector3(-300, 0, 0)
}
, new MultipleZones {
name = "1", radius = 200, center = new Vector3(100, 0, 0)
}
}
;
[JsonProperty("Event message(if empty, no message will be displayed)")]
public string message = "CargoPlane event started";
[JsonProperty("Crash message(if empty, no message will be displayed)")]
public string crashMessage = "Cargo plane crashed";
[JsonProperty("Kit name(you can use kits for passengers if you have Kits plugin)")]
public string kitName = "";
[JsonProperty("Passenger name")]
public string passengerName = "Mister bot";
[JsonProperty("NPCs amount(spawn after crash)")]
public int npcsAmount = 2;
[JsonProperty("NPCs lifetime(in seconds)")]
public int lifeTimeNpcs = 3600;
[JsonProperty("NPCs type(NPCs prefab, experimental setting, it is not known how the NPCs will behave) 0 - tunneldweller; 1 - underwaterdweller; 2 - excavator; 3 - full_any; 4 - lr300; 5 - mp5; 6 - pistol; 7 - shotgun; 8 - heavy; 9 - junkpile_pistol; 10 - oilrig; 11 - patrol; 12 - peacekeeper; 13 - roam; 14 - roamtethered; 15 - bandit_guard; 16 - cargo; 17 - cargo_turret_any; 18 - cargo_turret_lr300; 19 - ch47_gunner")]
public int typeNpcs = 0;
[JsonProperty("NPCs health(0 - default)")]
public int npcHealth = 0;
[JsonProperty("NPCs damage multiplier")]
public float npcDamageMultiplier = 1f;
[JsonProperty("NPCs attack range")]
public float npcAttackRange = 75f;
[JsonProperty("Minimum distance to NPC damage")]
public float npcMinDistToDmg = 75f;
[JsonProperty("Message if the player attacks far away NPCs")]
public string npcFarAwayMessage = "NPC is too far away, he doesn't take damage";
[JsonProperty("Kit for NPCs.The NPC will use the weapon that is in the first slot of the belt(requires Kits plugin)")]
public string npcKit = "";
[JsonProperty("Default displayName for NPC(for SimpleKillFeed/DeathNotes plugin)")]
public string displayNameNPC = "Crashsite NPC";
[JsonProperty("List of displayNames for each NPC(for SimpleKillFeed/DeathNotes plugin)")]
public List<string> displayNamesListNPC = new List<string> {
"Crashsite NPC1", "Crashsite NPC2", "Crashsite NPC3"
}
;
[JsonProperty("Prohibit building near the crash site")]
public bool buildingBlock = false;
[JsonProperty("How long construction is prohibited near the crash site(in seconds)")]
public int buildingBlockTime = 1800;
[JsonProperty("Event marker on the map(spawn an event marker at the crash site)")]
public bool eventMarker = false;
[JsonProperty("Event marker name")]
public string markerName = "Cargo plane crash site";
[JsonProperty("Event marker lifetime(in seconds)")]
public int markerLifetime = 3600;
[JsonProperty("Event marker transparency(0-1)")]
public float markerAlpha = 0.75f;
[JsonProperty("Event marker radius")]
public float markerRadius = 0.5f;
[JsonProperty("Event marker color.R(0-1)")]
public float markerColorR = 1.0f;
[JsonProperty("Event marker color.G(0-1)")]
public float markerColorG = 0f;
[JsonProperty("Event marker color.B(0-1)")]
public float markerColorB = 0f;
[JsonProperty("Do not spawn crates and NPCs when a cargo plane falls under water (if the water depth is greater than)")]
public float spawnDepth = 0.5f;
[JsonProperty("Do not choose a crash site near monuments")]
public bool monumentsProhibition = false;
}
private void OnServerInitialized() {
LoadConfig();
remainToEvent = Configuration.remainToEvent;
remain = remainToEvent;
speed = Configuration.speed;
cratesAmount = Configuration.cratesAmount;
airdropsAmount = Configuration.airdropsAmount;
fireballsAmount = Configuration.fireballsAmount;
passengersAmount = Configuration.passengersAmount;
expMarker = Configuration.expMarker;
mapSize = Configuration.mapSize / 4f;
altitude = Configuration.altitude;
message = Configuration.message;
kitName = Configuration.kitName;
passengerName = Configuration.passengerName;
crashZoneCenter = Configuration.crashZoneCenter;
lifeTimeExpMarker = Configuration.lifeTimeExpMarker;
lifeTimeCrates = Configuration.lifeTimeCrates;
lifeTimeAirdrops = Configuration.lifeTimeAirdrops;
signalSmoke = Configuration.signalSmoke;
lifeTimeSignalSmoke = Configuration.lifeTimeSignalSmoke;
typeNpcs = Configuration.typeNpcs;
npcHealth = Configuration.npcHealth;
npcDamageMultiplier = Configuration.npcDamageMultiplier;
npcsAmount = Configuration.npcsAmount;
lifeTimeNpcs = Configuration.lifeTimeNpcs;
randomEventTime = Configuration.randomEventTime;
minimumRemainToEvent = Configuration.minimumRemainToEvent;
maximumRemainToEvent = Configuration.maximumRemainToEvent;
minOnline = Configuration.minOnline;
buildingBlock = Configuration.buildingBlock;
buildingBlockTime = Configuration.buildingBlockTime;
npcKit = Configuration.npcKit;
npcAttackRange = Configuration.npcAttackRange;
if (lifeTimeSignalSmoke > 214) lifeTimeSignalSmoke = 214;
if (npcsAmount > 15) npcsAmount = 15;
Unsubscribe("OnTick");
foreach (var item in TerrainMeta.Path.Monuments) monumentsList.Add(item.transform.position);
switch (typeNpcs) {
case 0 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/tunneldweller/npc_tunneldweller.prefab";
break;
case 1 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/underwaterdweller/npc_underwaterdweller.prefab";
break;
case 2 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_excavator.prefab";
break;
case 3 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_any.prefab";
break;
case 4 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_lr300.prefab";
break;
case 5 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_mp5.prefab";
break;
case 6 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_pistol.prefab";
break;
case 7 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_shotgun.prefab";
break;
case 8 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_heavy.prefab";
break;
case 9 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_junkpile_pistol.prefab";
break;
case 10 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_oilrig.prefab";
break;
case 11 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_patrol.prefab";
break;
case 12 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_peacekeeper.prefab";
break;
case 13 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_roam.prefab";
break;
case 14 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_roamtethered.prefab";
break;
case 15 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/banditguard/npc_bandit_guard.prefab";
break;
case 16 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_cargo.prefab";
break;
case 17 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_cargo_turret_any.prefab";
break;
case 18 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_cargo_turret_lr300.prefab";
break;
case 19 : npcPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_ch47_gunner.prefab";
break;
}
if (randomEventTime) remainToEvent = UnityEngine.Random.Range(minimumRemainToEvent, maximumRemainToEvent);
remain = remainToEvent;
if (Configuration.timerStart) {
Puts("Event will start in " + remainToEvent.ToString() + " seconds");
timer.Every(1f, () => {
remain--;
buildingBlockTimer--;
if (remain < 0) {
int s = 0;
if (entity) s = -9999;
foreach (BasePlayer player in BasePlayer.activePlayerList) s++;
if (s >= minOnline) startEvent();
else {
remain = remainToEvent;
if (entity) Puts("The event is already running");
else Puts("Not enough online players on the server, event will not start!");
}
}
}
);
}
else Puts("The event will be triggered only in manual mode");
}
void SaveConfig(object config) => Config.WriteObject(config, true);
void LoadConfig() {
base.Config.Settings.ObjectCreationHandling = ObjectCreationHandling.Replace;
Configuration = Config.ReadObject<ConfigData>();
SaveConfig(Configuration);
}
protected override void LoadDefaultConfig() {
var config = new ConfigData();
SaveConfig(config);
}
void startEvent() {
Interface.CallHook("CargoPlaneCrashStarted");
Puts("Event started");
RemoveEvent();
findTarget();
entity = GameManager.server.CreateEntity(prefabstr, new Vector3(0, 1000, 0), new Quaternion(), false);
entity.Spawn();
var str = "assets/bundled/prefabs/oilfireballsmall.prefab";
BaseEntity fire = GameManager.server.CreateEntity(str, entity.transform.position);
fire.Spawn();
fire.SetParent(entity);
fire.transform.localPosition = new Vector3(-6.8f, 6.8f, 3f);
Subscribe("OnTick");
if (message != null) foreach (BasePlayer player in BasePlayer.activePlayerList) player.ChatMessage(message);
entity.transform.position += Vector3.up * altitude;
if (randomEventTime) remainToEvent = UnityEngine.Random.Range(minimumRemainToEvent, maximumRemainToEvent);
remain = remainToEvent;
if (Configuration.timerStart) Puts("Next event will start in " + remainToEvent.ToString() + " seconds");
}
void OnTick() {
if (entity) {
entity.transform.LookAt(target);
direction = entity.transform.forward;
entity.transform.position += direction * speed;
if (Vector3.Distance(entity.transform.position, target) < speed) {
crashSite();
return;
}
if (Physics.Raycast(entity.transform.position + Vector3.up * 100, Vector3.down, out check, 200, layerS)) if (Vector3.Distance(check.point, entity.transform.position) < 3) crashSite();
}
}
void OnAirdrop(CargoPlane plane, Vector3 dropPosition) {
BaseEntity ent = plane as BaseEntity;
if (smokeFlag) {
ent.Kill();
smokeFlag = false;
}
}
void crashSite() {
if (Configuration.crashMessage != null) foreach (BasePlayer player in BasePlayer.activePlayerList) player.ChatMessage(Configuration.crashMessage);
//Puts(PhoneController.PositionToGridCoord(crashPosition).ToString());
Interface.CallHook("CargoPlaneCrashCrashed");
entityList.Clear();
Vector3 pos = Vector3.zero;
crashPosition = entity.transform.position;
spawnItems.Add(Vector3.zero);
spawnItems.Clear();
spawnItem("assets/prefabs/npc/patrol helicopter/effects/heli_explosion.prefab", 1, true);
spawnItem("assets/prefabs/misc/supply drop/supply_drop.prefab", airdropsAmount, false);
spawnItem("assets/prefabs/deployable/chinooklockedcrate/codelockedhackablecrate.prefab", cratesAmount, false);
spawnItem("assets/bundled/prefabs/oilfireballsmall.prefab", fireballsAmount, false);
spawnItem(botPrefab, passengersAmount, false);
if (signalSmoke) spawnItem("assets/prefabs/tools/supply signal/grenade.supplysignal.deployed.prefab", 1, false);
if (expMarker) {
var str = "assets/prefabs/tools/map/explosionmarker.prefab";
var marker = GameManager.server.CreateEntity(str, entity.transform.position);
marker.Spawn();
entityList.Add(marker);
timer.Once(lifeTimeExpMarker, () => {
if (marker) marker.Kill();
}
);
}
if (Configuration.eventMarker) DrawMarker();
Unsubscribe("OnTick");
entity.Kill();
buildingBlockTimer = buildingBlockTime;
RaycastHit hit = new RaycastHit();
for (int i = 0; i < npcsAmount; i++) {
int s = 0;
for (int x = 0; x < 22; x++) {
s = 0;
pos = new Vector3(crashPosition.x + UnityEngine.Random.Range(-crashRadius, crashRadius), crashPosition.y, crashPosition.z + UnityEngine.Random.Range(-crashRadius, crashRadius));
hit = new RaycastHit();
if (Physics.Raycast(pos + Vector3.up * 100f, Vector3.down, out hit, 500f, layerS)) pos = hit.point;
for (int f = 0; f < spawnItems.Count; f++) {
if (Vector3.Distance(pos, spawnItems[f]) < 2) s++;
}
if (s == 0) {
spawnItems.Add(pos);
break;
}
}
if (WaterLevel.GetWaterDepth(hit.point, false, false) < Configuration.spawnDepth) {
if (s > 0) spawnItems.Add(pos);
var npc = GameManager.server.CreateEntity(npcPrefab, pos, new Quaternion(), true);
npc.Spawn();
entityList.Add(npc);
BasePlayer player = npc as BasePlayer;
player.name = npcName;
player.displayName = Configuration.displayNameNPC;
if (i < Configuration.displayNamesListNPC.Count) if (Configuration.displayNamesListNPC[i] != null) player.displayName = Configuration.displayNamesListNPC[i];
BaseNavigator navigator = npc.GetComponent<BaseNavigator>();
navigator.CanUseNavMesh = false;
ScientistBrain brain = npc.GetComponent<ScientistBrain>();
ScientistNPC npcBrain = npc.gameObject.GetComponent<ScientistNPC>();
brain.AttackRangeMultiplier = 10f;
brain.VisionCone = -1;
brain.SenseRange = npcAttackRange;
brain.ListenRange = 15f;
brain.SenseTypes = EntityType.Player;
brain.MemoryDuration = 5f;
brain.TargetLostRange = npcAttackRange;
brain.CheckVisionCone = false;
brain.CheckLOS = true;
brain.IgnoreNonVisionSneakers = true;
brain.HostileTargetsOnly = false;
brain.IgnoreSafeZonePlayers = false;
brain.RefreshKnownLOS = true;
navigator.MaxRoamDistanceFromHome = navigator.BestMovementPointMaxDistance = navigator.BestRoamPointMaxDistance = 5f;
navigator.DefaultArea = "Walkable";
navigator.topologyPreference = ((TerrainTopology.Enum)TerrainTopology.EVERYTHING);
navigator.Agent.agentTypeID = -1372625422;
if (navigator.CanUseNavMesh) navigator.Init(player, navigator.Agent);
NpcBrain brainNPC = npc.gameObject.AddComponent<NpcBrain>();
brainNPC.homePosition = pos;
brainNPC.stateTimer = 5;
brainNPC.moveChance = 22;
botList.Add(npc);
timer.Once(1f, () => {
if (npc) MoveToPosition(brain, navigator, npc.transform.position + Vector3.forward * 0.1f, 0);
}
);
timer.Every(3f, () => {
if (npc) NpcAI(npc);
}
);
if (npcKit != "") {
player.inventory.Strip();
Kits?.Call("GiveKit", player, npcKit);
}
if (npcHealth > 0) {
player.startHealth = npcHealth;
player.health = npcHealth;
}
timer.Once(lifeTimeNpcs, () => {
if (npc) npc.Kill();
}
);
}
else {
PrintWarning("NPC position is under water, so NPC will not spawn");
continue;
}
}
AddWayPoints(crashPosition, crashRadius);
}
public void MoveToPosition(ScientistBrain brain, BaseNavigator navigator, Vector3 pos, int moveSpeed) {
var speed = BaseNavigator.NavigationSpeed.Slow;
if (moveSpeed == 1) speed = BaseNavigator.NavigationSpeed.Fast;
navigator.CanUseNavMesh = true;
brain.Navigator.SetDestination(pos, speed, 0f, 0f);
navigator.CanUseNavMesh = false;
}
public void NpcAI(BaseEntity npc) {
BaseNavigator navigator = npc.GetComponent<BaseNavigator>();
ScientistBrain brain = npc.GetComponent<ScientistBrain>();
NpcBrain x = npc.gameObject.GetComponent<NpcBrain>();
int speed = 0;
if (brain.Senses.Players.Count == 0) {
if (x.stateTimer == 0) {
brain.SwitchToState(AIState.Idle, 0);
x.moveChance = 22;
}
x.stateTimer--;
}
else {
x.stateTimer = coolDownTime;
speed = 1;
x.moveChance = 100;
if (brain.Senses.Players[0]) if (Vector3.Distance(brain.Senses.Players[0].transform.position, npc.transform.position) < chaseRadius) {
BasePlayer player = brain.Senses.Players[0] as BasePlayer;
if (!player.IsAlive()) {
brain.Senses.Players.Remove(brain.Senses.Players[0]);
return;
}
float xx = UnityEngine.Random.Range(-2, 2);
float zz = UnityEngine.Random.Range(-2, 2);
Vector3 offset = new Vector3(xx, 0, zz);
x.targetPosition = brain.Senses.Players[0].transform.position + offset;
MoveToPosition(brain, navigator, x.targetPosition, 1);
return;
}
}
if (Vector3.Distance(npc.transform.position, x.homePosition) < homeRadius) {
if (!navigator.Moving) {
var chanсe = UnityEngine.Random.Range(0, 100);
if (chanсe < x.moveChance) {
var y = UnityEngine.Random.Range(0, wayPoints.Count);
Vector3 point = wayPoints[y] + Vector3.up * 0.5f;
RaycastHit check;
Vector3 vec = new Vector3(point.x - npc.transform.position.x, point.y - npc.transform.position.y, point.z - npc.transform.position.z);
if (!Physics.Raycast(npc.transform.position + Vector3.up * 0.5f, vec, out check, Vector3.Distance(npc.transform.position, point), layerS)) x.targetPosition = wayPoints[y];
else x.targetPosition = check.point - Vector3.Normalize(vec) * 0.5f;
MoveToPosition(brain, navigator, x.targetPosition, speed);
}
}
}
else if (x.stateTimer < 0) MoveToPosition(brain, navigator, x.homePosition, 1);
}
public void AddWayPoints(Vector3 center, float radius) {
wayPoints.Clear();
float off = 1;
for (float i = -radius / 2 + off; i < radius / 2 + off; i += 1) for (float ii = -radius / 2 + off; ii < radius / 2 + off; ii += 1) {
RaycastHit check;
Vector3 offset = new Vector3(i, 0, ii);
if (Physics.Raycast(center + offset + Vector3.up * 100, Vector3.down, out check, 200, layerS)) if (WaterLevel.GetWaterDepth(check.point, false, false) < Configuration.spawnDepth) {
BaseEntity entity = check.GetEntity();
if (!entity) wayPoints.Add(check.point);
}
}
}
void spawnItem(string str, int amount, bool effect) {
RaycastHit hit = new RaycastHit();
for (int i = 0; i < amount; i++) {
Vector3 pos = new Vector3(entity.transform.position.x + UnityEngine.Random.Range(-crashRadius, crashRadius), entity.transform.position.y, entity.transform.position.z + UnityEngine.Random.Range(-crashRadius, crashRadius));
hit = new RaycastHit();
if (Physics.Raycast(pos + Vector3.up * 50f, Vector3.down, out hit, 500f, layerS)) if (hit.point.y > pos.y) pos += Vector3.up * (hit.point.y - pos.y);
if (effect) Effect.server.Run(str, entity.transform.position);
else {
var entityCrash = GameManager.server.CreateEntity(str, pos);
entityCrash.Spawn();
entityList.Add(entityCrash);
if (str == "assets/prefabs/tools/supply signal/grenade.supplysignal.deployed.prefab") {
smokeFlag = true;
timer.Once(lifeTimeSignalSmoke, () => {
if (entityCrash) entityCrash.Kill();
}
);
}
if (str == "assets/prefabs/deployable/chinooklockedcrate/codelockedhackablecrate.prefab") {
if (Configuration.crateTableName != "") SimpleLootTable?.Call("GetSetItems", entityCrash, Configuration.crateTableName, Configuration.crateMinItems, Configuration.crateMaxItems, 1f);
spawnItems.Add(entityCrash.transform.position);
HackableLockedCrate ent = entityCrash.GetComponent<HackableLockedCrate>();
ent.hackSeconds = serverHackSeconds - Configuration.timerCrates;
float oldTime = ent.hackSeconds;
TimerForCrate timerForCrate = ent.gameObject.AddComponent<TimerForCrate>();
timerForCrate.timer = timer.Every(1, () => {
if (Math.Abs(oldTime - ent.hackSeconds) > 5) if (ent.hackSeconds == 0 || ent.hackSeconds == 1) {
ent.hackSeconds = oldTime - 5;
if (ent.hackSeconds < serverHackSeconds - Configuration.timerCrates) ent.hackSeconds = serverHackSeconds - Configuration.timerCrates;
}
else {
if (ent.hackSeconds == 0 && Math.Abs(oldTime - ent.hackSeconds) == 0) ent.hackSeconds -= 5;
}
oldTime = ent.hackSeconds;
if (!ent) timerForCrate.timer.Destroy();
}
);
timer.Once(lifeTimeCrates, () => {
if (entityCrash) {
ent = entityCrash.GetComponent<HackableLockedCrate>();
if (ent.hackSeconds == serverHackSeconds - Configuration.timerCrates) ent.Kill();
}
}
);
}
if (str == botPrefab) {
BasePlayer pl = entityCrash as BasePlayer;
if (kitName != "") Kits?.Call("GiveKit", pl, kitName);
pl.displayName = passengerName;
pl.Hurt(100);
}
if (entityCrash is SupplyDrop) {
if (Configuration.airdropTableName != "") SimpleLootTable?.Call("GetSetItems", entityCrash, Configuration.airdropTableName, Configuration.airdropMinItems, Configuration.airdropMaxItems, 1f);
spawnItems.Add(entityCrash.transform.position);
SupplyDrop supplyDrop = entityCrash as SupplyDrop;
var drop = supplyDrop.GetComponent<Rigidbody>();
supplyDrop.RemoveParachute();
drop.drag = 1f;
timer.Once(lifeTimeAirdrops, () => {
if (entityCrash) entityCrash.Kill();
}
);
}
}
}
}
object OnConstructionPlace(BaseEntity entity, Construction component, Construction.Target constructionTarget, BasePlayer player) {
if (buildingBlock) if (buildingBlockTimer > 0) if (entity is BuildingBlock) if (Vector3.Distance(player.transform.position, crashPosition) < crashRadius * 2) {
NextFrame(() => {
if (entity) entity.AdminKill();
}
);
player.ChatMessage("You can't build near the crash site");
}
return null;
}
private void OnEntityTakeDamage(BaseEntity entity, HitInfo info) {
var killer = info.Initiator as BasePlayer;
if (killer) {
if (killer.name == npcName) info.damageTypes.ScaleAll(npcDamageMultiplier);
if (entity.name == npcName) if (Vector3.Distance(entity.transform.position, killer.transform.position) > Configuration.npcMinDistToDmg) {
info.damageTypes.ScaleAll(0);
BasePlayer player = killer as BasePlayer;
if (player && player.IsConnected) player.ChatMessage(Configuration.npcFarAwayMessage);
}
}
}
void Unload() {
RemoveEvent();
}
void RemoveEvent() {
if (entity) entity.Kill();
if (vending) vending.Kill();
for (int i = 0; i < entityList.Count; i++) if (entityList[i]) entityList[i].Kill();
}
private void findTarget() {
target = Vector3.zero;
int index = zoneSequence;
if (Configuration.selectZoneSequentially) {
zoneSequence++;
if (zoneSequence > Configuration.zonesList.Count - 1) zoneSequence = 0;
}
else index = UnityEngine.Random.Range(0, Configuration.zonesList.Count);
if (Configuration.monumentsProhibition) monumentsRadius = 150;
else monumentsRadius = -1;
for (int i = 0; i < 99; i++) {
calculateTarget(index);
if (target != Vector3.zero) break;
}
}
private void calculateTarget(int index) {
if (!Configuration.useMultipleZones) target = new Vector3(crashZoneCenter.x + UnityEngine.Random.Range(-mapSize, mapSize), 300, crashZoneCenter.z + UnityEngine.Random.Range(-mapSize, mapSize));
else {
crashZoneCenter = Configuration.zonesList[index].center;
mapSize = Configuration.zonesList[index].radius / 4;
target = new Vector3(crashZoneCenter.x + UnityEngine.Random.Range(-mapSize, mapSize), 300, crashZoneCenter.z + UnityEngine.Random.Range(-mapSize, mapSize));
}
RaycastHit hit = new RaycastHit();
if (Physics.Raycast(target, Vector3.down, out hit, 500, layerS)) target = hit.point;
foreach (Vector3 item in monumentsList) if (Vector3.Distance(target, item) < monumentsRadius) target = Vector3.zero;
}
void drawDot(BasePlayer player, Vector3 targetPoint, string str) {
RaycastHit hit = new RaycastHit();
if (Physics.Raycast(targetPoint, Vector3.down, out hit, 2000, layerS)) targetPoint = hit.point;
player.SendConsoleCommand("ddraw.text", 10f, Color.green, targetPoint, "<size=30>" + str + "</size>");
}
void DrawMarker() {
string markerPrefab = "assets/prefabs/tools/map/genericradiusmarker.prefab";
marker = GameManager.server.CreateEntity(markerPrefab, crashPosition).GetComponent<MapMarkerGenericRadius>();
markerPrefab = "assets/prefabs/deployable/vendingmachine/vending_mapmarker.prefab";
vending = GameManager.server.CreateEntity(markerPrefab, crashPosition).GetComponent<VendingMachineMapMarker>();
vending.markerShopName = Configuration.markerName;
vending.enableSaving = false;
vending.Spawn();
marker.radius = Configuration.markerRadius;
marker.alpha = Configuration.markerAlpha;
marker.color1.r = Configuration.markerColorR;
marker.color1.g = Configuration.markerColorG;
marker.color1.b = Configuration.markerColorB;
marker.enableSaving = false;
marker.Spawn();
marker.SetParent(vending);
marker.transform.localPosition = new Vector3(0, 0, 0);
marker.SendUpdate();
vending.SendNetworkUpdate();
timer.Once(Configuration.markerLifetime, () => {
if (vending) vending.Kill();
}
);
}
void OnPlayerSleepEnded(BasePlayer player) {
if (vending != null) {
marker.SendUpdate();
vending.SendNetworkUpdate();
}
}
void OnServerShutdown() {
RemoveEvent();
}
[Command("crashcargoplane")]
private void crashcargoplane(IPlayer iplayer) {
var player = (BasePlayer)iplayer.Object;
if (!player || player.IsAdmin) if (entity) crashSite();
}
[Command("callcargoplane")]
private void callcargoplane(IPlayer iplayer) {
var player = (BasePlayer)iplayer.Object;
if (!player || player.IsAdmin) if (!entity) {
startEvent();
}
}
[Command("setcrashzonecenter")]
private void setcrashzonecenter(IPlayer iplayer) {
var player = (BasePlayer)iplayer.Object;
if (player && player.IsAdmin) {
crashZoneCenter = player.transform.position;
Configuration = Config.ReadObject<ConfigData>();
Configuration.crashZoneCenter = crashZoneCenter;
SaveConfig(Configuration);
player.ChatMessage("Сenter successfully saved " + crashZoneCenter);
showcrashzone(player.IPlayer);
}
}
[Command("cpc_add_crashzone")]
private void cpc_add_crashzone(IPlayer iplayer, string command, string[] args) {
var player = (BasePlayer)iplayer.Object;
if (player && player.IsAdmin) {
string zoneName = Configuration.zonesList.Count.ToString();
int zoneRadius = 1000;
if (args.Length > 0) zoneName = args[0];
if (args.Length > 1) zoneRadius = int.Parse(args[1]);
Configuration.zonesList.Add(new MultipleZones {
name = zoneName, radius = zoneRadius, center = player.transform.position
}
);
SaveConfig(Configuration);
player.ChatMessage("Zone was added successfully " + zoneName);
if (Configuration.useMultipleZones) showcrashzone(player.IPlayer);
else PrintWarning("In order to see the zones, please set the setting 'Use multiple zones': true");
}
}
[Command("cpdebug")]
private void cpdebug(IPlayer iplayer) {
var player = (BasePlayer)iplayer.Object;
if (player && player.IsAdmin) {
string str = "+";
if (entity) player.SendConsoleCommand("ddraw.text", 10f, Color.blue, entity.transform.position, "<size=30>" + str + "</size>");
player.SendConsoleCommand("ddraw.text", 10f, Color.red, target, "<size=30>" + str + "</size>");
showcrashzone(player.IPlayer);
}
}
[Command("changetarget")]
private void changetarget(IPlayer iplayer) {
var player = (BasePlayer)iplayer.Object;
if (player && player.IsAdmin) target = player.transform.position;
}
[Command("showcrashzone")]
private void showcrashzone(IPlayer iplayer) {
var player = (BasePlayer)iplayer.Object;
int poitsAmount;
float pos = mapSize;
Vector3 tar = target;
Vector3 center = target;
if (player && player.IsAdmin) {
if (!Configuration.useMultipleZones) {
poitsAmount = (int)mapSize / 8;
for (int i = 0; i < poitsAmount + 1; i++) {
drawDot(player, crashZoneCenter, "+");
tar = new Vector3(crashZoneCenter.x - pos + i * pos / poitsAmount * 2, 1000, crashZoneCenter.z - pos);
drawDot(player, tar, "o");
tar = new Vector3(crashZoneCenter.x - pos + i * pos / poitsAmount * 2, 1000, crashZoneCenter.z + pos);
drawDot(player, tar, "o");
tar = new Vector3(crashZoneCenter.x - pos, 1000, crashZoneCenter.z - pos + i * pos / poitsAmount * 2);
drawDot(player, tar, "o");
tar = new Vector3(crashZoneCenter.x + pos, 1000, crashZoneCenter.z - pos + i * pos / poitsAmount * 2);
drawDot(player, tar, "o");
}
}
else {
for (int f = 0; f < Configuration.zonesList.Count; f++) {
center = Configuration.zonesList[f].center;
pos = Configuration.zonesList[f].radius / 4;
poitsAmount = (int)pos / 6;
for (int i = 0; i < poitsAmount + 1; i++) {
drawDot(player, center, Configuration.zonesList[f].name);
tar = new Vector3(center.x - pos + i * pos / poitsAmount * 2, 1000, center.z - pos);
drawDot(player, tar, "o");
tar = new Vector3(center.x - pos + i * pos / poitsAmount * 2, 1000, center.z + pos);
drawDot(player, tar, "o");
tar = new Vector3(center.x - pos, 1000, center.z - pos + i * pos / poitsAmount * 2);
drawDot(player, tar, "o");
tar = new Vector3(center.x + pos, 1000, center.z - pos + i * pos / poitsAmount * 2);
drawDot(player, tar, "o");
}
}
}
}
}
}
}