diff --git a/Gamemode Mods/Stable/Starcore_Sharetrack/Data/Scripts/ShipPoints/API/SCDAPI.cs b/Gamemode Mods/Stable/Starcore_Sharetrack/Data/Scripts/ShipPoints/API/SCDAPI.cs new file mode 100644 index 000000000..81f5c047c --- /dev/null +++ b/Gamemode Mods/Stable/Starcore_Sharetrack/Data/Scripts/ShipPoints/API/SCDAPI.cs @@ -0,0 +1,232 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Sandbox.ModAPI; +using VRage.Game.Entity; + +namespace StarCore.ShareTrack.API +{ + public class FieldGeneratorAPI + { + private bool _initialized; + + private Func _getFirstFieldGeneratorOnGrid; + + private Func _isSiegeActive; + private Action _setSiegeActive; + + private Func _isSiegeCooldownActive; + private Action _setSiegeCooldownActive; + + private Func _getSiegeCooldown; + private Action _setSiegeCooldown; + + private Func _getFieldPower; + private Action _setFieldPower; + + private Func _getMaximumFieldPower; + private Func_getMinimumFieldPower; + + private Func _getPowerDraw; + + private Func _getStability; + private Action _setStability; + + /// + /// Returns first valid field generator for the specified grid EntityID. + /// + /// EntityID of the cubegrid to check against. + /// IMyFunctionalBlock of the first field generator if one exists; otherwise, null. + public IMyFunctionalBlock GetFirstFieldGeneratorOnGrid(long entityID) => _getFirstFieldGeneratorOnGrid?.Invoke(entityID) ?? null; + + /// + /// Returns whether or not the specified block is in siege mode. + /// + /// Block to check. + /// true if siege mode is active; otherwise, false. + public bool IsSiegeActive(IMyFunctionalBlock block) => _isSiegeActive?.Invoke(block) ?? false; + + /// + /// Sets the siege mode state on the given block. + /// + /// Block whose siege state will be modified. + /// Whether siege mode should be active (true) or inactive (false). + public void SetSiegeActive(IMyFunctionalBlock block, bool Active) => _setSiegeActive?.Invoke(block, Active); + + /// + /// Returns whether or not the specified blocks siege mode is on cooldown. + /// + /// Block to check. + /// true if the cooldown is active; otherwise, false. + public bool IsSiegeCooldownActive(IMyFunctionalBlock block) => _isSiegeCooldownActive?.Invoke(block) ?? false; + + /// + /// Sets the siege mode cooldown state on the given block. + /// + /// Block whose cooldown state will be modified. + /// Whether the cooldown should be active (true) or inactive (false). + public void SetSiegeCooldownActive(IMyFunctionalBlock block, bool Active) => _setSiegeCooldownActive?.Invoke(block, Active); + + /// + /// Returns the specified blocks current cooldown time. + /// + /// Block to check. + /// The siege cooldown time, or 0 if no cooldown is active. + public int GetSiegeCooldown(IMyFunctionalBlock block) => _getSiegeCooldown?.Invoke(block) ?? 0; + + /// + /// Sets the cooldown time on the given block. + /// + /// Block whose cooldown will be modified. + /// Time to set the cooldown to, in seconds. + public void SetSiegeCooldown(IMyFunctionalBlock block, int Time) => _setSiegeCooldown?.Invoke(block, Time); + + /// + /// Returns the specified block current field power. + /// + /// Block to check. + /// The current field power. + public float GetFieldPower(IMyFunctionalBlock block) => _getFieldPower?.Invoke(block) ?? 0; + + /// + /// Sets the field power on the given block. + /// + /// Block whose field power will be modified. + /// + /// The field power to set as a float, expressed as a percentage and capped by minimum/maximum field power. + /// + public void SetFieldPower(IMyFunctionalBlock block, float Power) => _setFieldPower?.Invoke(block, Power); + + /// + /// Returns the specified blocks maximum field power. + /// + /// Block to check. + /// The maximum field power. + public float GetMaximumFieldPower(IMyFunctionalBlock block) => _getMaximumFieldPower?.Invoke(block) ?? 0; + + /// + /// Returns the specified block minimum field power. + /// + /// Block to check. + /// The minimum field power. + public float GetMinimumFieldPower(IMyFunctionalBlock block) => _getMinimumFieldPower?.Invoke(block) ?? 0; + + /// + /// Returns the specified blocks current power draw. + /// + /// Block to check. + /// The current power draw. + public float GetPowerDraw(IMyFunctionalBlock block) => _getPowerDraw?.Invoke(block) ?? 0; + + /// + /// Returns the specified blocks current stability. + /// + /// Block to check. + /// The current stability. + public float GetStability(IMyFunctionalBlock block) => _getStability?.Invoke(block) ?? 0; + + /// + /// Sets the stability on the given block. + /// + /// Block whose stability will be modified. + /// + /// The stability to set as a float, expressed as a percentage with a maximum of 100. + /// + public void SetStability(IMyFunctionalBlock block, float Stability) => _setStability?.Invoke(block, Stability); + + + private const long HandlerID = 917632; + private bool _APIRegistered; + private Action _ReadyCallback; + + public bool IsReady { get; private set; } + + + public void LoadAPI(Action ReadyCallback = null) + { + if (_APIRegistered) + throw new Exception($"{GetType().Name}.LoadAPI() should not be called multiple times!"); + + _ReadyCallback = ReadyCallback; + _APIRegistered = true; + MyAPIGateway.Utilities.RegisterMessageHandler(HandlerID, HandleMessage); + MyAPIGateway.Utilities.SendModMessage(HandlerID, "APIRequest"); + } + + public void UnloadAPI() + { + MyAPIGateway.Utilities.UnregisterMessageHandler(HandlerID, HandleMessage); + + ApiAssign(null); + + _APIRegistered = false; + _initialized = false; + IsReady = false; + } + + private void HandleMessage(object obj) + { + if (_initialized || obj is string) + return; + + var dict = obj as IReadOnlyDictionary; + + if (dict == null) + return; + + ApiAssign(dict); + + IsReady = true; + _ReadyCallback?.Invoke(); + } + + public void ApiAssign(IReadOnlyDictionary delegates) + { + _initialized = delegates != null; + + AssignMethod(delegates, "GetFirstFieldGeneratorOnGrid", ref _getFirstFieldGeneratorOnGrid); + + AssignMethod(delegates, "IsSiegeActive", ref _isSiegeActive); + AssignMethod(delegates, "SetSiegeActive", ref _setSiegeActive); + + AssignMethod(delegates, "IsSiegeCooldownActive", ref _isSiegeCooldownActive); + AssignMethod(delegates, "SetSiegeCooldownActive", ref _setSiegeCooldownActive); + + AssignMethod(delegates, "GetSiegeCooldown", ref _getSiegeCooldown); + AssignMethod(delegates, "SetSiegeCooldown", ref _setSiegeCooldown); + + AssignMethod(delegates, "GetFieldPower", ref _getFieldPower); + AssignMethod(delegates, "SetFieldPower", ref _setFieldPower); + + AssignMethod(delegates, "GetMaximumFieldPower", ref _getMaximumFieldPower); + AssignMethod(delegates, "GetMinimumFieldPower", ref _getMinimumFieldPower); + + AssignMethod(delegates, "GetPowerDraw", ref _getPowerDraw); + + AssignMethod(delegates, "GetStability", ref _getStability); + AssignMethod(delegates, "SetStability", ref _setStability); + } + + private void AssignMethod(IReadOnlyDictionary delegates, string name, ref T field) + where T : class + { + if (delegates == null) + { + field = null; + return; + } + + Delegate del; + if (!delegates.TryGetValue(name, out del)) + throw new Exception($"{GetType().Name} :: Couldn't find {name} delegate of type {typeof(T)}"); + + field = del as T; + + if (field == null) + throw new Exception( + $"{GetType().Name} :: Delegate {name} is not type {typeof(T)}, instead it's: {del.GetType()}"); + } + } +} diff --git a/Gamemode Mods/Stable/Starcore_Sharetrack/Data/Scripts/ShipPoints/AllGridsList.cs b/Gamemode Mods/Stable/Starcore_Sharetrack/Data/Scripts/ShipPoints/AllGridsList.cs index cb8dc4e54..e631096e1 100644 --- a/Gamemode Mods/Stable/Starcore_Sharetrack/Data/Scripts/ShipPoints/AllGridsList.cs +++ b/Gamemode Mods/Stable/Starcore_Sharetrack/Data/Scripts/ShipPoints/AllGridsList.cs @@ -264,8 +264,18 @@ private string CreateDisplayString(string ownerName, ShipTracker tracker, int we var functionalColor = tracker.IsFunctional ? "white" : "red"; var integrityColor = integrityPercent >= 75 ? "White" : integrityPercent >= 50 ? "LightCoral" : integrityPercent >= 25 ? "IndianRed" : "FireBrick"; + var siegeColor = "white"; + string siegeDisplay = ""; + if (tracker.FieldGenerator != null) + { + siegeDisplay = tracker.IsSiegeActive ? "[SIEGED] " : ""; + siegeColor = tracker.IsSiegeActive ? tracker.GeneratorDisplayBlink == 1 ? "red" : "yellow" : "white"; + + tracker.GeneratorDisplayBlink = 1 - tracker.GeneratorDisplayBlink; + } + return - $"{ownerDisplay,-8}{integrityPercent,3}% P:{power,3} T:{thrust,3} W:{wep} S:{shieldPercent,3}%"; + $"{siegeDisplay}{ownerDisplay,-8}{integrityPercent,3}% P:{power,3} T:{thrust,3} W:{wep} S:{shieldPercent,3}%"; } @@ -322,6 +332,7 @@ public static IMyCubeGrid RaycastGridFromCamera() public WcApi WcApi { get; private set; } public ShieldApi ShieldApi { get; private set; } public RtsApi RtsApi { get; private set; } + public FieldGeneratorAPI FieldGeneratorAPI { get; private set; } private HudPointsList _hudPointsList; @@ -372,6 +383,9 @@ public void InitApi() // Initialize the RTS_api and load it if it's not null RtsApi = new RtsApi(); RtsApi?.Load(); + + FieldGeneratorAPI = new FieldGeneratorAPI(); + FieldGeneratorAPI?.LoadAPI(); } public void Close() @@ -381,6 +395,7 @@ public void Close() WcApi?.Unload(); ShieldApi?.Unload(); RtsApi?.Unload(); + FieldGeneratorAPI?.UnloadAPI(); if (PointValues != null) { PointValues.Clear(); diff --git a/Gamemode Mods/Stable/Starcore_Sharetrack/Data/Scripts/ShipPoints/ShipTracking/ShipTracker.cs b/Gamemode Mods/Stable/Starcore_Sharetrack/Data/Scripts/ShipPoints/ShipTracking/ShipTracker.cs index 57511dc9d..137085f65 100644 --- a/Gamemode Mods/Stable/Starcore_Sharetrack/Data/Scripts/ShipPoints/ShipTracking/ShipTracker.cs +++ b/Gamemode Mods/Stable/Starcore_Sharetrack/Data/Scripts/ShipPoints/ShipTracking/ShipTracker.cs @@ -124,6 +124,7 @@ private void TransferToGrid(IMyCubeGrid newGrid, bool showOnHud = true) } private ShieldApi ShieldApi => AllGridsList.I.ShieldApi; + private FieldGeneratorAPI FieldGeneratorAPI => AllGridsList.I.FieldGeneratorAPI; public IMyCubeGrid Grid { get; private set; } @@ -370,6 +371,8 @@ public void UpdateHud() nameTagText += "\n" + GridName; if (!IsFunctional) nameTagText += ":[Dead]"; + if (FieldGenerator != null) + nameTagText += IsSiegeActive ? " [SIEGED]" : ""; _nametag.Message.Append(nameTagText.TrimStart('\n')); _nametag.Offset = -_nametag.GetTextLength() / 2; @@ -655,6 +658,33 @@ public Dictionary WeaponCounts #endregion + #region Field Generator Stats + public IMyFunctionalBlock FieldGenerator => FieldGeneratorAPI.GetFirstFieldGeneratorOnGrid(Grid.EntityId); + + public bool IsSiegeActive + { + get + { + var fieldGenerator = FieldGeneratorAPI.GetFirstFieldGeneratorOnGrid(Grid.EntityId); + if (fieldGenerator == null) + return false; + return FieldGeneratorAPI.IsSiegeActive(fieldGenerator); + } + } + + public float CurrentFieldPower + { + get + { + var fieldGenerator = FieldGeneratorAPI.GetFirstFieldGeneratorOnGrid(Grid.EntityId); + if (fieldGenerator == null) + return 0; + return FieldGeneratorAPI.GetFieldPower(fieldGenerator); + } + } + + public int GeneratorDisplayBlink; + #endregion #endregion } } \ No newline at end of file