C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using Rust;
using UnityEngine;
using UnityEngine.Playables;
using Oxide.Game.Rust;
using System.Globalization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using UnityEngine.SceneManagement;
using Facepunch;
namespace Oxide.Plugins
//comments are wide to the right --->
{
[Info("BotSpawn", "Steenamaroo", "1.4.6", ResourceId = 2580)]
[Description("Spawn tailored AI with kits at monuments and custom locations.")]
class BotSpawn : RustPlugin
{
[PluginReference]
Plugin Vanish, Kits;
const string permAllowed = "botspawn.allowed";
bool HasPermission(string id, string perm) => permission.UserHasPermission(id, perm);
int no_of_AI = 0;
System.Random rnd = new System.Random();
static System.Random random = new System.Random();
bool isInAir;
#region Data
class StoredData
{
public Dictionary<string, MonumentSettings> CustomProfiles = new Dictionary<string, MonumentSettings>();
public StoredData()
{
}
}
StoredData storedData;
#endregion
public double GetRandomNumber(double minimum, double maximum)
{
return random.NextDouble() * (maximum - minimum) + minimum;
}
void Init()
{
JsonConvert.DefaultSettings = () => new JsonSerializerSettings {
Formatting = Newtonsoft.Json.Formatting.Indented,
ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
};
var filter = RustExtension.Filter.ToList(); //Thanks Fuji.:)
filter.Add("cover points");
filter.Add("resulted in a conflict");
RustExtension.Filter = filter.ToArray();
no_of_AI = 0;
Wipe();
LoadConfigVariables();
}
void OnServerInitialized()
{
FindMonuments();
}
void Loaded()
{
lang.RegisterMessages(messages, this);
permission.RegisterPermission(permAllowed, this);
storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>("BotSpawn");
}
void Unload()
{
var filter = RustExtension.Filter.ToList();
filter.Remove("OnServerInitialized");
filter.Remove("cover points");
filter.Remove("resulted in a conflict");
RustExtension.Filter = filter.ToArray();
Wipe();
}
void Wipe()
{
foreach (var bot in TempRecord.NPCPlayers)
{
if (bot == null)
{
TempRecord.NPCPlayers.Remove(bot);
Wipe();
return;
}
var comp = bot.GetComponent<BasePlayer>();
if (comp != null)
comp.Kill();
else
continue;
}
TempRecord.NPCPlayers.Clear();
}
bool isAuth(BasePlayer player)
{
if (player.net.connection != null)
if (player.net.connection.authLevel < 2)
return false;
return true;
}
object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
{
NPCPlayerApex Scientist = null;
if (entity is NPCPlayerApex)
{
Scientist = entity as NPCPlayerApex;
if (!TempRecord.NPCPlayers.Contains(Scientist))
return null;
if (info.Initiator is BasePlayer)
{
var damagedbot = entity as NPCPlayer;
var canNetwork = Vanish?.Call("IsInvisible", info.Initiator); //bots wont retaliate to vanished players
if ((canNetwork is bool))
if ((bool)canNetwork)
{
info.Initiator = null;
}
if (configData.Options.Peace_Keeper) //prevent melee farming with peacekeeper on
{
var heldMelee = info.Weapon as BaseMelee;
var heldTorchWeapon = info.Weapon as TorchWeapon;
if (heldMelee != null || heldTorchWeapon != null)
info.damageTypes.ScaleAll(0);
}
var bData = Scientist.GetComponent<botData>();
float multiplier = 100f / bData.health;
info.damageTypes.ScaleAll(multiplier);
}
}
if (info?.Initiator is NPCPlayer && entity is BasePlayer) //add in bot accuracy
{
var attacker = info.Initiator as NPCPlayerApex;
if (TempRecord.NPCPlayers.Contains(attacker))
{
var bData = attacker.GetComponent<botData>();
System.Random rnd = new System.Random();
int rand = rnd.Next(1, 10);
if (bData.accuracy < rand) //scale bot attack damage
{
return true;
}
else
{
info.damageTypes.ScaleAll(bData.damage);
return null;
}
}
}
return null;
}
void OnPlayerDie(BasePlayer player)
{
string respawnLocationName = "";
NPCPlayerApex Scientist = null;
if (player is NPCPlayerApex)
{
Scientist = player as NPCPlayerApex;
if (!TempRecord.NPCPlayers.Contains(Scientist))
return;
if (TempRecord.NPCPlayers.Contains(Scientist)) //kill radio effects
{
var bData = Scientist.GetComponent<botData>();
Item activeItem = player.GetActiveItem();
if (bData.dropweapon == true)
{
using (TimeWarning timeWarning = TimeWarning.New("PlayerBelt.DropActive", 0.1f))
{
activeItem.Drop(player.eyes.position, new Vector3(), new Quaternion());
player.svActiveItemID = 0;
player.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
}
}
no_of_AI--;
respawnLocationName = bData.monumentName;
TempRecord.DeadNPCPlayerIds.Add(Scientist.userID);
if (TempRecord.MonumentProfiles[respawnLocationName].Disable_Radio == true)
Scientist.DeathEffect = new GameObjectRef();
if(bData.respawn == false)
{
UnityEngine.Object.Destroy(Scientist.GetComponent<botData>());
UpdateRecords(Scientist);
return;
}
foreach (var profile in TempRecord.MonumentProfiles)
{
if(profile.Key == respawnLocationName)
{
timer.Once(profile.Value.Respawn_Timer, () => SpawnBots(profile.Key, profile.Value, null));
UnityEngine.Object.Destroy(Scientist.GetComponent<botData>());
UpdateRecords(Scientist);
}
}
}
}
}
void UpdateRecords(NPCPlayerApex player)
{
if (TempRecord.NPCPlayers.Contains(player))
{
TempRecord.NPCPlayers.Remove(player);
return;
}
}
// Facepunch.RandomUsernames
public static string Get(ulong v) //credit Fujikura.{
return Facepunch.RandomUsernames.Get((int)(v % 2147483647uL));
}
BaseEntity InstantiateSci(Vector3 position, Quaternion rotation, bool murd) //Spawn population spam fix - credit Fujikura
{
string prefabname = "assets/prefabs/npc/scientist/scientist.prefab";
if (murd == true)
{
prefabname ="assets/prefabs/npc/murderer/murderer.prefab";
}
var prefab = GameManager.server.FindPrefab(prefabname);
GameObject gameObject = Instantiate.GameObject(prefab, position, rotation);
gameObject.name = prefabname;
SceneManager.MoveGameObjectToScene(gameObject, Rust.Server.EntityScene);
if (gameObject.GetComponent<Spawnable>())
UnityEngine.Object.Destroy(gameObject.GetComponent<Spawnable>());
if (!gameObject.activeSelf)
gameObject.SetActive(true);
BaseEntity component = gameObject.GetComponent<BaseEntity>();
return component;
}
void SpawnBots(string name, MonumentSettings settings, string type = null)
{
var murd = settings.Murderer;
var pos = new Vector3 (settings.LocationX, settings.LocationY, settings.LocationZ);
var zone = settings;
int X = rnd.Next((-zone.Radius/2), (zone.Radius/2)); //no need for /2
int Z = rnd.Next((-zone.Radius/2), (zone.Radius/2));
int dropX = rnd.Next(5, 10);
int dropZ = rnd.Next(5, 10);
int Y = 100;
var CentrePos = new Vector3((pos.x + X),200,(pos.z + Z));
Quaternion rot = Quaternion.Euler(0, 0, 0);
Vector3 newPos = (CalculateGroundPos(CentrePos));
NPCPlayer entity = (NPCPlayer)InstantiateSci(newPos, rot, murd);
var botapex = entity.GetComponent<NPCPlayerApex>();
var bData = botapex.gameObject.AddComponent<botData>();
TempRecord.NPCPlayers.Add(botapex);
if (zone.Roam_Range < 20)
zone.Roam_Range = 20;
botapex.Spawn();
bData.spawnPoint = newPos;
bData.accuracy = zone.Bot_Accuracy;
bData.damage = zone.Bot_Damage;
bData.health = zone.BotHealth;
bData.range = (zone.Aggression_Range / 3f);
bData.monumentName = name;
bData.respawn = true;
bData.roamRange = zone.Roam_Range;
bData.dropweapon = zone.Weapon_Drop;
bData.keepAttire = zone.Keep_Default_Loadout;
int suicInt = rnd.Next((configData.Options.Suicide_Timer), (configData.Options.Suicide_Timer + 10)); //slightly randomise suicide de-spawn time
if (type == "AirDrop" || type == "Attack")
{
bData.respawn = false;
timer.Once(suicInt, () =>
{
if (TempRecord.NPCPlayers.Contains(botapex))
{
if (botapex != null)
{
Effect.server.Run("assets/prefabs/weapons/rocketlauncher/effects/rocket_explosion.prefab", botapex.transform.position); //fix for manual OnEntityDeath
HitInfo nullHit = new HitInfo();
nullHit.damageTypes.Add(Rust.DamageType.Explosion, 10000);
botapex.Hurt(nullHit);
}
else
{
TempRecord.NPCPlayers.Remove(botapex);
Puts("This Shouldn't Happen");
return;
}
}
else return;
});
}
int kitRnd;
if (zone.Kit.Count != 0)
{
kitRnd = rnd.Next(zone.Kit.Count);
if (zone.Kit[kitRnd] != null)
{
object checkKit = (Kits.CallHook("GetKitInfo", zone.Kit[kitRnd], true));
if (checkKit == null)
{
PrintWarning($"Kit {zone.Kit[kitRnd]} does not exist - Defaulting to Scientist or Murderer.");
}
else
{
bool weaponInBelt = false;
if (checkKit != null && checkKit is JObject)
{
List<string> contentList = new List<string>();
JObject kitContents = checkKit as JObject;
JArray items = kitContents["items"] as JArray;
foreach (var weap in items)
{
JObject item = weap as JObject;
if (item["container"].ToString() == "belt")
weaponInBelt = true;
}
}
if (!weaponInBelt)
{
PrintWarning($"Kit {zone.Kit[kitRnd]} has no items in belt - Defaulting to Scientist or Murderer.");
}
else
{
if(bData.keepAttire == false)
entity.inventory.Strip();
Kits?.Call($"GiveKit", entity, zone.Kit[kitRnd], true);
TempRecord.kitList.Add(botapex.userID, zone.Kit[kitRnd]);
}
}
}
}
no_of_AI++;
foreach (Item item in botapex.inventory.containerBelt.itemList) //store organised weapons lists
{
var held = item.GetHeldEntity();
if (held as HeldEntity != null)
{
if (held as BaseMelee != null || held as TorchWeapon != null)
bData.MeleeWeapons.Add(item);
else
{
if (held as BaseProjectile != null)
{
bData.AllProjectiles.Add(item);
if (held.name.Contains("m92") || held.name.Contains("pistol") || held.name.Contains("python") || held.name.Contains("waterpipe"))
bData.CloseRangeWeapons.Add(item);
else if (held.name.Contains("bolt"))
bData.LongRangeWeapons.Add(item);
else
bData.MediumRangeWeapons.Add(item);
}
}
}
}
if (zone.BotName == "randomname")
entity.displayName = Get(entity.userID);
else
entity.displayName = zone.BotName;
botapex.Stats.VisionRange = bData.range;
entity.health = zone.BotHealth;
if (zone.Disable_Radio)
botapex.GetComponent<FacepunchBehaviour>().CancelInvoke(new Action(botapex.RadioChatter));
timer.Once(1, () => SelectWeapon(botapex, null, false));
}
void OnEntitySpawned(BaseEntity entity)
{
if (entity != null)
{
if (entity is NPCPlayerCorpse)
{
var corpse = entity as NPCPlayerCorpse;
if (!configData.Options.Allow_Rust_Loot)
NextTick(() =>
{
corpse.containers[0].Clear();
corpse.containers[1].Clear();
corpse.containers[2].Clear();
}
);
string kit;
if (TempRecord.kitList.ContainsKey(corpse.playerSteamID))
{
kit = TempRecord.kitList[corpse.playerSteamID];
if (kit == null)
return;
string[] checkKit = (Kits.CallHook("GetKitContents", kit)) as string[];
var tempbody = GameManager.server.CreateEntity("assets/prefabs/player/player.prefab", (corpse.transform.position - new Vector3(0,-100,0)), corpse.transform.rotation).ToPlayer();
tempbody.Spawn();
Kits?.Call($"GiveKit", tempbody, kit, true);
NextTick(() =>
{
var source = new ItemContainer[] { tempbody.inventory.containerMain, tempbody.inventory.containerWear, tempbody.inventory.containerBelt };
for (int i = 0; i < (int)source.Length; i++)
{
Item[] array = source[i].itemList.ToArray();
for (int j = 0; j < (int)array.Length; j++)
{
Item item = array[j];
if (!item.MoveToContainer(corpse.containers[i], -1, true))
{
item.Remove(0f);
}
}
}
tempbody.Kill();
if (configData.Options.Wipe_Belt)
corpse.containers[2].Clear();
if (configData.Options.Wipe_Clothing)
corpse.containers[1].Clear();
TempRecord.kitList.Remove(corpse.playerSteamID);
});
}
}
if (entity is DroppedItemContainer)
{
NextTick(() =>
{
if (entity == null || entity.IsDestroyed) return;
var container = entity as DroppedItemContainer;
ulong ownerID = container.playerSteamID;
if (ownerID == 0) return;
if (configData.Options.Remove_BackPacks)
{
if (TempRecord.DeadNPCPlayerIds.Contains(ownerID))
{
entity.Kill();
TempRecord.DeadNPCPlayerIds.Remove(ownerID);
return;
}
}
});
}
Vector3 dropLocation = new Vector3(0,0,0);
if (!(entity.name.Contains("supply_drop")))
return;
dropLocation = (CalculateGroundPos(entity.transform.position));
List<BaseEntity> entitiesWithinRadius = new List<BaseEntity>();
Vis.Entities(dropLocation, 50f, entitiesWithinRadius);
foreach (var BaseEntity in entitiesWithinRadius) //check for smoking grenade at proposed airdrop spawn location
{
if (BaseEntity.name.Contains("grenade.smoke.deployed") && !(configData.Options.Supply_Enabled))
return;
}
foreach (var profile in TempRecord.MonumentProfiles)
{
if(profile.Key == "AirDrop" && profile.Value.Activate == true)
{
timer.Repeat(0f,profile.Value.Bots, () =>
{
profile.Value.LocationX = entity.transform.position.x;
profile.Value.LocationY = entity.transform.position.y;
profile.Value.LocationZ = entity.transform.position.z;
SpawnBots(profile.Key, profile.Value, "AirDrop");
}
);
}
}
}
}
void SelectWeapon(NPCPlayerApex npcPlayer, BasePlayer victim, bool hasAttacker)
{
if (npcPlayer == null)
return;
if (npcPlayer.svActiveItemID == 0)
{
return;
}
var active = npcPlayer.GetActiveItem();
HeldEntity heldEntity1 = null;
AttackEntity heldGun = null;
if (active != null)
heldEntity1 = active.GetHeldEntity() as HeldEntity;
if (heldEntity1 != null)
heldGun = npcPlayer.GetHeldEntity() as AttackEntity;
var bData = npcPlayer.GetComponent<botData>();
if (hasAttacker == false)
{
List<int> weapons = new List<int>(); //check all their weapons
foreach (Item item in npcPlayer.inventory.containerBelt.itemList)
{
if (item.GetHeldEntity() as BaseProjectile != null || item.GetHeldEntity() as BaseMelee != null || item.GetHeldEntity() as TorchWeapon != null)
{
weapons.Add(Convert.ToInt16(item.position));
}
}
if (weapons.Count == 0)
{
Puts("No suitable weapon found in kit.");
return;
}
int index = rnd.Next(weapons.Count);
var currentTime = TOD_Sky.Instance.Cycle.Hour;
if (currentTime > 20 || currentTime < 8)
{
foreach (Item item in npcPlayer.inventory.containerBelt.itemList)
{
HeldEntity held = item.GetHeldEntity() as HeldEntity;
if (item.ToString().Contains("flashlight"))
{
if (heldEntity1 != null)
heldEntity1.SetHeld(false);
var UID = item.uid;
ChangeWeapon(npcPlayer, held, UID);
return;
}
}
}
else
{
foreach (Item item in npcPlayer.inventory.containerBelt.itemList) //pick one at random to start with
{
HeldEntity held = item.GetHeldEntity() as HeldEntity;
if (item.position == weapons[index])
{
if (heldEntity1 != null)
heldEntity1.SetHeld(false);
var UID = npcPlayer.inventory.containerBelt.GetSlot(weapons[index]).uid;
ChangeWeapon(npcPlayer, held, UID);
return;
}
}
}
}
if (hasAttacker == true)
{
bData.canChangeWeapon ++;
if (bData.canChangeWeapon > 3)
{
bData.canChangeWeapon = 0;
if (npcPlayer == null)
return;
float distance = Vector3.Distance(npcPlayer.transform.position, victim.transform.position);
int noOfAvailableWeapons = 0;
int selectedWeapon;
Item chosenWeapon = null;
HeldEntity held = null;
int newCurrentRange = 0;
var currentTime = TOD_Sky.Instance.Cycle.Hour;
bool night = false;
if (currentTime > 20 || currentTime < 8)
night = true;
if (npcPlayer.AttackTarget == null && night)
{
foreach (var weap in bData.MeleeWeapons)
{
if (weap.ToString().Contains("flashlight"))
{
chosenWeapon = weap;
newCurrentRange = 1;
}
}
}
else
{
if (distance < 2f && bData.MeleeWeapons != null)
{
foreach (var weap in bData.MeleeWeapons)
{
noOfAvailableWeapons++;
}
if (noOfAvailableWeapons > 0)
{
selectedWeapon = rnd.Next(bData.MeleeWeapons.Count);
chosenWeapon = bData.MeleeWeapons[selectedWeapon];
newCurrentRange = 1;
}
}
else if (distance > 1f && distance < 10f && bData.CloseRangeWeapons != null)
{
foreach (var weap in bData.CloseRangeWeapons)
{
noOfAvailableWeapons++;
}
if (noOfAvailableWeapons > 0)
{
selectedWeapon = rnd.Next(bData.CloseRangeWeapons.Count);
chosenWeapon = bData.CloseRangeWeapons[selectedWeapon];
newCurrentRange = 2;
}
}
else if (distance > 9f && distance < 30f && bData.MediumRangeWeapons != null)
{
foreach (var weap in bData.MediumRangeWeapons)
{
noOfAvailableWeapons++;
}
if (noOfAvailableWeapons > 0)
{
selectedWeapon = rnd.Next(bData.MediumRangeWeapons.Count);
chosenWeapon = bData.MediumRangeWeapons[selectedWeapon];
newCurrentRange = 3;
}
}
else if (distance > 29 && bData.LongRangeWeapons != null)
{
foreach (var weap in bData.LongRangeWeapons)
{
noOfAvailableWeapons++;
}
if (noOfAvailableWeapons > 0)
{
selectedWeapon = rnd.Next(bData.LongRangeWeapons.Count);
chosenWeapon = bData.LongRangeWeapons[selectedWeapon];
newCurrentRange = 4;
}
}
if (chosenWeapon == null) //if no weapon suited to range, pick any random bullet weapon
{ //prevents sticking with melee @>2m when no pistol is available
foreach (var weap in bData.AllProjectiles)
{
noOfAvailableWeapons++;
}
if (noOfAvailableWeapons > 0)
{
selectedWeapon = rnd.Next(bData.AllProjectiles.Count);
chosenWeapon = bData.AllProjectiles[selectedWeapon];
newCurrentRange = 5;
}
}
}
if (chosenWeapon == null) return;
if (newCurrentRange == bData.currentWeaponRange)
return;
else
bData.currentWeaponRange = newCurrentRange;
held = chosenWeapon.GetHeldEntity() as HeldEntity;
if (heldEntity1.name == held.name) return;
heldEntity1.SetHeld(false);
var UID = chosenWeapon.uid;
ChangeWeapon(npcPlayer, held, UID);
}
}
else
{
timer.Once(1, () => SelectWeapon(npcPlayer, victim, false));
}
}
void ChangeWeapon(NPCPlayer npcPlayer, HeldEntity held, uint UID)
{
npcPlayer.svActiveItemID = 0;
npcPlayer.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
npcPlayer.inventory.UpdatedVisibleHolsteredItems();
npcPlayer.svActiveItemID = UID;
npcPlayer.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
held.SetHeld(true);
npcPlayer.svActiveItemID = UID;
npcPlayer.inventory.UpdatedVisibleHolsteredItems();
AttackEntity heldGun = npcPlayer.GetHeldEntity() as AttackEntity;
if (heldGun != null)
{
if (heldGun as BaseMelee != null || heldGun as TorchWeapon != null)
heldGun.effectiveRange = 2;
else if (held.name.Contains("bolt"))
heldGun.effectiveRange = 800f;
else
heldGun.effectiveRange = 200f;
return;
}
}
#region targeting
object OnNpcPlayerTarget(NPCPlayerApex npcPlayer, BaseEntity entity)
{
if (!TempRecord.NPCPlayers.Contains(npcPlayer))
return null;
if (npcPlayer == null || entity == null)
return null;
if (entity is NPCPlayer)
return null;
BasePlayer victim = null;
if (entity is BasePlayer)
{
victim = entity as BasePlayer;
SelectWeapon(npcPlayer, victim, true);
var currentTime = TOD_Sky.Instance.Cycle.Hour;
var active = npcPlayer.GetActiveItem();
HeldEntity heldEntity1 = null;
HeldEntity attackerheldEntity1 = null;
if (active != null)
heldEntity1 = active.GetHeldEntity() as HeldEntity;
if (heldEntity1 != null)
{
if (currentTime > 20 || currentTime < 8)
heldEntity1.SetLightsOn(true);
else
heldEntity1.SetLightsOn(false);
}
if (configData.Options.Peace_Keeper)
{
if (victim.svActiveItemID == 0u)
{
return 0f;
}
else
{
var heldWeapon = victim.GetHeldEntity() as BaseProjectile;
var heldFlame = victim.GetHeldEntity() as FlameThrower;
if (heldWeapon == null && heldFlame == null)
return 0f;
}
}
if (TempRecord.NPCPlayers.Contains(npcPlayer))
{
var bData = npcPlayer.GetComponent<botData>();
var profile = bData.monumentName;
}
if(!victim.userID.IsSteamId() && configData.Options.Ignore_HumanNPC) //stops bots targeting humannpc
return 0f;
}
if (entity.name.Contains("agents/") && configData.Options.Ignore_Animals) //stops bots targeting animals
return 0f;
else
return null;
}
object CanBradleyApcTarget(BradleyAPC bradley, BaseEntity target) //stops bradley targeting bots
{
if (target is NPCPlayer && configData.Options.APC_Safe)
return false;
return null;
}
object OnNpcTarget(BaseNpc npc, BaseEntity entity) //stops animals targeting bots
{
Puts("OnNpcTargetFired"); //at present this is not working
if (entity is NPCPlayer && configData.Options.Animal_Safe)
return 0f;
return null;
}
object CanBeTargeted(BaseCombatEntity player, MonoBehaviour turret) //stops autoturrets targetting bots
{
if (player is NPCPlayer && configData.Options.Turret_Safe)
return false;
return null;
}
#endregion
void AttackPlayer(BasePlayer player, string name, MonumentSettings profile)
{
Vector3 location = (CalculateGroundPos(player.transform.position));
timer.Repeat(1f,profile.Bots, () =>
{
profile.LocationX = location.x;
profile.LocationY = location.y;
profile.LocationZ = location.z;
SpawnBots(name, profile, "Attack");
}
);
}
static BasePlayer FindPlayerByName(string name)
{
BasePlayer result = null;
foreach (BasePlayer current in BasePlayer.activePlayerList)
{
if (current.displayName.Equals(name, StringComparison.OrdinalIgnoreCase))
{
BasePlayer result2 = current;
return result2;
}
if (current.UserIDString.Contains(name, CompareOptions.OrdinalIgnoreCase))
{
BasePlayer result2 = current;
return result2;
}
if (current.displayName.Contains(name, CompareOptions.OrdinalIgnoreCase))
{
result = current;
}
}
return result;
}
static Vector3 CalculateGroundPos(Vector3 sourcePos) //credit Wulf & Nogrod
{
RaycastHit hitInfo;
if (UnityEngine.Physics.Raycast(sourcePos, Vector3.down, out hitInfo, 800f, LayerMask.GetMask("Terrain", "World", "Construction"), QueryTriggerInteraction.Ignore))
{
sourcePos.y = hitInfo.point.y;
}
sourcePos.y = Mathf.Max(sourcePos.y, TerrainMeta.HeightMap.GetHeight(sourcePos));
return sourcePos;
}
private void FindMonuments() //credit K1lly0u
{
TempRecord.MonumentProfiles.Clear();
var allobjects = UnityEngine.Object.FindObjectsOfType<GameObject>();
int warehouse = 0;
int lighthouse = 0;
int gasstation = 0;
int spermket = 0;
foreach (var gobject in allobjects)
{
if (gobject.name.Contains("autospawn/monument"))
{
var pos = gobject.transform.position;
if (gobject.name.Contains("mining_quarry_a"))
{
AddProfile("QuarryA", configData.Zones.QuarryA, pos);
continue;
}
if (gobject.name.Contains("mining_quarry_b"))
{
AddProfile("QuarryB", configData.Zones.QuarryB, pos);
continue;
}
if (gobject.name.Contains("mining_quarry_c"))
{
AddProfile("QuarryC", configData.Zones.QuarryB, pos);
continue;
}
if (gobject.name.Contains("powerplant_1"))
{
AddProfile("PowerPlant", configData.Zones.PowerPlant, pos);
continue;
}
if (gobject.name.Contains("airfield_1"))
{
AddProfile("Airfield", configData.Zones.Airfield, pos);
continue;
}
if (gobject.name.Contains("trainyard_1"))
{
AddProfile("Trainyard", configData.Zones.Trainyard, pos);
continue;
}
if (gobject.name.Contains("water_treatment_plant_1"))
{
AddProfile("Watertreatment", configData.Zones.Watertreatment, pos);
continue;
}
if (gobject.name.Contains("satellite_dish"))
{
AddProfile("Satellite", configData.Zones.Satellite, pos);
continue;
}
if (gobject.name.Contains("sphere_tank"))
{
AddProfile("Dome", configData.Zones.Dome, pos);
continue;
}
if (gobject.name.Contains("radtown_small_3"))
{
AddProfile("Radtown", configData.Zones.Radtown, pos);
continue;
}
if (gobject.name.Contains("launch_site"))
{
AddProfile("Launchsite", configData.Zones.Launchsite, pos);
continue;
}
if (gobject.name.Contains("junkyard"))
{
AddProfile("Junkyard", configData.Zones.Junkyard, pos);
continue;
}
if (gobject.name.Contains("military_tunnel_1"))
{
AddProfile("MilitaryTunnel", configData.Zones.MilitaryTunnel, pos);
continue;
}
if (gobject.name.Contains("harbor_1"))
{
AddProfile("Harbor1", configData.Zones.Harbor1, pos);
continue;
}
if (gobject.name.Contains("harbor_2"))
{
AddProfile("Harbor2", configData.Zones.Harbor2, pos);
continue;
}
if (gobject.name.Contains("gas_station_1") && gasstation == 0)
{
AddProfile("GasStation", configData.Zones.GasStation, pos);
gasstation++;
continue;
}
if (gobject.name.Contains("gas_station_1") && gasstation == 1)
{
AddProfile("GasStation1", configData.Zones.GasStation1, pos);
gasstation++;
continue;
}
if (gobject.name.Contains("supermarket_1") && spermket == 0)
{
AddProfile("SuperMarket", configData.Zones.SuperMarket, pos);
spermket++;
continue;
}
if (gobject.name.Contains("supermarket_1") && spermket == 1)
{
AddProfile("SuperMarket1", configData.Zones.SuperMarket1, pos);
spermket++;
continue;
}
if (gobject.name.Contains("lighthouse") && lighthouse == 0)
{
AddProfile("Lighthouse", configData.Zones.Lighthouse, pos);
lighthouse++;
continue;
}
if (gobject.name.Contains("lighthouse") && lighthouse == 1)
{
AddProfile("Lighthouse1", configData.Zones.Lighthouse1, pos);
lighthouse++;
continue;
}
if (gobject.name.Contains("lighthouse") && lighthouse == 2)
{
AddProfile("Lighthouse2", configData.Zones.Lighthouse2, pos);
lighthouse++;
continue;
}
if (gobject.name.Contains("warehouse") && warehouse == 0)
{
AddProfile("Warehouse", configData.Zones.Warehouse, pos);
warehouse++;
continue;
}
if (gobject.name.Contains("warehouse") && warehouse == 1)
{
AddProfile("Warehouse1", configData.Zones.Warehouse1, pos);
warehouse++;
continue;
}
if (gobject.name.Contains("warehouse") && warehouse == 2)
{
AddProfile("Warehouse2", configData.Zones.Warehouse2, pos);
warehouse++;
continue;
}
if (gobject.name.Contains("warehouse") && warehouse > 2)
continue;
if (gobject.name.Contains("lighthouse") && lighthouse > 2)
continue;
if (gobject.name.Contains("gas_station_1") && gasstation > 1)
continue;
if (gobject.name.Contains("supermarket_1") && spermket > 1)
continue;
}
}
TempRecord.MonumentProfiles.Add("AirDrop", new MonumentSettings
{
Activate = configData.Zones.AirDrop.Activate,
Murderer = configData.Zones.AirDrop.Murderer,
Bots = configData.Zones.AirDrop.Bots,
BotHealth = configData.Zones.AirDrop.BotHealth,
Radius = configData.Zones.AirDrop.Radius,
Kit = configData.Zones.AirDrop.Kit,
BotName = configData.Zones.AirDrop.BotName,
Bot_Accuracy = configData.Zones.AirDrop.Bot_Accuracy,
Bot_Damage = configData.Zones.AirDrop.Bot_Damage,
Disable_Radio = configData.Zones.AirDrop.Disable_Radio,
LocationX = 0f,
LocationY = 0f,
LocationZ = 0f,
Respawn_Timer = 10,
Aggressio
// ... [Code preview truncated due to length. Full source in attached file] ...