diff --git a/Advanced Gravity Collector/Data/Blocks.sbc b/Advanced Gravity Collector/Data/Blocks.sbc
index 8ff4eb16..af22d20e 100644
--- a/Advanced Gravity Collector/Data/Blocks.sbc
+++ b/Advanced Gravity Collector/Data/Blocks.sbc
@@ -99,6 +99,7 @@
Z
Y
212
+ 200
\ No newline at end of file
diff --git a/Advanced Gravity Collector/Data/Categories.sbc b/Advanced Gravity Collector/Data/Categories.sbc
index 2ba1e2b0..4b1ae50e 100644
--- a/Advanced Gravity Collector/Data/Categories.sbc
+++ b/Advanced Gravity Collector/Data/Categories.sbc
@@ -7,7 +7,7 @@
DisplayName_Category_LargeBlocks
- LargeBlocks
+ Section1_Position1_LargeBlocks
Collector/LargeGravityCollector
@@ -18,7 +18,7 @@
DisplayName_Category_SmallBlocks
- SmallBlocks
+ Section1_Position1_SmallBlocks
Collector/MediumGravityCollector
@@ -28,10 +28,11 @@
GuiBlockCategoryDefinition
- DisplayName_Category_ConveyorBlocks
- Conveyors
+ DisplayName_Category_Logistics
+ Section1_Position3_Logistics
- GravityCollector
+ Collector/LargeGravityCollector
+ Collector/MediumGravityCollector
diff --git a/Advanced Gravity Collector/Data/Scripts/GravityCollector/GravityCollector.cs b/Advanced Gravity Collector/Data/Scripts/GravityCollector/GravityCollector.cs
index c7744da7..9397d460 100644
--- a/Advanced Gravity Collector/Data/Scripts/GravityCollector/GravityCollector.cs
+++ b/Advanced Gravity Collector/Data/Scripts/GravityCollector/GravityCollector.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
using Sandbox.Common.ObjectBuilders;
using Sandbox.Definitions;
@@ -9,54 +10,58 @@
using Sandbox.ModAPI.Interfaces.Terminal;
using VRage.Game;
using VRage.Game.Components;
+using VRage.Game.Entity;
using VRage.Game.ModAPI;
using VRage.ModAPI;
using VRage.ObjectBuilders;
using VRage.Utils;
using VRageMath;
-namespace Digi.GravityCollector
-{
+
+namespace Digi.GravityCollector {
[MyEntityComponentDescriptor(typeof(MyObjectBuilder_Collector), false, "MediumGravityCollector", "LargeGravityCollector")]
- public class GravityCollector : MyGameLogicComponent
- {
+ public class GravityCollector : MyGameLogicComponent {
public const float RANGE_MIN = 0;
- public const float RANGE_MAX_MEDIUM = 40;
- public const float RANGE_MAX_LARGE = 60;
+ public const float RANGE_MAX_MEDIUM = 400;
+ public const float RANGE_MAX_LARGE = 600;
public const float RANGE_OFF_EXCLUSIVE = 1;
-
public const float STRENGTH_MIN = 1;
public const float STRENGTH_MAX = 200;
-
- public const int APPLY_FORCE_SKIP_TICKS = 3; // how many ticks between applying forces to floating objects
- public const double MAX_VIEW_RANGE_SQ = 500 * 500; // max distance that the cone and pulsing item sprites can be seen from, squared value.
-
- public const float MASS_MUL = 10; // multiply item mass to get force
- public const float MAX_MASS = 5000; // max mass to multiply
-
+ public const int APPLY_FORCE_SKIP_TICKS = 3;
+ public const double MAX_VIEW_RANGE_SQ = 500 * 500;
+ public const float MASS_MUL = 10;
+ public const float MAX_MASS = 5000;
public const string CONTROLS_PREFIX = "GravityCollector.";
public readonly Guid SETTINGS_GUID = new Guid("0DFC6F70-310D-4D1C-A55F-C57913E20389");
- public const int SETTINGS_CHANGED_COUNTDOWN = (60 * 1) / 10; // div by 10 because it runs in update10
+ public const int SETTINGS_CHANGED_COUNTDOWN = (60 * 1) / 10;
+ private AdvancedCollectionSystem collectionSystem;
+ public float adaptiveForceMultiplier = 1.0f;
+ public double ConeAngle => coneAngle;
+ public float Offset => offset;
+ public bool IsInCollectionCone(Vector3D position)
+ {
+ var conePos = block.WorldMatrix.Translation + (block.WorldMatrix.Forward * -offset);
+ var dirNormalized = Vector3D.Normalize(position - conePos);
+ var angle = Math.Acos(MathHelper.Clamp(Vector3D.Dot(block.WorldMatrix.Forward, dirNormalized), -1, 1));
+ return angle <= coneAngle;
+ }
public float Range
{
get { return Settings.Range; }
set
{
Settings.Range = MathHelper.Clamp((int)Math.Floor(value), RANGE_MIN, maxRange);
-
SettingsChanged();
-
- if(Settings.Range < RANGE_OFF_EXCLUSIVE)
+ if (Settings.Range < RANGE_OFF_EXCLUSIVE)
{
NeedsUpdate = MyEntityUpdateEnum.NONE;
}
else
{
- if((NeedsUpdate & MyEntityUpdateEnum.EACH_10TH_FRAME) == 0)
+ if ((NeedsUpdate & MyEntityUpdateEnum.EACH_10TH_FRAME) == 0)
NeedsUpdate |= MyEntityUpdateEnum.EACH_10TH_FRAME;
}
-
block?.Components?.Get()?.Update();
}
}
@@ -67,38 +72,35 @@ public float StrengthMul
set
{
Settings.Strength = MathHelper.Clamp(value, STRENGTH_MIN / 100f, STRENGTH_MAX / 100f);
-
SettingsChanged();
-
block?.Components?.Get()?.Update();
}
}
IMyCollector block;
MyPoweredCargoContainerDefinition blockDef;
-
public readonly GravityCollectorBlockSettings Settings = new GravityCollectorBlockSettings();
int syncCountdown;
-
double coneAngle;
float offset;
float maxRange;
-
int skipTicks;
List floatingObjects;
-
GravityCollectorMod Mod => GravityCollectorMod.Instance;
+ public CollectorNetwork network;
bool DrawCone
{
get
{
- if(MyAPIGateway.Utilities.IsDedicated || !block.ShowOnHUD)
+ if (MyAPIGateway.Utilities.IsDedicated || !block.ShowOnHUD)
return false;
-
- var relation = block.GetPlayerRelationToOwner();
-
- return (relation != MyRelationsBetweenPlayerAndBlock.Enemies);
+ IMyPlayer localPlayer = MyAPIGateway.Session?.Player;
+ if (localPlayer == null)
+ return false;
+ long localPlayerId = localPlayer.IdentityId;
+ MyRelationsBetweenPlayerAndBlock relation = block.GetUserRelationToOwner(localPlayerId);
+ return relation != MyRelationsBetweenPlayerAndBlock.Enemies;
}
}
@@ -112,17 +114,14 @@ public override void UpdateOnceBeforeFrame()
try
{
SetupTerminalControls();
-
block = (IMyCollector)Entity;
-
- if(block.CubeGrid?.Physics == null)
+ if (block.CubeGrid?.Physics == null)
return;
-
blockDef = (MyPoweredCargoContainerDefinition)block.SlimBlock.BlockDefinition;
-
floatingObjects = new List();
+ collectionSystem = new AdvancedCollectionSystem(this);
- switch(block.BlockDefinition.SubtypeId)
+ switch (block.BlockDefinition.SubtypeId)
{
case "MediumGravityCollector":
maxRange = RANGE_MAX_MEDIUM;
@@ -137,23 +136,21 @@ public override void UpdateOnceBeforeFrame()
}
NeedsUpdate = MyEntityUpdateEnum.EACH_FRAME | MyEntityUpdateEnum.EACH_10TH_FRAME;
-
- // override block's power usage behavior
- var sink = block.Components?.Get();
+ MyResourceSinkComponent sink = block.Components?.Get();
sink?.SetRequiredInputFuncByType(MyResourceDistributorComponent.ElectricityId, ComputeRequiredPower);
-
- // set default settings
Settings.Strength = 1.0f;
Settings.Range = maxRange;
- if(!LoadSettings())
+ if (!LoadSettings())
{
ParseLegacyNameStorage();
}
- SaveSettings(); // required for IsSerialized()
+ SaveSettings();
+ network = CollectorNetwork.GetNetwork(block.CubeGrid.EntityId);
+ network.RegisterCollector(this);
}
- catch(Exception e)
+ catch (Exception e)
{
Log.Error(e);
}
@@ -163,15 +160,15 @@ public override void Close()
{
try
{
- if(block == null)
+ if (block == null)
return;
-
floatingObjects?.Clear();
floatingObjects = null;
-
+ network?.UnregisterCollector(this);
+ network = null;
block = null;
}
- catch(Exception e)
+ catch (Exception e)
{
Log.Error(e);
}
@@ -179,10 +176,9 @@ public override void Close()
float ComputeRequiredPower()
{
- if(!block.IsWorking)
+ if (!block.IsWorking)
return 0f;
-
- var baseUsage = 0.002f; // same as vanilla collector
+ var baseUsage = 0.002f;
var maxPowerUsage = blockDef.RequiredPowerInput;
var mul = (StrengthMul / (STRENGTH_MAX / 100f)) * (Range / maxRange);
return baseUsage + maxPowerUsage * mul;
@@ -195,7 +191,7 @@ public override void UpdateBeforeSimulation10()
SyncSettings();
FindFloatingObjects();
}
- catch(Exception e)
+ catch (Exception e)
{
Log.Error(e);
}
@@ -207,30 +203,27 @@ void FindFloatingObjects()
entities.Clear();
floatingObjects.Clear();
- if(Range < RANGE_OFF_EXCLUSIVE || !block.IsWorking || !block.CubeGrid.Physics.Enabled)
+ if (Range < RANGE_OFF_EXCLUSIVE || !block.IsWorking || !block.CubeGrid.Physics.Enabled)
{
- if((NeedsUpdate & MyEntityUpdateEnum.EACH_FRAME) != 0)
+ if ((NeedsUpdate & MyEntityUpdateEnum.EACH_FRAME) != 0)
{
UpdateEmissive();
NeedsUpdate &= ~MyEntityUpdateEnum.EACH_FRAME;
}
-
return;
}
- if((NeedsUpdate & MyEntityUpdateEnum.EACH_FRAME) == 0)
+ if ((NeedsUpdate & MyEntityUpdateEnum.EACH_FRAME) == 0)
NeedsUpdate |= MyEntityUpdateEnum.EACH_FRAME;
- var collectPos = block.WorldMatrix.Translation + (block.WorldMatrix.Forward * offset);
- var sphere = new BoundingSphereD(collectPos, Range + 10);
-
+ Vector3D collectPos = GetCollectionPoint();
+ BoundingSphereD sphere = new BoundingSphereD(collectPos, Range + 10);
MyGamePruningStructure.GetAllTopMostEntitiesInSphere(ref sphere, entities, MyEntityQueryType.Dynamic);
- foreach(var ent in entities)
+ foreach (MyEntity ent in entities)
{
- var floatingObject = ent as IMyFloatingObject;
-
- if(floatingObject != null && floatingObject.Physics != null)
+ IMyFloatingObject floatingObject = ent as IMyFloatingObject;
+ if (floatingObject != null && floatingObject.Physics != null)
floatingObjects.Add(floatingObject);
}
@@ -241,22 +234,18 @@ void FindFloatingObjects()
void UpdateEmissive(bool pulling = false)
{
- var color = Color.Red;
+ Color color = Color.Red;
float strength = 0f;
-
- if(block.IsWorking)
+ if (block.IsWorking)
{
strength = 1f;
-
- if(pulling)
+ if (pulling)
color = Color.Cyan;
else
color = new Color(10, 255, 0);
}
-
- if(prevColor == color)
+ if (prevColor == color)
return;
-
prevColor = color;
block.SetEmissiveParts("Emissive", color, strength);
}
@@ -265,99 +254,73 @@ public override void UpdateAfterSimulation()
{
try
{
- if(Range < RANGE_OFF_EXCLUSIVE)
+ if (Range < RANGE_OFF_EXCLUSIVE || !block.IsWorking)
return;
- bool applyForce = false;
- if(++skipTicks >= APPLY_FORCE_SKIP_TICKS)
- {
+ collectionSystem.Update();
+
+ bool applyForce = (++skipTicks >= APPLY_FORCE_SKIP_TICKS);
+ if (applyForce)
skipTicks = 0;
- applyForce = true;
- }
- if(!applyForce && MyAPIGateway.Utilities.IsDedicated)
+ if (!applyForce && MyAPIGateway.Utilities.IsDedicated)
return;
- var conePos = block.WorldMatrix.Translation + (block.WorldMatrix.Forward * -offset);
- bool inViewRange = false;
-
- if(!MyAPIGateway.Utilities.IsDedicated)
- {
- var cameraMatrix = MyAPIGateway.Session.Camera.WorldMatrix;
- inViewRange = Vector3D.DistanceSquared(cameraMatrix.Translation, conePos) <= MAX_VIEW_RANGE_SQ;
-
- if(inViewRange && DrawCone)
- DrawInfluenceCone(conePos);
- }
-
- if(!applyForce && !inViewRange)
- return;
+ ProcessVisuals();
- if(floatingObjects.Count == 0)
+ if (floatingObjects.Count == 0)
{
- UpdateEmissive();
+ UpdateEmissive(false);
return;
}
- var collectPos = block.WorldMatrix.Translation + (block.WorldMatrix.Forward * offset);
- var blockVel = block.CubeGrid.Physics.GetVelocityAtPoint(collectPos);
- var rangeSq = Range * Range;
- int pulling = 0;
-
- for(int i = (floatingObjects.Count - 1); i >= 0; --i)
- {
- var floatingObject = floatingObjects[i];
-
- if(floatingObject.MarkedForClose || !floatingObject.Physics.Enabled)
- continue; // it'll get removed by FindFloatingObjects()
-
- var objPos = floatingObject.GetPosition();
- var distSq = Vector3D.DistanceSquared(collectPos, objPos);
-
- if(distSq > rangeSq)
- continue; // too far from cone
-
- var dirNormalized = Vector3D.Normalize(objPos - conePos);
- var angle = Math.Acos(MathHelper.Clamp(Vector3D.Dot(block.WorldMatrix.Forward, dirNormalized), -1, 1));
-
- if(angle > coneAngle)
- continue; // outside of the cone's FOV
-
- if(applyForce)
- {
- var collectDir = Vector3D.Normalize(objPos - collectPos);
-
- var vel = floatingObject.Physics.LinearVelocity - blockVel;
- var stop = vel - (collectDir * collectDir.Dot(vel));
- var force = -(stop + collectDir) * Math.Min(floatingObject.Physics.Mass * MASS_MUL, MAX_MASS) * StrengthMul;
-
- force *= APPLY_FORCE_SKIP_TICKS; // multiplied by how many ticks were skipped
-
- //MyTransparentGeometry.AddLineBillboard(Mod.MATERIAL_SQUARE, Color.Yellow, objPos, force, 1f, 0.1f);
-
- floatingObject.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_FORCE, force, null, null);
- }
+ ProcessObjects(applyForce);
+ }
+ catch (Exception e)
+ {
+ Log.Error(e);
+ }
+ }
- if(inViewRange)
- {
- var mul = (float)Math.Sin(DateTime.UtcNow.TimeOfDay.TotalMilliseconds * 0.01);
- var radius = floatingObject.Model.BoundingSphere.Radius * MinMaxPercent(0.75f, 1.25f, mul);
+ private void ProcessVisuals()
+ {
+ if (MyAPIGateway.Utilities.IsDedicated)
+ return;
- MyTransparentGeometry.AddPointBillboard(Mod.MATERIAL_DOT, Color.LightSkyBlue * MinMaxPercent(0.2f, 0.4f, mul), objPos, radius, 0);
- }
+ Vector3D conePos = block.WorldMatrix.Translation + (block.WorldMatrix.Forward * -offset);
+ MatrixD cameraMatrix = MyAPIGateway.Session.Camera.WorldMatrix;
+ bool inViewRange = Vector3D.DistanceSquared(cameraMatrix.Translation, conePos) <= MAX_VIEW_RANGE_SQ;
- pulling++;
- }
+ if (inViewRange && DrawCone)
+ DrawInfluenceCone(conePos);
+ }
+ private void ProcessObjects(bool applyForce)
+ {
+ int pulling = 0;
+ Vector3D cameraPos = MyAPIGateway.Session.Camera.WorldMatrix.Translation;
+ bool inViewRange = Vector3D.DistanceSquared(cameraPos, GetCollectionPoint()) <= MAX_VIEW_RANGE_SQ;
- if(applyForce)
- UpdateEmissive(pulling > 0);
- }
- catch(Exception e)
+ foreach (IMyFloatingObject obj in floatingObjects)
{
- Log.Error(e);
+ if (!IsValidCollectionTarget(obj))
+ continue;
+
+ GravityCollector bestCollector = network.GetBestCollectorFor(obj);
+ if (bestCollector != this) continue;
+ float priority = CalculateCollectionPriority(obj);
+ collectionSystem.QueueObject(obj, priority);
+ pulling++;
+
+ if (!inViewRange || MyAPIGateway.Utilities.IsDedicated) continue;
+ Vector3D objPos = obj.GetPosition();
+ var mul = (float)Math.Sin(DateTime.UtcNow.TimeOfDay.TotalMilliseconds * 0.01);
+ var radius = obj.Model.BoundingSphere.Radius * MinMaxPercent(0.75f, 1.25f, mul);
+ MyTransparentGeometry.AddPointBillboard(Mod.MATERIAL_DOT, Color.LightSkyBlue * MinMaxPercent(0.2f, 0.4f, mul), objPos, radius, 0);
}
- }
+ if (applyForce)
+ UpdateEmissive(pulling > 0);
+ }
void DrawInfluenceCone(Vector3D conePos)
{
Vector4 color = Color.Cyan.ToVector4() * 10;
@@ -365,35 +328,31 @@ void DrawInfluenceCone(Vector3D conePos)
const float LINE_THICK = 0.02f;
const int WIRE_DIV_RATIO = 16;
- var coneMatrix = block.WorldMatrix;
+ MatrixD coneMatrix = block.WorldMatrix;
coneMatrix.Translation = conePos;
- //MyTransparentGeometry.AddPointBillboard(Mod.MATERIAL_DOT, Color.Lime, collectPos, 0.05f, 0);
-
- float rangeOffset = Range + (offset * 2); // because range check starts from collectPos but cone starts from conePos
+ float rangeOffset = Range + (offset * 2);
float baseRadius = rangeOffset * (float)Math.Tan(coneAngle);
- //MySimpleObjectDraw.DrawTransparentCone(ref coneMatrix, baseRadius, rangeWithOffset, ref color, 16, Mod.MATERIAL_SQUARE);
-
- var apexPosition = coneMatrix.Translation;
- var directionVector = coneMatrix.Forward * rangeOffset;
- var maxPosCenter = conePos + coneMatrix.Forward * rangeOffset;
- var baseVector = coneMatrix.Up * baseRadius;
+ Vector3D apexPosition = coneMatrix.Translation;
+ Vector3D directionVector = coneMatrix.Forward * rangeOffset;
+ Vector3D maxPosCenter = conePos + coneMatrix.Forward * rangeOffset;
+ Vector3D baseVector = coneMatrix.Up * baseRadius;
Vector3 axis = directionVector;
axis.Normalize();
float stepAngle = (float)(Math.PI * 2.0 / (double)WIRE_DIV_RATIO);
- var prevConePoint = apexPosition + directionVector + Vector3.Transform(baseVector, Matrix.CreateFromAxisAngle(axis, (-1 * stepAngle)));
+ Vector3D prevConePoint = apexPosition + directionVector + Vector3.Transform(baseVector, Matrix.CreateFromAxisAngle(axis, (-1 * stepAngle)));
prevConePoint = (apexPosition + Vector3D.Normalize((prevConePoint - apexPosition)) * rangeOffset);
- var quad = default(MyQuadD);
+ MyQuadD quad = default(MyQuadD);
- for(int step = 0; step < WIRE_DIV_RATIO; step++)
+ for (int step = 0; step < WIRE_DIV_RATIO; step++)
{
- var conePoint = apexPosition + directionVector + Vector3.Transform(baseVector, Matrix.CreateFromAxisAngle(axis, (step * stepAngle)));
- var lineDir = (conePoint - apexPosition);
+ Vector3D conePoint = apexPosition + directionVector + Vector3.Transform(baseVector, Matrix.CreateFromAxisAngle(axis, (step * stepAngle)));
+ Vector3D lineDir = (conePoint - apexPosition);
lineDir.Normalize();
conePoint = (apexPosition + lineDir * rangeOffset);
@@ -403,15 +362,6 @@ void DrawInfluenceCone(Vector3D conePos)
MyTransparentGeometry.AddLineBillboard(Mod.MATERIAL_SQUARE, color, conePoint, (maxPosCenter - conePoint), 1f, LINE_THICK);
- // Unusable because SQUARE has reflectivity and this method uses materials' reflectivity... making it unable to be made transparent, also reflective xD
- //var normal = Vector3.Up;
- //MyTransparentGeometry.AddTriangleBillboard(
- // apexPosition, prevConePoint, conePoint,
- // normal, normal, normal,
- // new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 1),
- // Mod.MATERIAL_SQUARE, uint.MaxValue, conePoint, planeColor);
- // also NOTE: if triangle is used, color needs .ToLinearRGB().
-
quad.Point0 = prevConePoint;
quad.Point1 = conePoint;
quad.Point2 = apexPosition;
@@ -430,25 +380,25 @@ void DrawInfluenceCone(Vector3D conePos)
bool LoadSettings()
{
- if(block.Storage == null)
+ if (block.Storage == null)
return false;
string rawData;
- if(!block.Storage.TryGetValue(SETTINGS_GUID, out rawData))
+ if (!block.Storage.TryGetValue(SETTINGS_GUID, out rawData))
return false;
try
{
- var loadedSettings = MyAPIGateway.Utilities.SerializeFromBinary(Convert.FromBase64String(rawData));
+ GravityCollectorBlockSettings loadedSettings = MyAPIGateway.Utilities.SerializeFromBinary(Convert.FromBase64String(rawData));
- if(loadedSettings != null)
+ if (loadedSettings != null)
{
Settings.Range = loadedSettings.Range;
Settings.Strength = loadedSettings.Strength;
return true;
}
}
- catch(Exception e)
+ catch (Exception e)
{
Log.Error($"Error loading settings!\n{e}");
}
@@ -460,43 +410,43 @@ bool ParseLegacyNameStorage()
{
string name = block.CustomName.TrimEnd(' ');
- if(!name.EndsWith("]", StringComparison.Ordinal))
+ if (!name.EndsWith("]", StringComparison.Ordinal))
return false;
int startIndex = name.IndexOf('[');
- if(startIndex == -1)
+ if (startIndex == -1)
return false;
var settingsStr = name.Substring(startIndex + 1, name.Length - startIndex - 2);
- if(settingsStr.Length == 0)
+ if (settingsStr.Length == 0)
return false;
string[] args = settingsStr.Split(';');
- if(args.Length == 0)
+ if (args.Length == 0)
return false;
string[] data;
- foreach(string arg in args)
+ foreach (string arg in args)
{
data = arg.Split('=');
float f;
int i;
- if(data.Length == 2)
+ if (data.Length == 2)
{
- switch(data[0])
+ switch (data[0])
{
case "range":
- if(int.TryParse(data[1], out i))
+ if (int.TryParse(data[1], out i))
Range = i;
break;
case "str":
- if(float.TryParse(data[1], out f))
+ if (float.TryParse(data[1], out f))
StrengthMul = f;
break;
}
@@ -509,16 +459,16 @@ bool ParseLegacyNameStorage()
void SaveSettings()
{
- if(block == null)
- return; // called too soon or after it was already closed, ignore
+ if (block == null)
+ return;
- if(Settings == null)
+ if (Settings == null)
throw new NullReferenceException($"Settings == null on entId={Entity?.EntityId}; modInstance={GravityCollectorMod.Instance != null}");
- if(MyAPIGateway.Utilities == null)
+ if (MyAPIGateway.Utilities == null)
throw new NullReferenceException($"MyAPIGateway.Utilities == null; entId={Entity?.EntityId}; modInstance={GravityCollectorMod.Instance != null}");
- if(block.Storage == null)
+ if (block.Storage == null)
block.Storage = new MyModStorageComponent();
block.Storage.SetValue(SETTINGS_GUID, Convert.ToBase64String(MyAPIGateway.Utilities.SerializeToBinary(Settings)));
@@ -526,13 +476,13 @@ void SaveSettings()
void SettingsChanged()
{
- if(syncCountdown == 0)
+ if (syncCountdown == 0)
syncCountdown = SETTINGS_CHANGED_COUNTDOWN;
}
void SyncSettings()
{
- if(syncCountdown > 0 && --syncCountdown <= 0)
+ if (syncCountdown > 0 && --syncCountdown <= 0)
{
SaveSettings();
@@ -542,15 +492,11 @@ void SyncSettings()
public override bool IsSerialized()
{
- // called when the game iterates components to check if they should be serialized, before they're actually serialized.
- // this does not only include saving but also streaming and blueprinting.
- // NOTE for this to work reliably the MyModStorageComponent needs to already exist in this block with at least one element.
-
try
{
SaveSettings();
}
- catch(Exception e)
+ catch (Exception e)
{
Log.Error(e);
}
@@ -558,25 +504,84 @@ public override bool IsSerialized()
return base.IsSerialized();
}
- ///
- /// Returns the specified percentage multiplier (0 to 1) between min and max.
- ///
+ public Vector3D GetCollectionPoint()
+ {
+ return block.WorldMatrix.Translation + (block.WorldMatrix.Forward * offset);
+ }
+
+ public float GetEffectiveVolume()
+ {
+ float height = Range;
+ float radius = height * (float)Math.Tan(coneAngle);
+ return (float)(Math.PI * radius * radius * height / 3.0);
+ }
+
+ public float GetIdealVelocityForDistance(double distance)
+ {
+ float normalizedDist = (float)(distance / Range);
+ float baseVelocity = 20f;
+ return baseVelocity * (1f - normalizedDist * 0.5f);
+ }
+
+ public void UpdateForceMultiplier(float multiplier)
+ {
+ adaptiveForceMultiplier = MathHelper.Clamp(multiplier, 0.1f, 100.0f);
+ }
+
+ private float CalculateCollectionPriority(IMyEntity entity)
+ {
+ float priority = 0f;
+
+ var distance = Vector3D.Distance(GetCollectionPoint(), entity.GetPosition());
+ priority += 1.0f - (float)(distance / Range);
+
+ if (entity.Physics != null)
+ {
+ priority += Math.Min(entity.Physics.Mass / MAX_MASS, 1.0f) * 0.5f;
+ }
+
+ if (entity is IMyFloatingObject)
+ {
+ priority += 0.3f;
+ }
+
+ return priority;
+ }
+
+ private bool IsValidCollectionTarget(IMyEntity entity)
+ {
+ if (entity?.Physics == null || entity.MarkedForClose)
+ return false;
+
+ Vector3D objPos = entity.GetPosition();
+ Vector3D collectPos = GetCollectionPoint();
+
+ if (Vector3D.DistanceSquared(collectPos, objPos) > Range * Range)
+ return false;
+
+ Vector3D dirNormalized = Vector3D.Normalize(objPos - collectPos);
+ var angle = Math.Acos(MathHelper.Clamp(Vector3D.Dot(block.WorldMatrix.Forward, dirNormalized), -1, 1));
+
+ return angle <= coneAngle;
+ }
+
static float MinMaxPercent(float min, float max, float percentMul)
{
return min + (percentMul * (max - min));
}
#region Terminal controls
+
static void SetupTerminalControls()
{
- var mod = GravityCollectorMod.Instance;
+ GravityCollectorMod mod = GravityCollectorMod.Instance;
- if(mod.ControlsCreated)
+ if (mod.ControlsCreated)
return;
mod.ControlsCreated = true;
- var controlRange = MyAPIGateway.TerminalControls.CreateControl(CONTROLS_PREFIX + "Range");
+ IMyTerminalControlSlider controlRange = MyAPIGateway.TerminalControls.CreateControl(CONTROLS_PREFIX + "Range");
controlRange.Title = MyStringId.GetOrCompute("Pull Range");
controlRange.Tooltip = MyStringId.GetOrCompute("Max distance the cone extends to.");
controlRange.Visible = Control_Visible;
@@ -587,7 +592,7 @@ static void SetupTerminalControls()
controlRange.Writer = Control_Range_Writer;
MyAPIGateway.TerminalControls.AddControl(controlRange);
- var controlStrength = MyAPIGateway.TerminalControls.CreateControl(CONTROLS_PREFIX + "Strength");
+ IMyTerminalControlSlider controlStrength = MyAPIGateway.TerminalControls.CreateControl(CONTROLS_PREFIX + "Strength");
controlStrength.Title = MyStringId.GetOrCompute("Pull Strength");
controlStrength.Tooltip = MyStringId.GetOrCompute($"Formula used:\nForce = Min(ObjectMass * {MASS_MUL.ToString()}, {MAX_MASS.ToString()}) * (Strength / 100)");
controlStrength.Visible = Control_Visible;
@@ -608,34 +613,34 @@ static bool Control_Visible(IMyTerminalBlock block)
static float Control_Strength_Getter(IMyTerminalBlock block)
{
- var logic = GetLogic(block);
+ GravityCollector logic = GetLogic(block);
return (logic == null ? STRENGTH_MIN : logic.StrengthMul * 100);
}
static void Control_Strength_Setter(IMyTerminalBlock block, float value)
{
- var logic = GetLogic(block);
- if(logic != null)
+ GravityCollector logic = GetLogic(block);
+ if (logic != null)
logic.StrengthMul = ((int)value / 100f);
}
static void Control_Strength_Writer(IMyTerminalBlock block, StringBuilder writer)
{
- var logic = GetLogic(block);
- if(logic != null)
+ GravityCollector logic = GetLogic(block);
+ if (logic != null)
writer.Append((int)(logic.StrengthMul * 100f)).Append('%');
}
static float Control_Range_Getter(IMyTerminalBlock block)
{
- var logic = GetLogic(block);
+ GravityCollector logic = GetLogic(block);
return (logic == null ? 0 : logic.Range);
}
static void Control_Range_Setter(IMyTerminalBlock block, float value)
{
- var logic = GetLogic(block);
- if(logic != null)
+ GravityCollector logic = GetLogic(block);
+ if (logic != null)
logic.Range = (int)Math.Floor(value);
}
@@ -646,21 +651,448 @@ static float Control_Range_Min(IMyTerminalBlock block)
static float Control_Range_Max(IMyTerminalBlock block)
{
- var logic = GetLogic(block);
+ GravityCollector logic = GetLogic(block);
return (logic == null ? 0 : logic.maxRange);
}
static void Control_Range_Writer(IMyTerminalBlock block, StringBuilder writer)
{
- var logic = GetLogic(block);
- if(logic != null)
+ GravityCollector logic = GetLogic(block);
+ if (logic != null)
{
- if(logic.Range < RANGE_OFF_EXCLUSIVE)
+ if (logic.Range < RANGE_OFF_EXCLUSIVE)
writer.Append("OFF");
else
writer.Append(logic.Range.ToString("N2")).Append(" m");
}
}
+
#endregion
+
+ }
+
+ ///
+ /// Manages coordination between multiple collectors on the same grid
+ ///
+ public class CollectorNetwork {
+ private static Dictionary gridNetworks = new Dictionary();
+ private List collectors = new List();
+ private Dictionary objectAssignments = new Dictionary();
+ private readonly long gridId;
+
+ public static CollectorNetwork GetNetwork(long gridId)
+ {
+ CollectorNetwork network;
+ if (!gridNetworks.TryGetValue(gridId, out network))
+ {
+ network = new CollectorNetwork(gridId);
+ gridNetworks[gridId] = network;
+ }
+ return network;
+ }
+
+ public CollectorNetwork(long gridId)
+ {
+ this.gridId = gridId;
+ }
+
+ public void RegisterCollector(GravityCollector collector)
+ {
+ if (!collectors.Contains(collector))
+ {
+ collectors.Add(collector);
+ //Log.Info($"Collector {collector.Entity.EntityId} registered to grid network {gridId}");
+ }
+ }
+
+ public void UnregisterCollector(GravityCollector collector)
+ {
+ collectors.Remove(collector);
+
+ var reassignObjects = objectAssignments.Where(kvp => kvp.Value == collector)
+ .Select(kvp => kvp.Key)
+ .ToList();
+ foreach (IMyEntity obj in reassignObjects)
+ {
+ objectAssignments.Remove(obj);
+ }
+ }
+
+ public GravityCollector GetBestCollectorFor(IMyEntity entity)
+ {
+ GravityCollector assigned;
+ if (objectAssignments.TryGetValue(entity, out assigned))
+ return assigned;
+
+ Vector3D pos = entity.GetPosition();
+ return collectors.OrderBy(c => Vector3D.DistanceSquared(c.GetCollectionPoint(), pos))
+ .FirstOrDefault();
+ }
+
+ public void AssignObject(IMyEntity entity, GravityCollector collector)
+ {
+ objectAssignments[entity] = collector;
+ }
+
+ public void ReleaseObject(IMyEntity entity)
+ {
+ objectAssignments.Remove(entity);
+ }
+ }
+
+ ///
+ /// Handles advanced object collection behavior and queuing
+ ///
+ public class AdvancedCollectionSystem {
+ private readonly GravityCollector collector;
+ private readonly Dictionary activePaths = new Dictionary();
+ private readonly PriorityQueue collectionQueue = new PriorityQueue();
+ private readonly HashSet processingObjects = new HashSet();
+
+ private const int MAX_CONCURRENT_COLLECTIONS = 8;
+ private const float DENSITY_THRESHOLD = 5f;
+ private const float ADAPTIVE_FORCE_MAX_MULTIPLIER = 20.0f;
+
+ private int updateCounter = 0;
+ private const int PERFORMANCE_LOG_INTERVAL = 600;// Log every 10 seconds at 60 updates/second
+
+ public AdvancedCollectionSystem(GravityCollector collector)
+ {
+ this.collector = collector;
+ }
+
+ public void Update()
+ {
+ DateTime startTime = DateTime.Now;
+
+ UpdateActivePaths();
+ ProcessQueue();
+ AdaptForceSettings();
+
+ // Clear the queue after processing to prevent accumulation
+ collectionQueue.Clear();
+
+ if (++updateCounter >= PERFORMANCE_LOG_INTERVAL)
+ {
+ updateCounter = 0;
+ var processingTime = (DateTime.Now - startTime).TotalMilliseconds;
+ //Log.Info($"Collection System Performance: {processingTime:F2}ms, Active Objects: {processingObjects.Count}, Queued: {collectionQueue.Count}");
+ }
+ }
+
+ private void UpdateActivePaths()
+ {
+ foreach (var path in activePaths.ToList())
+ {
+ if (!IsPathValid(path.Key))
+ {
+ // Log.Info($"Object {path.Key.EntityId} left collection cone or range, stopping collection");
+ activePaths.Remove(path.Key);
+ processingObjects.Remove(path.Key);
+ collector.network.ReleaseObject(path.Key);
+ continue;
+ }
+
+ path.Value.Update();
+ ApplyPathForces(path.Key, path.Value);
+ }
+ }
+
+ private void ProcessQueue()
+ {
+ while(processingObjects.Count < MAX_CONCURRENT_COLLECTIONS && collectionQueue.Count > 0)
+ {
+ IMyEntity nextObject = collectionQueue.Dequeue();
+ if (IsValidForCollection(nextObject))
+ {
+ InitiateCollection(nextObject);
+ }
+ }
+ }
+
+ private void InitiateCollection(IMyEntity entity)
+ {
+ CollectionPath path = new CollectionPath(collector, entity);
+ activePaths[entity] = path;
+ processingObjects.Add(entity);
+ collector.network.AssignObject(entity, collector);
+ }
+ private const float DENSITY_FALLOFF_FACTOR = 0.5f; // Adjust this value to control how quickly density decreases with distance
+ private void AdaptForceSettings()
+ {
+ Vector3D collectionPoint = collector.GetCollectionPoint();
+ float totalWeightedDensity = 0;
+ float totalWeight = 0;
+
+ foreach (var entity in processingObjects)
+ {
+ float distance = (float)Vector3D.Distance(entity.GetPosition(), collectionPoint);
+ float weight = 1f / (1f + distance * DENSITY_FALLOFF_FACTOR);
+ totalWeightedDensity += weight;
+ totalWeight += 1;
+ }
+
+ float effectiveVolume = collector.GetEffectiveVolume();
+ float averageDensity = (totalWeight > 0) ? (totalWeightedDensity / totalWeight) : 0;
+ float normalizedDensity = averageDensity / effectiveVolume;
+
+ float adaptiveMul = MathHelper.Clamp(
+ 1.0f - (normalizedDensity / DENSITY_THRESHOLD),
+ 1.0f / ADAPTIVE_FORCE_MAX_MULTIPLIER,
+ ADAPTIVE_FORCE_MAX_MULTIPLIER
+ );
+
+ collector.UpdateForceMultiplier(adaptiveMul);
+
+ // Log.Info($"Adaptive Force Multiplier: {adaptiveMul}, Normalized Density: {normalizedDensity}");
+ }
+
+ public void QueueObject(IMyEntity entity, float priority)
+ {
+ if (!processingObjects.Contains(entity) && !activePaths.ContainsKey(entity))
+ {
+ collectionQueue.Enqueue(entity, priority);
+ }
+ }
+
+ private bool IsPathValid(IMyEntity entity)
+ {
+ if (entity?.Physics == null || entity.MarkedForClose)
+ return false;
+
+ var distance = Vector3D.Distance(entity.GetPosition(), collector.GetCollectionPoint());
+ if (distance > collector.Range)
+ return false;
+
+ // Use the new method to check if in cone
+ return collector.IsInCollectionCone(entity.GetPosition());
+ }
+
+ private bool IsValidForCollection(IMyEntity entity)
+ {
+ return entity?.Physics != null && !entity.MarkedForClose;
+ }
+
+ private void ApplyPathForces(IMyEntity entity, CollectionPath path)
+ {
+ if (entity?.Physics == null)
+ {
+ Log.Info($"Failed to apply forces to entity {entity?.EntityId}: Physics null");
+ return;
+ }
+
+ Vector3 currentVelocity = entity.Physics.LinearVelocity;
+ Vector3D idealForce = path.GetIdealForce(currentVelocity);
+
+ idealForce *= collector.adaptiveForceMultiplier;
+
+ Vector3D randomOffset = new Vector3D(
+ MyUtils.GetRandomFloat(-0.1f, 0.1f),
+ MyUtils.GetRandomFloat(-0.1f, 0.1f),
+ MyUtils.GetRandomFloat(-0.1f, 0.1f)
+ );
+
+ idealForce += idealForce * randomOffset;
+
+ try
+ {
+ entity.Physics.AddForce(
+ MyPhysicsForceType.APPLY_WORLD_FORCE,
+ idealForce,
+ entity.GetPosition(),
+ null
+ );
+
+ // Log.Info($"Applied force to entity {entity.EntityId}: Force={idealForce.Length():F2}"); // TODO: ratelimit this
+ }
+ catch (Exception e)
+ {
+ Log.Error($"Failed to apply force to entity {entity.EntityId}: {e.Message}");
+ }
+ }
+ }
+
+
+ ///
+ /// Represents and calculates an optimal collection path for an object
+ ///
+ ///
+ /// Represents and calculates an optimal collection path for an object
+ ///
+ public class CollectionPath {
+ private readonly GravityCollector collector;
+ private readonly IMyEntity target;
+ private readonly List pathPoints = new List();
+ private Vector3D currentIdealPosition;
+ private Vector3D currentIdealVelocity;
+
+ private const int PATH_POINTS = 10;
+ private const float PATH_UPDATE_FREQUENCY = 6;
+ private const float ARRIVAL_THRESHOLD = 0.5f;
+
+ public CollectionPath(GravityCollector collector, IMyEntity target)
+ {
+ this.collector = collector;
+ this.target = target;
+ CalculatePath();
+ }
+
+ public void Update()
+ {
+ if (MyAPIGateway.Session.GameDateTime.Millisecond % (1000 / PATH_UPDATE_FREQUENCY) == 0)
+ {
+ CalculatePath();
+ }
+
+ UpdateIdealPositionAndVelocity();
+ }
+
+ private void CalculatePath()
+ {
+ pathPoints.Clear();
+ Vector3D start = target.GetPosition();
+ Vector3D end = collector.GetCollectionPoint();
+
+ for (int i = 0; i < PATH_POINTS; i++)
+ {
+ var t = i / (float)(PATH_POINTS - 1);
+ Vector3D point = Vector3D.Lerp(start, end, t);
+
+ point = AvoidObstacles(point);
+ pathPoints.Add(point);
+ }
+ }
+
+ private Vector3D AvoidObstacles(Vector3D point)
+ {
+ const double AVOIDANCE_RADIUS = 2.0;
+ const double REPULSION_STRENGTH = 100.0;
+
+ var nearbyEntities = new List();// Change to MyEntity
+ BoundingSphereD sphere = new BoundingSphereD(point, AVOIDANCE_RADIUS);
+ MyGamePruningStructure.GetAllTopMostEntitiesInSphere(ref sphere, nearbyEntities, MyEntityQueryType.Dynamic);
+
+ Vector3D avoidanceForce = Vector3D.Zero;
+ foreach (MyEntity entity in nearbyEntities)
+ {
+ if (entity == target) continue;
+
+ Vector3D entityPos = entity.PositionComp.GetPosition();
+ Vector3D direction = point - entityPos;
+ var distance = direction.Length();
+
+ if (!(distance < AVOIDANCE_RADIUS)) continue;
+ direction.Normalize();
+ avoidanceForce += direction * (REPULSION_STRENGTH * (1.0 - distance / AVOIDANCE_RADIUS));
+ }
+
+ return point + avoidanceForce;
+ }
+
+
+ private void UpdateIdealPositionAndVelocity()
+ {
+ Vector3D currentPos = target.GetPosition();
+ Vector3D collectorPos = collector.GetCollectionPoint();
+
+ // Check if we've arrived at the collector
+ if (Vector3D.Distance(currentPos, collectorPos) < ARRIVAL_THRESHOLD)
+ {
+ currentIdealVelocity = Vector3D.Zero;
+ return;
+ }
+
+ var pathIndex = FindClosestPathIndex(currentPos);
+ if (pathIndex < pathPoints.Count - 1)
+ {
+ currentIdealPosition = pathPoints[pathIndex + 1];
+ currentIdealVelocity = Vector3D.Normalize(currentIdealPosition - currentPos) *
+ collector.GetIdealVelocityForDistance(Vector3D.Distance(currentPos, collectorPos));
+ }
+ }
+
+ public Vector3D GetIdealForce(Vector3D currentVelocity)
+ {
+ Vector3D targetVelocity = currentIdealVelocity;
+ return (targetVelocity - currentVelocity) * target.Physics.Mass;
+ }
+
+ private int FindClosestPathIndex(Vector3D position)
+ {
+ int closestIndex = 0;
+ double closestDistance = double.MaxValue;
+
+ for (int i = 0; i < pathPoints.Count; i++)
+ {
+ double distance = Vector3D.DistanceSquared(position, pathPoints[i]);
+ if (distance < closestDistance)
+ {
+ closestDistance = distance;
+ closestIndex = i;
+ }
+ }
+
+ return closestIndex;
+ }
+ }
+
+ public class PriorityQueue {
+ private SortedDictionary> queue = new SortedDictionary>();
+ private Queue> recycledQueues = new Queue>();
+
+ public int Count { get; private set; }
+
+ public void Enqueue(T item, float priority)
+ {
+ Queue itemQueue;
+ if (!queue.TryGetValue(priority, out itemQueue))
+ {
+ itemQueue = GetQueue();
+ queue[priority] = itemQueue;
+ }
+
+ itemQueue.Enqueue(item);
+ Count++;
+ }
+
+ public T Dequeue()
+ {
+ if (Count == 0)
+ throw new InvalidOperationException("Queue is empty");
+
+ var highestPriority = queue.Keys.Last();
+ var itemQueue = queue[highestPriority];
+ T item = itemQueue.Dequeue();
+
+ if (itemQueue.Count == 0)
+ {
+ queue.Remove(highestPriority);
+ RecycleQueue(itemQueue);
+ }
+
+ Count--;
+ return item;
+ }
+
+ public void Clear()
+ {
+ foreach (var itemQueue in queue.Values)
+ {
+ itemQueue.Clear();
+ RecycleQueue(itemQueue);
+ }
+ queue.Clear();
+ Count = 0;
+ }
+
+ private Queue GetQueue()
+ {
+ return recycledQueues.Count > 0 ? recycledQueues.Dequeue() : new Queue();
+ }
+
+ private void RecycleQueue(Queue itemQueue)
+ {
+ recycledQueues.Enqueue(itemQueue);
+ }
}
}
\ No newline at end of file
diff --git a/Advanced Gravity Collector/Data/Scripts/concatrecursivelyandminify.bat b/Advanced Gravity Collector/Data/Scripts/concatrecursivelyandminify.bat
new file mode 100644
index 00000000..9bbffa34
--- /dev/null
+++ b/Advanced Gravity Collector/Data/Scripts/concatrecursivelyandminify.bat
@@ -0,0 +1,60 @@
+@echo off
+setlocal enabledelayedexpansion
+chcp 65001
+REM ^^ this is to change the encoding to UTF-8, apparently
+
+echo Starting operation...
+
+set TEMP_OUTPUT=temp_concatenated.txt
+set FINAL_OUTPUT=minified_output.txt
+set /a COUNT=0
+set /a ERRORS=0
+
+if exist "%TEMP_OUTPUT%" (
+ echo Existing temporary file found. Deleting...
+ del "%TEMP_OUTPUT%"
+)
+
+if exist "%FINAL_OUTPUT%" (
+ echo Existing output file found. Deleting...
+ del "%FINAL_OUTPUT%"
+)
+
+for /r %%i in (*.cs) do (
+ echo Processing: "%%i"
+ type "%%i" >> "%TEMP_OUTPUT%"
+ if errorlevel 1 (
+ echo Error processing "%%i".
+ set /a ERRORS+=1
+ ) else (
+ set /a COUNT+=1
+ )
+)
+
+echo Concatenation completed.
+echo Total files processed: %COUNT%
+if %ERRORS% gtr 0 (
+ echo There were %ERRORS% errors during the concatenation.
+) else (
+ echo No errors encountered during concatenation.
+)
+
+echo Minifying concatenated file...
+csmin < "%TEMP_OUTPUT%" > "%FINAL_OUTPUT%"
+if errorlevel 1 (
+ echo Error occurred during minification.
+ set /a ERRORS+=1
+) else (
+ echo Minification completed successfully.
+)
+
+echo Cleaning up temporary file...
+del "%TEMP_OUTPUT%"
+
+echo Operation completed.
+if %ERRORS% gtr 0 (
+ echo There were %ERRORS% errors during the entire operation.
+) else (
+ echo No errors encountered during the entire operation.
+)
+pause
\ No newline at end of file
diff --git a/Advanced Gravity Collector/metadata.mod b/Advanced Gravity Collector/metadata.mod
new file mode 100644
index 00000000..0a020fdf
--- /dev/null
+++ b/Advanced Gravity Collector/metadata.mod
@@ -0,0 +1,4 @@
+
+
+ 1.0
+
\ No newline at end of file
diff --git a/Advanced Gravity Collector/modinfo.sbmi b/Advanced Gravity Collector/modinfo.sbmi
new file mode 100644
index 00000000..c361359a
--- /dev/null
+++ b/Advanced Gravity Collector/modinfo.sbmi
@@ -0,0 +1,11 @@
+
+
+ 76561198071098415
+ 0
+
+
+ 3346612989
+ Steam
+
+
+
\ No newline at end of file
diff --git a/Advanced Gravity Collector/Data/Categories_Digi.sbc b/BasicCargoTeleporter/Data/BlockCategories.sbc
similarity index 63%
rename from Advanced Gravity Collector/Data/Categories_Digi.sbc
rename to BasicCargoTeleporter/Data/BlockCategories.sbc
index 4dacf837..53935e29 100644
--- a/Advanced Gravity Collector/Data/Categories_Digi.sbc
+++ b/BasicCargoTeleporter/Data/BlockCategories.sbc
@@ -2,14 +2,15 @@
-
+
GuiBlockCategoryDefinition
- + Digi
- z-mod-digi
+ DisplayName_Category_ConveyorBlocks
+ Conveyors
- GravityCollector
+ ConveyorSorter/LargeBlockSmallSorterTeleport
+ ConveyorSorter/SmallBlockMediumSorterTeleport
diff --git a/BasicCargoTeleporter/Data/CubeBlocks_TeleportCargo.sbc b/BasicCargoTeleporter/Data/CubeBlocks_TeleportCargo.sbc
new file mode 100644
index 00000000..c0365eb2
--- /dev/null
+++ b/BasicCargoTeleporter/Data/CubeBlocks_TeleportCargo.sbc
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+ 13
+ TeleUnlock
+
+
+
+
+
+ 13
+ TeleUnlock
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ConveyorSorter
+ LargeBlockSmallSorterTeleport
+
+ Cargo Teleporter
+ Textures\GUI\Icons\Cubes\ConveyorSorterLarge.dds
+ Large
+ TriangleMesh
+
+
+ Models\Cubes\Large\ConveyorSorter.mwm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SorterCargoTeleport
+ Z
+ Y
+ Light
+ Utility
+ 1
+ 45
+
+ 2.5
+ 2.5
+ 2.5
+
+ Wireless conveyor sorter to any container on the same grid or connected grids (via antenna). Requires 1 MW of power.
+
+
+
+
+ ConveyorSorter
+ SmallBlockMediumSorterTeleport
+
+ Cargo Teleporter
+ Textures\GUI\Icons\Cubes\ConveyorSorterMedium.dds
+ Small
+ TriangleMesh
+
+
+ Models\Cubes\Small\ConveyorSorterMedium.mwm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SorterCargoTeleport
+ Z
+ Y
+ Light
+ Utility
+ 0.5
+ 25
+
+ 1.5
+ 1.5
+ 1.5
+
+ Wireless conveyor sorter to any container on the same grid or connected grids (via antenna). Requires 500 KW of power.
+
+
+
+
\ No newline at end of file
diff --git a/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/.idea/.idea.CargoTeleporter/.idea/.gitignore b/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/.idea/.idea.CargoTeleporter/.idea/.gitignore
new file mode 100644
index 00000000..bb8936c0
--- /dev/null
+++ b/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/.idea/.idea.CargoTeleporter/.idea/.gitignore
@@ -0,0 +1,13 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Rider ignored files
+/projectSettingsUpdater.xml
+/contentModel.xml
+/modules.xml
+/.idea.CargoTeleporter.iml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/.idea/.idea.CargoTeleporter/.idea/indexLayout.xml b/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/.idea/.idea.CargoTeleporter/.idea/indexLayout.xml
new file mode 100644
index 00000000..7b08163c
--- /dev/null
+++ b/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/.idea/.idea.CargoTeleporter/.idea/indexLayout.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/.idea/.idea.CargoTeleporter/.idea/vcs.xml b/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/.idea/.idea.CargoTeleporter/.idea/vcs.xml
new file mode 100644
index 00000000..c2365ab1
--- /dev/null
+++ b/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/.idea/.idea.CargoTeleporter/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/CargoTeleporterSorterServer.cs b/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/CargoTeleporterSorterServer.cs
new file mode 100644
index 00000000..3f95c54b
--- /dev/null
+++ b/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/CargoTeleporterSorterServer.cs
@@ -0,0 +1,320 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Sandbox.Common.ObjectBuilders;
+using Sandbox.Game.Entities;
+using Sandbox.ModAPI;
+using Sandbox.ModAPI.Ingame;
+using VRage.Game.Components;
+using VRage.Game.ModAPI;
+using VRage.ModAPI;
+using VRage.ObjectBuilders;
+using VRageMath;
+using IMyFunctionalBlock = Sandbox.ModAPI.IMyFunctionalBlock;
+using IMyLaserAntenna = Sandbox.ModAPI.Ingame.IMyLaserAntenna;
+using IMyRadioAntenna = Sandbox.ModAPI.Ingame.IMyRadioAntenna;
+using IMyTerminalBlock = Sandbox.ModAPI.IMyTerminalBlock;
+
+namespace CargoTeleporter
+{
+ [MyEntityComponentDescriptor(typeof(MyObjectBuilder_ConveyorSorter), false, "LargeBlockSmallSorterTeleport",
+ "SmallBlockMediumSorterTeleport")]
+ public class CargoTeleporterSorterServer : MyGameLogicComponent
+ {
+ private MyCubeBlock _cargoTeleporter;
+ private IMyInventory _inventory;
+ private MyObjectBuilder_EntityBase _objectBuilder;
+ private string _status;
+ private string _targetBlockName;
+ private string _targetGridName = "";
+ private bool _sending;
+ private string _oldName = "";
+
+ public override void Init(MyObjectBuilder_EntityBase objectBuilder)
+ {
+ Entity.NeedsUpdate |= MyEntityUpdateEnum.EACH_100TH_FRAME;
+ NeedsUpdate |= MyEntityUpdateEnum.EACH_100TH_FRAME;
+ NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME;
+ _objectBuilder = objectBuilder;
+ _cargoTeleporter = Entity as MyCubeBlock;
+ base.Init(objectBuilder);
+ (_cargoTeleporter as IMyTerminalBlock).AppendingCustomInfo += AppendingCustomInfo;
+ (_cargoTeleporter as IMyTerminalBlock).CustomNameChanged += CustomNameChange;
+ }
+
+ public override MyObjectBuilder_EntityBase GetObjectBuilder(bool copy = false)
+ {
+ return copy ? _objectBuilder.Clone() as MyObjectBuilder_EntityBase : _objectBuilder;
+ }
+
+ public override void Close()
+ {
+ Logging.Close();
+ }
+
+ public override void UpdateBeforeSimulation100()
+ {
+ if (_cargoTeleporter == null) return;
+ if (!((IMyFunctionalBlock) _cargoTeleporter).Enabled) return;
+
+ try
+ {
+ if (MyAPIGateway.Session == null)
+ {
+ Write("MyAPIGateway.Session is null");
+ return;
+ }
+
+ ParseName();
+
+ if (_targetBlockName == "") return;
+
+ if (_inventory == null) _inventory = _cargoTeleporter.GetInventory();
+ if (_sending && _inventory.Empty())
+ {
+ UpdateStatus("Status: Source Empty");
+ return;
+ }
+
+ //We use true, if it goes through the ref; (which I treat like an out) it will be changed.
+ //If it goes through the linq; then we are unchanged and true is the correct value. (we have found the grid, it is this one)
+ bool gridFound = true;
+ IMyEntity targetBlock;
+ if (_targetGridName.Length > 2 && _targetGridName != _cargoTeleporter.CubeGrid.Name)
+ {
+ targetBlock = GetTarget(ref gridFound);
+ }
+ else
+ {
+ var cubeBlocks = _cargoTeleporter.CubeGrid.GetFatBlocks();
+ targetBlock = cubeBlocks.First(x => x?.DisplayNameText == _targetBlockName && OwnershipUtils.IsSameFactionOrOwner(_cargoTeleporter, x));
+ }
+
+ var disonnectedStatus = "Status: Disconnected";
+ //If grid not found,
+ if (!gridFound)
+ {
+ Write("Grid Not Found");
+ }
+ disonnectedStatus += $"\nGrid: {(gridFound ? "" : "Not ")}Found";
+ if (targetBlock == null)
+ {
+ Write("Target Not Found");
+ }
+ //This message should only ever say T/S Not Found, but in case I flubbed it; it can say found
+ disonnectedStatus += $"\n{(_sending ? "Target" : "Source")}: {(targetBlock != null ? "" : "Not ")}Found";
+
+ if (targetBlock == null || !gridFound)
+ {
+ UpdateStatus(disonnectedStatus);
+ return;
+ }
+
+ var targetInventory = targetBlock.GetInventory();
+ var status = "Status: Connected\nTarget: ";
+ var targetStatus = targetInventory.IsFull ? "Full" : targetInventory.Empty() ? "Empty" : "Some";
+ var inventoryStatus = _inventory.IsFull ? "Full" : _inventory.Empty() ? "Empty" : "Some";
+ status += _sending ? targetStatus : inventoryStatus;
+ status += "\nSource: ";
+ status += !_sending ? targetStatus : inventoryStatus;
+
+ UpdateStatus(status);
+
+ if (!targetInventory.IsFull && _sending)
+ targetInventory.TransferItemFrom(_inventory, 0, null, true, null, false);
+ else if (!targetInventory.Empty() && !_inventory.IsFull && !_sending)
+ _inventory.TransferItemFrom(targetInventory, 0, null, true, null, false);
+ }
+ catch (Exception ex)
+ {
+ Logging.WriteLine(ex.ToString());
+ }
+ }
+
+ private void AppendingCustomInfo(IMyTerminalBlock block, StringBuilder sb)
+ {
+ sb.Clear();
+ sb.Append(_status);
+ }
+
+ private void CustomNameChange(IMyTerminalBlock block)
+ {
+ if (!ParseName()) return;
+
+ if (_targetBlockName.Length < 2)
+ {
+ Write("Name too small");
+ UpdateStatus("Status: No filters\n\nPlease add [T:Block Name] or [F:Block Name].\nPlease add [G:Grid Name] if using antennas.");
+ return;
+ }
+ }
+
+ private void UpdateStatus(string status)
+ {
+ if (status == _status) return;
+ _status = status;
+ (_cargoTeleporter as IMyTerminalBlock).RefreshCustomInfo();
+ }
+
+ private void Write(string v)
+ {
+ if (Config.enableDebug) Logging.WriteLine(_cargoTeleporter.CubeGrid.DisplayName + " - " + _cargoTeleporter.DisplayNameText + ": " + v);
+ }
+
+ private bool ParseName()
+ {
+ var displayName = _cargoTeleporter.DisplayNameText;
+ if (displayName == _oldName) return false;
+
+ //For ease of reading
+ const int NotFound = -1;
+ const char StartBracket = '[';
+ const char StopBracket = ']';
+ const char ModeDelimiter = ':';
+ const char ToMode = 'T';
+ const char ToModeLower = 't';
+ const char FromMode = 'F';
+ const char FromModeLower = 'f';
+ const char GlobalMode = 'G';
+ const char GlobalModeLower = 'g';
+
+ _targetBlockName = "";
+ _targetGridName = "";
+
+ var workingIndex = 0;
+ while (true)
+ {
+ if (workingIndex >= displayName.Length)
+ {
+ Write("Parsing Name - End Of String");
+ break;
+ }
+
+ var start = displayName.IndexOf(StartBracket, workingIndex);
+ if (start == NotFound)
+ {
+ Write("Parsing Name - '[' Not Found");
+ break;
+ }
+
+ var stop = displayName.IndexOf(StopBracket, start);
+ if (stop == NotFound)
+ {
+ Write("Parsing Name - Closing ']' Not Found");
+ break;
+ }
+ var delimiter = displayName.IndexOf(ModeDelimiter, start, stop - start);
+ if (delimiter == NotFound)
+ {
+ workingIndex = stop + 1; //We jump to stop instead of start because the delimiter does not exist; not because it is invalid
+ Write("Parsing Name - Missing ':' in [] pair");
+ continue;
+ }
+
+ //Trims [mode:name] to just mode and name
+ var modePart = displayName.Substring(start + 1, delimiter - start - 1);
+ var namePart = displayName.Substring(delimiter + 1, stop - delimiter - 1);
+
+ //Parses name
+ namePart = namePart.Trim();
+
+ //Parses mode
+ //First strip whitespace
+ modePart = modePart.Trim();
+
+ if (modePart.Length != 1)
+ {
+ //Mode is invalid, advance start and resume search
+ workingIndex = start + 1;
+ Write($"Parsing Name - '{modePart}' is not 1 character.");
+ continue;
+ }
+ var modeChar = modePart[0];
+ switch (modeChar)
+ {
+ case ToMode:
+ case ToModeLower:
+ _targetBlockName = namePart;
+ _sending = true;
+ break;
+ case FromMode:
+ case FromModeLower:
+ _targetBlockName = namePart;
+ _sending = false;
+ break;
+ case GlobalMode:
+ case GlobalModeLower:
+ _targetGridName = namePart;
+ break;
+ default:
+ //Mode is invalid char, advance start and resume search
+ workingIndex = start + 1;
+ Write($"Parsing Name - '{modePart}' is not a valid character.");
+ continue;
+ }
+ workingIndex = stop + 1;
+
+ if (_targetBlockName != "" && _targetGridName != "") break;
+ }
+ Write("Parsed: " + _targetGridName + ", " + _targetBlockName + ", " + _sending);
+ _oldName = displayName;
+ return true;
+ }
+
+ private IMyEntity GetTarget(ref bool foundGrid)
+ {
+ Write("Looking for [" + _targetGridName + "] " + _targetBlockName);
+
+ var gridsToProcess = new List();
+ var gridsProcessed = new HashSet();
+ IMyEntity target = null;
+ foundGrid = false;
+
+ gridsToProcess.Add(_cargoTeleporter.CubeGrid);
+
+ while (target == null && gridsToProcess.Count > 0)
+ {
+ var processing = gridsToProcess.Pop();
+ if (gridsProcessed.Contains(processing)) continue;
+ Write("Processing Grid: \"" + processing.DisplayName + "\"");
+
+ var gridBlocks = processing.GetFatBlocks().ToArray();
+
+ if (processing.DisplayName == _targetGridName)
+ {
+ try
+ {
+ target = gridBlocks.First(x => x?.DisplayNameText == _targetBlockName);
+ foundGrid = true;
+ break;
+ }
+ catch (InvalidOperationException e)
+ {
+ Write(e.ToString());
+ }
+ }
+
+ foreach (var antenna in gridBlocks.Where(x => x is IMyRadioAntenna && OwnershipUtils.IsSameFactionOrOwner(processing, x)).Cast().Where(x => x.Enabled && x.IsFunctional && x.IsBroadcasting))
+ {
+ var sphere = new BoundingSphereD(antenna.GetPosition(), antenna.Radius);
+ var toCheck = MyAPIGateway.Entities.GetEntitiesInSphere(ref sphere).Where(x => x is IMyCubeGrid).Cast().Where(x => !gridsProcessed.Contains(x) && !gridsToProcess.Contains(x) && OwnershipUtils.IsSameFactionOrOwner(processing, x)).ToArray();
+ if (toCheck.Length != 0) Write("Found grids to check: " + string.Join(", ", toCheck.Select(x => "\"" + x.DisplayName + "\"")));
+ gridsToProcess.AddRange(toCheck);
+ }
+
+ foreach (var antenna in gridBlocks.Where(x => x is IMyLaserAntenna && OwnershipUtils.IsSameFactionOrOwner(processing, x)).Cast().Where(x => x.Status == MyLaserAntennaStatus.Connected))
+ {
+ var sphere = new BoundingSphereD(antenna.TargetCoords, 1);
+ var toCheck = MyAPIGateway.Entities.GetEntitiesInSphere(ref sphere).Where(x => x is IMyCubeGrid).Cast().Where(x => !gridsProcessed.Contains(x) && !gridsToProcess.Contains(x) && OwnershipUtils.IsSameFactionOrOwner(processing, x)).ToArray();
+ if (toCheck.Length != 0) Write("Found grids to check: " + string.Join(", ", toCheck.Select(x => "\"" + x.DisplayName + "\"")));
+ gridsToProcess.AddRange(toCheck);
+ }
+
+ gridsProcessed.Add(processing);
+ }
+
+ return target;
+ }
+ }
+}
\ No newline at end of file
diff --git a/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/Config.cs b/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/Config.cs
new file mode 100644
index 00000000..5b548a2f
--- /dev/null
+++ b/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/Config.cs
@@ -0,0 +1,7 @@
+namespace CargoTeleporter
+{
+ public static class Config
+ {
+ public const bool enableDebug = false;
+ }
+}
diff --git a/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/Logging.cs b/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/Logging.cs
new file mode 100644
index 00000000..815d5570
--- /dev/null
+++ b/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/Logging.cs
@@ -0,0 +1,45 @@
+using Sandbox.ModAPI;
+using System;
+using System.IO;
+
+namespace CargoTeleporter
+{
+ public static class Logging
+ {
+ private static TextWriter writer = null;
+ public static void Setup()
+ {
+ try
+ {
+ writer = MyAPIGateway.Utilities.WriteFileInLocalStorage("CargoTeleport" + ".log", typeof(Logging));
+ }
+ catch { }
+ }
+
+ public static void WriteLine(string s)
+ {
+ try
+ {
+ if (writer == null)
+ Setup();
+ writer.WriteLine(DateTime.Now.ToString("[HH:mm:ss] ") + s);
+ writer.Flush();
+ }
+ catch { }
+ }
+
+ public static void Close()
+ {
+ try
+ {
+ if (writer != null)
+ {
+ writer.Flush();
+ writer.Close();
+ }
+ }
+ catch { }
+
+ }
+ }
+}
diff --git a/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/OwnershipUtils.cs b/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/OwnershipUtils.cs
new file mode 100644
index 00000000..1998bff2
--- /dev/null
+++ b/BasicCargoTeleporter/Data/Scripts/CargoTeleporter/OwnershipUtils.cs
@@ -0,0 +1,58 @@
+using System.Collections.Generic;
+using System.Linq;
+using VRage.Game.ModAPI;
+
+namespace CargoTeleporter
+{
+ public static class OwnershipUtils
+ {
+
+ //Faction
+ public static string GetFaction(IMyCubeGrid grid)
+ {
+ var blocks = grid.GetFatBlocks();
+ return !blocks.Any() ? "" : blocks.First().GetOwnerFactionTag();
+ }
+
+ public static bool IsSameFaction(IMyCubeBlock blockA, IMyCubeBlock blockB)
+ {
+ return blockA.GetOwnerFactionTag() == blockB.GetOwnerFactionTag();
+ }
+
+ public static bool IsSameFaction(IMyCubeGrid gridA, IMyCubeBlock blockB)
+ {
+ return GetFaction(gridA) == blockB.GetOwnerFactionTag();
+ }
+
+ public static bool IsSameFaction(IMyCubeGrid gridA, IMyCubeGrid gridB)
+ {
+ return GetFaction(gridA) == GetFaction(gridB);
+ }
+
+ //Ownership
+ public static bool IsSameOwner(IMyCubeBlock blockA, IMyCubeBlock blockB)
+ {
+ return blockA.OwnerId == blockB.OwnerId;
+ }
+
+ public static bool IsSameOwner(long playerID, IMyCubeBlock blockB)
+ {
+ return playerID == blockB.OwnerId;
+ }
+
+ public static bool IsSameFactionOrOwner(IMyCubeBlock blockA, IMyCubeBlock blockB)
+ {
+ return IsSameOwner(blockA, blockB) || IsSameFaction(blockA, blockB);
+ }
+
+ internal static bool IsSameFactionOrOwner(IMyCubeGrid gridA, IMyCubeBlock blockB)
+ {
+ return IsSameFaction(gridA, blockB) || gridA.BigOwners.Any(x => IsSameOwner(x, blockB));
+ }
+
+ internal static bool IsSameFactionOrOwner(IMyCubeGrid gridA, IMyCubeGrid gridB)
+ {
+ return IsSameFaction(gridA, gridB) || gridA.BigOwners.Any(x => gridB.BigOwners.Contains(x));
+ }
+ }
+}
diff --git a/ConfigurableGridPoints/Audio/MW4_Enemy_Target_Destroyed.wav b/ConfigurableGridPoints/Audio/MW4_Enemy_Target_Destroyed.wav
new file mode 100644
index 00000000..1be193aa
Binary files /dev/null and b/ConfigurableGridPoints/Audio/MW4_Enemy_Target_Destroyed.wav differ
diff --git a/ConfigurableGridPoints/Audio/MW4_Friendly_Unit_Destroyed.wav b/ConfigurableGridPoints/Audio/MW4_Friendly_Unit_Destroyed.wav
new file mode 100644
index 00000000..95aced01
Binary files /dev/null and b/ConfigurableGridPoints/Audio/MW4_Friendly_Unit_Destroyed.wav differ
diff --git a/ConfigurableGridPoints/Audio/MW4_V_Betty_MULTIPLAYER_Hill_Captured.wav b/ConfigurableGridPoints/Audio/MW4_V_Betty_MULTIPLAYER_Hill_Captured.wav
new file mode 100644
index 00000000..d20532b3
Binary files /dev/null and b/ConfigurableGridPoints/Audio/MW4_V_Betty_MULTIPLAYER_Hill_Captured.wav differ
diff --git a/ConfigurableGridPoints/Audio/MW4_V_Betty_MULTIPLAYER_Hill_Contested.wav b/ConfigurableGridPoints/Audio/MW4_V_Betty_MULTIPLAYER_Hill_Contested.wav
new file mode 100644
index 00000000..182aa7c5
Binary files /dev/null and b/ConfigurableGridPoints/Audio/MW4_V_Betty_MULTIPLAYER_Hill_Contested.wav differ
diff --git a/ConfigurableGridPoints/Data/CaptureZoneSound.sbc b/ConfigurableGridPoints/Data/CaptureZoneSound.sbc
new file mode 100644
index 00000000..d9e92779
--- /dev/null
+++ b/ConfigurableGridPoints/Data/CaptureZoneSound.sbc
@@ -0,0 +1,81 @@
+
+
+
+
+
+ MyObjectBuilder_AudioDefinition
+ Zone_Captured
+
+ SHOT
+ 400
+ 2
+ HeavyFight
+ 3
+ 4
+ false
+
+
+ Audio/MW4_V_Betty_MULTIPLAYER_Hill_Captured.wav
+
+
+
+
+
+
+
+ MyObjectBuilder_AudioDefinition
+ Zone_Lost
+
+ SHOT
+ 400
+ 2
+ HeavyFight
+ 3
+ 4
+ false
+
+
+ Audio/MW4_V_Betty_MULTIPLAYER_Hill_Contested.wav
+
+
+
+
+
+
+ MyObjectBuilder_AudioDefinition
+ Enemy_Destroyed
+
+ SHOT
+ 400
+ 2
+ HeavyFight
+ 3
+ 4
+ false
+
+
+ Audio/MW4_Enemy_Target_Destroyed.wav
+
+
+
+
+
+
+ MyObjectBuilder_AudioDefinition
+ Team_Destroyed
+
+ SHOT
+ 400
+ 2
+ HeavyFight
+ 3
+ 4
+ false
+
+
+ Audio/MW4_Friendly_Unit_Destroyed.wav
+
+
+
+
+
\ No newline at end of file
diff --git a/ConfigurableGridPoints/Data/Scripts/ShipPoints/API/CoreSystem/CoreSystemsApiBase.cs b/ConfigurableGridPoints/Data/Scripts/ShipPoints/API/CoreSystem/CoreSystemsApiBase.cs
new file mode 100644
index 00000000..b832a4b2
--- /dev/null
+++ b/ConfigurableGridPoints/Data/Scripts/ShipPoints/API/CoreSystem/CoreSystemsApiBase.cs
@@ -0,0 +1,942 @@
+using System;
+using System.Collections.Generic;
+using Sandbox.ModAPI;
+using VRage;
+using VRage.Collections;
+using VRage.Game;
+using VRage.Game.Entity;
+using VRage.Game.ModAPI;
+using VRageMath;
+
+//using CoreSystems.Platform;
+
+namespace CGP.ShareTrack.API.CoreSystem
+{
+ ///
+ /// https://github.com/sstixrud/CoreSystems/blob/master/BaseData/Scripts/CoreSystems/Api/CoreSystemsApiBase.cs
+ ///
+ public partial class WcApi
+ {
+ public enum ChangeMode
+ {
+ Add,
+ Release,
+ Lock
+ }
+
+ public enum EventTriggers
+ {
+ Reloading,
+ Firing,
+ Tracking,
+ Overheated,
+ TurnOn,
+ TurnOff,
+ BurstReload,
+ NoMagsToLoad,
+ PreFire,
+ EmptyOnGameLoad,
+ StopFiring,
+ StopTracking,
+ LockDelay,
+ Init,
+ Homing,
+ TargetAligned,
+ WhileOn,
+ TargetRanged100,
+ TargetRanged75,
+ TargetRanged50,
+ TargetRanged25
+ }
+
+ public enum ShootState
+ {
+ EventStart,
+ EventEnd,
+ Preceding,
+ Canceled
+ }
+
+ private const long Channel = 67549756549;
+
+ ///
+ /// Only filled if giving true to .
+ ///
+ public readonly List WeaponDefinitions = new List();
+
+ private Action> _addProjectileMonitor;
+ private bool _apiInit;
+ private Func _canShootTarget;
+ private Func _currentPowerConsumption;
+ private Action _disableRequiredPower;
+ private Action _fireWeaponOnce;
+ private Func _forceReload;
+ private Func _getActiveAmmo;
+ private Func _getAiFocus;
+
+ private Action>>>>
+ _getAllNpcSafeWeaponMagazines;
+
+ private Action> _getAllWeaponDefinitions;
+
+ private Action>>>>
+ _getAllWeaponMagazines;
+
+ private Func _getConstructEffectiveDps;
+ private Action> _getCoreArmors;
+ private Action> _getCorePhantoms;
+ private Action> _getCoreRifles;
+
+ private Action> _getCoreStaticLaunchers;
+ private Action> _getCoreTurrets;
+ private Action> _getCoreWeapons;
+ private Func _getHeatLevel;
+ private Func> _getMagazineMap;
+ private Func _getMaxPower;
+ private Func _getMaxWeaponRange;
+
+ private Action>>
+ _getMuzzleInfo;
+
+ private Action> _getNpcSafeWeapons;
+ private Action> _getObstructions;
+
+ private Func _getOptimalDps;
+
+ private Func _getPlayerController;
+ private Func _getPredictedTargetPos;
+ private Func> _getProjectilesLockedOn;
+ private Action> _getProjectilesLockedOnPos;
+
+ private Func> _getProjectileState;
+ private Func _getShotsFired;
+
+ private Action>> _getSortedThreats;
+ private Func, int, bool> _getTurretTargetTypes;
+
+ private Func _getWeaponAzimuthMatrix;
+ private bool _getWeaponDefinitions;
+ private Func _getWeaponElevationMatrix;
+ private Func> _getWeaponScope;
+
+ private Func> _getWeaponTarget;
+ private Func _hasAi;
+ private Func _hasCoreWeapon;
+ private Func, bool> _hudHandler;
+ private Func> _isInRange;
+ private bool _isRegistered;
+ private Func _isTargetAligned;
+ private Func> _isTargetAlignedExtended;
+ private Func _isTargetValid;
+ private Func _isWeaponReadyToFire;
+ private Func _isWeaponShooting;
+ private Action> _monitorEvents;
+ private Action _readyCallback;
+
+ private Action>>>>>
+ _registerDamageEvent;
+
+ private Func _releaseAiFocus;
+ private Action> _removeProjectileMonitor;
+ private Action _setActiveAmmo;
+ private Func _setAiFocus;
+ private Action _setBlockTrackingRange;
+ private Func _setMagazine;
+ private Action> _setProjectileState;
+ private Action, int> _setTurretTargetTypes;
+ private Action _setWeaponTarget;
+ private Func, bool> _shootHandler;
+
+ private Func _shootRequest;
+ private Func, bool> _targetFocusHandler;
+ private Action _toggleWeaponFire;
+
+ private Func _toggoleInfiniteResources;
+ private Action> _unmonitorEvents;
+
+ ///
+ /// True if CoreSystems replied when got called.
+ ///
+ public bool IsReady { get; private set; }
+
+ public void SetWeaponTarget(MyEntity weapon, MyEntity target, int weaponId = 0)
+ {
+ _setWeaponTarget?.Invoke(weapon, target, weaponId);
+ }
+
+ public void FireWeaponOnce(MyEntity weapon, bool allWeapons = true, int weaponId = 0)
+ {
+ _fireWeaponOnce?.Invoke(weapon, allWeapons, weaponId);
+ }
+
+ public void ToggleWeaponFire(MyEntity weapon, bool on, bool allWeapons, int weaponId = 0)
+ {
+ _toggleWeaponFire?.Invoke(weapon, on, allWeapons, weaponId);
+ }
+
+ public bool IsWeaponReadyToFire(MyEntity weapon, int weaponId = 0, bool anyWeaponReady = true,
+ bool shootReady = false)
+ {
+ return _isWeaponReadyToFire?.Invoke(weapon, weaponId, anyWeaponReady, shootReady) ?? false;
+ }
+
+ public float GetMaxWeaponRange(MyEntity weapon, int weaponId)
+ {
+ return _getMaxWeaponRange?.Invoke(weapon, weaponId) ?? 0f;
+ }
+
+ public bool GetTurretTargetTypes(MyEntity weapon, IList collection, int weaponId = 0)
+ {
+ return _getTurretTargetTypes?.Invoke(weapon, collection, weaponId) ?? false;
+ }
+
+ public void SetTurretTargetTypes(MyEntity weapon, IList collection, int weaponId = 0)
+ {
+ _setTurretTargetTypes?.Invoke(weapon, collection, weaponId);
+ }
+
+ public void SetBlockTrackingRange(MyEntity weapon, float range)
+ {
+ _setBlockTrackingRange?.Invoke(weapon, range);
+ }
+
+ public bool IsTargetAligned(MyEntity weapon, MyEntity targetEnt, int weaponId)
+ {
+ return _isTargetAligned?.Invoke(weapon, targetEnt, weaponId) ?? false;
+ }
+
+ public MyTuple IsTargetAlignedExtended(MyEntity weapon, MyEntity targetEnt, int weaponId)
+ {
+ return _isTargetAlignedExtended?.Invoke(weapon, targetEnt, weaponId) ?? new MyTuple();
+ }
+
+ public bool CanShootTarget(MyEntity weapon, MyEntity targetEnt, int weaponId)
+ {
+ return _canShootTarget?.Invoke(weapon, targetEnt, weaponId) ?? false;
+ }
+
+ public Vector3D? GetPredictedTargetPosition(MyEntity weapon, MyEntity targetEnt, int weaponId)
+ {
+ return _getPredictedTargetPos?.Invoke(weapon, targetEnt, weaponId) ?? null;
+ }
+
+ public float GetHeatLevel(MyEntity weapon)
+ {
+ return _getHeatLevel?.Invoke(weapon) ?? 0f;
+ }
+
+ public float GetCurrentPower(MyEntity weapon)
+ {
+ return _currentPowerConsumption?.Invoke(weapon) ?? 0f;
+ }
+
+ public void DisableRequiredPower(MyEntity weapon)
+ {
+ _disableRequiredPower?.Invoke(weapon);
+ }
+
+ public bool HasCoreWeapon(MyEntity weapon)
+ {
+ return _hasCoreWeapon?.Invoke(weapon) ?? false;
+ }
+
+ public string GetActiveAmmo(MyEntity weapon, int weaponId)
+ {
+ return _getActiveAmmo?.Invoke(weapon, weaponId) ?? null;
+ }
+
+ public void SetActiveAmmo(MyEntity weapon, int weaponId, string ammoType)
+ {
+ _setActiveAmmo?.Invoke(weapon, weaponId, ammoType);
+ }
+
+ public long GetPlayerController(MyEntity weapon)
+ {
+ return _getPlayerController?.Invoke(weapon) ?? -1;
+ }
+
+ public Matrix GetWeaponAzimuthMatrix(MyEntity weapon, int weaponId)
+ {
+ return _getWeaponAzimuthMatrix?.Invoke(weapon, weaponId) ?? Matrix.Zero;
+ }
+
+ public Matrix GetWeaponElevationMatrix(MyEntity weapon, int weaponId)
+ {
+ return _getWeaponElevationMatrix?.Invoke(weapon, weaponId) ?? Matrix.Zero;
+ }
+
+ public bool IsTargetValid(MyEntity weapon, MyEntity target, bool onlyThreats, bool checkRelations)
+ {
+ return _isTargetValid?.Invoke(weapon, target, onlyThreats, checkRelations) ?? false;
+ }
+
+ public void GetAllWeaponDefinitions(IList collection)
+ {
+ _getAllWeaponDefinitions?.Invoke(collection);
+ }
+
+ public void GetAllCoreWeapons(ICollection collection)
+ {
+ _getCoreWeapons?.Invoke(collection);
+ }
+
+ public void GetNpcSafeWeapons(ICollection collection)
+ {
+ _getNpcSafeWeapons?.Invoke(collection);
+ }
+
+ public void GetAllCoreStaticLaunchers(ICollection collection)
+ {
+ _getCoreStaticLaunchers?.Invoke(collection);
+ }
+
+ public void GetAllWeaponMagazines(
+ IDictionary>>> collection)
+ {
+ _getAllWeaponMagazines?.Invoke(collection);
+ }
+
+ public void GetAllNpcSafeWeaponMagazines(
+ IDictionary>>> collection)
+ {
+ _getAllNpcSafeWeaponMagazines?.Invoke(collection);
+ }
+
+ public void GetAllCoreTurrets(ICollection collection)
+ {
+ _getCoreTurrets?.Invoke(collection);
+ }
+
+ public void GetAllCorePhantoms(ICollection collection)
+ {
+ _getCorePhantoms?.Invoke(collection);
+ }
+
+ public void GetAllCoreRifles(ICollection collection)
+ {
+ _getCoreRifles?.Invoke(collection);
+ }
+
+ public void GetAllCoreArmors(IList collection)
+ {
+ _getCoreArmors?.Invoke(collection);
+ }
+
+ public MyTuple GetProjectilesLockedOn(MyEntity victim)
+ {
+ return _getProjectilesLockedOn?.Invoke(victim) ?? new MyTuple();
+ }
+
+ public void GetProjectilesLockedOnPos(MyEntity victim, ICollection collection)
+ {
+ _getProjectilesLockedOnPos?.Invoke(victim, collection);
+ }
+
+ public void GetSortedThreats(MyEntity shooter, ICollection> collection)
+ {
+ _getSortedThreats?.Invoke(shooter, collection);
+ }
+
+ public void GetObstructions(MyEntity shooter, ICollection collection)
+ {
+ _getObstructions?.Invoke(shooter, collection);
+ }
+
+ public MyEntity GetAiFocus(MyEntity shooter, int priority = 0)
+ {
+ return _getAiFocus?.Invoke(shooter, priority);
+ }
+
+ public bool SetAiFocus(MyEntity shooter, MyEntity target, int priority = 0)
+ {
+ return _setAiFocus?.Invoke(shooter, target, priority) ?? false;
+ }
+
+ public bool ReleaseAiFocus(MyEntity shooter, long playerId)
+ {
+ return _releaseAiFocus?.Invoke(shooter, playerId) ?? false;
+ }
+
+ public MyTuple GetWeaponTarget(MyEntity weapon, int weaponId = 0)
+ {
+ return _getWeaponTarget?.Invoke(weapon, weaponId) ?? new MyTuple();
+ }
+
+ public float GetMaxPower(MyDefinitionId weaponDef)
+ {
+ return _getMaxPower?.Invoke(weaponDef) ?? 0f;
+ }
+
+ public bool HasAi(MyEntity entity)
+ {
+ return _hasAi?.Invoke(entity) ?? false;
+ }
+
+ public float GetOptimalDps(MyEntity entity)
+ {
+ return _getOptimalDps?.Invoke(entity) ?? 0f;
+ }
+
+ public MyTuple GetProjectileState(ulong projectileId)
+ {
+ return _getProjectileState?.Invoke(projectileId) ??
+ new MyTuple();
+ }
+
+ public float GetConstructEffectiveDps(MyEntity entity)
+ {
+ return _getConstructEffectiveDps?.Invoke(entity) ?? 0f;
+ }
+
+ public MyTuple GetWeaponScope(MyEntity weapon, int weaponId)
+ {
+ return _getWeaponScope?.Invoke(weapon, weaponId) ?? new MyTuple();
+ }
+
+ public void AddProjectileCallback(MyEntity entity, int weaponId,
+ Action action)
+ {
+ _addProjectileMonitor?.Invoke(entity, weaponId, action);
+ }
+
+ public void RemoveProjectileCallback(MyEntity entity, int weaponId,
+ Action action)
+ {
+ _removeProjectileMonitor?.Invoke(entity, weaponId, action);
+ }
+
+
+ // block/grid/player, Threat, Other
+ public MyTuple IsInRange(MyEntity entity)
+ {
+ return _isInRange?.Invoke(entity) ?? new MyTuple();
+ }
+
+ ///
+ /// Set projectile values *Warning* be sure to pass in Vector3D.MinValue or float.MinValue to NOT set that value.
+ /// bool = EndNow
+ /// Vector3D Position
+ /// Vector3D Additive velocity
+ /// float BaseDamagePool
+ ///
+ ///
+ ///
+ public void SetProjectileState(ulong projectileId, MyTuple values)
+ {
+ _setProjectileState?.Invoke(projectileId, values);
+ }
+
+ ///
+ /// Gets whether the weapon is shooting, used by Hakerman's Beam Logic
+ /// Unexpected behavior may occur when using this method
+ ///
+ ///
+ ///
+ ///
+ internal bool IsWeaponShooting(MyEntity weaponBlock, int weaponId)
+ {
+ return _isWeaponShooting?.Invoke(weaponBlock, weaponId) ?? false;
+ }
+
+ ///
+ /// Gets how many shots the weapon fired, used by Hakerman's Beam Logic
+ /// Unexpected behavior may occur when using this method
+ ///
+ ///
+ ///
+ ///
+ internal int GetShotsFired(MyEntity weaponBlock, int weaponId)
+ {
+ return _getShotsFired?.Invoke(weaponBlock, weaponId) ?? -1;
+ }
+
+ ///
+ /// Gets the info of the weapon's all muzzles, used by Hakerman's Beam Logic
+ /// returns: A list that contains every muzzle's Position, LocalPosition, Direction, UpDirection, ParentMatrix,
+ /// DummyMatrix
+ /// Unexpected behavior may occur when using this method
+ ///
+ ///
+ ///
+ ///
+ internal void GetMuzzleInfo(MyEntity weaponBlock, int weaponId,
+ List> output)
+ {
+ _getMuzzleInfo?.Invoke(weaponBlock, weaponId, output);
+ }
+
+ ///
+ /// Entity can be a weapon or a grid/player (enables on all subgrids as well)
+ ///
+ ///
+ ///
+ public bool ToggleInfiniteResources(MyEntity entity)
+ {
+ return _toggoleInfiniteResources?.Invoke(entity) ?? false;
+ }
+
+ ///
+ /// Monitor various kind of events, see WcApiDef.WeaponDefinition.AnimationDef.PartAnimationSetDef.EventTriggers for
+ /// int mapping, bool is for active/inactive
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void MonitorEvents(MyEntity entity, int partId, Action action)
+ {
+ _monitorEvents?.Invoke(entity, partId, action);
+ }
+
+ ///
+ /// Monitor various kind of events, see WcApiDef.WeaponDefinition.AnimationDef.PartAnimationSetDef.EventTriggers for
+ /// int mapping, bool is for active/inactive
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void UnMonitorEvents(MyEntity entity, int partId, Action action)
+ {
+ _unmonitorEvents?.Invoke(entity, partId, action);
+ }
+
+ ///
+ /// Monitor all weaponcore damage
+ ///
+ ///
+ ///
+ /// 0 unregister, 1 register
+ ///
+ /// object casts (ulong = projectileId, IMySlimBlock, MyFloatingObject, IMyCharacter, MyVoxelBase, MyPlanet, MyEntity Shield see next line)
+ /// You can detect the shield entity in a performant way by creating a hash check ShieldHash = MyStringHash.GetOrCompute("DefenseShield");
+ /// then use it by Session.ShieldApiLoaded && Session.ShieldHash == ent.DefinitionId?.SubtypeId && ent.Render.Visible; Visible means shield online
+ public void RegisterDamageEvent(long modId, int type,
+ Action>>>> callback)
+ {
+ _registerDamageEvent?.Invoke(modId, type, callback);
+ }
+
+ ///
+ /// This allows you to determine when and if a player can modify the current target focus on a player/grid/phantonm.
+ /// Use only on server
+ ///
+ ///
+ /// is the player/grid/phantom you want to control the target focus for, applies to subgrids
+ /// as well
+ ///
+ /// be sure to unregister when you no longer want to receive callbacks
+ public void TargetFocushandler(long handledEntityId, bool unregister)
+ {
+ _targetFocusHandler(handledEntityId, unregister, TargetFocusCallback);
+ }
+
+ ///
+ /// This callback fires whenever a player attempts to modify the target focus
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private bool TargetFocusCallback(MyEntity target, IMyCharacter requestingCharacter, long handledEntityId,
+ int modeCode)
+ {
+ var mode = (ChangeMode)modeCode;
+
+ return true;
+ }
+
+ ///
+ /// Enables you to allow/deny hud draw requests. Do not use this on dedicated server.
+ ///
+ ///
+ ///
+ public void Hudhandler(long handledEntityId, bool unregister)
+ {
+ _hudHandler?.Invoke(handledEntityId, unregister, HudCallback);
+ }
+
+ ///
+ /// This callback fires whenever the hud tries to update
+ ///
+ ///
+ ///
+ ///
+ ///
+ private bool HudCallback(IMyCharacter requestingCharacter, long handledEntityId, int modeCode)
+ {
+ var mode = (HudMode)modeCode;
+
+ return true;
+ }
+
+ ///
+ ///
+ ///
+ /// MyEntity, ulong (projectile) or Vector3D
+ /// Most weapons have only id 0, but some are multi-weapon entities
+ ///
+ ///
+ public bool ShootRequest(MyEntity weaponEntity, object target, int weaponId = 0,
+ double additionalDeviateShotAngle = 0)
+ {
+ return _shootRequest?.Invoke(weaponEntity, target, weaponId, additionalDeviateShotAngle) ?? false;
+ }
+
+ ///
+ /// Enables you to monitor and approve shoot requests for this weapon/construct/player/grid network
+ ///
+ ///
+ ///
+ ///
+ public void ShootRequestHandler(long handledEntityId, bool unregister,
+ Func callback)
+ {
+ _shootHandler?.Invoke(handledEntityId, unregister, callback); // see example callback below
+ }
+
+ ///
+ /// This callback fires whenever a shoot request is being evaluated for against a success criteria or is pending some
+ /// action
+ ///
+ ///
+ ///
+ /// This is the state of your request, state 0 means proceeding as requested
+ ///
+ /// This is false if wc thinks the target is occluded, you can choose to allow it to proceed anyway or
+ /// not
+ ///
+ /// valid objects to cast too are MyEntity, ulong (projectile ids) and target Vector3Ds
+ ///
+ ///
+ ///
+ /// The number of times this callback will fire will depend on the relevant firing stages for
+ /// this weapon/ammo and how far it gets
+ ///
+ ///
+ private bool ShootCallBack(Vector3D scopePos, Vector3D scopeDirection, int requestState, bool hasLos,
+ object target, int currentAmmo, int remainingMags, int requestStage)
+ {
+ var stage = (EventTriggers)requestStage;
+ var state = (ShootState)requestState;
+ var targetAsEntity = target as MyEntity;
+ var targetAsProjectileId = target as ulong? ?? 0;
+ var targetAsPosition = target as Vector3D? ?? Vector3D.Zero;
+
+ return true;
+ }
+
+ ///
+ /// Get active ammo Mag map from weapon
+ ///
+ ///
+ ///
+ /// Mag definitionId, mag name, ammoRound name, weapon must aim (not manual aim) true/false
+ public MyTuple GetMagazineMap(MyEntity weapon, int weaponId)
+ {
+ return _getMagazineMap?.Invoke(weapon, weaponId) ?? new MyTuple();
+ }
+
+ ///
+ /// Set the active ammo type via passing Mag DefinitionId
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool SetMagazine(MyEntity weapon, int weaponId, MyDefinitionId id, bool forceReload)
+ {
+ return _setMagazine?.Invoke(weapon, weaponId, id, forceReload) ?? false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool ForceReload(MyEntity weapon, int weaponId)
+ {
+ return _forceReload?.Invoke(weapon, weaponId) ?? false;
+ }
+
+ ///
+ /// Ask CoreSystems to send the API methods.
+ /// Throws an exception if it gets called more than once per session without .
+ ///
+ /// Method to be called when CoreSystems replies.
+ /// Set to true to fill .
+ public void Load(Action readyCallback = null, bool getWeaponDefinitions = false)
+ {
+ if (_isRegistered)
+ throw new Exception($"{GetType().Name}.Load() should not be called multiple times!");
+
+ _readyCallback = readyCallback;
+ _getWeaponDefinitions = getWeaponDefinitions;
+ _isRegistered = true;
+ MyAPIGateway.Utilities.RegisterMessageHandler(Channel, HandleMessage);
+ MyAPIGateway.Utilities.SendModMessage(Channel, "ApiEndpointRequest");
+ }
+
+ public void Unload()
+ {
+ MyAPIGateway.Utilities.UnregisterMessageHandler(Channel, HandleMessage);
+
+ ApiAssign(null);
+
+ _isRegistered = false;
+ _apiInit = false;
+ IsReady = false;
+ }
+
+ private void HandleMessage(object obj)
+ {
+ if (_apiInit || obj is string
+ ) // the sent "ApiEndpointRequest" will also be received here, explicitly ignoring that
+ return;
+
+ var dict = obj as IReadOnlyDictionary;
+
+ if (dict == null)
+ return;
+
+ ApiAssign(dict, _getWeaponDefinitions);
+
+ IsReady = true;
+ _readyCallback?.Invoke();
+ }
+
+ public void ApiAssign(IReadOnlyDictionary delegates, bool getWeaponDefinitions = false)
+ {
+ _apiInit = delegates != null;
+ /// base methods
+ AssignMethod(delegates, "GetAllWeaponDefinitions", ref _getAllWeaponDefinitions);
+ AssignMethod(delegates, "GetCoreWeapons", ref _getCoreWeapons);
+ AssignMethod(delegates, "GetNpcSafeWeapons", ref _getNpcSafeWeapons);
+
+ AssignMethod(delegates, "GetAllWeaponMagazines", ref _getAllWeaponMagazines);
+ AssignMethod(delegates, "GetAllNpcSafeWeaponMagazines", ref _getAllNpcSafeWeaponMagazines);
+
+ AssignMethod(delegates, "GetCoreStaticLaunchers", ref _getCoreStaticLaunchers);
+ AssignMethod(delegates, "GetCoreTurrets", ref _getCoreTurrets);
+ AssignMethod(delegates, "GetCorePhantoms", ref _getCorePhantoms);
+ AssignMethod(delegates, "GetCoreRifles", ref _getCoreRifles);
+ AssignMethod(delegates, "GetCoreArmors", ref _getCoreArmors);
+
+ AssignMethod(delegates, "GetBlockWeaponMap", ref _getBlockWeaponMap);
+ AssignMethod(delegates, "GetSortedThreatsBase", ref _getSortedThreats);
+ AssignMethod(delegates, "GetObstructionsBase", ref _getObstructions);
+ AssignMethod(delegates, "GetMaxPower", ref _getMaxPower);
+ AssignMethod(delegates, "GetProjectilesLockedOnBase", ref _getProjectilesLockedOn);
+ AssignMethod(delegates, "GetProjectilesLockedOnPos", ref _getProjectilesLockedOnPos);
+ AssignMethod(delegates, "GetAiFocusBase", ref _getAiFocus);
+ AssignMethod(delegates, "SetAiFocusBase", ref _setAiFocus);
+ AssignMethod(delegates, "ReleaseAiFocusBase", ref _releaseAiFocus);
+ AssignMethod(delegates, "HasGridAiBase", ref _hasAi);
+ AssignMethod(delegates, "GetOptimalDpsBase", ref _getOptimalDps);
+ AssignMethod(delegates, "GetConstructEffectiveDpsBase", ref _getConstructEffectiveDps);
+ AssignMethod(delegates, "IsInRangeBase", ref _isInRange);
+ AssignMethod(delegates, "GetProjectileState", ref _getProjectileState);
+ AssignMethod(delegates, "SetProjectileState", ref _setProjectileState);
+
+ AssignMethod(delegates, "AddMonitorProjectile", ref _addProjectileMonitor);
+ AssignMethod(delegates, "RemoveMonitorProjectile", ref _removeProjectileMonitor);
+
+ AssignMethod(delegates, "TargetFocusHandler", ref _targetFocusHandler);
+ AssignMethod(delegates, "HudHandler", ref _hudHandler);
+ AssignMethod(delegates, "ShootHandler", ref _shootHandler);
+ AssignMethod(delegates, "ShootRequest", ref _shootRequest);
+
+ /// block methods
+ AssignMethod(delegates, "GetWeaponTargetBase", ref _getWeaponTarget);
+ AssignMethod(delegates, "SetWeaponTargetBase", ref _setWeaponTarget);
+ AssignMethod(delegates, "FireWeaponOnceBase", ref _fireWeaponOnce);
+ AssignMethod(delegates, "ToggleWeaponFireBase", ref _toggleWeaponFire);
+ AssignMethod(delegates, "IsWeaponReadyToFireBase", ref _isWeaponReadyToFire);
+ AssignMethod(delegates, "GetMaxWeaponRangeBase", ref _getMaxWeaponRange);
+ AssignMethod(delegates, "GetTurretTargetTypesBase", ref _getTurretTargetTypes);
+ AssignMethod(delegates, "SetTurretTargetTypesBase", ref _setTurretTargetTypes);
+ AssignMethod(delegates, "SetBlockTrackingRangeBase", ref _setBlockTrackingRange);
+ AssignMethod(delegates, "IsTargetAlignedBase", ref _isTargetAligned);
+ AssignMethod(delegates, "IsTargetAlignedExtendedBase", ref _isTargetAlignedExtended);
+ AssignMethod(delegates, "CanShootTargetBase", ref _canShootTarget);
+ AssignMethod(delegates, "GetPredictedTargetPositionBase", ref _getPredictedTargetPos);
+ AssignMethod(delegates, "GetHeatLevelBase", ref _getHeatLevel);
+ AssignMethod(delegates, "GetCurrentPowerBase", ref _currentPowerConsumption);
+ AssignMethod(delegates, "DisableRequiredPowerBase", ref _disableRequiredPower);
+ AssignMethod(delegates, "HasCoreWeaponBase", ref _hasCoreWeapon);
+ AssignMethod(delegates, "GetActiveAmmoBase", ref _getActiveAmmo);
+ AssignMethod(delegates, "SetActiveAmmoBase", ref _setActiveAmmo);
+ AssignMethod(delegates, "GetPlayerControllerBase", ref _getPlayerController);
+ AssignMethod(delegates, "GetWeaponAzimuthMatrixBase", ref _getWeaponAzimuthMatrix);
+ AssignMethod(delegates, "GetWeaponElevationMatrixBase", ref _getWeaponElevationMatrix);
+ AssignMethod(delegates, "IsTargetValidBase", ref _isTargetValid);
+ AssignMethod(delegates, "GetWeaponScopeBase", ref _getWeaponScope);
+
+ //Phantom methods
+ AssignMethod(delegates, "GetTargetAssessment", ref _getTargetAssessment);
+ //AssignMethod(delegates, "GetPhantomInfo", ref _getPhantomInfo);
+ AssignMethod(delegates, "SetTriggerState", ref _setTriggerState);
+ AssignMethod(delegates, "AddMagazines", ref _addMagazines);
+ AssignMethod(delegates, "SetAmmo", ref _setAmmo);
+ AssignMethod(delegates, "ClosePhantom", ref _closePhantom);
+ AssignMethod(delegates, "SpawnPhantom", ref _spawnPhantom);
+ AssignMethod(delegates, "SetFocusTarget", ref _setPhantomFocusTarget);
+
+ //Hakerman's Beam Logic
+ AssignMethod(delegates, "IsWeaponShootingBase", ref _isWeaponShooting);
+ AssignMethod(delegates, "GetShotsFiredBase", ref _getShotsFired);
+ AssignMethod(delegates, "GetMuzzleInfoBase", ref _getMuzzleInfo);
+ AssignMethod(delegates, "ToggleInfiniteAmmoBase", ref _toggoleInfiniteResources);
+ AssignMethod(delegates, "RegisterEventMonitor", ref _monitorEvents);
+ AssignMethod(delegates, "UnRegisterEventMonitor", ref _unmonitorEvents);
+ AssignMethod(delegates, "GetMagazineMap", ref _getMagazineMap);
+
+ AssignMethod(delegates, "SetMagazine", ref _setMagazine);
+ AssignMethod(delegates, "ForceReload", ref _forceReload);
+
+ // Damage handler
+ AssignMethod(delegates, "DamageHandler", ref _registerDamageEvent);
+
+ if (getWeaponDefinitions)
+ {
+ var byteArrays = new List();
+ GetAllWeaponDefinitions(byteArrays);
+ foreach (var byteArray in byteArrays)
+ WeaponDefinitions.Add(
+ MyAPIGateway.Utilities.SerializeFromBinary(byteArray));
+ }
+ }
+
+ 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()}");
+ }
+
+ internal enum HudMode
+ {
+ Selector,
+ Reload,
+ TargetInfo,
+ Lead,
+ Drone,
+ PainterMarks
+ }
+
+ public class DamageHandlerHelper
+ {
+ public enum EventType
+ {
+ Unregister,
+ SystemWideDamageEvents
+ }
+
+ private readonly List _convertedObjects = new List();
+
+ private readonly Stack> _hitPool =
+ new Stack>(256);
+
+
+ private readonly WcApi _wcApi;
+
+ public DamageHandlerHelper(WcApi wcApi)
+ {
+ _wcApi = wcApi;
+ }
+
+ public void YourCallBackFunction(List list)
+ {
+ // Your code goes here
+ //
+ // Once this function completes the data in the list will be deleted... if you need to use the data in this list
+ // after this function completes make a copy of it.
+ //
+ // This is setup to be easy to use. If you need more performance modify the Default Callback for your purposes and avoid
+ // copying callbacks into new lists with ProjectileDamageEvent structs. Note that the ListReader will remain usable for only 1 tick, then it will be cleared by wc.
+ //
+ }
+
+
+ /// Don't touch anything below this line
+ public void RegisterForDamage(long modId, EventType type)
+ {
+ _wcApi.RegisterDamageEvent(modId, (int)type, DefaultCallBack);
+ }
+
+ private void DefaultCallBack(
+ ListReader>>>
+ listReader)
+ {
+ YourCallBackFunction(ProcessEvents(listReader));
+ CleanUpEvents();
+ }
+
+ private List ProcessEvents(
+ ListReader>>>
+ projectiles)
+ {
+ foreach (var p in projectiles)
+ {
+ var hits = _hitPool.Count > 0 ? _hitPool.Pop() : new List();
+
+ foreach (var hitObj in p.Item6)
+ hits.Add(new ProjectileDamageEvent.ProHit
+ { HitPosition = hitObj.Item1, ObjectHit = hitObj.Item2, Damage = hitObj.Item3 });
+ _convertedObjects.Add(new ProjectileDamageEvent
+ {
+ ProId = p.Item1, PlayerId = p.Item2, WeaponId = p.Item3, WeaponEntity = p.Item4,
+ WeaponParent = p.Item5, ObjectsHit = hits
+ });
+ }
+
+ return _convertedObjects;
+ }
+
+ private void CleanUpEvents()
+ {
+ foreach (var p in _convertedObjects)
+ {
+ p.ObjectsHit.Clear();
+ _hitPool.Push(p.ObjectsHit);
+ }
+
+ _convertedObjects.Clear();
+ }
+
+ public struct ProjectileDamageEvent
+ {
+ public ulong ProId;
+ public long PlayerId;
+ public int WeaponId;
+ public MyEntity WeaponEntity;
+ public MyEntity WeaponParent;
+ public List ObjectsHit;
+
+ public struct ProHit
+ {
+ public Vector3D HitPosition; // To == first hit, From = projectile start position this frame
+ public object ObjectHit; // block, player, etc...
+ public float Damage;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ConfigurableGridPoints/Data/Scripts/ShipPoints/API/CoreSystem/CoreSystemsApiBlocks.cs b/ConfigurableGridPoints/Data/Scripts/ShipPoints/API/CoreSystem/CoreSystemsApiBlocks.cs
new file mode 100644
index 00000000..ba5ddfb7
--- /dev/null
+++ b/ConfigurableGridPoints/Data/Scripts/ShipPoints/API/CoreSystem/CoreSystemsApiBlocks.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using Sandbox.ModAPI;
+
+namespace CGP.ShareTrack.API.CoreSystem
+{
+ ///
+ /// https://github.com/sstixrud/CoreSystems/blob/master/BaseData/Scripts/CoreSystems/Api/CoreSystemsApiBlocks.cs
+ ///
+ public partial class WcApi
+ {
+ private Func, bool> _getBlockWeaponMap;
+
+ public bool GetBlockWeaponMap(IMyTerminalBlock weaponBlock, IDictionary collection)
+ {
+ return _getBlockWeaponMap?.Invoke(weaponBlock, collection) ?? false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ConfigurableGridPoints/Data/Scripts/ShipPoints/API/CoreSystem/CoreSystemsApiDefs.cs b/ConfigurableGridPoints/Data/Scripts/ShipPoints/API/CoreSystem/CoreSystemsApiDefs.cs
new file mode 100644
index 00000000..6aa82bf2
--- /dev/null
+++ b/ConfigurableGridPoints/Data/Scripts/ShipPoints/API/CoreSystem/CoreSystemsApiDefs.cs
@@ -0,0 +1,1541 @@
+using System.Collections.Generic;
+using ProtoBuf;
+using VRageMath;
+
+//using static CoreSystems.Support.WeaponDefinition.AmmoDef.GraphicDef.LineDef;
+//using static CoreSystems.Support.WeaponDefinition.AmmoDef.TrajectoryDef.ApproachDef;
+//using static CoreSystems.Support.WeaponDefinition.AnimationDef.PartAnimationSetDef;
+
+namespace CGP.ShareTrack.API.CoreSystem
+{
+ public static class WcApiDef
+ {
+ [ProtoContract]
+ public class ContainerDefinition
+ {
+ [ProtoMember(2)] internal ArmorDefinition[] ArmorDefs;
+ [ProtoMember(4)] internal SupportDefinition[] SupportDefs;
+ [ProtoMember(3)] internal UpgradeDefinition[] UpgradeDefs;
+ [ProtoMember(1)] internal WeaponDefinition[] WeaponDefs;
+ }
+
+ [ProtoContract]
+ public class ConsumeableDef
+ {
+ [ProtoMember(5)] internal float EnergyCost;
+ [ProtoMember(4)] internal bool Hybrid;
+ [ProtoMember(2)] internal string InventoryItem;
+ [ProtoMember(1)] internal string ItemName;
+ [ProtoMember(3)] internal int ItemsNeeded;
+ [ProtoMember(6)] internal float Strength;
+ }
+
+ [ProtoContract]
+ public class UpgradeDefinition
+ {
+ [ProtoMember(3)] internal WeaponDefinition.AnimationDef Animations;
+ [ProtoMember(1)] internal ModelAssignmentsDef Assignments;
+ [ProtoMember(5)] internal ConsumeableDef[] Consumable;
+ [ProtoMember(2)] internal HardPointDef HardPoint;
+ [ProtoMember(4)] internal string ModPath;
+
+ [ProtoContract]
+ public struct ModelAssignmentsDef
+ {
+ [ProtoMember(1)] internal MountPointDef[] MountPoints;
+
+ [ProtoContract]
+ public struct MountPointDef
+ {
+ [ProtoMember(1)] internal string SubtypeId;
+ [ProtoMember(2)] internal float DurabilityMod;
+ [ProtoMember(3)] internal string IconName;
+ }
+ }
+
+ [ProtoContract]
+ public struct HardPointDef
+ {
+ [ProtoMember(1)] internal string PartName;
+ [ProtoMember(2)] internal HardwareDef HardWare;
+ [ProtoMember(3)] internal UiDef Ui;
+ [ProtoMember(4)] internal OtherDef Other;
+
+ [ProtoContract]
+ public struct UiDef
+ {
+ [ProtoMember(1)] internal bool StrengthModifier;
+ }
+
+ [ProtoContract]
+ public struct HardwareDef
+ {
+ public enum HardwareType
+ {
+ Default
+ }
+
+ [ProtoMember(1)] internal float InventorySize;
+ [ProtoMember(2)] internal HardwareType Type;
+ [ProtoMember(3)] internal int BlockDistance;
+ }
+
+ [ProtoContract]
+ public struct OtherDef
+ {
+ [ProtoMember(1)] internal int ConstructPartCap;
+ [ProtoMember(2)] internal int EnergyPriority;
+ [ProtoMember(3)] internal bool Debug;
+ [ProtoMember(4)] internal double RestrictionRadius;
+ [ProtoMember(5)] internal bool CheckInflatedBox;
+ [ProtoMember(6)] internal bool CheckForAnySupport;
+ [ProtoMember(7)] internal bool StayCharged;
+ }
+ }
+ }
+
+ [ProtoContract]
+ public class SupportDefinition
+ {
+ [ProtoMember(3)] internal WeaponDefinition.AnimationDef Animations;
+ [ProtoMember(1)] internal ModelAssignmentsDef Assignments;
+ [ProtoMember(5)] internal ConsumeableDef[] Consumable;
+ [ProtoMember(6)] internal SupportEffect Effect;
+ [ProtoMember(2)] internal HardPointDef HardPoint;
+ [ProtoMember(4)] internal string ModPath;
+
+ [ProtoContract]
+ public struct ModelAssignmentsDef
+ {
+ [ProtoMember(1)] internal MountPointDef[] MountPoints;
+
+ [ProtoContract]
+ public struct MountPointDef
+ {
+ [ProtoMember(1)] internal string SubtypeId;
+ [ProtoMember(2)] internal float DurabilityMod;
+ [ProtoMember(3)] internal string IconName;
+ }
+ }
+
+ [ProtoContract]
+ public struct HardPointDef
+ {
+ [ProtoMember(1)] internal string PartName;
+ [ProtoMember(2)] internal HardwareDef HardWare;
+ [ProtoMember(3)] internal UiDef Ui;
+ [ProtoMember(4)] internal OtherDef Other;
+
+ [ProtoContract]
+ public struct UiDef
+ {
+ [ProtoMember(1)] internal bool ProtectionControl;
+ }
+
+ [ProtoContract]
+ public struct HardwareDef
+ {
+ [ProtoMember(1)] internal float InventorySize;
+ }
+
+ [ProtoContract]
+ public struct OtherDef
+ {
+ [ProtoMember(1)] internal int ConstructPartCap;
+ [ProtoMember(2)] internal int EnergyPriority;
+ [ProtoMember(3)] internal bool Debug;
+ [ProtoMember(4)] internal double RestrictionRadius;
+ [ProtoMember(5)] internal bool CheckInflatedBox;
+ [ProtoMember(6)] internal bool CheckForAnySupport;
+ [ProtoMember(7)] internal bool StayCharged;
+ }
+ }
+
+ [ProtoContract]
+ public struct SupportEffect
+ {
+ public enum AffectedBlocks
+ {
+ Armor,
+ ArmorPlus,
+ PlusFunctional,
+ All
+ }
+
+ public enum Protections
+ {
+ KineticProt,
+ EnergeticProt,
+ GenericProt,
+ Regenerate,
+ Structural
+ }
+
+ [ProtoMember(1)] internal Protections Protection;
+ [ProtoMember(2)] internal AffectedBlocks Affected;
+ [ProtoMember(3)] internal int BlockRange;
+ [ProtoMember(4)] internal int MaxPoints;
+ [ProtoMember(5)] internal int PointsPerCharge;
+ [ProtoMember(6)] internal int UsablePerSecond;
+ [ProtoMember(7)] internal int UsablePerMinute;
+ [ProtoMember(8)] internal float Overflow;
+ [ProtoMember(9)] internal float Effectiveness;
+ [ProtoMember(10)] internal float ProtectionMin;
+ [ProtoMember(11)] internal float ProtectionMax;
+ }
+ }
+
+ [ProtoContract]
+ public class ArmorDefinition
+ {
+ [ProtoMember(4)] internal double EnergeticResistance;
+ [ProtoMember(2)] internal ArmorType Kind;
+ [ProtoMember(3)] internal double KineticResistance;
+
+ [ProtoMember(1)] internal string[] SubtypeIds;
+
+ internal enum ArmorType
+ {
+ Light,
+ Heavy,
+ NonArmor
+ }
+ }
+
+ [ProtoContract]
+ public class WeaponDefinition
+ {
+ [ProtoMember(5)] internal AmmoDef[] Ammos;
+ [ProtoMember(3)] internal AnimationDef Animations;
+ [ProtoMember(1)] internal ModelAssignmentsDef Assignments;
+ [ProtoMember(4)] internal HardPointDef HardPoint;
+ [ProtoMember(6)] internal string ModPath;
+ [ProtoMember(2)] internal TargetingDef Targeting;
+ [ProtoMember(7)] internal Dictionary Upgrades;
+
+ [ProtoContract]
+ public struct ModelAssignmentsDef
+ {
+ [ProtoMember(1)] internal MountPointDef[] MountPoints;
+ [ProtoMember(2)] internal string[] Muzzles;
+ [ProtoMember(3)] internal string Ejector;
+ [ProtoMember(4)] internal string Scope;
+
+ [ProtoContract]
+ public struct MountPointDef
+ {
+ [ProtoMember(1)] internal string SubtypeId;
+ [ProtoMember(2)] internal string SpinPartId;
+ [ProtoMember(3)] internal string MuzzlePartId;
+ [ProtoMember(4)] internal string AzimuthPartId;
+ [ProtoMember(5)] internal string ElevationPartId;
+ [ProtoMember(6)] internal float DurabilityMod;
+ [ProtoMember(7)] internal string IconName;
+ }
+ }
+
+ [ProtoContract]
+ public struct TargetingDef
+ {
+ public enum Threat
+ {
+ Projectiles,
+ Characters,
+ Grids,
+ Neutrals,
+ Meteors,
+ Other,
+ ScanNeutralGrid,
+ ScanFriendlyGrid,
+ ScanFriendlyCharacter,
+ ScanRoid,
+ ScanPlanet,
+ ScanEnemyCharacter,
+ ScanEnemyGrid,
+ ScanNeutralCharacter,
+ ScanUnOwnedGrid,
+ ScanOwnersGrid
+ }
+
+ public enum BlockTypes
+ {
+ Any,
+ Offense,
+ Utility,
+ Power,
+ Production,
+ Thrust,
+ Jumping,
+ Steering
+ }
+
+ [ProtoMember(1)] internal int TopTargets;
+ [ProtoMember(2)] internal int TopBlocks;
+ [ProtoMember(3)] internal double StopTrackingSpeed;
+ [ProtoMember(4)] internal float MinimumDiameter;
+ [ProtoMember(5)] internal float MaximumDiameter;
+ [ProtoMember(6)] internal bool ClosestFirst;
+ [ProtoMember(7)] internal BlockTypes[] SubSystems;
+ [ProtoMember(8)] internal Threat[] Threats;
+ [ProtoMember(9)] internal float MaxTargetDistance;
+ [ProtoMember(10)] internal float MinTargetDistance;
+ [ProtoMember(11)] internal bool IgnoreDumbProjectiles;
+ [ProtoMember(12)] internal bool LockedSmartOnly;
+ [ProtoMember(13)] internal bool UniqueTargetPerWeapon;
+ [ProtoMember(14)] internal int MaxTrackingTime;
+ [ProtoMember(15)] internal bool ShootBlanks;
+ [ProtoMember(19)] internal CommunicationDef Communications;
+ [ProtoMember(20)] internal bool FocusOnly;
+ [ProtoMember(21)] internal bool EvictUniqueTargets;
+ [ProtoMember(22)] internal int CycleTargets;
+ [ProtoMember(23)] internal int CycleBlocks;
+
+ [ProtoContract]
+ public struct CommunicationDef
+ {
+ public enum Comms
+ {
+ NoComms,
+ BroadCast,
+ Relay,
+ Jamming,
+ RelayAndBroadCast
+ }
+
+ public enum SecurityMode
+ {
+ Public,
+ Private,
+ Secure
+ }
+
+ [ProtoMember(1)] internal bool StoreTargets;
+ [ProtoMember(2)] internal int StorageLimit;
+ [ProtoMember(3)] internal string StorageLocation;
+ [ProtoMember(4)] internal Comms Mode;
+ [ProtoMember(5)] internal SecurityMode Security;
+ [ProtoMember(6)] internal string BroadCastChannel;
+ [ProtoMember(7)] internal double BroadCastRange;
+ [ProtoMember(8)] internal double JammingStrength;
+ [ProtoMember(9)] internal string RelayChannel;
+ [ProtoMember(10)] internal double RelayRange;
+ [ProtoMember(11)] internal bool TargetPersists;
+ [ProtoMember(12)] internal bool StoreLimitPerBlock;
+ [ProtoMember(13)] internal int MaxConnections;
+ }
+ }
+
+
+ [ProtoContract]
+ public struct AnimationDef
+ {
+ [ProtoMember(1)] internal PartAnimationSetDef[] AnimationSets;
+ [ProtoMember(2)] internal PartEmissive[] Emissives;
+ [ProtoMember(3)] internal string[] HeatingEmissiveParts;
+ [ProtoMember(4)] internal Dictionary EventParticles;
+
+ [ProtoContract(IgnoreListHandling = true)]
+ public struct PartAnimationSetDef
+ {
+ public enum EventTriggers
+ {
+ Reloading,
+ Firing,
+ Tracking,
+ Overheated,
+ TurnOn,
+ TurnOff,
+ BurstReload,
+ NoMagsToLoad,
+ PreFire,
+ EmptyOnGameLoad,
+ StopFiring,
+ StopTracking,
+ LockDelay
+ }
+
+ public enum ResetConditions
+ {
+ None,
+ Home,
+ Off,
+ On,
+ Reloaded
+ }
+
+ [ProtoMember(1)] internal string[] SubpartId;
+ [ProtoMember(2)] internal string BarrelId;
+ [ProtoMember(3)] internal uint StartupFireDelay;
+ [ProtoMember(4)] internal Dictionary AnimationDelays;
+ [ProtoMember(5)] internal EventTriggers[] Reverse;
+ [ProtoMember(6)] internal EventTriggers[] Loop;
+ [ProtoMember(7)] internal Dictionary EventMoveSets;
+ [ProtoMember(8)] internal EventTriggers[] TriggerOnce;
+ [ProtoMember(9)] internal EventTriggers[] ResetEmissives;
+ [ProtoMember(10)] internal ResetConditions Resets;
+ }
+
+ [ProtoContract]
+ public struct PartEmissive
+ {
+ [ProtoMember(1)] internal string EmissiveName;
+ [ProtoMember(2)] internal string[] EmissivePartNames;
+ [ProtoMember(3)] internal bool CycleEmissivesParts;
+ [ProtoMember(4)] internal bool LeavePreviousOn;
+ [ProtoMember(5)] internal Vector4[] Colors;
+ [ProtoMember(6)] internal float[] IntensityRange;
+ }
+
+ [ProtoContract]
+ public struct EventParticle
+ {
+ [ProtoMember(1)] internal string[] EmptyNames;
+ [ProtoMember(2)] internal string[] MuzzleNames;
+ [ProtoMember(3)] internal ParticleDef Particle;
+ [ProtoMember(4)] internal uint StartDelay;
+ [ProtoMember(5)] internal uint LoopDelay;
+ [ProtoMember(6)] internal bool ForceStop;
+ }
+
+ [ProtoContract]
+ internal struct RelMove
+ {
+ public enum MoveType
+ {
+ Linear,
+ ExpoDecay,
+ ExpoGrowth,
+ Delay,
+ Show, //instant or fade
+ Hide //instant or fade
+ }
+
+ [ProtoMember(1)] internal MoveType MovementType;
+ [ProtoMember(2)] internal XYZ[] LinearPoints;
+ [ProtoMember(3)] internal XYZ Rotation;
+ [ProtoMember(4)] internal XYZ RotAroundCenter;
+ [ProtoMember(5)] internal uint TicksToMove;
+ [ProtoMember(6)] internal string CenterEmpty;
+ [ProtoMember(7)] internal bool Fade;
+ [ProtoMember(8)] internal string EmissiveName;
+
+ [ProtoContract]
+ internal struct XYZ
+ {
+ [ProtoMember(1)] internal double x;
+ [ProtoMember(2)] internal double y;
+ [ProtoMember(3)] internal double z;
+ }
+ }
+ }
+
+ [ProtoContract]
+ public struct UpgradeValues
+ {
+ [ProtoMember(1)] internal string[] Ammo;
+ [ProtoMember(2)] internal Dependency[] Dependencies;
+ [ProtoMember(3)] internal int RateOfFireMod;
+ [ProtoMember(4)] internal int BarrelsPerShotMod;
+ [ProtoMember(5)] internal int ReloadMod;
+ [ProtoMember(6)] internal int MaxHeatMod;
+ [ProtoMember(7)] internal int HeatSinkRateMod;
+ [ProtoMember(8)] internal int ShotsInBurstMod;
+ [ProtoMember(9)] internal int DelayAfterBurstMod;
+ [ProtoMember(10)] internal int AmmoPriority;
+
+ [ProtoContract]
+ public struct Dependency
+ {
+ internal string SubtypeId;
+ internal int Quanity;
+ }
+ }
+
+ [ProtoContract]
+ public struct HardPointDef
+ {
+ public enum Prediction
+ {
+ Off,
+ Basic,
+ Accurate,
+ Advanced
+ }
+
+ [ProtoMember(1)] internal string PartName;
+ [ProtoMember(2)] internal int DelayCeaseFire;
+ [ProtoMember(3)] internal float DeviateShotAngle;
+ [ProtoMember(4)] internal double AimingTolerance;
+ [ProtoMember(5)] internal Prediction AimLeadingPrediction;
+ [ProtoMember(6)] internal LoadingDef Loading;
+ [ProtoMember(7)] internal AiDef Ai;
+ [ProtoMember(8)] internal HardwareDef HardWare;
+ [ProtoMember(9)] internal UiDef Ui;
+ [ProtoMember(10)] internal HardPointAudioDef Audio;
+ [ProtoMember(11)] internal HardPointParticleDef Graphics;
+ [ProtoMember(12)] internal OtherDef Other;
+ [ProtoMember(13)] internal bool AddToleranceToTracking;
+ [ProtoMember(14)] internal bool CanShootSubmerged;
+ [ProtoMember(15)] internal bool NpcSafe;
+ [ProtoMember(16)] internal bool ScanTrackOnly;
+
+ [ProtoContract]
+ public struct LoadingDef
+ {
+ [ProtoMember(1)] internal int ReloadTime;
+ [ProtoMember(2)] internal int RateOfFire;
+ [ProtoMember(3)] internal int BarrelsPerShot;
+ [ProtoMember(4)] internal int SkipBarrels;
+ [ProtoMember(5)] internal int TrajectilesPerBarrel;
+ [ProtoMember(6)] internal int HeatPerShot;
+ [ProtoMember(7)] internal int MaxHeat;
+ [ProtoMember(8)] internal int HeatSinkRate;
+ [ProtoMember(9)] internal float Cooldown;
+ [ProtoMember(10)] internal int DelayUntilFire;
+ [ProtoMember(11)] internal int ShotsInBurst;
+ [ProtoMember(12)] internal int DelayAfterBurst;
+ [ProtoMember(13)] internal bool DegradeRof;
+ [ProtoMember(14)] internal int BarrelSpinRate;
+ [ProtoMember(15)] internal bool FireFull;
+ [ProtoMember(16)] internal bool GiveUpAfter;
+ [ProtoMember(17)] internal bool DeterministicSpin;
+ [ProtoMember(18)] internal bool SpinFree;
+ [ProtoMember(19)] internal bool StayCharged;
+ [ProtoMember(20)] internal int MagsToLoad;
+ [ProtoMember(21)] internal int MaxActiveProjectiles;
+ [ProtoMember(22)] internal int MaxReloads;
+ [ProtoMember(23)] internal bool GoHomeToReload;
+ [ProtoMember(24)] internal bool DropTargetUntilLoaded;
+ }
+
+
+ [ProtoContract]
+ public struct UiDef
+ {
+ [ProtoMember(1)] internal bool RateOfFire;
+ [ProtoMember(2)] internal bool DamageModifier;
+ [ProtoMember(3)] internal bool ToggleGuidance;
+ [ProtoMember(4)] internal bool EnableOverload;
+ [ProtoMember(5)] internal bool AlternateUi;
+ [ProtoMember(6)] internal bool DisableStatus;
+ }
+
+
+ [ProtoContract]
+ public struct AiDef
+ {
+ [ProtoMember(1)] internal bool TrackTargets;
+ [ProtoMember(2)] internal bool TurretAttached;
+ [ProtoMember(3)] internal bool TurretController;
+ [ProtoMember(4)] internal bool PrimaryTracking;
+ [ProtoMember(5)] internal bool LockOnFocus;
+ [ProtoMember(6)] internal bool SuppressFire;
+ [ProtoMember(7)] internal bool OverrideLeads;
+ [ProtoMember(8)] internal int DefaultLeadGroup;
+ [ProtoMember(9)] internal bool TargetGridCenter;
+ }
+
+ [ProtoContract]
+ public struct HardwareDef
+ {
+ public enum HardwareType
+ {
+ BlockWeapon = 0,
+ HandWeapon = 1,
+ Phantom = 6
+ }
+
+ [ProtoMember(1)] internal float RotateRate;
+ [ProtoMember(2)] internal float ElevateRate;
+ [ProtoMember(3)] internal Vector3D Offset;
+ [ProtoMember(4)] internal bool FixedOffset;
+ [ProtoMember(5)] internal int MaxAzimuth;
+ [ProtoMember(6)] internal int MinAzimuth;
+ [ProtoMember(7)] internal int MaxElevation;
+ [ProtoMember(8)] internal int MinElevation;
+ [ProtoMember(9)] internal float InventorySize;
+ [ProtoMember(10)] internal HardwareType Type;
+ [ProtoMember(11)] internal int HomeAzimuth;
+ [ProtoMember(12)] internal int HomeElevation;
+ [ProtoMember(13)] internal CriticalDef CriticalReaction;
+ [ProtoMember(14)] internal float IdlePower;
+
+ [ProtoContract]
+ public struct CriticalDef
+ {
+ [ProtoMember(1)] internal bool Enable;
+ [ProtoMember(2)] internal int DefaultArmedTimer;
+ [ProtoMember(3)] internal bool PreArmed;
+ [ProtoMember(4)] internal bool TerminalControls;
+ [ProtoMember(5)] internal string AmmoRound;
+ }
+ }
+
+ [ProtoContract]
+ public struct HardPointAudioDef
+ {
+ [ProtoMember(1)] internal string ReloadSound;
+ [ProtoMember(2)] internal string NoAmmoSound;
+ [ProtoMember(3)] internal string HardPointRotationSound;
+ [ProtoMember(4)] internal string BarrelRotationSound;
+ [ProtoMember(5)] internal string FiringSound;
+ [ProtoMember(6)] internal bool FiringSoundPerShot;
+ [ProtoMember(7)] internal string PreFiringSound;
+ [ProtoMember(8)] internal uint FireSoundEndDelay;
+ [ProtoMember(9)] internal bool FireSoundNoBurst;
+ }
+
+ [ProtoContract]
+ public struct OtherDef
+ {
+ [ProtoMember(1)] internal int ConstructPartCap;
+ [ProtoMember(2)] internal int EnergyPriority;
+ [ProtoMember(3)] internal int RotateBarrelAxis;
+ [ProtoMember(4)] internal bool MuzzleCheck;
+ [ProtoMember(5)] internal bool Debug;
+ [ProtoMember(6)] internal double RestrictionRadius;
+ [ProtoMember(7)] internal bool CheckInflatedBox;
+ [ProtoMember(8)] internal bool CheckForAnyWeapon;
+ [ProtoMember(9)] internal bool DisableLosCheck;
+ [ProtoMember(10)] internal bool NoVoxelLosCheck;
+ }
+
+ [ProtoContract]
+ public struct HardPointParticleDef
+ {
+ [ProtoMember(1)] internal ParticleDef Effect1;
+ [ProtoMember(2)] internal ParticleDef Effect2;
+ }
+ }
+
+ [ProtoContract]
+ public class AmmoDef
+ {
+ [ProtoMember(17)] internal AmmoAudioDef AmmoAudio;
+ [ProtoMember(16)] internal GraphicDef AmmoGraphics;
+ [ProtoMember(1)] internal string AmmoMagazine;
+ [ProtoMember(2)] internal string AmmoRound;
+ [ProtoMember(13)] internal AreaDamageDef AreaEffect;
+ [ProtoMember(24)] internal AreaOfDamageDef AreaOfDamage;
+ [ProtoMember(8)] internal float BackKickForce;
+ [ProtoMember(5)] internal float BaseDamage;
+ [ProtoMember(14)] internal BeamDef Beams;
+ [ProtoMember(9)] internal DamageScaleDef DamageScales;
+ [ProtoMember(21)] internal float DecayPerShot;
+ [ProtoMember(22)] internal EjectionDef Ejection;
+ [ProtoMember(4)] internal float EnergyCost;
+ [ProtoMember(20)] internal int EnergyMagazineSize;
+ [ProtoMember(25)] internal EwarDef Ewar;
+ [ProtoMember(15)] internal FragmentDef Fragment;
+ [ProtoMember(18)] internal bool HardPointUsable;
+ [ProtoMember(7)] internal float Health;
+ [ProtoMember(28)] internal double HeatModifier;
+ [ProtoMember(3)] internal bool HybridRound;
+ [ProtoMember(26)] internal bool IgnoreVoxels;
+ [ProtoMember(23)] internal bool IgnoreWater;
+ [ProtoMember(6)] internal float Mass;
+ [ProtoMember(31)] internal bool NoGridOrArmorScaling;
+ [ProtoMember(29)] internal bool NpcSafe;
+ [ProtoMember(11)] internal ObjectsHitDef ObjectsHit;
+ [ProtoMember(19)] internal PatternDef Pattern;
+ [ProtoMember(10)] internal ShapeDef Shape;
+ [ProtoMember(30)] internal SynchronizeDef Sync;
+ [ProtoMember(27)] internal bool Synchronize;
+ [ProtoMember(12)] internal TrajectoryDef Trajectory;
+
+ [ProtoContract]
+ public struct SynchronizeDef
+ {
+ [ProtoMember(1)] internal bool Full;
+ [ProtoMember(2)] internal bool PointDefense;
+ [ProtoMember(3)] internal bool OnHitDeath;
+ }
+
+ [ProtoContract]
+ public struct DamageScaleDef
+ {
+ [ProtoMember(1)] internal float MaxIntegrity;
+ [ProtoMember(2)] internal bool DamageVoxels;
+ [ProtoMember(3)] internal float Characters;
+ [ProtoMember(4)] internal bool SelfDamage;
+ [ProtoMember(5)] internal GridSizeDef Grids;
+ [ProtoMember(6)] internal ArmorDef Armor;
+ [ProtoMember(7)] internal CustomScalesDef Custom;
+ [ProtoMember(8)] internal ShieldDef Shields;
+ [ProtoMember(9)] internal FallOffDef FallOff;
+ [ProtoMember(10)] internal double HealthHitModifier;
+ [ProtoMember(11)] internal double VoxelHitModifier;
+ [ProtoMember(12)] internal DamageTypes DamageType;
+ [ProtoMember(13)] internal DeformDef Deform;
+
+ [ProtoContract]
+ public struct FallOffDef
+ {
+ [ProtoMember(1)] internal float Distance;
+ [ProtoMember(2)] internal float MinMultipler;
+ }
+
+ [ProtoContract]
+ public struct GridSizeDef
+ {
+ [ProtoMember(1)] internal float Large;
+ [ProtoMember(2)] internal float Small;
+ }
+
+ [ProtoContract]
+ public struct ArmorDef
+ {
+ [ProtoMember(1)] internal float Armor;
+ [ProtoMember(2)] internal float Heavy;
+ [ProtoMember(3)] internal float Light;
+ [ProtoMember(4)] internal float NonArmor;
+ }
+
+ [ProtoContract]
+ public struct CustomScalesDef
+ {
+ internal enum SkipMode
+ {
+ NoSkip,
+ Inclusive,
+ Exclusive
+ }
+
+ [ProtoMember(1)] internal CustomBlocksDef[] Types;
+ [ProtoMember(2)] internal bool IgnoreAllOthers;
+ [ProtoMember(3)] internal SkipMode SkipOthers;
+ }
+
+ [ProtoContract]
+ public struct DamageTypes
+ {
+ internal enum Damage
+ {
+ Energy,
+ Kinetic
+ }
+
+ [ProtoMember(1)] internal Damage Base;
+ [ProtoMember(2)] internal Damage AreaEffect;
+ [ProtoMember(3)] internal Damage Detonation;
+ [ProtoMember(4)] internal Damage Shield;
+ }
+
+ [ProtoContract]
+ public struct ShieldDef
+ {
+ internal enum ShieldType
+ {
+ Default,
+ Heal,
+ Bypass,
+ EmpRetired
+ }
+
+ [ProtoMember(1)] internal float Modifier;
+ [ProtoMember(2)] internal ShieldType Type;
+ [ProtoMember(3)] internal float BypassModifier;
+ }
+
+ [ProtoContract]
+ public struct DeformDef
+ {
+ internal enum DeformTypes
+ {
+ HitBlock,
+ AllDamagedBlocks,
+ NoDeform
+ }
+
+ [ProtoMember(1)] internal DeformTypes DeformType;
+ [ProtoMember(2)] internal int DeformDelay;
+ }
+ }
+
+ [ProtoContract]
+ public struct ShapeDef
+ {
+ public enum Shapes
+ {
+ LineShape,
+ SphereShape
+ }
+
+ [ProtoMember(1)] internal Shapes Shape;
+ [ProtoMember(2)] internal double Diameter;
+ }
+
+ [ProtoContract]
+ public struct ObjectsHitDef
+ {
+ [ProtoMember(1)] internal int MaxObjectsHit;
+ [ProtoMember(2)] internal bool CountBlocks;
+ }
+
+
+ [ProtoContract]
+ public struct CustomBlocksDef
+ {
+ [ProtoMember(1)] internal string SubTypeId;
+ [ProtoMember(2)] internal float Modifier;
+ }
+
+ [ProtoContract]
+ public struct GraphicDef
+ {
+ [ProtoMember(1)] internal bool ShieldHitDraw;
+ [ProtoMember(2)] internal float VisualProbability;
+ [ProtoMember(3)] internal string ModelName;
+ [ProtoMember(4)] internal AmmoParticleDef Particles;
+ [ProtoMember(5)] internal LineDef Lines;
+ [ProtoMember(6)] internal DecalDef Decals;
+
+ [ProtoContract]
+ public struct AmmoParticleDef
+ {
+ [ProtoMember(1)] internal ParticleDef Ammo;
+ [ProtoMember(2)] internal ParticleDef Hit;
+ [ProtoMember(3)] internal ParticleDef Eject;
+ }
+
+ [ProtoContract]
+ public struct LineDef
+ {
+ internal enum Texture
+ {
+ Normal,
+ Cycle,
+ Chaos,
+ Wave
+ }
+
+ public enum FactionColor
+ {
+ DontUse,
+ Foreground,
+ Background
+ }
+
+ [ProtoMember(1)] internal TracerBaseDef Tracer;
+ [ProtoMember(2)] internal string TracerMaterial;
+ [ProtoMember(3)] internal Randomize ColorVariance;
+ [ProtoMember(4)] internal Randomize WidthVariance;
+ [ProtoMember(5)] internal TrailDef Trail;
+ [ProtoMember(6)] internal OffsetEffectDef OffsetEffect;
+ [ProtoMember(7)] internal bool DropParentVelocity;
+
+ [ProtoContract]
+ public struct OffsetEffectDef
+ {
+ [ProtoMember(1)] internal double MaxOffset;
+ [ProtoMember(2)] internal double MinLength;
+ [ProtoMember(3)] internal double MaxLength;
+ }
+
+ [ProtoContract]
+ public struct TracerBaseDef
+ {
+ [ProtoMember(1)] internal bool Enable;
+ [ProtoMember(2)] internal float Length;
+ [ProtoMember(3)] internal float Width;
+ [ProtoMember(4)] internal Vector4 Color;
+ [ProtoMember(5)] internal uint VisualFadeStart;
+ [ProtoMember(6)] internal uint VisualFadeEnd;
+ [ProtoMember(7)] internal SegmentDef Segmentation;
+ [ProtoMember(8)] internal string[] Textures;
+ [ProtoMember(9)] internal Texture TextureMode;
+ [ProtoMember(10)] internal bool AlwaysDraw;
+ [ProtoMember(11)] internal FactionColor FactionColor;
+
+ [ProtoContract]
+ public struct SegmentDef
+ {
+ [ProtoMember(1)] internal string Material; //retired
+ [ProtoMember(2)] internal double SegmentLength;
+ [ProtoMember(3)] internal double SegmentGap;
+ [ProtoMember(4)] internal double Speed;
+ [ProtoMember(5)] internal Vector4 Color;
+ [ProtoMember(6)] internal double WidthMultiplier;
+ [ProtoMember(7)] internal bool Reverse;
+ [ProtoMember(8)] internal bool UseLineVariance;
+ [ProtoMember(9)] internal Randomize ColorVariance;
+ [ProtoMember(10)] internal Randomize WidthVariance;
+ [ProtoMember(11)] internal string[] Textures;
+ [ProtoMember(12)] internal bool Enable;
+ [ProtoMember(13)] internal FactionColor FactionColor;
+ }
+ }
+
+ [ProtoContract]
+ public struct TrailDef
+ {
+ [ProtoMember(1)] internal bool Enable;
+ [ProtoMember(2)] internal string Material;
+ [ProtoMember(3)] internal int DecayTime;
+ [ProtoMember(4)] internal Vector4 Color;
+ [ProtoMember(5)] internal bool Back;
+ [ProtoMember(6)] internal float CustomWidth;
+ [ProtoMember(7)] internal bool UseWidthVariance;
+ [ProtoMember(8)] internal bool UseColorFade;
+ [ProtoMember(9)] internal string[] Textures;
+ [ProtoMember(10)] internal Texture TextureMode;
+ [ProtoMember(11)] internal bool AlwaysDraw;
+ [ProtoMember(12)] internal FactionColor FactionColor;
+ }
+ }
+
+ [ProtoContract]
+ public struct DecalDef
+ {
+ [ProtoMember(1)] internal int MaxAge;
+ [ProtoMember(2)] internal TextureMapDef[] Map;
+
+ [ProtoContract]
+ public struct TextureMapDef
+ {
+ [ProtoMember(1)] internal string HitMaterial;
+ [ProtoMember(2)] internal string DecalMaterial;
+ }
+ }
+ }
+
+ [ProtoContract]
+ public struct BeamDef
+ {
+ [ProtoMember(1)] internal bool Enable;
+ [ProtoMember(2)] internal bool ConvergeBeams;
+ [ProtoMember(3)] internal bool VirtualBeams;
+ [ProtoMember(4)] internal bool RotateRealBeam;
+ [ProtoMember(5)] internal bool OneParticle;
+ [ProtoMember(6)] internal bool FakeVoxelHits;
+ }
+
+ [ProtoContract]
+ public struct FragmentDef
+ {
+ [ProtoMember(1)] internal string AmmoRound;
+ [ProtoMember(2)] internal int Fragments;
+ [ProtoMember(3)] internal float Radial;
+ [ProtoMember(4)] internal float BackwardDegrees;
+ [ProtoMember(5)] internal float Degrees;
+ [ProtoMember(6)] internal bool Reverse;
+ [ProtoMember(7)] internal bool IgnoreArming;
+ [ProtoMember(8)] internal bool DropVelocity;
+ [ProtoMember(9)] internal float Offset;
+ [ProtoMember(10)] internal int MaxChildren;
+ [ProtoMember(11)] internal TimedSpawnDef TimedSpawns;
+ [ProtoMember(12)] internal bool FireSound;
+ [ProtoMember(13)] internal Vector3D AdvOffset;
+ [ProtoMember(14)] internal bool ArmWhenHit;
+
+ [ProtoContract]
+ public struct TimedSpawnDef
+ {
+ public enum PointTypes
+ {
+ Direct,
+ Lead,
+ Predict
+ }
+
+ [ProtoMember(1)] internal bool Enable;
+ [ProtoMember(2)] internal int Interval;
+ [ProtoMember(3)] internal int StartTime;
+ [ProtoMember(4)] internal int MaxSpawns;
+ [ProtoMember(5)] internal double Proximity;
+ [ProtoMember(6)] internal bool ParentDies;
+ [ProtoMember(7)] internal bool PointAtTarget;
+ [ProtoMember(8)] internal int GroupSize;
+ [ProtoMember(9)] internal int GroupDelay;
+ [ProtoMember(10)] internal PointTypes PointType;
+ }
+ }
+
+ [ProtoContract]
+ public struct PatternDef
+ {
+ public enum PatternModes
+ {
+ Never,
+ Weapon,
+ Fragment,
+ Both
+ }
+
+
+ [ProtoMember(1)] internal string[] Patterns;
+ [ProtoMember(2)] internal bool Enable;
+ [ProtoMember(3)] internal float TriggerChance;
+ [ProtoMember(4)] internal bool SkipParent;
+ [ProtoMember(5)] internal bool Random;
+ [ProtoMember(6)] internal int RandomMin;
+ [ProtoMember(7)] internal int RandomMax;
+ [ProtoMember(8)] internal int PatternSteps;
+ [ProtoMember(9)] internal PatternModes Mode;
+ }
+
+ [ProtoContract]
+ public struct EjectionDef
+ {
+ public enum SpawnType
+ {
+ Item,
+ Particle
+ }
+
+ [ProtoMember(1)] internal float Speed;
+ [ProtoMember(2)] internal float SpawnChance;
+ [ProtoMember(3)] internal SpawnType Type;
+ [ProtoMember(4)] internal ComponentDef CompDef;
+
+ [ProtoContract]
+ public struct ComponentDef
+ {
+ [ProtoMember(1)] internal string ItemName;
+ [ProtoMember(2)] internal int ItemLifeTime;
+ [ProtoMember(3)] internal int Delay;
+ }
+ }
+
+ [ProtoContract]
+ public struct AreaOfDamageDef
+ {
+ public enum Falloff
+ {
+ Legacy,
+ NoFalloff,
+ Linear,
+ Curve,
+ InvCurve,
+ Squeeze,
+ Pooled,
+ Exponential
+ }
+
+ public enum AoeShape
+ {
+ Round,
+ Diamond
+ }
+
+ [ProtoMember(1)] internal ByBlockHitDef ByBlockHit;
+ [ProtoMember(2)] internal EndOfLifeDef EndOfLife;
+
+ [ProtoContract]
+ public struct ByBlockHitDef
+ {
+ [ProtoMember(1)] internal bool Enable;
+ [ProtoMember(2)] internal double Radius;
+ [ProtoMember(3)] internal float Damage;
+ [ProtoMember(4)] internal float Depth;
+ [ProtoMember(5)] internal float MaxAbsorb;
+ [ProtoMember(6)] internal Falloff Falloff;
+ [ProtoMember(7)] internal AoeShape Shape;
+ }
+
+ [ProtoContract]
+ public struct EndOfLifeDef
+ {
+ [ProtoMember(1)] internal bool Enable;
+ [ProtoMember(2)] internal double Radius;
+ [ProtoMember(3)] internal float Damage;
+ [ProtoMember(4)] internal float Depth;
+ [ProtoMember(5)] internal float MaxAbsorb;
+ [ProtoMember(6)] internal Falloff Falloff;
+ [ProtoMember(7)] internal bool ArmOnlyOnHit;
+ [ProtoMember(8)] internal int MinArmingTime;
+ [ProtoMember(9)] internal bool NoVisuals;
+ [ProtoMember(10)] internal bool NoSound;
+ [ProtoMember(11)] internal float ParticleScale;
+ [ProtoMember(12)] internal string CustomParticle;
+ [ProtoMember(13)] internal string CustomSound;
+ [ProtoMember(14)] internal AoeShape Shape;
+ }
+ }
+
+ [ProtoContract]
+ public struct EwarDef
+ {
+ public enum EwarType
+ {
+ AntiSmart,
+ JumpNull,
+ EnergySink,
+ Anchor,
+ Emp,
+ Offense,
+ Nav,
+ Dot,
+ Push,
+ Pull,
+ Tractor
+ }
+
+ public enum EwarMode
+ {
+ Effect,
+ Field
+ }
+
+ [ProtoMember(1)] internal bool Enable;
+ [ProtoMember(2)] internal EwarType Type;
+ [ProtoMember(3)] internal EwarMode Mode;
+ [ProtoMember(4)] internal float Strength;
+ [ProtoMember(5)] internal double Radius;
+ [ProtoMember(6)] internal int Duration;
+ [ProtoMember(7)] internal bool StackDuration;
+ [ProtoMember(8)] internal bool Depletable;
+ [ProtoMember(9)] internal int MaxStacks;
+ [ProtoMember(10)] internal bool NoHitParticle;
+ [ProtoMember(11)] internal PushPullDef Force;
+ [ProtoMember(12)] internal FieldDef Field;
+
+
+ [ProtoContract]
+ public struct FieldDef
+ {
+ [ProtoMember(1)] internal int Interval;
+ [ProtoMember(2)] internal int PulseChance;
+ [ProtoMember(3)] internal int GrowTime;
+ [ProtoMember(4)] internal bool HideModel;
+ [ProtoMember(5)] internal bool ShowParticle;
+ [ProtoMember(6)] internal double TriggerRange;
+ [ProtoMember(7)] internal ParticleDef Particle;
+ }
+
+ [ProtoContract]
+ public struct PushPullDef
+ {
+ public enum Force
+ {
+ ProjectileLastPosition,
+ ProjectileOrigin,
+ HitPosition,
+ TargetCenter,
+ TargetCenterOfMass
+ }
+
+ [ProtoMember(1)] internal Force ForceFrom;
+ [ProtoMember(2)] internal Force ForceTo;
+ [ProtoMember(3)] internal Force Position;
+ [ProtoMember(4)] internal bool DisableRelativeMass;
+ [ProtoMember(5)] internal double TractorRange;
+ [ProtoMember(6)] internal bool ShooterFeelsForce;
+ }
+ }
+
+
+ [ProtoContract]
+ public struct AreaDamageDef
+ {
+ public enum AreaEffectType
+ {
+ Disabled,
+ Explosive,
+ Radiant,
+ AntiSmart,
+ JumpNullField,
+ EnergySinkField,
+ AnchorField,
+ EmpField,
+ OffenseField,
+ NavField,
+ DotField,
+ PushField,
+ PullField,
+ TractorField
+ }
+
+ [ProtoMember(1)] internal double AreaEffectRadius;
+ [ProtoMember(2)] internal float AreaEffectDamage;
+ [ProtoMember(3)] internal AreaEffectType AreaEffect;
+ [ProtoMember(4)] internal PulseDef Pulse;
+ [ProtoMember(5)] internal DetonateDef Detonation;
+ [ProtoMember(6)] internal ExplosionDef Explosions;
+ [ProtoMember(7)] internal EwarFieldsDef EwarFields;
+ [ProtoMember(8)] internal AreaInfluence Base;
+
+ [ProtoContract]
+ public struct AreaInfluence
+ {
+ [ProtoMember(1)] internal double Radius;
+ [ProtoMember(2)] internal float EffectStrength;
+ }
+
+
+ [ProtoContract]
+ public struct PulseDef
+ {
+ [ProtoMember(1)] internal int Interval;
+ [ProtoMember(2)] internal int PulseChance;
+ [ProtoMember(3)] internal int GrowTime;
+ [ProtoMember(4)] internal bool HideModel;
+ [ProtoMember(5)] internal bool ShowParticle;
+ [ProtoMember(6)] internal ParticleDef Particle;
+ }
+
+ [ProtoContract]
+ public struct EwarFieldsDef
+ {
+ [ProtoMember(1)] internal int Duration;
+ [ProtoMember(2)] internal bool StackDuration;
+ [ProtoMember(3)] internal bool Depletable;
+ [ProtoMember(4)] internal double TriggerRange;
+ [ProtoMember(5)] internal int MaxStacks;
+ [ProtoMember(6)] internal PushPullDef Force;
+ [ProtoMember(7)] internal bool DisableParticleEffect;
+
+ [ProtoContract]
+ public struct PushPullDef
+ {
+ public enum Force
+ {
+ ProjectileLastPosition,
+ ProjectileOrigin,
+ HitPosition,
+ TargetCenter,
+ TargetCenterOfMass
+ }
+
+ [ProtoMember(1)] internal Force ForceFrom;
+ [ProtoMember(2)] internal Force ForceTo;
+ [ProtoMember(3)] internal Force Position;
+ [ProtoMember(4)] internal bool DisableRelativeMass;
+ [ProtoMember(5)] internal double TractorRange;
+ [ProtoMember(6)] internal bool ShooterFeelsForce;
+ }
+ }
+
+ [ProtoContract]
+ public struct DetonateDef
+ {
+ [ProtoMember(1)] internal bool DetonateOnEnd;
+ [ProtoMember(2)] internal bool ArmOnlyOnHit;
+ [ProtoMember(3)] internal float DetonationRadius;
+ [ProtoMember(4)] internal float DetonationDamage;
+ [ProtoMember(5)] internal int MinArmingTime;
+ }
+
+ [ProtoContract]
+ public struct ExplosionDef
+ {
+ [ProtoMember(1)] internal bool NoVisuals;
+ [ProtoMember(2)] internal bool NoSound;
+ [ProtoMember(3)] internal float Scale;
+ [ProtoMember(4)] internal string CustomParticle;
+ [ProtoMember(5)] internal string CustomSound;
+ [ProtoMember(6)] internal bool NoShrapnel;
+ [ProtoMember(7)] internal bool NoDeformation;
+ }
+ }
+
+ [ProtoContract]
+ public struct AmmoAudioDef
+ {
+ [ProtoMember(1)] internal string TravelSound;
+ [ProtoMember(2)] internal string HitSound;
+ [ProtoMember(3)] internal float HitPlayChance;
+ [ProtoMember(4)] internal bool HitPlayShield;
+ [ProtoMember(5)] internal string VoxelHitSound;
+ [ProtoMember(6)] internal string PlayerHitSound;
+ [ProtoMember(7)] internal string FloatingHitSound;
+ [ProtoMember(8)] internal string ShieldHitSound;
+ [ProtoMember(9)] internal string ShotSound;
+ }
+
+ [ProtoContract]
+ public struct TrajectoryDef
+ {
+ internal enum GuidanceType
+ {
+ None,
+ Remote,
+ TravelTo,
+ Smart,
+ DetectTravelTo,
+ DetectSmart,
+ DetectFixed,
+ DroneAdvanced
+ }
+
+ [ProtoMember(1)] internal float MaxTrajectory;
+ [ProtoMember(2)] internal float AccelPerSec;
+ [ProtoMember(3)] internal float DesiredSpeed;
+ [ProtoMember(4)] internal float TargetLossDegree;
+ [ProtoMember(5)] internal int TargetLossTime;
+ [ProtoMember(6)] internal int MaxLifeTime;
+ [ProtoMember(7)] internal int DeaccelTime;
+ [ProtoMember(8)] internal Randomize SpeedVariance;
+ [ProtoMember(9)] internal Randomize RangeVariance;
+ [ProtoMember(10)] internal GuidanceType Guidance;
+ [ProtoMember(11)] internal SmartsDef Smarts;
+ [ProtoMember(12)] internal MinesDef Mines;
+ [ProtoMember(13)] internal float GravityMultiplier;
+ [ProtoMember(14)] internal uint MaxTrajectoryTime;
+ [ProtoMember(15)] internal ApproachDef[] Approaches;
+ [ProtoMember(16)] internal double TotalAcceleration;
+
+ [ProtoContract]
+ public struct SmartsDef
+ {
+ [ProtoMember(1)] internal double Inaccuracy;
+ [ProtoMember(2)] internal double Aggressiveness;
+ [ProtoMember(3)] internal double MaxLateralThrust;
+ [ProtoMember(4)] internal double TrackingDelay;
+ [ProtoMember(5)] internal int MaxChaseTime;
+ [ProtoMember(6)] internal bool OverideTarget;
+ [ProtoMember(7)] internal int MaxTargets;
+ [ProtoMember(8)] internal bool NoTargetExpire;
+ [ProtoMember(9)] internal bool Roam;
+ [ProtoMember(10)] internal bool KeepAliveAfterTargetLoss;
+ [ProtoMember(11)] internal float OffsetRatio;
+ [ProtoMember(12)] internal int OffsetTime;
+ [ProtoMember(13)] internal bool CheckFutureIntersection;
+ [ProtoMember(14)] internal double NavAcceleration;
+ [ProtoMember(15)] internal bool AccelClearance;
+ [ProtoMember(16)] internal double SteeringLimit;
+ [ProtoMember(17)] internal bool FocusOnly;
+ [ProtoMember(18)] internal double OffsetMinRange;
+ [ProtoMember(19)] internal bool FocusEviction;
+ [ProtoMember(20)] internal double ScanRange;
+ [ProtoMember(21)] internal bool NoSteering;
+ [ProtoMember(22)] internal double FutureIntersectionRange;
+ [ProtoMember(23)] internal double MinTurnSpeed;
+ [ProtoMember(24)] internal bool NoTargetApproach;
+ [ProtoMember(25)] internal bool AltNavigation;
+ }
+
+ [ProtoContract]
+ public struct ApproachDef
+ {
+ public enum ReInitCondition
+ {
+ Wait,
+ MoveToPrevious,
+ MoveToNext,
+ ForceRestart
+ }
+
+ public enum Conditions
+ {
+ Ignore,
+ Spawn,
+ DistanceFromPositionC,
+ Lifetime,
+ DesiredElevation,
+ MinTravelRequired,
+ MaxTravelRequired,
+ Deadtime,
+ DistanceToPositionC,
+ NextTimedSpawn,
+ RelativeLifetime,
+ RelativeDeadtime,
+ SinceTimedSpawn,
+ RelativeSpawns,
+ EnemyTargetLoss,
+ RelativeHealthLost,
+ HealthRemaining,
+ DistanceFromPositionB,
+ DistanceToPositionB,
+ DistanceFromTarget,
+ DistanceToTarget,
+ DistanceFromEndTrajectory,
+ DistanceToEndTrajectory
+ }
+
+ public enum UpRelativeTo
+ {
+ UpRelativeToBlock,
+ UpRelativeToGravity,
+ UpTargetDirection,
+ UpTargetVelocity,
+ UpStoredStartDontUse,
+ UpStoredEndDontUse,
+ UpStoredStartPosition,
+ UpStoredEndPosition,
+ UpStoredStartLocalPosition,
+ UpStoredEndLocalPosition,
+ UpRelativeToShooter,
+ UpOriginDirection,
+ UpElevationDirection
+ }
+
+ public enum FwdRelativeTo
+ {
+ ForwardElevationDirection,
+ ForwardRelativeToBlock,
+ ForwardRelativeToGravity,
+ ForwardTargetDirection,
+ ForwardTargetVelocity,
+ ForwardStoredStartDontUse,
+ ForwardStoredEndDontUse,
+ ForwardStoredStartPosition,
+ ForwardStoredEndPosition,
+ ForwardStoredStartLocalPosition,
+ ForwardStoredEndLocalPosition,
+ ForwardRelativeToShooter,
+ ForwardOriginDirection
+ }
+
+ public enum RelativeTo
+ {
+ Origin,
+ Shooter,
+ Target,
+ Surface,
+ MidPoint,
+ PositionA,
+ Nothing,
+ StoredStartDontUse,
+ StoredEndDontUse,
+ StoredStartPosition,
+ StoredEndPosition,
+ StoredStartLocalPosition,
+ StoredEndLocalPosition
+ }
+
+ public enum ConditionOperators
+ {
+ StartEnd_And,
+ StartEnd_Or,
+ StartAnd_EndOr,
+ StartOr_EndAnd
+ }
+
+ public enum StageEvents
+ {
+ DoNothing,
+ EndProjectile,
+ EndProjectileOnRestart,
+ StoreDontUse,
+ StorePositionDontUse,
+ Refund,
+ StorePositionA,
+ StorePositionB,
+ StorePositionC
+ }
+
+ [ProtoContract]
+ public struct WeightedIdListDef
+ {
+ [ProtoMember(1)] public int ApproachId;
+ [ProtoMember(2)] public Randomize Weight;
+ [ProtoMember(3)] public double End1WeightMod;
+ [ProtoMember(4)] public double End2WeightMod;
+ [ProtoMember(5)] public int MaxRuns;
+ [ProtoMember(6)] public double End3WeightMod;
+ }
+
+ [ProtoMember(1)] internal ReInitCondition RestartCondition;
+ [ProtoMember(2)] internal Conditions StartCondition1;
+ [ProtoMember(3)] internal Conditions EndCondition1;
+ [ProtoMember(4)] internal UpRelativeTo Up;
+ [ProtoMember(5)] internal RelativeTo PositionB;
+ [ProtoMember(6)] internal double AngleOffset;
+ [ProtoMember(7)] internal double Start1Value;
+ [ProtoMember(8)] internal double End1Value;
+ [ProtoMember(9)] internal double LeadDistance;
+ [ProtoMember(10)] internal double DesiredElevation;
+ [ProtoMember(11)] internal double AccelMulti;
+ [ProtoMember(12)] internal double SpeedCapMulti;
+ [ProtoMember(13)] internal bool AdjustPositionC;
+ [ProtoMember(14)] internal bool CanExpireOnceStarted;
+ [ProtoMember(15)] internal ParticleDef AlternateParticle;
+ [ProtoMember(16)] internal string AlternateSound;
+ [ProtoMember(17)] internal string AlternateModel;
+ [ProtoMember(18)] internal int OnRestartRevertTo;
+ [ProtoMember(19)] internal ParticleDef StartParticle;
+ [ProtoMember(20)] internal bool AdjustPositionB;
+ [ProtoMember(21)] internal bool AdjustUp;
+ [ProtoMember(22)] internal bool PushLeadByTravelDistance;
+ [ProtoMember(23)] internal double TrackingDistance;
+ [ProtoMember(24)] internal Conditions StartCondition2;
+ [ProtoMember(25)] internal double Start2Value;
+ [ProtoMember(26)] internal Conditions EndCondition2;
+ [ProtoMember(27)] internal double End2Value;
+ [ProtoMember(28)] internal RelativeTo Elevation;
+ [ProtoMember(29)] internal double ElevationTolerance;
+ [ProtoMember(30)] internal ConditionOperators Operators;
+ [ProtoMember(31)] internal StageEvents StartEvent;
+ [ProtoMember(32)] internal StageEvents EndEvent;
+ [ProtoMember(33)] internal double TotalAccelMulti;
+ [ProtoMember(34)] internal double DeAccelMulti;
+ [ProtoMember(35)] internal bool Orbit;
+ [ProtoMember(36)] internal double OrbitRadius;
+ [ProtoMember(37)] internal int OffsetTime;
+ [ProtoMember(38)] internal double OffsetMinRadius;
+ [ProtoMember(39)] internal bool NoTimedSpawns;
+ [ProtoMember(40)] internal double OffsetMaxRadius;
+ [ProtoMember(41)] internal bool ForceRestart;
+ [ProtoMember(42)] internal RelativeTo PositionC;
+ [ProtoMember(43)] internal bool DisableAvoidance;
+ [ProtoMember(44)] internal int StoredStartId;
+ [ProtoMember(45)] internal int StoredEndId;
+ [ProtoMember(46)] internal WeightedIdListDef[] RestartList;
+ [ProtoMember(47)] internal RelativeTo StoredStartType;
+ [ProtoMember(48)] internal RelativeTo StoredEndType;
+ [ProtoMember(49)] internal bool LeadRotateElevatePositionB;
+ [ProtoMember(50)] internal bool LeadRotateElevatePositionC;
+ [ProtoMember(51)] internal bool NoElevationLead;
+ [ProtoMember(52)] internal bool IgnoreAntiSmart;
+ [ProtoMember(53)] internal double HeatRefund;
+ [ProtoMember(54)] internal Randomize AngleVariance;
+ [ProtoMember(55)] internal bool ReloadRefund;
+ [ProtoMember(56)] internal int ModelRotateTime;
+ [ProtoMember(57)] internal FwdRelativeTo Forward;
+ [ProtoMember(58)] internal bool AdjustForward;
+ [ProtoMember(59)] internal bool ToggleIngoreVoxels;
+ [ProtoMember(60)] internal bool SelfAvoidance;
+ [ProtoMember(61)] internal bool TargetAvoidance;
+ [ProtoMember(62)] internal bool SelfPhasing;
+ [ProtoMember(63)] internal bool TrajectoryRelativeToB;
+ [ProtoMember(64)] internal Conditions EndCondition3;
+ [ProtoMember(65)] internal double End3Value;
+ [ProtoMember(66)] internal bool SwapNavigationType;
+ [ProtoMember(67)] internal bool ElevationRelativeToC;
+ }
+
+ [ProtoContract]
+ public struct MinesDef
+ {
+ [ProtoMember(1)] internal double DetectRadius;
+ [ProtoMember(2)] internal double DeCloakRadius;
+ [ProtoMember(3)] internal int FieldTime;
+ [ProtoMember(4)] internal bool Cloak;
+ [ProtoMember(5)] internal bool Persist;
+ }
+ }
+
+ [ProtoContract]
+ public struct Randomize
+ {
+ [ProtoMember(1)] internal float Start;
+ [ProtoMember(2)] internal float End;
+ }
+ }
+
+ [ProtoContract]
+ public struct ParticleOptionDef
+ {
+ [ProtoMember(1)] internal float Scale;
+ [ProtoMember(2)] internal float MaxDistance;
+ [ProtoMember(3)] internal float MaxDuration;
+ [ProtoMember(4)] internal bool Loop;
+ [ProtoMember(5)] internal bool Restart;
+ [ProtoMember(6)] internal float HitPlayChance;
+ }
+
+
+ [ProtoContract]
+ public struct ParticleDef
+ {
+ [ProtoMember(1)] internal string Name;
+ [ProtoMember(2)] internal Vector4 Color;
+ [ProtoMember(3)] internal Vector3D Offset;
+ [ProtoMember(4)] internal ParticleOptionDef Extras;
+ [ProtoMember(5)] internal bool ApplyToShield;
+ [ProtoMember(6)] internal bool DisableCameraCulling;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ConfigurableGridPoints/Data/Scripts/ShipPoints/API/CoreSystem/CoreSystemsApiPhantoms.cs b/ConfigurableGridPoints/Data/Scripts/ShipPoints/API/CoreSystem/CoreSystemsApiPhantoms.cs
new file mode 100644
index 00000000..09135359
--- /dev/null
+++ b/ConfigurableGridPoints/Data/Scripts/ShipPoints/API/CoreSystem/CoreSystemsApiPhantoms.cs
@@ -0,0 +1,144 @@
+using System;
+using VRage;
+using VRage.Game.Entity;
+using VRageMath;
+
+namespace CGP.ShareTrack.API.CoreSystem
+{
+ ///
+ /// https://github.com/sstixrud/CoreSystems/blob/master/BaseData/Scripts/CoreSystems/Api/CoreSystemsApiPhantoms.cs
+ ///
+ public partial class WcApi
+ {
+ public enum TriggerActions
+ {
+ TriggerOff,
+ TriggerOn,
+ TriggerOnce
+ }
+
+ private Action _addMagazines;
+ private Func _closePhantom;
+
+ private Func> _getTargetAssessment;
+ private Action _setAmmo;
+
+ private Func _setPhantomFocusTarget;
+
+ //private Action>> _getPhantomInfo;
+ private Action _setTriggerState;
+
+ private Func
+ _spawnPhantom;
+
+ ///
+ /// Get information about a particular target relative to this phantom
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ internal void GetTargetAssessment(MyEntity phantom, MyEntity target, int weapon = 0, bool mustBeInrange = false,
+ bool checkTargetOrb = false)
+ {
+ _getTargetAssessment?.Invoke(phantom, target, weapon, mustBeInrange, checkTargetOrb);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ //internal void GetPhantomInfo(string phantomSubtypeId, ICollection> collection) => _getPhantomInfo?.Invoke(phantomSubtypeId, collection);
+
+ ///
+ /// Change the phantoms current fire state
+ ///
+ ///
+ ///
+ internal void SetTriggerState(MyEntity phantom, TriggerActions trigger)
+ {
+ _setTriggerState?.Invoke(phantom, (int)trigger);
+ }
+
+ ///
+ /// Add additional magazines
+ ///
+ ///
+ ///
+ ///
+ internal void AddMagazines(MyEntity phantom, int weapon, long quanity)
+ {
+ _addMagazines?.Invoke(phantom, weapon, quanity);
+ }
+
+ ///
+ /// Set/switch ammo
+ ///
+ ///
+ ///
+ ///
+ internal void SetAmmo(MyEntity phantom, int weapon, string ammoName)
+ {
+ _setAmmo?.Invoke(phantom, weapon, ammoName);
+ }
+
+ ///
+ /// Close phantoms, required for phantoms that do not auto close
+ ///
+ ///
+ ///
+ internal bool ClosePhantom(MyEntity phantom)
+ {
+ return _closePhantom?.Invoke(phantom) ?? false;
+ }
+
+ ///
+ /// string: weapon subtypeId
+ /// uint: max age, defaults to never die, you must issue close request! Max duration is 14400 ticks (4 minutes)
+ /// bool: close when phantom runs out of ammo
+ /// long: Number of ammo reloads phantom has per default, prior to you adding more, defaults to long.MaxValue
+ /// string: name of the ammo you want the phantom to start with, if different than default
+ /// TriggerActions: TriggerOff, TriggerOn, TriggerOnce
+ /// float?: scales the model if defined in the WeaponDefinition for this subtypeId
+ /// MyEntity: Parent's this phantom to another world entity.
+ /// StringerBuilder: Assign a name to this phantom
+ /// bool: Add this phantom to the world PrunningStructure
+ /// bool: Enable shadows for the model.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ internal MyEntity SpawnPhantom(string phantomType, uint maxAge = 0, bool closeWhenOutOfAmmo = false,
+ long defaultReloads = long.MaxValue, string ammoOverideName = null,
+ TriggerActions trigger = TriggerActions.TriggerOff, float? modelScale = null, MyEntity parnet = null,
+ bool addToPrunning = false, bool shadows = false, long identityId = 0, bool sync = false)
+ {
+ return _spawnPhantom?.Invoke(phantomType, maxAge, closeWhenOutOfAmmo, defaultReloads, ammoOverideName,
+ (int)trigger, modelScale, parnet, addToPrunning, shadows, identityId, sync) ?? null;
+ }
+
+ ///
+ /// Set/switch ammo
+ /// focusId is a value between 0 and 1, can have two active focus targets.
+ ///
+ ///
+ ///
+ ///
+ internal bool SetPhantomFocusTarget(MyEntity phantom, MyEntity target, int focusId)
+ {
+ return _setPhantomFocusTarget?.Invoke(phantom, target, focusId) ?? false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ConfigurableGridPoints/Data/Scripts/ShipPoints/API/HudAPIv2.cs b/ConfigurableGridPoints/Data/Scripts/ShipPoints/API/HudAPIv2.cs
new file mode 100644
index 00000000..f2653b0c
--- /dev/null
+++ b/ConfigurableGridPoints/Data/Scripts/ShipPoints/API/HudAPIv2.cs
@@ -0,0 +1,2217 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ProtoBuf;
+using Sandbox.ModAPI;
+using VRage;
+using VRage.Input;
+using VRage.ModAPI;
+using VRage.Utils;
+using VRageMath;
+using BlendTypeEnum = VRageRender.MyBillboard.BlendTypeEnum;
+
+namespace CGP.ShareTrack.API
+{
+ public class HudAPIv2
+ {
+ public enum TextOrientation : byte
+ {
+ ltr = 1,
+ center = 2,
+ rtl = 3
+ }
+
+ public const string DefaultFont = "white";
+ public const BlendTypeEnum DefaultHUDBlendType = BlendTypeEnum.PostPP;
+ public const BlendTypeEnum DefaultWorldBlendType = BlendTypeEnum.Standard;
+ private const long REGISTRATIONID = 573804956;
+
+ private static HudAPIv2 instance;
+ private Action m_onRegisteredAction;
+
+ private Func MessageFactory;
+ private Func