C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Oxide.Core.Plugins;
using Oxide.Core;
using Newtonsoft.Json;
using UnityEngine;
using System.Collections.Generic;
namespace Oxide.Plugins {
[Info("Traffic Drivers", "walkinrey", "1.2.92")]
[Description("This plugin was fixed by Инкуб to order [Rust Plugin Sliv]: https://discord.gg/pFgKw6Dyyq")]
public class TrafficDrivers : RustPlugin {
public static TrafficDrivers Instance;
[PluginReference]
private Plugin SpawnModularCar, Convoy, MarkerManager;
private SpawnManager _spawner;
private List<Vector3[]> _roadPathes = new List<Vector3[]>();
private Dictionary<ulong, TrafficCompanion> _driverCompanions = new Dictionary<ulong, TrafficCompanion>();
private Dictionary<ulong, TrafficDriver> _carsDrivers = new Dictionary<ulong, TrafficDriver>();
private Dictionary<ulong, List<BaseNetworkable>> _debugMarkers = new Dictionary<ulong, List<BaseNetworkable>>();
private Dictionary<ulong, PlayerPathRecorder> _recorders = new Dictionary<ulong, PlayerPathRecorder>();
private TrafficCompanion GetCompanion(ulong playerNetID) {
if(_driverCompanions.ContainsKey(playerNetID)) {
var value = _driverCompanions[playerNetID];
if(value == null) return null;
return value;
}
return null;
}
private TrafficDriver GetDriver(ulong playerNetID) {
if(_carsDrivers.ContainsKey(playerNetID)) {
var value = _carsDrivers[playerNetID];
if(value == null) return null;
return value;
}
return null;
}
#region Конфиг
private Configuration _config;
public class Configuration {
[JsonProperty("Enable path recorder?")]
public bool enableRecording = false;
[JsonProperty("Vehicle presets")]
public Dictionary<string, CarPreset> carPresets = new Dictionary<string, CarPreset>();
[JsonProperty("Driver presets")]
public Dictionary<string, DriverPreset> driverPresets = new Dictionary<string, DriverPreset>();
[JsonProperty("Limits, spawn and interaction setup")]
public Limits limits = new Limits();
public class Limits {
[JsonProperty("Maximum amount of cars")]
public MinMax maxCars = new MinMax();
[JsonProperty("Minimum road width")]
public int minRoadWidth = 100;
[JsonProperty("After how many seconds destroy stuck car?")]
public float stuckDespawnTime = 60f;
[JsonProperty("Delay between spawn next car")]
public int spawnCooldown = 5;
[JsonProperty("Prevent bots from attacking drivers and companions?")]
public bool blockTrafficTarget = true;
[JsonProperty("Despawn vehicle if it collides with next prefabs")]
public string[] despawnPrefabs = new string[] {
"train_wagon", "trainwagon"
}
;
[JsonProperty("Convoy plugin support")]
public ConvoySupport convoy = new ConvoySupport();
public class ConvoySupport {
[JsonProperty("Enable the Convoy plugin support?")]
public bool enableConvoySupport = false;
[JsonProperty("Destroy traffic vehicles at the start of the Convoy plugin event?")]
public bool destroyCarsOnEvent = false;
[JsonProperty("Destroy traffic vehicles when colliding with Convoy plugin event vehicles?")]
public bool destroyCarsOnHit = false;
}
}
public class DriverPreset {
[JsonProperty("Display driver name")]
public string name = "Водитель Ярик";
[JsonProperty("Bot skin (0 - random)")]
public ulong skin = 0;
[JsonProperty("Bot health")]
public MinMax health = new MinMax();
[JsonProperty("Bot loot")]
public List<LootInfo> loot = new List<LootInfo>();
[JsonProperty("Driver will be moving with default speed (1) or will be increase max.speed for a while (2) when attacked?")]
public int attackBehaviour = 1;
[JsonProperty("Damage receive rate")]
public float damageReceiveRate = 0.5f;
[JsonProperty("Clothes")]
public List<ClothInfo> clothes = new List<ClothInfo>();
[JsonProperty("Companion")]
public CompanionSetup companion = new CompanionSetup();
[JsonProperty("Lock player inventory containers")]
public ContainerLock containerLock = new ContainerLock();
public class ContainerLock {
[JsonProperty("Lock player main inventory container?")]
public bool lockMain = false;
[JsonProperty("Lock player wear inventory container?")]
public bool lockWear = false;
[JsonProperty("Lock player belt inventory container?")]
public bool lockBelt = false;
}
public class CompanionSetup {
[JsonProperty("Spawn companion for driver? (he will shoot and protect him)")]
public bool enableCompanion = false;
[JsonProperty("Display companion name")]
public string name = "Компаньон-защитник";
[JsonProperty("Prevent companion from attacking first?")]
public bool preventAttackFirst = true;
[JsonProperty("Companion health")]
public MinMax health = new MinMax();
[JsonProperty("Clothes")]
public List<ClothInfo> clothes = new List<ClothInfo>();
[JsonProperty("Weapons")]
public List<ClothInfo> weapons = new List<ClothInfo>();
[JsonProperty("Damage receive rate")]
public float damageReceiveRate = 0.5f;
[JsonProperty("Damage rate")]
public float damageHurtRate = 2f;
}
public class LootInfo : ClothInfo {
[JsonProperty("Item name", Order = -1)]
public string name;
[JsonProperty("Spawn chance", Order = 3)]
public float chance;
[JsonProperty("Item amount", Order = 4)]
public MinMax amount;
[JsonProperty("Target container (main, belt, wear)", Order = 5)]
public string container;
}
public class ClothInfo {
[JsonProperty("Item shortname")]
public string shortname;
[JsonProperty("Item skin")]
public ulong skin;
}
}
public class CarPreset {
[JsonProperty("Random modules count (2-4, 0 for random count)")]
public int modulesCount;
[JsonProperty("Modules (if you enter modules here the random modules option will not work)")]
public string[] modules = new string[] {
}
;
[JsonProperty("Add codelock?")]
public bool addCodeLock = false;
[JsonProperty("Add door lock?")]
public bool addDoorLock = false;
[JsonProperty("Engine parts tier (0-3, 0 to spawn without parts)")]
public int enginePartsTier = 3;
[JsonProperty("Fuel amount (-1 for max amount)")]
public int fuelAmount = -1;
[JsonProperty("Water amount for fuel tank (not necessary, -1 for max amount)")]
public int waterAmount = 0;
[JsonProperty("Max speed")]
public float maxSpeed = 15;
[JsonProperty("Enable infinite fuel")]
public bool infiniteFuel = true;
[JsonProperty("Driver preset name (leave blank to spawn random driver)")]
public string driverPreset = "";
[JsonProperty("Destroy car after driver death?")]
public bool destroyCarAfterDeath = false;
[JsonProperty("Block access to engine parts?")]
public bool blockEngineLooting = true;
[JsonProperty("Destroy engine parts after driver death?")]
public bool destroyEngineParts = true;
[JsonProperty("Add flashing lights to car driver module?")]
public bool enableBlueLights = false;
[JsonProperty("Vehicle and passenger immortal time after spawn")]
public float immortalTime = 5f;
[JsonProperty("Make vehicle immortal?")]
public bool enableImmortal = false;
[JsonProperty("Detonator (for vehicle despawn)")]
public Detonator detonator = new Detonator();
[JsonProperty("Loot in Storage Module")]
public StorageLoot storage = new StorageLoot();
[JsonProperty("Passengers")]
public List<Passenger> passengers = new List<Passenger>();
[JsonProperty("Car Headlights")]
public CarHeadlights carHeadlights = new CarHeadlights();
public class CarHeadlights {
[JsonProperty("Enable car headlights?")]
public bool enableHeadlights = true;
[JsonProperty("Enable headlights only at night?")]
public bool onlyAtNightMode = true;
}
public class Passenger {
[JsonProperty("Spawn chance")]
public float chance = 50f;
[JsonProperty("Make passenger scientist?")]
public bool makePassengerScientist = false;
[JsonProperty("Passenger display name")]
public string displayName = "Passenger";
[JsonProperty("Passenger skin (0 for random, this option isn't available when passenger is scientist)")]
public ulong id = 0;
[JsonProperty("Passenger health")]
public MinMax health = new MinMax();
[JsonProperty("Passenger loot (scientists will be have a standard rust loot, here you can give them clothes and guns)")]
public List<DriverPreset.LootInfo> loot = new List<DriverPreset.LootInfo>();
[JsonProperty("Passenger lock inventory containers (this option isn't available when passenger is scientist)")]
public DriverPreset.ContainerLock lockInventory = new DriverPreset.ContainerLock();
}
public class Detonator {
[JsonProperty("Add a detonator to the car after the death of the driver (useful to despawn cars)")]
public bool enableDetonator = true;
[JsonProperty("In how many seconds detonator will be blow up")]
public float timer = 300f;
[JsonProperty("Detonator position offset on the car")]
public Vector3 offset = new Vector3(0, 0.5f, 0);
}
public class StorageLoot {
[JsonProperty("Add loot to Storage Module")]
public bool enableLoot = true;
[JsonProperty("Loot")]
public List<ItemInfo> lootInfo = new List<ItemInfo>();
public struct ItemInfo {
[JsonProperty("Item shortname")]
public string shortname;
[JsonProperty("Item skin")]
public ulong skin;
[JsonProperty("Item name (not necessary)")]
public string name;
[JsonProperty("Spawn chance")]
public float chance;
[JsonProperty("Item amount")]
public MinMax amount;
}
}
public Dictionary<string, object> ConvertForAPI() {
var dict = new Dictionary<string, object>();
dict.Add("Modules", modules);
dict.Add("CodeLock", addCodeLock);
dict.Add("KeyLock", addDoorLock);
dict.Add("EnginePartsTier", enginePartsTier);
dict.Add("FuelAmount", fuelAmount);
dict.Add("FreshWaterAmount", waterAmount);
return dict;
}
}
public class MinMax {
[JsonProperty("Minimum")]
public float min = 1;
[JsonProperty("Maximum")]
public float max = 5;
public MinMax(float minimum = 1, float maximum = 5) {
min = minimum;
max = maximum;
}
public float Randomize() => UnityEngine.Random.Range(min, max);
}
}
protected override void LoadDefaultConfig() {
_config = new Configuration();
_config.carPresets.Add("3 module vehicle", new Configuration.CarPreset {
modules = new string[] {
"vehicle.1mod.engine", "vehicle.1mod.storage", "vehicle.1mod.cockpit.with.engine"
}
, maxSpeed = 10, storage = new Configuration.CarPreset.StorageLoot {
enableLoot = true, lootInfo = new List<Configuration.CarPreset.StorageLoot.ItemInfo> {
new Configuration.CarPreset.StorageLoot.ItemInfo {
shortname = "wood", chance = 100, amount = new Configuration.MinMax {
min = 1000, max = 10000,
}
}
, new Configuration.CarPreset.StorageLoot.ItemInfo {
shortname = "stones", chance = 100, amount = new Configuration.MinMax {
min = 5000, max = 50000
}
}
}
}
, passengers = new List<Configuration.CarPreset.Passenger> {
new Configuration.CarPreset.Passenger {
health = new Configuration.MinMax(100, 150), loot = new List<Configuration.DriverPreset.LootInfo> {
new Configuration.DriverPreset.LootInfo {
shortname = "wood", chance = 100, amount = new Configuration.MinMax {
min = 1000, max = 10000,
}
, container = "main"
}
, new Configuration.DriverPreset.LootInfo {
shortname = "stones", chance = 100, amount = new Configuration.MinMax {
min = 5000, max = 50000
}
, container = "main"
}
}
}
}
}
);
_config.driverPresets.Add("Yarik Driver", new Configuration.DriverPreset {
attackBehaviour = 2, health = new Configuration.MinMax(100, 150), loot = new List<Configuration.DriverPreset.LootInfo> {
new Configuration.DriverPreset.LootInfo {
shortname = "rifle.ak", amount = new Configuration.MinMax(1, 1), chance = 100, container = "belt"
}
, new Configuration.DriverPreset.LootInfo {
shortname = "hatchet", amount = new Configuration.MinMax(1, 1), chance = 100, container = "main"
}
}
, clothes = new List<Configuration.DriverPreset.ClothInfo> {
new Configuration.DriverPreset.ClothInfo {
shortname = "hazmatsuit"
}
}
, companion = new Configuration.DriverPreset.CompanionSetup {
enableCompanion = true, health = new Configuration.MinMax(100, 150), clothes = new List<Configuration.DriverPreset.ClothInfo> {
new Configuration.DriverPreset.ClothInfo {
shortname = "attire.banditguard"
}
}
, weapons = new List<Configuration.DriverPreset.ClothInfo> {
new Configuration.DriverPreset.ClothInfo {
shortname = "rifle.ak"
}
}
}
}
);
}
protected override void SaveConfig() => Config.WriteObject(_config);
protected override void LoadConfig() {
base.LoadConfig();
try {
_config = Config.ReadObject<Configuration>();
if (_config == null) throw new System.Exception();
SaveConfig();
}
catch (System.Exception ex) {
PrintError("{0}", ex);
LoadDefaultConfig();
}
}
#endregion
#region Дата
private DataFile _data;
private class DataFile {
[JsonProperty("Recorded pathes | Записанные пути")]
public Dictionary<int, List<Vector3>> pathes = new Dictionary<int, List<Vector3>>();
}
private void LoadData() => _data = Interface.Oxide.DataFileSystem.ReadObject<DataFile>("TrafficDrivers_Pathes");
private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject("TrafficDrivers_Pathes", _data);
#endregion
#region Хуки
private void OnTrafficDestroyed() => _spawner.OnTrafficDestroyed();
private object CanNetworkTo(BaseNetworkable entity, BasePlayer target) {
foreach(var pair in _debugMarkers) {
if(pair.Value.Contains(entity)) {
if(!_debugMarkers.ContainsKey(target.userID)) return false;
else {
var marker = _debugMarkers[target.userID];
if(!marker.Contains(entity)) return false;
}
}
}
return null;
}
private void Loaded() {
Instance = this;
NextTick(() => {
if(SpawnModularCar == null) {
PrintError("SpawnModularCar plugin is not installed");
NextTick(() => Interface.Oxide.UnloadPlugin(Title));
return;
}
if(!_config.enableRecording) Unsubscribe("OnPlayerInput");
else Subscribe("OnPlayerInput");
if(_config.limits.convoy.enableConvoySupport && _config.limits.convoy.destroyCarsOnEvent) {
Subscribe("OnConvoyStart");
Subscribe("OnConvoyStop");
}
else {
Unsubscribe("OnConvoyStart");
Unsubscribe("OnConvoyStop");
}
LoadData();
}
);
}
private void OnConvoyStart() {
if(_spawner) _spawner.Pause();
foreach(var driver in _carsDrivers.Values) {
if(driver == null) continue;
var bot = driver.GetComponent<BasePlayer>();
var mountable = bot?.GetMountedVehicle();
if(mountable != null) mountable.Kill();
if(bot != null) bot.Kill();
}
}
private void OnConvoyStop() {
if(_spawner) _spawner.Resume(true);
}
private void Unload() {
if(_spawner) {
_spawner.Pause();
UnityEngine.Object.DestroyImmediate(_spawner);
}
foreach(var driver in _carsDrivers.Values) {
if(driver == null) continue;
var bot = driver.GetComponent<BasePlayer>();
var mountable = bot?.GetMountedVehicle();
if(mountable != null) mountable.Kill();
if(bot != null) bot.Kill();
}
foreach(var recorder in _recorders.Values) {
if(recorder != null) UnityEngine.Object.Destroy(recorder);
}
}
private void OnPlayerInput(BasePlayer player, InputState input) {
if(!input.WasJustPressed(BUTTON.RELOAD)) return;
if(!_recorders.ContainsKey(player.userID)) return;
var recorder = _recorders[player.userID];
if(recorder == null) return;
recorder.Input();
}
private object OnEntityTakeDamage(BaseVehicleModule module, HitInfo info) {
if(module == null) return null;
var car = module.Vehicle;
if(car == null) return null;
var driver = car.GetDriver();
if(driver) {
var traffic = GetDriver(driver.net.ID.Value);
if(traffic) {
if(traffic.IsCarImmortal) {
info.damageTypes = new Rust.DamageTypeList();
info.DidHit = false;
info.DoHitEffects = false;
return true;
}
}
}
return null;
}
private object CanMoveItem(Item item, PlayerInventory playerLoot, ulong targetContainer, int targetSlot, int amount) {
if(item == null) return null;
if(item.parent == null) return null;
if(item.parent.IsLocked()) return false;
return null;
}
private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
if(entity == null || info == null || info?.damageTypes == null) return null;
if(entity is BaseVehicleModule) OnEntityTakeDamage(entity as BaseVehicleModule, info);
if(entity is BasePlayer) {
var player = entity.ToPlayer();
if(player != null) {
if(!player.userID.IsSteamId() && player.net != null) {
var driver = GetDriver(player.net.ID.Value);
if(driver) {
if(driver.IsImmortal) return true;
info.damageTypes.ScaleAll(driver.GetDamageReceiveRate());
}
else {
var companion = GetCompanion(player.net.ID.Value);
if(companion) {
var companionDriver = GetDriver(companion.GetDriverID());
if(companionDriver) {
if(companionDriver.IsImmortal) return true;
}
info.damageTypes.ScaleAll(companion.GetDamageReceiveRate());
}
}
}
}
}
else {
if(info.Initiator is ModularCar) {
if(_config.limits.convoy.enableConvoySupport) {
if(_config.limits.convoy.destroyCarsOnHit) {
if(Convoy) {
var driverMounted = ((ModularCar)info.Initiator).GetDriver();
if(driverMounted != null) {
var driver = GetDriver(driverMounted.net.ID.Value);
if(driver != null) {
var callResult = Convoy.Call("IsConvoyVehicle", entity);
if(callResult != null) {
if(callResult is bool) {
if(((bool)callResult)) {
UnityEngine.Object.Destroy(driver);
return null;
}
}
}
}
}
}
}
}
if(_config.limits.despawnPrefabs.Length != 0) {
var find = Physics.OverlapSphere(entity.transform.position, 1f, -1);
foreach(var collider in find) {
if(collider == null) continue;
var ent = collider.ToBaseEntity();
if(ent != null) {
if(_config.limits.despawnPrefabs.Contains(ent.ShortPrefabName)) {
var driverMounted = ((ModularCar)info.Initiator).GetDriver();
if(driverMounted != null) {
var driver = GetDriver(driverMounted.net.ID.Value);
if(driver != null) {
info.Initiator.KillMessage();
return null;
}
}
}
}
}
}
}
BaseModularVehicle vehicle = null;
if(entity is BaseVehicleModule) {
var module = (BaseVehicleModule)entity;
if(module.Vehicle != null) vehicle = module.Vehicle;
}
if(entity is BaseModularVehicle) vehicle = (BaseModularVehicle)entity;
if(vehicle != null) {
var driverMounted = vehicle.GetDriver();
if(driverMounted == null || driverMounted?.net == null) return null;
var driver = GetDriver(driverMounted.net.ID.Value);
if(driver == null) return null;
if(driver.IsImmortal) return true;
if(info.InitiatorPlayer != null) driver.OnAttacked(info.InitiatorPlayer);
else if(info.Initiator != null) {
if(info.Initiator is BaseVehicle && info.Initiator != entity) {
var attackerVehicle = (BaseVehicle)info.Initiator;
if(attackerVehicle != null) {
if(attackerVehicle.HasDriver()) {
driver.OnAttacked(attackerVehicle.GetDriver());
return null;
}
}
}
if(info.damageTypes.Total() > 2f) driver.OnPhysicAttacked();
}
}
}
if(info.InitiatorPlayer) {
var initiatorCompanion = GetCompanion(info.InitiatorPlayer.net.ID.Value);
if(initiatorCompanion) {
if(initiatorCompanion.GetExcludeList().Contains(entity.net.ID.Value)) return true;
}
}
return null;
}
private void OnServerInitialized() {
if(_data == null) LoadData();
if(_data.pathes.Count == 0) {
Puts("Recorded paths not found, load standard Rust roads");
foreach(var path in TerrainMeta.Path.Roads) {
if(path.Path.Points.Length < _config.limits.minRoadWidth || path.Splat == 1) continue;
_roadPathes.Add(path.Path.Points);
}
if(_roadPathes.Count == 0) {
PrintError("No suitable roads found! Decrease the minimum road length for traffic in the config.");
NextTick(() => Interface.Oxide.UnloadPlugin(Title));
return;
}
}
else {
Puts("Recorded paths found in data file, load them");
foreach(var path in _data.pathes) {
_roadPathes.Add(path.Value.ToArray());
}
}
_spawner = new GameObject("Traffic SpawnManager", typeof(SpawnManager)).GetComponent<SpawnManager>();
_spawner.Init(_config.limits, this, _roadPathes);
Puts($"Found suitable roads: {_roadPathes.Count}");
}
private object OnNpcTarget(BaseEntity npc, BaseEntity entity) {
if(npc == null || entity == null) return null;
if(npc.net == null || entity.net == null) return null;
var driver = GetDriver(entity.net.ID.Value);
if(driver != null && _config.limits.blockTrafficTarget) return true;
var companionBlock = GetCompanion(entity.net.ID.Value);
if(companionBlock != null && _config.limits.blockTrafficTarget) return true;
var companion = GetCompanion(npc.net.ID.Value);
if(companion != null) {
if(driver != null || companionBlock != null) return true;
if(!companion.CanTargetEntity(entity)) return true;
}
return null;
}
private void OnPlayerCorpseSpawned(BasePlayer player, PlayerCorpse corpse) {
if(player.inventory.containerMain.IsLocked()) corpse.containers[0].SetLocked(true);
if(player.inventory.containerBelt.IsLocked()) corpse.containers[1].SetLocked(true);
if(player.inventory.containerWear.IsLocked()) corpse.containers[2].SetLocked(true);
}
#endregion
#region Методы
[ConsoleCommand("trafficdrivers.debug")]
private void showDebugInfo(ConsoleSystem.Arg arg) {
var drivers = _spawner.GetDrivers();
string msg = $"Traffic cars amount: {drivers.Count}";
if(arg.Player() != null) {
var player = arg.Player();
if(!player.IsAdmin) return;
foreach(var driver in drivers) {
if(driver == null) continue;
msg += $"\n{driver.CarPresetName}: {PhoneController.PositionToGridCoord(driver.transform.position)}";
DebugMarker marker = new GameObject("Debug Marker", typeof(DebugMarker)).GetComponent<DebugMarker>();
marker.displayName = driver.CarPresetName;
marker.radius = 0.2f;
marker.alpha = 0.5f;
marker.refreshRate = 3f;
marker.position = driver.transform.position;
marker.duration = 15;
marker.playerID = player.userID;
ColorUtility.TryParseHtmlString($"#00FFFF", out marker.color1);
ColorUtility.TryParseHtmlString($"#00FFFFFF", out marker.color2);
var instance = TrafficDrivers.Instance;
marker.instance = instance;
if(instance._debugMarkers.ContainsKey(player.userID)) {
var found = instance._debugMarkers[player.userID];
if(found != null) {
foreach(var mrkr in found) {
if(mrkr != null) UnityEngine.Object.Destroy(mrkr);
}
}
instance._debugMarkers.Remove(player.userID);
}
}
player.ChatMessage(msg);
return;
}
foreach(var driver in drivers) {
if(driver == null) continue;
msg += $"\n{driver.CarPresetName}: {PhoneController.PositionToGridCoord(driver.transform.position)}";
}
Puts(msg);
}
[ChatCommand("trafficdrivers")]
private void chatAdminCommand(BasePlayer player, string command, string[] args) {
if(!player.IsAdmin) return;
if(args?.Length == 0) return;
if(args[0] == "recorder") {
if(!_config.enableRecording) {
player.ChatMessage("Recorder disabled in config!");
return;
}
PlayerPathRecorder recorder;
if(_recorders.ContainsKey(player.userID)) {
recorder = _recorders[player.userID];
if(recorder != null) UnityEngine.Object.Destroy(recorder);
_recorders.Remove(player.userID);
}
recorder = player.gameObject.AddComponent<PlayerPathRecorder>();
recorder.Init(this);
_recorders.Add(player.userID, recorder);
switch(lang.GetLanguage(player.UserIDString)) {
case "ru" : player.ChatMessage("Рекордер добавлен.Чтобы начать/закончить запись пути, нажмите кнопку R");
break;
default : player.ChatMessage("Recorder added.To start/stop recording a path, press R button");
break;
}
return;
}
if(args[0] == "markers") {
if(player.IsAdmin) {
if(MarkerManager) {
foreach(var driver in _carsDrivers.Values) {
if(driver != null) {
MarkerManager.Call("API_CreateMarker", driver.transform.position, driver.CarPresetName, 5, 3f, 0.4f, driver.CarPresetName, "34495e", "7f8c8d");
}
}
player.ChatMessage("Car drivers now visible on the in-game map for everyone for 5 seconds");
}
else player.ChatMessage("MarkerManager plugin isn't installed");
}
}
}
private TrafficDriver SpawnTrafficCarParams(Vector3[] path, Vector3 position, TrafficDriver.DriveSide side) {
var presetsList = new List<Configuration.CarPreset>(_config.carPresets.Values);
var driversList = new List<Configuration.DriverPreset>(_config.driverPresets.Values);
var carPreset = presetsList[UnityEngine.Random.Range(0, presetsList.Count)];
var driverPreset = !string.IsNullOrEmpty(carPreset.driverPreset) ? _config.driverPresets[carPreset.driverPreset] : driversList[UnityEngine.Random.Range(0, driversList.Count)];
BasePlayer bot = GameManager.server.CreateEntity("assets/prefabs/player/player.prefab", position) as BasePlayer;
bot.displayName = driverPreset.name;
bot.userID = driverPreset.skin == 0 ? (ulong)UnityEngine.Random.Range(1, 99999) : driverPreset.skin;
bot.UserIDString = bot.userID.ToString();
bot.enableSaving = false;
bot.Spawn();
bot.InitializeHealth(driverPreset.health.min, driverPreset.health.max);
if(driverPreset.containerLock.lockWear) bot.inventory.containerWear.SetLocked(true);
if(driverPreset.containerLock.lockBelt) bot.inventory.containerBelt.SetLocked(true);
if(driverPreset.containerLock.lockMain) bot.inventory.containerMain.SetLocked(true);
foreach(var cloth in driverPreset.clothes) bot.inventory.containerWear.Insert(ItemManager.CreateByName(cloth.shortname, 1, cloth.skin));
foreach(var loot in driverPreset.loot) {
if(UnityEngine.Random.Range(0, 100) < loot.chance) {
Item item = ItemManager.CreateByName(loot.shortname, (int)loot.amount.Randomize(), loot.skin);
if(item == null) continue;
if(!string.IsNullOrEmpty(loot.name)) item.name = loot.name;
if(loot.container == "main") bot.inventory.containerMain.Insert(item);
if(loot.container == "belt") bot.inventory.containerBelt.Insert(item);
if(loot.container == "wear") bot.inventory.containerWear.Insert(item);
}
}
bool isFilledWithRandom = false;
if(carPreset.modules == null || carPreset.modules?.Length == 0) {
List<string> modules = new List<string>();
string prefab;
if(carPreset.modulesCount == 0) prefab = $"assets/content/vehicles/modularcar/{UnityEngine.Random.Range(3, 5)}module_car_spawned.entity.prefab";
else prefab = $"assets/content/vehicles/modularcar/{carPreset.modulesCount}module_car_spawned.entity.prefab";
ModularCar vehicle = GameManager.server.CreateEntity(prefab) as ModularCar;
vehicle.Spawn();
foreach (KeyValuePair<BaseVehicleModule, System.Action> entry in (new List<KeyValuePair<BaseVehicleModule, System.Action>>(vehicle.moduleAddActions))) {
modules.Add(entry.Key.AssociatedItemDef.shortname);
}
isFilledWithRandom = true;
vehicle.Kill();
carPreset.modules = modules.ToArray();
}
ModularCar car = SpawnModularCar.Call<ModularCar>("API_SpawnPresetCar", bot, carPreset.ConvertForAPI());
car.enableSaving = false;
if(isFilledWithRandom) carPreset.modules = new string[] {
}
;
if(carPreset.infiniteFuel) {
var container = car.GetFuelSystem().fuelStorageInstance.Get(true);
if (container != null) {
var item = ItemManager.CreateByName("lowgradefuel", 200, 12345);
item.OnDirty += delegate(Item item1) {
item1.amount = 200;
}
;
container.inventory.Insert(item);
item.SetFlag(global : : Item.Flag.IsLocked, true);
container.dropsLoot = false;
container.inventory.SetFlag(ItemContainer.Flag.IsLocked, true);
container.SetFlag(BaseEntity.Flags.Locked, true);
}
}
VehicleModuleStorage storage = null;
BaseMountable driverPlace = null, companionPlace = null;
List<VehicleModuleSeating> seatingModules = new List<VehicleModuleSeating>();
foreach(var module in car.AttachedModuleEntities) {
module.SetHealth(module.MaxHealth());
if(carPreset.storage.enableLoot && storage == null) {
if(module is VehicleModuleStorage && module.ShortPrefabName == "1module_storage") {
storage = module as VehicleModuleStorage;
var container = storage.GetContainer();
if(container.inventory.entityOwner is StorageContainer) {
((StorageContainer)container.inventory.entityOwner).dropsLoot = false;
}
foreach(var item in carPreset.storage.lootInfo) {
if(UnityEngine.Random.Range(0, 100) > item.chance) continue;
Item loot = ItemManager.CreateByName(item.shortname, (int)item.amount.Randomize(), item.skin);
if(!string.IsNullOrEmpty(item.name)) loot.name = item.name;
container.inventory.Insert(loot);
}
}
}
if(carPreset.blockEngineLooting) {
if(module is VehicleModuleEngine) {
var container = ((VehicleModuleEngine)module).GetContainer();
container.inventory.SetLocked(true);
if(container.inventory.entityOwner is StorageContainer) ((StorageContainer)container.inventory.entityOwner).dropsLoot = false;
}
}
if(module is VehicleModuleSeating) {
var seating = module as VehicleModuleSeating;
seatingModules.Add(seating);
foreach(var info in seating.mountPoints) {
if(driverPlace != null && companionPlace != null) break;
if(info.isDriver && driverPlace == null) {
driverPlace = info.mountable;
if(carPreset.enableBlueLights) AddFlashingLights(seating);
}
else if(!info.isDriver && companionPlace == null) {
companionPlace = info.mountable;
}
}
}
}
driverPlace.MountPlayer(bot);
TrafficCompanion trafficCompanion = null;
if(driverPreset.companion.enableCompanion) {
var companion = GameManager.server.CreateEntity("assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_any.prefab", position, Quaternion.identity) as ScientistNPC;
companion.Spawn();
companion.enableSaving = false;
trafficCompanion = companion.gameObject.AddComponent<TrafficCompanion>();
trafficCompanion.Init(driverPreset.companion);
trafficCompanion.AddExclude(bot.net.ID.Value);
trafficCompanion.AddExclude(car.net.ID.Value);
companionPlace.MountPlayer(companion);
_driverCompanions.Add(companion.net.ID.Value, trafficCompanion);
}
List<BasePlayer> passengers = new List<BasePlayer>();
foreach(var passenger in carPreset.passengers) {
if(UnityEngine.Random.Range(0f, 100f) < passenger.chance) {
BasePlayer passengerPlayer = GameManager.server.CreateEntity(passenger.makePassengerScientist ? "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_any.prefab" : "assets/prefabs/player/player.prefab", bot.transform.position) as BasePlayer;
passengerPlayer.displayName = passenger.displayName;
if(!passenger.makePassengerScientist) {
passengerPlayer.userID = passenger.id == 0 ? (ulong)UnityEngine.Random.Range(1, 99999) : passenger.id;
passengerPlayer.UserIDString = passengerPlayer.userID.ToString();
}
passengerPlayer.enableSaving = false;
passengerPlayer.Spawn();
if(!passenger.makePassengerScientist) {
passengerPlayer.InitializeHealth(passenger.health.min, passenger.health.max);
if(passenger.lockInventory.lockWear) passengerPlayer.inventory.containerWear.SetLocked(true);
if(passenger.lockInventory.lockBelt) passengerPlayer.inventory.containerBelt.SetLocked(true);
if(passenger.lockInventory.lockMain) passengerPlayer.inventory.containerMain.SetLocked(true);
}
passengerPlayer.inventory.Strip();
if(!passenger.makePassengerScientist) {
foreach(var loot in passenger.loot) {
if(UnityEngine.Random.Range(0, 100) < loot.chance) {
Item item = ItemManager.CreateByName(loot.shortname, (int)loot.amount.Randomize(), loot.skin);
if(item == null) continue;
if(!string.IsNullOrEmpty(loot.name)) item.name = loot.name;
if(loot.container == "main") passengerPlayer.inventory.containerMain.Insert(item);
if(loot.container == "belt") passengerPlayer.inventory.containerBelt.Insert(item);
if(loot.container == "wear") passengerPlayer.inventory.containerWear.Insert(item);
}
}
}
foreach(var seating in seatingModules) {
var seat = seating.mountPoints.Find(x => x.mountable != driverPlace && x.mountable != companionPlace && x.isDriver == false && !x.mountable.IsBusy());
if(seat != null) {
seat.mountable.MountPlayer(passengerPlayer);
break;
}
}
if(!passengerPlayer.isMounted) {
passengerPlayer.Teleport(new Vector3(0, -1000, 0));
passengerPlayer.Kill();
}
else {
if(trafficCompanion) trafficCompanion.AddExclude(passengerPlayer.net.ID.Value);
var _npc = passengerPlayer.GetComponent<ScientistNPC>();
if(_npc) {
var navigator = _npc.GetComponent<BaseNavigator>();
navigator.CanUseNavMesh = false;
navigator.MaxRoamDistanceFromHome = navigator.BestMovementPointMaxDistance = navigator.BestRoamPointMaxDistance = 0f;
navigator.DefaultArea = "Not Walkable";
_npc._health = UnityEngine.Random.Range(passenger.health.min, passenger.health.max);
_npc.Brain = _npc.GetComponent<ScientistBrain>();
_npc.CancelInvoke(_npc.EquipTest);
_npc.inventory.Strip();
foreach(var item in _npc.inventory.containerBelt.itemList) item.Remove();
foreach(var loot in passenger.loot) {
if(UnityEngine.Random.Range(0, 100) < loot.chance) {
Item item = ItemManager.CreateByName(loot.shortname, (int)loot.amount.Randomize(), loot.skin);
if(item == null) continue;
if(!string.IsNullOrEmpty(loot.name)) item.name = loot.name;
if(loot.container == "main") _npc.inventory.containerMain.Insert(item);
if(loot.container == "belt") _npc.inventory.containerBelt.Insert(item);
if(loot.container == "wear") _npc.inventory.containerWear.Insert(
// ... [Code preview truncated due to length. Full source in attached file] ...