diff --git a/Utility Mods/SCDefenseBlocks/Audio/Alert_Damaged.wav b/Utility Mods/SCDefenseBlocks/Audio/Alert_Damaged.wav new file mode 100644 index 000000000..1bd27b3c4 Binary files /dev/null and b/Utility Mods/SCDefenseBlocks/Audio/Alert_Damaged.wav differ diff --git a/Utility Mods/SCDefenseBlocks/Audio/Alert_Offline.wav b/Utility Mods/SCDefenseBlocks/Audio/Alert_Offline.wav new file mode 100644 index 000000000..296869a29 Binary files /dev/null and b/Utility Mods/SCDefenseBlocks/Audio/Alert_Offline.wav differ diff --git a/Utility Mods/SCDefenseBlocks/Audio/Brake_Applied.wav b/Utility Mods/SCDefenseBlocks/Audio/Brake_Applied.wav new file mode 100644 index 000000000..ede85d719 Binary files /dev/null and b/Utility Mods/SCDefenseBlocks/Audio/Brake_Applied.wav differ diff --git a/Utility Mods/SCDefenseBlocks/Audio/DamageRepaired.wav b/Utility Mods/SCDefenseBlocks/Audio/DamageRepaired.wav new file mode 100644 index 000000000..8681c1260 Binary files /dev/null and b/Utility Mods/SCDefenseBlocks/Audio/DamageRepaired.wav differ diff --git a/Utility Mods/SCDefenseBlocks/Audio/PowerRestored.wav b/Utility Mods/SCDefenseBlocks/Audio/PowerRestored.wav new file mode 100644 index 000000000..35a1cb119 Binary files /dev/null and b/Utility Mods/SCDefenseBlocks/Audio/PowerRestored.wav differ diff --git a/Utility Mods/SCDefenseBlocks/Audio/Warning_Damaged.wav b/Utility Mods/SCDefenseBlocks/Audio/Warning_Damaged.wav new file mode 100644 index 000000000..45deb9351 Binary files /dev/null and b/Utility Mods/SCDefenseBlocks/Audio/Warning_Damaged.wav differ diff --git a/Utility Mods/SCDefenseBlocks/Audio/Warning_Offline.wav b/Utility Mods/SCDefenseBlocks/Audio/Warning_Offline.wav new file mode 100644 index 000000000..de0e97a33 Binary files /dev/null and b/Utility Mods/SCDefenseBlocks/Audio/Warning_Offline.wav differ diff --git a/Utility Mods/SCDefenseBlocks/Data/Audio_FieldGen.sbc b/Utility Mods/SCDefenseBlocks/Data/Audio_FieldGen.sbc new file mode 100644 index 000000000..783a37257 --- /dev/null +++ b/Utility Mods/SCDefenseBlocks/Data/Audio_FieldGen.sbc @@ -0,0 +1,102 @@ + + + + + + + MyObjectBuilder_AudioDefinition + FieldGen_Brake + + HUD + true + false + 50 + false + 4 + 0.75 + + + Audio\Brake_Applied.wav + + + + + + + MyObjectBuilder_AudioDefinition + FieldGen_Damaged + + HUD + true + false + 50 + false + 4 + 0.75 + + + Audio\Warning_Damaged.wav + Audio\Alert_Damaged.wav + + + + + + + MyObjectBuilder_AudioDefinition + FieldGen_Offline + + HUD + true + false + 50 + false + 4 + 0.75 + + + Audio\Warning_Offline.wav + Audio\Alert_Offline.wav + + + + + + + MyObjectBuilder_AudioDefinition + FieldGen_PowerRestored + + HUD + true + false + 50 + false + 4 + 0.75 + + + Audio\PowerRestored.wav + + + + + + + MyObjectBuilder_AudioDefinition + FieldGen_DamagedRepaired + + HUD + true + false + 50 + false + 4 + 0.75 + + + Audio\DamageRepaired.wav + + + + + \ No newline at end of file diff --git a/Utility Mods/SCDefenseBlocks/Data/Scripts/OneFuckingFolderDeeper/FieldGenerator/FieldGenerator_Core.cs b/Utility Mods/SCDefenseBlocks/Data/Scripts/OneFuckingFolderDeeper/FieldGenerator/FieldGenerator_Core.cs index 28f4cdf96..fa4f8d219 100644 --- a/Utility Mods/SCDefenseBlocks/Data/Scripts/OneFuckingFolderDeeper/FieldGenerator/FieldGenerator_Core.cs +++ b/Utility Mods/SCDefenseBlocks/Data/Scripts/OneFuckingFolderDeeper/FieldGenerator/FieldGenerator_Core.cs @@ -5,9 +5,9 @@ using ProtoBuf; using Sandbox.Common.ObjectBuilders; using Sandbox.Game; +using Sandbox.Game.Entities; using Sandbox.Game.EntityComponents; using Sandbox.ModAPI; -using VRage.Game; using VRage.Game.Components; using VRage.Game.Entity; using VRage.Game.ModAPI; @@ -16,11 +16,11 @@ using VRage.Network; using VRage.ObjectBuilders; using VRage.Sync; +using VRage.Utils; using VRageMath; using static Draygo.API.HudAPIv2; using static VRageRender.MyBillboard; -using Sandbox.Game.Gui; -using Draygo.API; + namespace Starcore.FieldGenerator { @@ -36,7 +36,15 @@ public class FieldGenerator : MyGameLogicComponent, IMyEventProxy private int _damageEventCounter = 0; private float _stabilityChange = 0; private int _resetCounter = 0; - private bool _lowStability = false; + private bool _lowStability = false; + + internal int _stopTickCounter = -1; + internal Vector3? angularAxis1 = null; + internal Vector3? angularAxis2 = null; + + internal bool _cachedState; + internal MyEntity3DSoundEmitter BlockSoundEmitter; + internal MySoundPair BlockSoundPair; private int initValueDelayTicks = 60; // 1 second delay (60 ticks) private bool valuesInitialized = false; @@ -44,7 +52,8 @@ public class FieldGenerator : MyGameLogicComponent, IMyEventProxy #region Sync Properties public MySync SiegeMode; public MySync SiegeCooldownActive; - public MySync GridStopped = null; + public MySync SlowdownActive; + public MySync GridStopped; public MySync SiegeElapsedTime; public MySync SiegeCooldownTime; @@ -85,6 +94,7 @@ public override void UpdateOnceBeforeFrame() if (Block?.CubeGrid?.Physics == null) return; + BlockSoundEmitter = new MyEntity3DSoundEmitter((MyEntity)MyAPIGateway.Entities.GetEntityById(Block.EntityId)); FieldGeneratorControls.DoOnce(ModContext); Sink = Block.Components.Get(); @@ -130,7 +140,7 @@ public override void UpdateOnceBeforeFrame() NeedsUpdate |= MyEntityUpdateEnum.EACH_FRAME; NeedsUpdate |= MyEntityUpdateEnum.EACH_10TH_FRAME; - } + } public override void UpdateAfterSimulation() { @@ -146,11 +156,37 @@ public override void UpdateAfterSimulation() } else { + _cachedState = Block.IsWorking; Stability.Value = 100; InitExistingUpgrades(); valuesInitialized = true; } } + + if (SiegeMode.Value && !GridStopped.Value) + { + if (Block.CubeGrid.Physics.LinearVelocity != Vector3D.Zero) + { + SiegeEmergencyStop(); + _stopTickCounter++; + } + } + } + + if (SiegeMode.Value && !GridStopped.Value) + { + if (!SlowdownActive.Value) + { + BlockSoundPair = new MySoundPair("FieldGen_Brake"); + BlockSoundEmitter?.PlaySound(BlockSoundPair, false, false, true, true, false, null, true); + SlowdownActive.Value = true; + } + } + + if (_cachedState != Block.IsWorking) + { + _cachedState = Block.IsWorking; + Block_IsWorkingChanged(); } if (MyAPIGateway.Session.GameplayFrameCounter % 60 == 0) @@ -159,7 +195,10 @@ public override void UpdateAfterSimulation() { if (IsServer) { - UpdateSiegeState(); + if (GridStopped.Value || SiegeCooldownActive.Value) + { + UpdateSiegeState(); + } if (!Config.SimplifiedMode) { @@ -350,7 +389,7 @@ private void HandleResistence() return; } - if (SiegeMode.Value) + if (SiegeMode.Value && GridStopped.Value) { MyVisualScriptLogicProvider.SetGridGeneralDamageModifier(Block.CubeGrid.Name, (1 - Config.SiegeModeResistence)); return; @@ -400,6 +439,20 @@ private void OnGridStopValueChange(MySync obj) if (obj?.Value ?? false) Block.CubeGrid.Physics.LinearVelocity = Vector3.Zero; } + + private void Block_IsWorkingChanged() + { + if (!Block.IsWorking) + { + BlockSoundPair = Block.IsFunctional ? BlockSoundPair = new MySoundPair("FieldGen_Offline") : BlockSoundPair = new MySoundPair("FieldGen_Damaged"); + BlockSoundEmitter?.PlaySound(BlockSoundPair, false, false, true, true, false, null, true); + } + else + { + BlockSoundPair = Block.SlimBlock.IsFullIntegrity ? BlockSoundPair = new MySoundPair("FieldGen_PowerRestored") : BlockSoundPair = new MySoundPair("FieldGen_DamagedRepaired"); + BlockSoundEmitter?.PlaySound(BlockSoundPair, false, false, true, true, false, null, true); + } + } #endregion #region Siege Mode @@ -458,12 +511,82 @@ private void SiegeBlockEnabler(IEnumerable allFunctionalBloc FieldGeneratorSession.CoreSysAPI.SetFiringAllowed(entBlock, enabled); block.Enabled = enabled; } + else if (block is IMyThrust || block is IMyGyro) + { + block.Enabled = enabled; + } } else continue; } } + private void SiegeEmergencyStop() + { + if (Block.CubeGrid.Physics == null) + return; + + float elapsed = _stopTickCounter / 60f; + float maxTime = 10f; + + float minForce = 1000000f; + float maxForce = 120000000f; + + float timeScale = MathHelper.Clamp(elapsed / maxTime, 0f, 1f); + float forceMagnitude = MathHelper.Lerp(minForce, maxForce, timeScale); + + Vector3 direction = Vector3.Normalize(Block.CubeGrid.Physics.LinearVelocity); + Vector3 linearDrag = -direction * forceMagnitude; + + Block.CubeGrid.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_FORCE, linearDrag, null, null); + + if (Block.CubeGrid.Physics.LinearVelocity.LengthSquared() < 25f || elapsed >= maxTime) // 5 m/s squared = 25 + { + Block.CubeGrid.Physics.LinearVelocity = Vector3D.Zero; + GridStopped.Value = true; + SlowdownActive.Value = false; + _stopTickCounter = -1; + angularAxis1 = null; + angularAxis2 = null; + return; + } + + // ----- ANGULAR DRAG ----- + if (angularAxis1 == null) + { + angularAxis1 = GetRandomUnitVector(); + + Vector3 candidate; + do + { + candidate = GetRandomUnitVector(); + } + while (Math.Abs(Vector3D.Dot(candidate, angularAxis1.Value)) > 0.99f); + + angularAxis2 = candidate; + } + + float targetAngularAccel = 0.1f; + Vector3 torqueDirection = new Vector3(0,0,0); + + torqueDirection += angularAxis1.Value; + torqueDirection += angularAxis2.Value; + + Vector3 angularImpulse = torqueDirection * targetAngularAccel / 60f; + + Block.CubeGrid.Physics.AngularVelocity += angularImpulse; + } + + Vector3 GetRandomUnitVector() + { + Vector3 v = new Vector3( + MyUtils.GetRandomFloat(-1f, 1f), + MyUtils.GetRandomFloat(-1f, 1f), + MyUtils.GetRandomFloat(-1f, 1f) + ); + return Vector3.Normalize(v); + } + private void EndSiegeMode() { if (IsServer && GridStopped.Value) @@ -606,6 +729,20 @@ public float CalculatePowerDraw() return Config.MinPowerDraw + t * (Config.MaxPowerDraw - Config.MinPowerDraw); } + public float CheckPowerDraw(float fieldValue) + { + float maxPossibleFieldPowerV = Config.PerModuleAmount * Config.MaxModuleCount; + float clampedFieldPowerV = MathHelper.Clamp(fieldValue, 0, maxPossibleFieldPowerV); + float tV = clampedFieldPowerV / maxPossibleFieldPowerV; + + return Config.MinPowerDraw + tV * (Config.MaxPowerDraw - Config.MinPowerDraw); + } + + public float CheckPowerGeneration() + { + return Block.CubeGrid.ResourceDistributor.MaxAvailableResourceByType(MyResourceDistributorComponent.ElectricityId); + } + private bool IsClientInShip() { if (Block != null) @@ -751,7 +888,11 @@ private void UpdateHUD() GeneratorHUDContent.Append(GenerateBar("Stability:", Stability.Value, 100, true)); } - if (SiegeMode.Value) + if (SiegeMode.Value && !GridStopped.Value) + { + GeneratorHUDContent.Append($"\nSiege Mode Actived | Emergency Braking Applied"); + } + else if (SiegeMode.Value) { GeneratorHUDContent.Append($"\nSiege Mode Active | {SiegeElapsedTime.Value} / {Config.MaxSiegeTime}"); } diff --git a/Utility Mods/SCDefenseBlocks/Data/Scripts/OneFuckingFolderDeeper/FieldGenerator/FieldGenerator_TerminalControls.cs b/Utility Mods/SCDefenseBlocks/Data/Scripts/OneFuckingFolderDeeper/FieldGenerator/FieldGenerator_TerminalControls.cs index 0b7f693dc..50a852471 100644 --- a/Utility Mods/SCDefenseBlocks/Data/Scripts/OneFuckingFolderDeeper/FieldGenerator/FieldGenerator_TerminalControls.cs +++ b/Utility Mods/SCDefenseBlocks/Data/Scripts/OneFuckingFolderDeeper/FieldGenerator/FieldGenerator_TerminalControls.cs @@ -48,7 +48,7 @@ static bool CooldownEnabler(IMyTerminalBlock b) var logic = GetLogic(b); if (logic != null) { - return !logic.SiegeCooldownActive; + return !logic.SiegeCooldownActive && !logic.SlowdownActive; } return false; } @@ -149,6 +149,9 @@ static void CreateActions(IMyModContext context) var logic = GetLogic(b); if (logic != null) { + if (logic.CheckPowerDraw(logic.FieldPower.Value + 2.5f) > logic.CheckPowerGeneration()) + return; + logic.FieldPower.Value += 2.5f; } };