C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System.Collections.Generic;
using CompanionServer.Handlers;
using Newtonsoft.Json;
using UnityEngine;
using System;
using Oxide.Plugins.CustomModulesExtensionMethods;
using Oxide.Core;
using Rust.Modular;
using System.Reflection;
using System.Collections;
using ProtoBuf;
using Oxide.Core.Plugins;
namespace Oxide.Plugins {
[Info("CustomModules", "Adem", "1.1.9")]
class CustomModules : RustPlugin {
#region Variables
[PluginReference]
Plugin VehicleDeployedLocks;
const bool en = true;
private static CustomModules ins;
HashSet<CustomCarSaveData> customCarSaveDatas = new HashSet<CustomCarSaveData>();
HashSet<CustomCarClass> customCarClasses = new HashSet<CustomCarClass>();
HashSet<string> subscribeMethods = new HashSet<string> {
"OnVehicleModulesAssigned", "OnLootEntityEnd", "OnEntitySpawned", "OnEntityMounted", "OnEntityDismounted", "OnEngineStopped", "OnBookmarkControlStarted", "OnBookmarkControlEnded", "CanPickupEntity", "OnEntityDeath", "OnVehicleModuleMove", "OnTurretAuthorize", "OnRfFrequencyChange", "CanEntityTakeDamage", "CanEntityBeTargeted", "OnLootSpawn", "OnTurretTarget"
}
;
bool unloading = false;
bool fullLoad = false;
#endregion Variables
#region Hooks
void Init() => Unsubscribes();
void OnServerInitialized() {
ins = this;
UpdateConfig();
LoadDefaultMessages();
PermissionManager.RegisterPermissions();
LoadAllCustomCars();
UpdateAllComputerStation();
Subscribes();
CustomCarSpawner.StartRespawnCorountime();
NextTick(() => fullLoad = true);
}
void Unload() {
unloading = true;
CustomCarSpawner.StopRespawnCorountime();
Unsubscribes();
SaveAllCustomCars();
DeleteAllCustomCars();
}
void OnServerSave() {
SaveAllCustomCars();
}
void OnVehicleModulesAssigned(ModularCar car, ItemModVehicleModule[] modulePreset) {
if (car == null) return;
NextTick(() => {
AttachOrUpdateCustomCarClass(car);
}
);
}
void OnEntitySpawned(ModularCar car) {
NextTick(() => {
UpdateNewCar(car);
AttachOrUpdateCustomCarClass(car);
}
);
}
void OnLootEntityEnd(BasePlayer player, ModularCarGarage entity) {
if (entity != null && entity.lockedOccupant != null) AttachOrUpdateCustomCarClass(entity.lockedOccupant);
}
void OnEntityMounted(ModularCarSeat modularCarSeat, BasePlayer player) {
if (modularCarSeat == null || modularCarSeat.associatedSeatingModule == null || !modularCarSeat.associatedSeatingModule.Vehicle.HasDriver()) return;
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetCarId() == modularCarSeat.associatedSeatingModule.Vehicle.net.ID.Value);
if (customCarClass != null) customCarClass.OnPlayerMounted();
}
void OnEntityDismounted(ModularCarSeat modularCarSeat, BasePlayer player) {
if (modularCarSeat == null || !player.IsRealPlayer() || modularCarSeat.associatedSeatingModule == null || modularCarSeat.associatedSeatingModule.Vehicle.HasDriver()) return;
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetCarId() == modularCarSeat.associatedSeatingModule.Vehicle.net.ID.Value);
if (customCarClass != null) customCarClass.OnPlayerDismounted();
}
object OnEngineStop(ModularCar modularCar) {
if (modularCar == null) return null;
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetCarId() == modularCar.net.ID.Value);
if (customCarClass != null) {
if (customCarClass.underwater && modularCar.HasDriver() && modularCar.GetFuelSystem().HasFuel() && modularCar.MeetsEngineRequirements()) return true;
}
return null;
}
void OnBookmarkControlStarted(ComputerStation computerStation, BasePlayer player, string bookmarkName, IRemoteControllable remoteControllable) {
if (remoteControllable == null || remoteControllable.GetEnt() == null || player == null) return;
foreach (CustomCarClass customCarClass in customCarClasses) {
if (customCarClass == null || !customCarClass.PlayerHasKey(player)) continue;
ModuleBaseClass moduleBaseClass = customCarClass.GetModuleByEntId(remoteControllable.GetEnt().net.ID.Value);
if (moduleBaseClass == null) continue;
RemoteModuleClass remoteModuleClass = moduleBaseClass as RemoteModuleClass;
if (remoteModuleClass == null) continue;
remoteModuleClass.StartControl(player);
break;
}
}
void OnBookmarkControlEnded(ComputerStation computerStation, BasePlayer player, BaseEntity controlledEntity) {
if (controlledEntity == null || player == null) return;
foreach (CustomCarClass customCarClass in customCarClasses) {
if (customCarClass == null) continue;
ModuleBaseClass moduleBaseClass = customCarClass.GetModuleByEntId(controlledEntity.net.ID.Value);
if (moduleBaseClass == null) continue;
RemoteModuleClass remoteModuleClass = moduleBaseClass as RemoteModuleClass;
if (remoteModuleClass == null) continue;
remoteModuleClass.StopControl();
break;
}
}
object CanPickupEntity(BasePlayer player, AutoTurret autoTurret) {
if (autoTurret == null) return null;
if (customCarClasses.Any(x => x != null && x.GetModuleByEntId(autoTurret.net.ID.Value) != null)) return false;
return null;
}
object CanPickupEntity(BasePlayer player, RFBroadcaster broadcaster) {
if (broadcaster == null) return null;
if (customCarClasses.Any(x => x != null && x.GetModuleByEntId(broadcaster.net.ID.Value) != null)) return false;
return null;
}
object CanPickupEntity(BasePlayer player, CCTV_RC cctv) {
if (cctv == null) return null;
if (customCarClasses.Any(x => x != null && x.GetModuleByEntId(cctv.net.ID.Value) != null)) return false;
return null;
}
object OnVehicleModuleMove(BaseVehicleModule module, BaseModularVehicle vehicle, BasePlayer player) {
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetCarId() == vehicle.net.ID.Value);
if (customCarClass == null) return null;
return customCarClass.CanMoveCarModule(module.net.ID.Value);
}
object CanMoveItem(Item item, PlayerInventory playerLoot, ItemContainerId targetContainer, int targetSlot, int amount) {
if (item == null || playerLoot == null || playerLoot.loot == null || playerLoot.loot.entitySource == null) return null;
if (playerLoot.loot.entitySource is ModularCarGarage) {
if (!LootManager.IsPlayerCanInstallItemToCar(playerLoot.baseEntity.UserIDString, item.info.shortname, item.skin)) {
NotifyManager.SendMessageToPlayer(playerLoot.baseEntity, "NoPermission", _config.prefix);
return true;
}
}
return null;
}
object OnTurretAuthorize(AutoTurret turret, BasePlayer player) {
if (turret == null || player == null) return null;
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetModuleByEntId(turret.net.ID.Value) != null);
if (customCarClass == null) return null;
if (!customCarClass.PlayerHasKey(player)) return true;
return null;
}
object OnEntityTakeDamage(AutoTurret turret, HitInfo info) {
if (!turret.IsExists() || info == null) return null;
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetModuleByEntId(turret.net.ID.Value) != null);
if (customCarClass != null) {
customCarClass.OnChildEntityTakeDamage(turret.net.ID.Value, info);
return true;
}
return null;
}
object OnEntityTakeDamage(RFBroadcaster rFBroadcaster, HitInfo info) {
if (!rFBroadcaster.IsExists() || info == null) return null;
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetModuleByEntId(rFBroadcaster.net.ID.Value) != null);
if (customCarClass != null) return true;
return null;
}
void OnEntityTakeDamage(BaseVehicleModule entity, HitInfo info) {
if (!entity.IsExists() || info == null || entity.net == null) return;
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetModuleByNetId(entity.net.ID.Value) != null);
if (customCarClass != null) {
ModuleBaseClass moduleBaseClass = customCarClass.GetModuleByNetId(entity.net.ID.Value);
if (moduleBaseClass != null) moduleBaseClass.OnModuleTakeDamage();
}
}
object OnRfFrequencyChange(RFBroadcaster rFBroadcaster, int frequency, BasePlayer player) {
if (player == null || rFBroadcaster == null) return null;
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetModuleByEntId(rFBroadcaster.net.ID.Value) != null);
if (customCarClass == null) return null;
if (!customCarClass.PlayerHasKey(player)) return true;
else if (_config.otherPluginsConfig.vehicleDeployedLocksConfig.enable && ins.plugins.Exists("VehicleDeployedLocks") && !(bool)VehicleDeployedLocks.Call("API_CanAccessVehicle", player, customCarClass.modularCar, true)) {
return true;
}
RemoteModuleClass remoteModuleClass = customCarClass.GetModuleByEntId(rFBroadcaster.net.ID.Value) as RemoteModuleClass;
if (remoteModuleClass == null) return null;
remoteModuleClass.UpdateFrequency(frequency.ToString());
return null;
}
void OnLootSpawn(LootContainer container) {
if (container == null || container.inventory == null) return;
HashSet<ItemConfig> itemConfigs = _config.customItems.Where(x => x.cratesSetting.Any(y => container.ShortPrefabName == y.Key));
foreach (ItemConfig itemConfig in itemConfigs) {
if (UnityEngine.Random.Range(0f, 100f) <= itemConfig.cratesSetting.FirstOrDefault(x => container.ShortPrefabName == x.Key).Value) {
LootManager.TrySpawnItemInDefaultCrate(container, itemConfig);
return;
}
}
}
object OnTurretTarget(AutoTurret turret, BasePlayer player) {
if (!turret.IsExists() || player == null) return null;
if (turret.skinID != TurretModuleClass.turretSkinID) return null;
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetModuleByEntId(turret.net.ID.Value) != null);
if (customCarClass != null) {
if (player.UserIDString.IsSteamId()) {
if (!_config.mainConfig.allowAttackPlayers) return true;
}
else if (!_config.mainConfig.allowAttackNpc) {
return true;
}
else if (player.InSafeZone()) {
return true;
}
}
return null;
}
#region OtherPlugins
object CanEntityTakeDamage(AutoTurret autoTurret, HitInfo hitinfo) {
if (!autoTurret.IsExists() || hitinfo == null) return null;
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetModuleByEntId(autoTurret.net.ID.Value) != null);
if (customCarClass != null) {
customCarClass.OnChildEntityTakeDamage(autoTurret.net.ID.Value, hitinfo);
return false;
}
return null;
}
object CanEntityTakeDamage(RFBroadcaster rFBroadcaster, HitInfo hitinfo) {
if (!rFBroadcaster.IsExists() || hitinfo == null) return null;
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetModuleByEntId(rFBroadcaster.net.ID.Value) != null);
if (customCarClass != null) return true;
return null;
}
object CanEntityBeTargeted(BasePlayer player, BaseEntity turret) {
if (player == null || turret == null) return null;
if (turret.skinID != TurretModuleClass.turretSkinID) return null;
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetModuleByEntId(turret.net.ID.Value) != null);
if (customCarClass != null) {
if (player.UserIDString.IsSteamId()) {
if (!_config.mainConfig.allowAttackPlayers) return false;
}
else if (!_config.mainConfig.allowAttackNpc) {
return false;
}
else if (player.InSafeZone()) {
return false;
}
}
return null;
}
object CanUseLockedEntity(BasePlayer player, BaseLock baseLock) {
if (player == null || player.skinID != RemoteModuleClass.dummySkinID) return null;
if (baseLock == null) return null;
VehicleModuleSeating seatingModule = baseLock.GetParentEntity() as VehicleModuleSeating;
if (seatingModule == null) return null;
ModularCar car = seatingModule.Vehicle as ModularCar;
if (car != null && player.skinID == RemoteModuleClass.dummySkinID) return true;
return null;
}
#endregion OtherPlugins
#endregion Hooks
#region Commands
[ChatCommand("givemodule")]
void ModuleGiveChatCommande(BasePlayer player, string command, string[] arg) {
if (player == null || arg == null || arg.Length == 0) return;
string customModuleName = arg[0];
int amount = 1;
if (arg.Length > 1) amount = Int32.Parse(arg[1]);
ItemConfig itemConfig = _config.customItems.FirstOrDefault(x => x.customShortname == customModuleName);
if (itemConfig == null) return;
if (!player.IsAdmin && !permission.UserHasPermission(player.UserIDString, _config.mainConfig.givePermission)) {
PrintToChat(player, "You do not have permission to use this command!");
return;
}
LootManager.GiveCustomItemToPlayer(player, itemConfig, amount);
NotifyManager.SendMessageToPlayer(player, "GetModule", ins._config.prefix);
}
[ConsoleCommand("givemodule")]
void ModuleGiveConsoleCommande(ConsoleSystem.Arg arg) {
if (arg == null || arg.Player() != null || arg.Args.Length < 2) return;
ulong userId = Convert.ToUInt64(arg.Args[0]);
BasePlayer target = BasePlayer.FindByID(userId);
if (target == null) {
PrintError("Player not found!");
return;
}
string customModuleName = arg.Args[1];
int amount = 1;
if (arg.Args.Length > 2) {
amount = Convert.ToInt32(arg.Args[2]);
if (amount <= 0) return;
}
ItemConfig itemConfig = _config.customItems.FirstOrDefault(x => x.customShortname == customModuleName);
if (itemConfig == null) return;
LootManager.GiveCustomItemToPlayer(target, itemConfig, amount);
PrintToChat(target, GetMessage("GetModule", target.UserIDString, ins._config.prefix));
Puts($"{itemConfig.name} was given to the {target.displayName}");
;
}
[ChatCommand("spawncustomcar")]
void SpawnCustomCarChatCommande(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin || arg.Length == 0) return;
CustomCarSpawner.SpawnCar(arg[0], player.transform.position, player.transform.rotation, player);
}
[ChatCommand("customcarspawnpoint")]
private void ChatNewCustomSpawnPoint(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
string carPresetConfig = "";
if (arg.Length > 0) {
carPresetConfig = arg[0];
if (!_config.carPresets.Any(x => x.presetName == carPresetConfig)) {
NotifyManager.PrintError(player, "PresetNotFoundExeption", carPresetConfig);
return;
}
}
MonumentInfo monumentInfo = TerrainMeta.Path.Monuments.FirstOrDefault(x => Vector3.Distance(player.transform.position, x.transform.position) < x.Bounds.size.x);
if (monumentInfo != null) {
CustomCarSpawner.AddMonumentSpawnPoint(player, monumentInfo, carPresetConfig);
}
else {
CustomCarSpawner.AddMapSpawnPoint(player, carPresetConfig);
}
}
#endregion Commands
#region Methods
void UpdateConfig() {
if (_config.version == Version) return;
if (_config.version.Minor == 0) {
if (_config.version.Patch <= 1) {
}
if (_config.version.Patch < 6) {
_config.respawnSetting = new RespawnSetting {
enable = false, respawnPeriod = 7200, mapRespawnConfig = new RespawnPositionsConfig {
carPresetLocations = new Dictionary<string, List<LocationConfig>>(), randomSpawnLocations = new List<LocationConfig>()
}
, monumentRespawnConfigs = new HashSet<MonumentRespawnPositionsConfig> {
new MonumentRespawnPositionsConfig {
monumentPreset = "assets/bundled/prefabs/autospawn/monument/roadside/supermarket_1.prefab", randomSpawnLocations = new List<LocationConfig> {
new LocationConfig {
position = "(16.6, 0.0, -3.8)", rotation = "(0, 172.9239, 0)"
}
}
, carPresetLocations = new Dictionary<string, List<LocationConfig>>()
}
, new MonumentRespawnPositionsConfig {
monumentPreset = "assets/bundled/prefabs/autospawn/monument/roadside/gas_station_1.prefab", randomSpawnLocations = new List<LocationConfig> {
new LocationConfig {
position = "(4.0, 3.0, 7.4)", rotation = "(0, 90, 0)"
}
, new LocationConfig {
position = "(4.0, 3.0, -8.8)", rotation = "(0, 90, 0)"
}
}
, carPresetLocations = new Dictionary<string, List<LocationConfig>>()
}
}
, presets = new Dictionary<string, float> {
["buoyancy_car_1"]
= 70, ["remote_car_1"] = 30
}
}
;
_config.carPresets = new List<CarPresetConfig> {
new CarPresetConfig {
presetName = "buoyancy_car_1", carPrefabName = "assets/content/vehicles/modularcar/3module_car_spawned.entity.prefab", modules = new List<string> {
"buoyancyitem_1", "vehicle.1mod.cockpit.with.engine", "buoyancyitem_1"
}
, engineComponents = true, engineComponentsLvl = 1, fuel = 50,
}
, new CarPresetConfig {
presetName = "remote_car_1", carPrefabName = "assets/content/vehicles/modularcar/3module_car_spawned.entity.prefab", modules = new List<string> {
"remoteitem_1", "vehicle.2mod.flatbed"
}
, engineComponents = true, engineComponentsLvl = 1, fuel = 50,
}
}
;
_config.otherPluginsConfig.vehicleDeployedLocksConfig = new VehicleDeployedLocksConfig();
}
if (_config.version.Patch < 7) {
_config.mainConfig.allowAttackPlayers = true;
_config.mainConfig.allowAttackNpc = true;
}
_config.mainConfig.lightOperatonModeAtRemote = 1;
_config.version = new VersionNumber(1, 1, 0);
}
if (_config.version.Minor == 1) {
if (_config.version.Patch < 7) {
for (int i = 0; i < _config.turretModules.Count; i++) {
TurretModuleConfig turretModuleConfig = _config.turretModules[i];
for (int a = 0; a < turretModuleConfig.turretlocations.Count; a++) {
LocationConfig locationConfig = turretModuleConfig.turretlocations[a];
string[] versionArray = locationConfig.position.Split(',');
locationConfig.position = locationConfig.position.Replace(versionArray[1], " -0.16");
}
}
foreach (BaseModuleConfig baseModuleConfig in _config.turretModules) baseModuleConfig.permissionForPlacement = "";
foreach (BaseModuleConfig baseModuleConfig in _config.boostModules) baseModuleConfig.permissionForPlacement = "";
foreach (BaseModuleConfig baseModuleConfig in _config.buoyancyModules) baseModuleConfig.permissionForPlacement = "";
foreach (BaseModuleConfig baseModuleConfig in _config.remoteControlModuleConfigs) baseModuleConfig.permissionForPlacement = "";
foreach (BaseModuleConfig baseModuleConfig in _config.regularModules) baseModuleConfig.permissionForPlacement = "";
}
}
_config.version = Version;
SaveConfig();
}
void Unsubscribes() {
foreach (string hook in subscribeMethods) Unsubscribe(hook);
if (_config.mainConfig.enableSpawnInCrates) Unsubscribe("OnLootSpawn");
}
void Subscribes() {
Subscribe("OnLootSpawn");
foreach (string hook in subscribeMethods) Subscribe(hook);
}
void SaveAllCustomCars() {
foreach (CustomCarClass customCarClass in customCarClasses) customCarClass.SaveCar();
Interface.Oxide.DataFileSystem.WriteObject(Title, customCarSaveDatas);
}
void LoadAllCustomCars() {
customCarSaveDatas = Interface.Oxide.DataFileSystem.ReadObject<HashSet<CustomCarSaveData>>(Title);
foreach (ModularCar modularCar in ModularCar.allCarsList) {
if (modularCar.IsExists()) AttachOrUpdateCustomCarClass(modularCar);
}
}
void UpdateAllComputerStation() {
foreach (ComputerStation computerStation in BaseNetworkable.serverEntities.OfType<ComputerStation>()) {
computerStation.autoGatherRadius = 0;
List<string> cameraIDs = new List<string>();
foreach (string cameraId in computerStation.controlBookmarks) cameraIDs.Add(cameraId);
computerStation.controlBookmarks.Clear();
if (computerStation != null) computerStation.GatherStaticCameras();
foreach (string cameraId in cameraIDs) computerStation.ForceAddBookmark(cameraId);
}
}
void UpdateNewCar(ModularCar modularCar) {
foreach (BaseVehicleModule baseVehicleModule in modularCar.AttachedModuleEntities) {
if (baseVehicleModule == null || baseVehicleModule.AssociatedItemInstance.skin != 0) continue;
HashSet<ItemConfig> customModules = _config.customItems.Where(x => x.spawnChance > 0 && x.skin != 0 && x.shortname == baseVehicleModule.AssociatedItemInstance.info.shortname);
if (customModules.Count == 0) continue;
customModules.OrderBy(x => x.spawnChance);
foreach (ItemConfig itemConfig in customModules) {
if (UnityEngine.Random.Range(0, 100) <= itemConfig.spawnChance) {
baseVehicleModule.AssociatedItemInstance.skin = itemConfig.skin;
break;
}
}
}
}
void AttachOrUpdateCustomCarClass(ModularCar modularCar) {
if (modularCar == null || modularCar.net == null) return;
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetCarId() == modularCar.net.ID.Value);
if (customCarClass != null) {
customCarClass.UpdateModules();
return;
}
if (HasAnyCustomModule(modularCar) || (customCarSaveDatas != null && customCarSaveDatas.Any(x => x != null && x.netId == modularCar.net.ID.Value))) {
customCarClass = modularCar.gameObject.AddComponent<CustomCarClass>();
customCarClass.Init(modularCar);
customCarClasses.Add(customCarClass);
}
}
void DeleteAllCustomCars() {
foreach (CustomCarClass customCarClass in customCarClasses) if (customCarClass != null) GameObject.DestroyImmediate(customCarClass);
}
bool HasAnyCustomModule(ModularCar modularCar) {
return modularCar.AttachedModuleEntities.Any(x => x != null && x.AssociatedItemInstance != null && _config.customItems.Any(y => x.AssociatedItemInstance.info.shortname == y.shortname && x.AssociatedItemInstance.skin == y.skin));
}
#endregion Methods
#region Classes
class CustomCarClass : FacepunchBehaviour {
internal bool underwater = false;
internal ModularCar modularCar;
HashSet<ModuleBaseClass> customModules = new HashSet<ModuleBaseClass>();
internal CustomCarSaveData customCarSaveData;
internal BasePlayer playerController;
internal Vector3 GetCarPosition() {
return modularCar.transform.position;
}
internal ulong GetCarId() {
if (modularCar == null) return 0;
return modularCar.net.ID.Value;
}
internal object CanMoveCarModule(ulong moduleId) {
HashSet<ModuleBaseClass> moduleBaseClasses = customModules.Where(x => x != null && x.baseVehicleModule.net.ID.Value == moduleId);
if (moduleBaseClasses.Count > 0 && moduleBaseClasses.Any(x => x != null && !x.CanMoveModule())) return false;
return null;
}
internal ModuleBaseClass GetModuleByEntId(ulong netId) {
return customModules.FirstOrDefault(x => x != null && x.IsOwnEntity(netId));
}
internal ModuleBaseClass GetModuleByNetId(ulong netId) {
return customModules.FirstOrDefault(x => x != null && x.baseVehicleModule.IsExists() && x.baseVehicleModule.net != null && x.baseVehicleModule.net.ID.Value == netId);
}
internal void OnPlayerMounted() {
foreach (ModuleBaseClass moduleBaseClass in customModules) moduleBaseClass.AwakeClass();
if (modularCar.transform.position.y < 0f && modularCar.GetFuelSystem().HasFuel()) {
modularCar.engineController.owner.SetFlag(BaseEntity.Flags.On, true, false, true);
}
}
internal void OnPlayerDismounted() {
if (!modularCar.AnyMounted()) foreach (ModuleBaseClass moduleBaseClass in customModules) moduleBaseClass.Sleep();
}
internal bool PlayerHasKey(BasePlayer player) => modularCar.PlayerHasUnlockPermission(player);
internal void OnChildEntityTakeDamage(ulong netId, HitInfo info) {
ModuleBaseClass moduleBaseClass = GetModuleByEntId(netId);
if (moduleBaseClass != null) moduleBaseClass.OnChildEntityTakeDamage(info);
}
internal void Init(ModularCar modularCar) {
this.modularCar = modularCar;
LoadCarData();
UpdateModules();
}
internal void SaveCar() {
if (!modularCar.IsExists()) return;
customCarSaveData = ins.customCarSaveDatas.FirstOrDefault(x => x != null && x.netId == modularCar.net.ID.Value);
if (customCarSaveData == null) {
customCarSaveData = new CustomCarSaveData(modularCar.net.ID.Value);
ins.customCarSaveDatas.Add(customCarSaveData);
}
customCarSaveData.modules.Clear();
foreach (ModuleBaseClass moduleBaseClass in customModules) if (moduleBaseClass != null) moduleBaseClass.Save();
}
internal void LoadCarData() {
customCarSaveData = ins.customCarSaveDatas.FirstOrDefault(x => x != null && x.netId == modularCar.net.ID.Value);
}
#region Build
internal void UpdateModules() {
foreach (BaseVehicleModule attachModule in modularCar.AttachedModuleEntities.Where(x => x != null && x.AssociatedItemInstance != null)) {
TryUpdateItem(attachModule.AssociatedItemInstance);
TryAddCustomModuleToCar(attachModule.AssociatedItemInstance);
}
underwater = customModules.Any(x => x != null && x.baseModuleConfig.underwaerEngine);
customModules.RemoveWhere(x => x == null);
SaveCar();
}
internal void TryUpdateItem(Item item) {
if (item.skin == 0 && !ins.fullLoad && customCarSaveData != null) {
HashSet<ItemConfig> itemConfigs = ins._config.customItems.Where(x => x.shortname == item.info.shortname);
if (itemConfigs.Count == 0) return;
CustomCarModuleSaveData customCarModuleSaveData = customCarSaveData.modules.FirstOrDefault(x => itemConfigs.Any(y => y.customShortname == x.customShortname && y.shortname == item.info.shortname) && !modularCar.AttachedModuleEntities.Any(z => z != null && z.AssociatedItemInstance.uid.Value == x.itemuid));
if (customCarModuleSaveData == null) return;
customCarModuleSaveData.itemuid = item.uid.Value;
ItemConfig itemConfig = itemConfigs.FirstOrDefault(x => x.customShortname == customCarModuleSaveData.customShortname);
if (itemConfig == null) return;
if (itemConfig.name != "") item.name = itemConfig.name;
item.skin = itemConfig.skin;
}
}
void TryAddCustomModuleToCar(Item item) {
if (item == null || customModules.Any(x => x != null && x.IsOwnItem(item.uid.Value))) return;
BaseVehicleModule baseVehicleModule = FindVehicleModule(item);
if (baseVehicleModule == null) return;
HashSet<ItemConfig> customItemsForItem = ins._config.customItems.Where(x => x.shortname == item.info.shortname && x.skin == item.skin);
TurretModuleConfig turretModuleConfig = ins._config.turretModules.FirstOrDefault(x => customItemsForItem.Any(y => y.customShortname == x.customItemShortname));
if (turretModuleConfig != null) TryAddTurretModule(turretModuleConfig, baseVehicleModule);
BuoyancyModuleConfig buoyancyModuleConfig = ins._config.buoyancyModules.FirstOrDefault(x => customItemsForItem.Any(y => y.customShortname == x.customItemShortname));
if (buoyancyModuleConfig != null) TryAddBuoyancyModule(buoyancyModuleConfig, baseVehicleModule);
BoostModuleConfig boostModuleConfig = ins._config.boostModules.FirstOrDefault(x => customItemsForItem.Any(y => y.customShortname == x.customItemShortname));
if (boostModuleConfig != null) TryAddBoostModule(boostModuleConfig, baseVehicleModule);
RemoteControlModuleConfig remoteControlModuleConfig = ins._config.remoteControlModuleConfigs.FirstOrDefault(x => customItemsForItem.Any(y => y.customShortname == x.customItemShortname));
if (remoteControlModuleConfig != null) TryAddRemoteModule(remoteControlModuleConfig, baseVehicleModule);
BaseModuleConfig baseModuleConfig = ins._config.regularModules.FirstOrDefault(x => customItemsForItem.Any(y => y.customShortname == x.customItemShortname));
if (baseModuleConfig != null) TryAddBaseModule(baseModuleConfig, baseVehicleModule);
}
void TryAddTurretModule(TurretModuleConfig turretModuleConfig, BaseVehicleModule baseVehicleModule) {
TurretModuleClass newTurretModule = baseVehicleModule.gameObject.AddComponent<TurretModuleClass>();
newTurretModule.InitTurretModule(turretModuleConfig, baseVehicleModule, this);
customModules.Add(newTurretModule);
}
void TryAddBuoyancyModule(BuoyancyModuleConfig buoyancyModuleConfig, BaseVehicleModule baseVehicleModule) {
BuoyancyModuleClass newBuoyancyModule = baseVehicleModule.gameObject.AddComponent<BuoyancyModuleClass>();
newBuoyancyModule.InitBuoyancyModule(buoyancyModuleConfig, baseVehicleModule, this);
customModules.Add(newBuoyancyModule);
}
void TryAddBoostModule(BoostModuleConfig boostModuleConfig, BaseVehicleModule baseVehicleModule) {
BoostModuleClass newBuoyancyModule = baseVehicleModule.gameObject.AddComponent<BoostModuleClass>();
newBuoyancyModule.InitBoostModule(boostModuleConfig, baseVehicleModule, this);
customModules.Add(newBuoyancyModule);
}
void TryAddRemoteModule(RemoteControlModuleConfig remoteModuleConfig, BaseVehicleModule baseVehicleModule) {
RemoteModuleClass newRemoteModule = baseVehicleModule.gameObject.AddComponent<RemoteModuleClass>();
newRemoteModule.InitRemoteModule(remoteModuleConfig, baseVehicleModule, this);
customModules.Add(newRemoteModule);
}
void TryAddBaseModule(BaseModuleConfig baseModuleConfig, BaseVehicleModule baseVehicleModule) {
ModuleBaseClass newModuleBaseClass = baseVehicleModule.gameObject.AddComponent<ModuleBaseClass>();
newModuleBaseClass.Init(baseModuleConfig, baseVehicleModule, this);
customModules.Add(newModuleBaseClass);
}
BaseVehicleModule FindVehicleModule(Item item) {
return modularCar.AttachedModuleEntities.FirstOrDefault(x => x != null && x.AssociatedItemInstance.uid == item.uid);
}
#endregion Build
void OnDestroy() {
foreach (ModuleBaseClass moduleBase in customModules) if (moduleBase != null) Destroy(moduleBase);
}
}
class RemoteModuleClass : ModuleBaseClass {
internal const uint dummySkinID = 3432446;
RemoteControlModuleConfig remoteConfig;
Coroutine remoteCorountine;
CCTV_RC camera;
RFBroadcaster rfBroadcaster;
BasePlayer dummy;
internal void InitRemoteModule(RemoteControlModuleConfig remoteConfig, BaseVehicleModule baseVehicleModule, CustomCarClass customCarClass) {
this.remoteConfig = remoteConfig;
Init(remoteConfig, baseVehicleModule, customCarClass);
CreateBroadcaster();
CreateCamera();
}
internal override void Save() {
base.Save();
if (rfBroadcaster == null) return;
customCarModuleSaveData.cameraId = rfBroadcaster.frequency.ToString();
}
internal void UpdateFrequency(string frequency) {
if (camera != null) camera.UpdateIdentifier(frequency, false);
}
internal void StartControl(BasePlayer player) {
if (ins._config.otherPluginsConfig.vehicleDeployedLocksConfig.enable && ins.plugins.Exists("VehicleDeployedLocks") && !(bool)ins.VehicleDeployedLocks.Call("API_CanAccessVehicle", player, customCarClass.modularCar, true)) {
return;
}
if (this.customCarClass.playerController != null) {
return;
}
this.customCarClass.playerController = player;
SpawnDummy();
if (remoteCorountine == null) remoteCorountine = ServerMgr.Instance.StartCoroutine(RemoteCorountine());
if (baseVehicleModule.Vehicle.engineController != null) baseVehicleModule.Vehicle.engineController.TryStartEngine(dummy);
CheckLight();
}
internal void StopControl() {
customCarClass.playerController = null;
KillDummy();
if (remoteCorountine != null) ServerMgr.Instance.StopCoroutine(remoteCorountine);
remoteCorountine = null;
}
void CreateCamera() {
Vector3 localPosition = remoteConfig.cameraLocationConfig.position.ToVector3();
Vector3 localRotation = remoteConfig.cameraLocationConfig.rotation.ToVector3();
camera = BuildManager.CreateChildEntity(baseVehicleModule, "assets/prefabs/deployable/cctvcamera/cctv_deployed.prefab", localPosition, localRotation) as CCTV_RC;
camera.isStatic = true;
camera.clientLerpSpeed = 0;
camera.serverLerpSpeed = 0;
camera.turnSpeed = 0;
camera.hasPTZ = false;
camera.decay = null;
camera.InitializeHealth(float.MaxValue, float.MaxValue);
camera.UpdateFromInput(5, 0);
camera.rcIdentifier = rfBroadcaster.frequency.ToString();
attachedEntities.Add(camera);
}
void CreateBroadcaster() {
Vector3 localPosition = remoteConfig.broadcasterLocationConfig.position.ToVector3();
Vector3 localRotation = remoteConfig.broadcasterLocationConfig.rotation.ToVector3();
rfBroadcaster = BuildManager.CreateChildEntity(baseVehicleModule, "assets/prefabs/deployable/playerioents/gates/rfbroadcaster/rfbroadcaster.prefab", localPosition, localRotation) as RFBroadcaster;
attachedEntities.Add(rfBroadcaster);
rfBroadcaster.decay = null;
rfBroadcaster.InitializeHealth(float.MaxValue, float.MaxValue);
rfBroadcaster.limitNetworking = true;
rfBroadcaster.limitNetworking = false;
rfBroadcaster.frequency = customCarModuleSaveData != null && customCarModuleSaveData.cameraId != "" ? Int32.Parse(customCarModuleSaveData.cameraId) : UnityEngine.Random.Range(0, 9999);
}
void SpawnDummy() {
KillDummy();
BaseVehicle.MountPointInfo mountInfo = baseVehicleModule.Vehicle.allMountPoints.FirstOrDefault(x => x.isDriver && !x.mountable.AnyMounted());
if (mountInfo == null) return;
dummy = GameManager.server.CreateEntity("assets/prefabs/player/player.prefab", baseVehicleModule.transform.position) as BasePlayer;
dummy.enableSaving = false;
dummy.skinID = dummySkinID;
dummy.Spawn();
dummy.InitializeHealth(float.MaxValue, float.MaxValue);
dummy.limitNetworking = true;
mountInfo.mountable.MountPlayer(dummy);
}
void KillDummy() {
if (dummy.IsExists()) {
foreach (BaseVehicle.MountPointInfo allMountPoint in baseVehicleModule.allMountPoints) {
if (allMountPoint.mountable != null && allMountPoint.isDriver) allMountPoint.mountable.DismountAllPlayers();
}
dummy.Kill();
}
customCarClass.OnPlayerDismounted();
}
IEnumerator RemoteCorountine() {
while (CheckDriver() && CheckCar()) {
baseVehicleModule.Vehicle.PlayerServerInput(customCarClass.playerController.serverInput, dummy);
NightLightCheck();
yield return CoroutineEx.waitForSeconds(0.075f);
}
StopControl();
}
internal void CheckLight() {
if (ins._config.mainConfig.lightOperatonModeAtRemote == 2) baseVehicleModule.Vehicle.LightToggle(dummy);
}
bool CheckDriver() {
return dummy.IsExists() && customCarClass.playerController.IsExists() && customCarClass.playerController.isMounted && !customCarClass.playerController.IsSleeping();
}
bool CheckCar() {
return baseVehicleModule.health >= baseVehicleModule.MaxHealth() * baseModuleConfig.minHealthPercent / 100;
}
void NightLightCheck() {
if (ins._config.mainConfig.lightOperatonModeAtRemote != 1) return;
if (baseVehicleModule.Vehicle.LightsAreOn) {
if (ConVar.Env.time > 9 && ConVar.Env.time < 18) baseVehicleModule.Vehicle.LightToggle(dummy);
}
if (!baseVehicleModule.Vehicle.LightsAreOn) {
if (ConVar.Env.time < 9 || ConVar.Env.time > 18) baseVehicleModule.Vehicle.LightToggle(dummy);
}
}
override internal void OnDestroy() {
KillDummy();
StopControl();
base.OnDestroy();
}
}
class BoostModuleClass : ModuleBaseClass {
BoostModuleConfig boostModuleConfig;
Coroutine boostCorountine;
HashSet<BaseEntity> rochetLaunchers = new HashSet<BaseEntity>();
HashSet<BaseEntity> fireEntities = new HashSet<BaseEntity>();
float boostScale;
internal void InitBoostModule(BoostModuleConfig boostModuleConfig, BaseVehicleModule baseVehicleModule, CustomCarClass customCarClass) {
this.boostModuleConfig = boostModuleConfig;
Init(boostModuleConfig, baseVehicleModule, customCarClass);
SpawnRocketLaunchers();
boostScale = 35000 * boostModuleConfig.boostScale;
}
void SpawnRocketLaunchers() {
foreach (LocationConfig locationConfig in boostModuleConfig.rocketLauncherLocations) {
Vector3 localPosition = locationConfig.position.ToVector3();
Vector3 localRotation = locationConfig.rotation.ToVector3();
BaseEntity entity = BuildManager.CreateDecorativeChildEntity(baseVehicleModule, "assets/prefabs/weapons/rocketlauncher/rocket_launcher.entity.prefab", localPosition, localRotation);
rochetLaunchers.Add(entity);
}
}
internal override void AwakeClass() {
if (boostCorountine == null) boostCorountine = ServerMgr.Instance.StartCoroutine(BoostCorountine());
}
IEnumerator BoostCorountine() {
while (baseVehicleModule != null && baseVehicleModule.Vehicle.HasDriver() && baseVehicleModule.Vehicle.GetFuelSystem().HasFuel() && baseVehicleModule.health >= baseVehicleModule.MaxHealth() * baseModuleConfig.minHealthPercent / 100) {
PlayerBoostControl();
yield return CoroutineEx.waitForSeconds(0.2f);
}
boostCorountine = null;
DeleteFires();
}
void PlayerBoostControl() {
if (!baseVehicleModule.Vehicle.engineController.IsOn) return;
BasePlayer driver = baseVehicleModule.Vehicle.GetDriver();
if (driver == null) return;
InputState inputState = driver.userID.IsSteamId() ? driver.serverInput : customCarClass.playerController.serverInput;
if (inputState.IsDown(BUTTON.SPRINT)) {
Effect.server.Run("assets/bundled/prefabs/fx/impacts/blunt/snow/snow.prefab", baseVehicleModule.transform.position);
Vector3 force = baseVehicleModule.Vehicle.transform.forward.normalized * boostScale;
if (boostModuleConfig.reduceEffectivenessModuleAfterdamage) force *= baseVehicleModule.health / baseVehicleModule.MaxHealth();
baseVehicleModule.Vehicle.rigidBody.AddForce(force, ForceMode.Force);
CreateFires();
TakeFuel();
}
else DeleteFires();
}
void TakeFuel() {
baseVehicleModule.Vehicle.GetFuelSystem().pendingFuel = +boostModuleConfig.fuelConsScale;
}
void CreateFires() {
if (!fireEntities.IsEmpty()) return;
foreach (BaseEntity entity in rochetLaunchers) {
if (entity != null) CreateFire(entity);
}
}
void CreateFire(BaseEntity entity) {
BaseEntity fireEntity = GameManager.server.CreateEntity("assets/prefabs/weapons/flamethrower/flamethrower.entity.prefab");
fireEntity.enableSaving = false;
fireEntity.SetFlag(BaseEntity.Flags.Reserved8, true);
fireEntity.SetParent(entity);
fireEntity.transform.localPosition = new Vector3(0.253f, 0.393f, -0.106f);
fireEntity.transform.localEulerAngles = new Vector3(341.829f, 6.471f, 47.888f);
fireEntity.Spawn();
fireEntity.SetFlag(BaseEntity.Flags.Reserved8, true);
fireEntities.Add(fireEntity);
}
void DeleteFires() {
// ... [Code preview truncated due to length. Full source in attached file] ...