C#:
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.0.6")]
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();
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);
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);
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);
if (customCarClass != null && customCarClass.underwater && modularCar.HasDriver() && modularCar.GetFuelSystem().HasFuel()) 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);
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);
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) != 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) != 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) != null)) return false;
return null;
}
void OnEntityDeath(ModularCar entity, HitInfo info) {
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetCarId() == entity.net.ID);
if (customCarClass == null) return;
customCarClasses.Remove(customCarClass);
GameObject.DestroyImmediate(customCarClass);
}
object OnVehicleModuleMove(BaseVehicleModule module, BaseModularVehicle vehicle, BasePlayer player) {
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetCarId() == vehicle.net.ID);
if (customCarClass == null) return null;
return customCarClass.CanMoveCarModule(module.net.ID);
}
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) != 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) != null);
if (customCarClass != null) {
customCarClass.OnChildEntityTakeDamage(turret.net.ID, 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) != null);
if (customCarClass != null) return true;
return null;
}
void OnEntityTakeDamage(BaseVehicleModule entity, HitInfo info) {
if (!entity.IsExists() || info == null) return;
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.IsOwnCarModule(entity.net.ID));
if (customCarClass != null) customCarClass.OnModuleTakeDamage(entity.net.ID);
}
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) != 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;
}
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.Contains(y.Key)));
foreach (ItemConfig itemConfig in _config.customItems) {
if (UnityEngine.Random.Range(0f, 100f) <= itemConfig.cratesSetting.FirstOrDefault(x => container.ShortPrefabName.Contains(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;
if (!player.InSafeZone()) return null;
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetModuleByEntId(turret.net.ID) != null);
if (customCarClass != null) 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) != null);
if (customCarClass != null) {
customCarClass.OnChildEntityTakeDamage(autoTurret.net.ID, 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) != null);
if (customCarClass != null) return true;
return null;
}
object CanEntityBeTargeted(BasePlayer player, AutoTurret 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) != null);
if (customCarClass != null) {
if (!player.userID.IsSteamId() && _config.otherPluginsConfig.truePveConfig.disallowTurretTargetToNpcs) return false;
else if (_config.otherPluginsConfig.truePveConfig.disallowTurretTargetToPlayers) 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) {
_config.otherPluginsConfig = new OtherPluginsConfig {
truePveConfig = new TruePveConfig {
disallowTurretTargetToNpcs = true, disallowTurretTargetToPlayers = true,
}
}
;
}
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();
}
}
_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 RegisterPermissions() {
permission.RegisterPermission(_config.mainConfig.givePermission, this);
}
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.Keys) 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 (customCarClasses == null ) return;
CustomCarClass customCarClass = customCarClasses.FirstOrDefault(x => x != null && x.GetCarId() == modularCar.net.ID);
if (customCarClass != null) {
customCarClass.UpdateModules();
return;
}
if (HasAnyCustomModule(modularCar) || (customCarSaveDatas.Any(x => x != null && x.netId == modularCar.net.ID))) {
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 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 StartControl(BasePlayer player) {
if (ins._config.otherPluginsConfig.vehicleDeployedLocksConfig.enable && ins.plugins.Exists("VehicleDeployedLocks") && !(bool)ins.VehicleDeployedLocks.Call("API_CanAccessVehicle", player, customCarClass.modularCar, true)) {
camera.StopControl();
return;
}
if (this.customCarClass.playerController != null) StopControl();
this.customCarClass.playerController = player;
SpawnDummy();
if (remoteCorountine == null) remoteCorountine = ServerMgr.Instance.StartCoroutine(RemoteCorountine());
if (baseVehicleModule.Vehicle.engineController != null) baseVehicleModule.Vehicle.engineController.TryStartEngine(dummy);
}
internal void StopControl() {
customCarClass.playerController = null;
KillDummy();
if (remoteCorountine != null) ServerMgr.Instance.StopCoroutine(remoteCorountine);
remoteCorountine = null;
}
void SpawnDummy() {
KillDummy();
BaseVehicle.MountPointInfo mountInfo = baseVehicleModule.Vehicle.allMountPoints.FirstOrDefault(x => x.isDriver && !x.mountable.IsMounted());
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 (dummy.IsExists() && customCarClass.playerController.IsExists() && customCarClass.playerController.isMounted && !customCarClass.playerController.IsSleeping() && baseVehicleModule.health >= baseVehicleModule.MaxHealth() * baseModuleConfig.minHealthPercent / 100) {
baseVehicleModule.Vehicle.PlayerServerInput(customCarClass.playerController.serverInput, dummy);
yield return CoroutineEx.waitForSeconds(0.1f);
}
StopControl();
}
void CreateCamera() {
if (camera.IsExists()) camera.Kill();
camera = CreateEntitiy("assets/prefabs/deployable/cctvcamera/cctv_deployed.prefab", remoteConfig.cameraLocationConfig) as CCTV_RC;
camera.isStatic = true;
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() {
rfBroadcaster = CreateEntitiy("assets/prefabs/deployable/playerioents/gates/rfbroadcaster/rfbroadcaster.prefab", remoteConfig.broadcasterLocationConfig) 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);
}
override internal void OnDestroy() {
KillDummy();
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) {
rochetLaunchers.Add(CreateEntitiy("assets/prefabs/weapons/rocketlauncher/rocket_launcher.entity.prefab", locationConfig));
}
}
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() {
if (fireEntities.IsEmpty()) return;
foreach (BaseEntity entity in fireEntities) if (entity.IsExists()) entity.Kill();
fireEntities.Clear();
}
override internal void OnDestroy() {
if (boostCorountine != null) ServerMgr.Instance.StopCoroutine(boostCorountine);
DeleteFires();
base.OnDestroy();
}
}
class TurretModuleClass : ModuleBaseClass {
internal const uint turretSkinID = 3432445;
TurretModuleConfig turretModuleConfig;
List<AutoTurret> turrets = new List<AutoTurret>();
internal override bool CanMoveModule() {
if (turrets.Any(x => x != null && x.inventory.itemList.Count > 0)) return false;
else return true;
}
internal void InitTurretModule(TurretModuleConfig turretModuleConfig, BaseVehicleModule baseVehicleModule, CustomCarClass customCarClass) {
this.turretModuleConfig = turretModuleConfig;
Init(turretModuleConfig, baseVehicleModule, customCarClass);
SpawnTurrets();
LoadTurrets();
if (baseVehicleModule.Vehicle.AnyMounted()) AwakeClass();
}
internal override void Save() {
base.Save();
List<TurretData> turretDatas = new List<TurretData>();
foreach (AutoTurret autoTurret in turrets) {
if (autoTurret == null) continue;
string weaponshortname = "";
Item weaponItem = autoTurret.inventory.GetSlot(0);
if (weaponItem != null) weaponshortname = weaponItem.info.shortname;
Dictionary<string, int> ammoCounts = new Dictionary<string, int>();
foreach (Item item in autoTurret.inventory.itemList) {
if (item.info.shortname == weaponshortname) continue;
if (ammoCounts.ContainsKey(item.info.shortname)) ammoCounts[item.info.shortname] += item.amount;
else ammoCounts.Add(item.info.shortname, item.amount);
}
List<ulong> authedPalyerIDs = new List<ulong>();
foreach (PlayerNameID playerNameID in autoTurret.authorizedPlayers) authedPalyerIDs.Add(playerNameID.userid);
TurretData turretData = new TurretData(weaponshortname, authedPalyerIDs, ammoCounts);
turretDatas.Add(turretData);
}
customCarModuleSaveData.turretDatas = turretDatas;
}
void SpawnTurrets() {
bool rear = Vector3.Angle(baseVehicleModule.CenterPoint() - baseVehicleModule.Vehicle.transform.position, baseVehicleModule.Vehicle.transform.forward) >= 90;
foreach (LocationConfig locationConfig in turretModuleConfig.turretlocations) {
AutoTurret turret = CreateEntitiy("assets/prefabs/npc/autoturret/autoturret_deployed.prefab", new LocationConfig {
position = locationConfig.position, rotation = rear ? "(0, 180, 0)" : "(0, 0, 0)"
}
) as AutoTurret;
turret.skinID = turretSkinID;
turrets.Add(turret);
}
}
void LoadTurrets() {
if (customCarModuleSaveData == null) return;
for (int i = 0; i < customCarModuleSaveData.turretDatas.Count; i++) {
TurretData turretData = customCarModuleSaveData.turretDatas[i];
if (i >= turrets.Count) return;
AutoTurret autoTurret = turrets[i];
if (autoTurret == null) return;
if (turretData.weaponShortname != "") autoTurret.inventory.Insert(ItemManager.CreateByName(turretData.weaponShortname));
foreach (ulong userId in turretData.authedPlayerIDs) {
BasePlayer player = BasePlayer.allPlayerList.FirstOrDefault(x => x != null && x.userID == userId);
if (player == null) continue;
PlayerNameID playerNameID = new PlayerNameID();
playerNameID.userid = player.userID;
playerNameID.username = player.displayName;
autoTurret.authorizedPlayers.Add(playerNameID);
}
foreach (var pair in turretData.ammoCounts) {
autoTurret.inventory.Insert(ItemManager.CreateByName(pair.Key, pair.Value));
}
}
}
internal override void Sleep() {
foreach (AutoTurret autoTurret in turrets) {
if (autoTurret != null) autoTurret.UpdateFromInput(0, 0);
}
}
internal override void AwakeClass() {
if (baseVehicleModule.health <= baseVehicleModule._maxHealth * turretModuleConfig.minHealthPercent / 100) {
Sleep();
return;
}
foreach (AutoTurret autoTurret in turrets) {
autoTurret.ClearConnections();
if (autoTurret == null) continue;
autoTurret.UpdateFromInput(100, 0);
foreach (BaseVehicle.MountPointInfo mountPointInfo in baseVehicleModule.Vehicle.allMountPoints) {
if (mountPointInfo != null && mountPointInfo.mountable._mounted != null) {
PlayerNameID playerNameID = new PlayerNameID();
playerNameID.userid = mountPointInfo.mountable._mounted.userID;
playerNameID.username = mountPointInfo.mountable._mounted.displayName;
autoTurret.authorizedPlayers.Add(playerNameID);
}
}
}
}
}
class BuoyancyModuleClass : ModuleBaseClass {
BuoyancyModuleConfig buoyancyModuleConfig;
Coroutine buoyancyCorountine;
bool doubleModule = false;
bool inWater = false;
internal void InitBuoyancyModule(BuoyancyModuleConfig buoyancyModuleConfig, BaseVehicleModule baseVehicleModule, CustomCarClass customCarClass) {
this.buoyancyModuleConfig = buoyancyModuleConfig;
Init(buoyancyModuleConfig, baseVehicleModule, customCarClass);
if (baseVehicleModule.Vehicle.HasDriver() || baseVehicleModule.Vehicle.transform.position.y < 0) AwakeClass();
doubleModule = baseVehicleModule.AssociatedItemDef.shortname.Contains("2mod");
}
internal override void AwakeClass() {
if (buoyancyCorountine == null) buoyancyCorountine = ServerMgr.Instance.StartCoroutine(BuoyancyCorountine());
}
IEnumerator BuoyancyCorountine() {
while (baseVehicleModule != null && (baseVehicleModule.Vehicle.HasDriver() || baseVehicleModule.Vehicle.transform.position.y <= 0) && baseVehicleModule.health > baseVehicleModule._maxHealth * buoyancyModuleConfig.minHealthPercent / 100) {
if (baseVehicleModule.Vehicle.transform.position.y <= -0.35f) {
AddBuoyancy();
PlayerWaterControl();
if (!inWater) InWater();
}
else if (inWater) OutWater();
yield return CoroutineEx.waitForSeconds(0.1f);
}
if (inWater) OutWater();
buoyancyCorountine = null;
}
void InWater() {
baseVehicleModule.Vehicle.rigidBody.maxAngularVelocity = 0.4f;
inWater = true;
}
void OutWater() {
baseVehicleModule.Vehicle.rigidBody.maxAngularVelocity = 0.7f;
inWater = false;
}
void AddBuoyancy() {
float currentDepth = -baseVehicleModule.transform.position.y + 0.35f;
if (currentDepth > 1) currentDepth = 1;
Vector3 force = new Vector3(0f, currentDepth * 10000 * buoyancyModuleConfig.buoyancy, 0f);
if (buoyancyModuleConfig.reduceEffectivenessModuleAfterdamage) force *= baseVehicleModule.health / baseVehicleModule.MaxHealth();
if (doubleModule) {
baseVehicleModule.Vehicle.rigidBody.AddForceAtPosition(force, baseVehicleModule.CenterPoint() + baseVehicleModule.transform.forward.normalized * 2.15f, ForceMode.Force);
baseVehicleModule.Vehicle.rigidBody.AddForceAtPosition(force, baseVehicleModule.CenterPoint() - baseVehicleModule.transform.forward.normalized * 2f, ForceMode.Force);
}
baseVehicleModule.Vehicle.rigidBody.AddForceAtPosition(force, baseVehicleModule.CenterPoint() + baseVehicleModule.transform.right.normalized * 2, ForceMode.Force);
baseVehicleModule.Vehicle.rigidBody.AddForceAtPosition(force, baseVehicleModule.CenterPoint() - baseVehicleModule.transform.right.normalized * 2, ForceMode.Force);
}
void PlayerWaterControl() {
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;
ControlGas(inputState);
ControlRotate(inputState);
}
void ControlGas(InputState inputState) {
if (inputState.IsDown(BUTTON.FORWARD)) baseVehicleModule.Vehicle.rigidBody.AddForce(transform.forward.normalized * 6000 * buoyancyModuleConfig.boostScale, ForceMode.Force);
else if (inputState.IsDown(BUTTON.BACKWARD)) baseVehicleModule.Vehicle.rigidBody.AddForce(-transform.forward.normalized * 6000 * buoyancyModuleConfig.boostScale, ForceMode.Force);
}
void ControlRotate(InputState inputState) {
float multiplicator = buoyancyModuleConfig.rotateScale * baseVehicleModule.Vehicle.rigidBody.velocity.magnitude * 50;
if (Vector3.Angle(baseVehicleModule.Vehicle.rigidBody.velocity, baseVehicleModule.transform.forward) > 90) multiplicator *= -1;
if (multiplicator > 300 * buoyancyModuleConfig.rotateScale) multiplicator = 300 * buoyancyModuleConfig.rotateScale;
if (inputState.IsDown(BUTTON.RIGHT)) baseVehicleModule.Vehicle.rigidBody.AddTorque(transform.up.normalized * multiplicator, ForceMode.Force);
if (inputState.IsDown(BUTTON.LEFT)) baseVehicleModule.Vehicle.rigidBody.AddTorque(transform.up.normalized * -multiplicator, ForceMode.Force);
}
override internal void OnDestroy() {
if (buoyancyCorountine != null) ServerMgr.Instance.StopCoroutine(buoyancyCorountine);
base.OnDestroy();
}
}
class ModuleBaseClass : FacepunchBehaviour {
internal BaseModuleConfig baseModuleConfig;
internal BaseVehicleModule baseVehicleModule;
internal CustomCarClass customCarClass;
internal HashSet<BaseEntity> attachedEntities = new HashSet<BaseEntity>();
protected CustomCarModuleSaveData customCarModuleSaveData;
internal bool IsOwnItem(uint uid) => baseVehicleModule.AssociatedItemInstance.uid == uid ;
internal bool IsOwnEntity(uint uid) => attachedEntities.Any(x => x != null && x.net != null && x.net.ID == uid);
internal void OnChildEntityTakeDamage(HitInfo info) {
baseVehicleModule.AcceptPropagatedDamage(info.damageTypes.Total(), Rust.DamageType.Bullet);
OnModuleTakeDamage();
}
internal void OnModuleTakeDamage() {
if (baseVehicleModule.health <= baseVehicleModule.MaxHealth() * baseModuleConfig.minHealthPercent / 100) Sleep();
}
internal virtual bool CanMoveModule() => true;
internal void Init(BaseModuleConfig baseModuleConfig, BaseVehicleModule baseVehicleModule, CustomCarClass customCarClass) {
this.baseModuleConfig = baseModuleConfig;
this.baseVehicleModule = baseVehicleModule;
this.customCarClass = customCarClass;
LoadModuleData();
CreateEntities();
AwakeClass();
}
void LoadModuleData() {
if (customCarClass.customCarSaveData == null) return;
customCarModuleSaveData = customCarClass.customCarSaveData.modules.FirstOrDefault(x => x != null && x.itemuid == baseVehicleModule.AssociatedItemInstance.uid);
}
protected void CreateEntities() {
foreach (var pair in baseModuleConfig.entities) {
if (pair.Key == "diving.tank") {
foreach (LocationConfig locationConfig in pair.Value) SpawnDroppedItem(pair.Key, locationConfig);
}
else {
foreach (LocationConfig locationConfig in pair.Value) CreateEntitiy(pair.Key, locationConfig);
}
}
}
void SpawnDroppedItem(string shortname, LocationConfig locationConfig) {
DroppedItem droppedItem = GameManager.server.CreateEntity("assets/prefabs/misc/burlap sack/generic_world.prefab", baseVehicleModule.transform.position, baseVehicleModule.transform.rotation) as DroppedItem;
droppedItem.InitializeItem(ItemManager.CreateByName(shortname));
droppedItem.enableSaving = false;
droppedItem.Spawn();
foreach (Component component in droppedItem.GetComponents
// ... [Code preview truncated due to length. Full source in attached file] ...