diff --git a/GrappleHook/Data/Scripts/hook/WeaponControlLayer.cs b/GrappleHook/Data/Scripts/hook/WeaponControlLayer.cs index d32d44f..78f062e 100644 --- a/GrappleHook/Data/Scripts/hook/WeaponControlLayer.cs +++ b/GrappleHook/Data/Scripts/hook/WeaponControlLayer.cs @@ -8,9 +8,8 @@ using SENetworkAPI; using System; using System.Collections.Generic; -using System.Drawing; -using System.Security.Policy; -using System.Security.Principal; +using System.Data.SqlTypes; +using System.Reflection; using System.Text; using VRage.Game; using VRage.Game.Components; @@ -66,6 +65,7 @@ public override void Init(MyObjectBuilder_EntityBase objectBuilder) if (MyAPIGateway.Session.IsServer) { Settings.Init(); + settings = new NetSync(this, TransferType.ServerToClient, Settings.Instance, true, false); } else @@ -299,30 +299,24 @@ private void UpdateGrappleLength() public void ApplyForce() { - try + if (Turret.CubeGrid.Physics == null || ConnectedEntity == null || ConnectedEntity.Physics == null || Entity.MarkedForClose || ConnectedEntity.MarkedForClose) { - if (Turret.CubeGrid.Physics == null || ConnectedEntity == null || ConnectedEntity.Physics == null || Entity.MarkedForClose || ConnectedEntity.MarkedForClose) - { - return; - } + return; + } - Vector3D turretPostion = Turret.PositionComp.WorldMatrixRef.Translation; - Vector3D entityPostion = Vector3D.Transform(LocalGrapplePosition.Value, ConnectedEntity.WorldMatrix); - Vector3D direction = turretPostion - entityPostion; - double currentLength = direction.Length(); - direction.Normalize(); + Vector3D turretPostion = Turret.PositionComp.WorldMatrixRef.Translation; + Vector3D entityPostion = Vector3D.Transform(LocalGrapplePosition.Value, ConnectedEntity.WorldMatrix); + Vector3D direction = turretPostion - entityPostion; + double currentLength = direction.Length(); + direction = direction / currentLength; - double force = settings.Value.RopeForce * Math.Max(0, currentLength - GrappleLength.Value) - settings.Value.RopeDamping * (Turret.CubeGrid.Physics.LinearVelocity + ConnectedEntity.Physics.LinearVelocity).Length(); + double force = settings.Value.RopeForce * (currentLength - GrappleLength.Value) - (settings.Value.RopeDamping * (Turret.CubeGrid.Physics.LinearVelocity + ConnectedEntity.Physics.LinearVelocity).Length()); + Vector3D forceVector = direction * force; - if (force > 0 && turretPostion != Vector3D.Zero && entityPostion != Vector3D.Zero) - { - Turret.CubeGrid.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_FORCE, -1 * direction * force, turretPostion, null, null, true); - ConnectedEntity.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_FORCE, direction * force, entityPostion, null, null, true); - } - } - catch (Exception e) + if (force > 0) { - Tools.Debug(e.ToString()); + Turret.CubeGrid.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_FORCE, -1 * forceVector, turretPostion, null, null, true); + ConnectedEntity.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_FORCE, forceVector, entityPostion, null, null, true); } } @@ -348,7 +342,7 @@ private void UpdateZiplineInteract() if (MyAPIGateway.Session.Player == null || !(MyAPIGateway.Session.Player.Controller.ControlledEntity is IMyCharacter)) return; ZiplineEntity e; - if ((e = GetZiplineEntity(MyAPIGateway.Session.Player.IdentityId)) != null) + if ((e = GetZiplineEntity(MyAPIGateway.Session.Player.IdentityId)) != null) { if (interactKeyPressed) { @@ -357,7 +351,6 @@ private void UpdateZiplineInteract() return; } - IMyCamera cam = MyAPIGateway.Session.Camera; if (cam == null) return; @@ -372,9 +365,6 @@ private void UpdateZiplineInteract() MatrixD worldMatrix = Turret.WorldMatrix; BoundingBoxD bounds = new BoundingBoxD(Vector3D.Min(a, b), Vector3D.Max(a, b)); - VRageMath.Color color = VRageMath.Color.Green; - MySimpleObjectDraw.DrawTransparentBox(ref worldMatrix, ref bounds, ref color, MySimpleObjectRasterizer.Wireframe, 1, 0.01f); - double? result; bounds.Intersects(ref camRay, out result); if (result.HasValue && result.Value < 3.5f) @@ -408,16 +398,16 @@ private void AttachToZipline(ZiplineEntity ziplineData) IMyCharacter character = ziplineData.player.Character; Vector3D[] points = GetLinePoints(); - double nearIndex = 0; - double nearValue = double.MaxValue; - Vector3D anchorSegment = Vector3D.Zero; + Vector3D centerSegment = Vector3D.Zero; Vector3D nextSegment = Vector3D.Zero; Vector3D previousSegment = Vector3D.Zero; - for (int j = 0; j < points.Length; j++) + + int nearIndex = 0; + double nearValue = double.MaxValue; + for (int i = 0; i < points.Length; i++) { - int index = j; - if (!ziplineData.direction) - index = points.Length - 1 - j; + // iterates from end to start if the character is facing twards the turret + int index = (ziplineData.direction) ? i : points.Length - 1 - i; Vector3D point = points[index]; @@ -426,78 +416,85 @@ private void AttachToZipline(ZiplineEntity ziplineData) { nearIndex = index; nearValue = distance; + centerSegment = point; + } + } - anchorSegment = point; - - int j2 = j + 1; - if (!ziplineData.direction) - j2 = points.Length - 1 - (j + 1); - - if (j2 >= 0 && j2 < points.Length) - { - nextSegment = points[j2]; - } - - int j3 = j - 1; - if (!ziplineData.direction) - j3 = points.Length - 1 - (j - 1); + // Correctly assign next and previous segments based on nearIndex + if (nearIndex + 1 < points.Length) + { + nextSegment = points[nearIndex + 1]; + } + else + { + nextSegment = centerSegment; + } - if (j3 >= 0 && j3 < points.Length) - { - previousSegment = points[j3]; - } - } + if (nearIndex - 1 >= 0) + { + previousSegment = points[nearIndex - 1]; + } + else + { + previousSegment = centerSegment; } - //Tools.Debug($"find the distance and direction of attachment force"); - Vector3D characterPosition = character.WorldMatrix.Translation + character.WorldMatrix.Up; + // If direction is false, swap next and previous segments + if (!ziplineData.direction) + { + Vector3D temp = nextSegment; + nextSegment = previousSegment; + previousSegment = temp; + } - Vector3D anchorToNext = nextSegment - anchorSegment; - double anchorToNextMag = anchorToNext.Length(); + Vector3D pulley; + Vector3D anchor; + Vector3D anchorNorm; + double sinTheta; - Vector3D previousToAnchor = anchorSegment - previousSegment; - double previousToAnchorMag = previousToAnchor.Length(); + Vector3D characterPosition = character.WorldMatrix.Translation + character.WorldMatrix.Up; + Vector3D centerToNext = nextSegment - centerSegment; + Vector3D playerToCenter = centerSegment - characterPosition; + double playerToCenterMag = playerToCenter.Length(); - Vector3D playerToAnchor = anchorSegment - characterPosition; - double playerToAnchorMag = playerToAnchor.Length(); + // check if we are infront or behind the center point. + double directionDot = Vector3D.Dot(playerToCenter, centerToNext); - // check if we are moving towards or away from the current point. - double directionDot = Vector3D.Dot(playerToAnchor, anchorToNext); - Vector3D pulley; if (directionDot < 0) { - double sinTheta = Tools.GetSinAngle(anchorToNext, -playerToAnchor); - double playerPulleyMag = sinTheta * playerToAnchorMag; - double pulleyToAnchorMag = Math.Sqrt(playerToAnchorMag * playerToAnchorMag - playerPulleyMag * playerPulleyMag); - Vector3D anchorToNextNorm = Vector3D.Normalize(anchorToNext); - - pulley = anchorSegment + anchorToNextNorm * pulleyToAnchorMag; - + // infront uses the next segment point as the anchor + anchor = centerToNext; + anchorNorm = Vector3D.Normalize(anchor); + sinTheta = Tools.GetSinAngle(anchor, -playerToCenter); } - else + else { - double sinTheta = Tools.GetSinAngle(previousToAnchor, playerToAnchor); - double playerPulleyMag = sinTheta * playerToAnchorMag; - double pulleyToAnchorMag = Math.Sqrt(playerToAnchorMag * playerToAnchorMag - playerPulleyMag * playerPulleyMag); - Vector3D previousToAnchorNorm = -Vector3D.Normalize(previousToAnchor); - - pulley = anchorSegment + previousToAnchorNorm * pulleyToAnchorMag; + // behind uses the center segment point as the anchor + anchor = centerSegment - previousSegment; + anchorNorm = -Vector3D.Normalize(anchor); + sinTheta = Tools.GetSinAngle(anchor, playerToCenter); } + double playerPulleyMag = sinTheta * playerToCenterMag; + double pulleyToAnchorMag = Math.Sqrt(playerToCenterMag * playerToCenterMag - playerPulleyMag * playerPulleyMag); + pulley = centerSegment + anchorNorm * pulleyToAnchorMag; + Tools.Debug($"Got pulley location {pulley}"); ziplineData.pulley = pulley; ziplineData.lastPulley = pulley; } + + + private void UpdateZiplineForces() { Vector3D[] points = GetLinePoints(); for (int i = 0; i < ZiplinePlayers.Value.Count; i++) { ZiplineEntity zipEntity = ZiplinePlayers.Value[i]; - ZiplineEntity.Populate(ref zipEntity); if (zipEntity.player == null || !(zipEntity.player.Controller.ControlledEntity is IMyCharacter)) return; @@ -513,13 +510,12 @@ private void UpdateZiplineForces() } Vector3D characterPosition = character.WorldMatrix.Translation + character.WorldMatrix.Up * 1.7f; - Vector3D ropeForceDirection = zipEntity.pulley - characterPosition; - Vector3D ropeForceDirectionNorm = ropeForceDirection.Normalized(); - - double force = settings.Value.ZiplineTetherForce * Math.Max(0, ropeForceDirection.Length() - settings.Value.ZiplineTetherLength); - - Vector3D forceVector = ropeForceDirectionNorm * force - settings.Value.ZiplineDamping * character.Physics.LinearVelocity; + Vector3D tetherVector = zipEntity.pulley - characterPosition; + double tetherLength = tetherVector.Length(); + Vector3D tetherDirectionNorm = tetherVector / tetherLength; + double force = settings.Value.ZiplineTetherForce * (tetherLength - settings.Value.ZiplineTetherLength); + Vector3D forceVector = tetherDirectionNorm * force - settings.Value.ZiplineDamping * character.Physics.LinearVelocity; if (force > 0) { character.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_FORCE, forceVector, characterPosition, null, null, true); @@ -535,25 +531,23 @@ private void UpdateZiplineForces() double a = 0; if (deltaVector != Vector3D.Zero) { - a = Vector3D.Dot(-ropeForceDirectionNorm, deltaVector.Normalized()) * g; + a = Vector3D.Dot(-tetherDirectionNorm, deltaVector.Normalized()) * g; } double min = settings.Value.ZiplinePulleyMinSpeed * 0.01666667f; double velocityCalc = v0 * v0 + 2d * a * xDelta * xDelta; - // ADD BACK IN 'a' when you fix it double velocitySquared = Math.Max(velocityCalc, min * min); double velocityToApply = Math.Sqrt(velocitySquared); - //Tools.Debug($"V0: {v0}, a:{a}, xd:{xDelta} => Velocity: {velocityCalc}, min: {min*min}"); - double distanceRemaining = velocityToApply; zipEntity.lastPulley = zipEntity.pulley; zipEntity.lastPulleyVelocity = zipEntity.pulleyVelocity; - zipEntity.pulleyVelocity = velocityToApply; + + double distanceRemaining = velocityToApply; for (int j = 0; j < points.Length - 1; j++) { if (distanceRemaining == 0) break; @@ -583,8 +577,6 @@ private void UpdateZiplineForces() Vector3D endNorm = endDirection.Normalized(); - - if ((Vector3D.Dot(startNorm, segmentNorm) <= 0 || Math.Abs((zipEntity.pulley - startDirection).Length()) < 0.01f) && Vector3D.Dot(endNorm, segmentNorm) >= 0) { double length = endDirection.Length(); @@ -694,7 +686,7 @@ private void Draw() texture = MyStringId.GetOrCompute("cable"); } - Vector3D sagDirection = GetSagDirection(); + Vector3D sagDirection = GetSegmentDirection(); Vector3D gunPosition = Turret.PositionComp.WorldMatrixRef.Translation; Vector3D position; @@ -746,7 +738,7 @@ private void Draw() } } - private Vector3D GetSagDirection() + private Vector3D GetSegmentDirection() { ExternalForceData planetForces = WorldPlanets.GetExternalForces(Turret.PositionComp.WorldMatrixRef.Translation); Vector3D sagDirection = planetForces.Gravity; @@ -767,12 +759,12 @@ public Vector3D[] GetLinePoints() Vector3D gunPosition = Turret.WorldMatrix.Translation; Vector3D position = Vector3D.Transform(LocalGrapplePosition.Value, ConnectedEntity.WorldMatrix); - Vector3D sagDirection = GetSagDirection(); + Vector3D sagDirection = GetSegmentDirection(); return ComputeCurvePoints(gunPosition, position, sagDirection, GrappleLength.Value, settings.Value.RopeSegments); } - catch + catch { - return new Vector3D[0]; + return new Vector3D[0]; } } @@ -796,7 +788,7 @@ public Vector3D[] ComputeCurvePoints(Vector3D start, Vector3D end, Vector3D sagD Vector3D newPt = start * v + end * u; if (sagAmount > 0) { - newPt += sagDirection * ComputeRopeSag(u) * sagAmount; + newPt += sagDirection * ComputeRopeSegment(u) * sagAmount; } result[i] = newPt; } @@ -804,7 +796,7 @@ public Vector3D[] ComputeCurvePoints(Vector3D start, Vector3D end, Vector3D sagD return result; } - public double ComputeRopeSag(double x) + public double ComputeRopeSegment(double x) { return -4 * x * x + 4 * x; } diff --git a/ShrapnelDamageV2/Data/Scripts/shrapnel/Core.cs b/ShrapnelDamageV2/Data/Scripts/shrapnel/Core.cs deleted file mode 100644 index 4e18e8c..0000000 --- a/ShrapnelDamageV2/Data/Scripts/shrapnel/Core.cs +++ /dev/null @@ -1,86 +0,0 @@ -using Sandbox.Definitions; -using Sandbox.ModAPI; -using System.Collections.Generic; -using VRage.Game; -using VRage.Game.Components; -using VRage.Game.ModAPI; - -namespace Shrapnel -{ - [MySessionComponentDescriptor(MyUpdateOrder.BeforeSimulation)] - public class Core : MySessionComponentBase - { - public const float ReductionMult = 1.0f; - - private Queue queue = new Queue(); - - public override void Init(MyObjectBuilder_SessionComponent sessionComponent) - { - MyAPIGateway.Session.DamageSystem.RegisterBeforeDamageHandler(9, ProcessDamage); - } - - public void ProcessDamage(object target, ref MyDamageInformation info) - { - IMySlimBlock slim = target as IMySlimBlock; - if (slim == null) return; - - if (info.Type != MyDamageType.Bullet) - { - if (slim.Integrity >= info.Amount) return; - - float overkill = info.Amount - slim.Integrity; - info.Amount = slim.Integrity; - - queue.Enqueue(new ShrapnelData() - { - Neighbours = slim.Neighbours, - OverKill = overkill - }); - } - else if (info.Type == MyDamageType.Explosion && !(slim.FatBlock is IMyWarhead)) - { - queue.Enqueue(new ShrapnelData() - { - OverKill = info.Amount, - Neighbours = new List() { slim }, - }); - info.Amount = 0; - - } - - } - - public override void UpdateBeforeSimulation() - { - int tasks = 0; - while (queue.Count > 0 && tasks < 200) - { - tasks++; - ShrapnelData data = queue.Dequeue(); - int count = data.Neighbours.Count; - foreach (IMySlimBlock neighbour in data.Neighbours) - { - if (neighbour == null) continue; - // get block resistance - float generalMult = 1; - if (neighbour.BlockDefinition is MyCubeBlockDefinition) - { - generalMult = ((MyCubeBlockDefinition)neighbour.BlockDefinition).GeneralDamageMultiplier; - } - - // total over kill damage devided by the number of neighbours - // that times the reduction multiplier 0 to 1 - // that times the blocks general reduction multiplier 0 - 1 - float damage = ((data.OverKill / (float)count) * ReductionMult * generalMult); - neighbour.DoDamage(damage, MyDamageType.Bullet, true); - } - } - } - } - - internal class ShrapnelData - { - public float OverKill { get; set; } - public List Neighbours { get; set; } - } -} diff --git a/ShrapnelDamageV2/metadata.mod b/ShrapnelDamageV2/metadata.mod deleted file mode 100644 index 0a020fd..0000000 --- a/ShrapnelDamageV2/metadata.mod +++ /dev/null @@ -1,4 +0,0 @@ - - - 1.0 - \ No newline at end of file diff --git a/ShrapnelDamageV2/modinfo.sbmi b/ShrapnelDamageV2/modinfo.sbmi deleted file mode 100644 index ae8451f..0000000 --- a/ShrapnelDamageV2/modinfo.sbmi +++ /dev/null @@ -1,11 +0,0 @@ - - - 76561198079985653 - 0 - - - 3278152123 - Steam - - - \ No newline at end of file diff --git a/ShrapnelDamageV2/thumb.jpg b/ShrapnelDamageV2/thumb.jpg deleted file mode 100644 index 33aebfb..0000000 Binary files a/ShrapnelDamageV2/thumb.jpg and /dev/null differ diff --git a/SuiteCombatBalancer/Data/Scripts/hacking/Core.cs b/SuiteCombatBalancer/Data/Scripts/hacking/Core.cs index 70541f1..7cca873 100644 --- a/SuiteCombatBalancer/Data/Scripts/hacking/Core.cs +++ b/SuiteCombatBalancer/Data/Scripts/hacking/Core.cs @@ -25,8 +25,6 @@ public override void Init(MyObjectBuilder_SessionComponent sessionComponent) private void Handler(object target, ref MyDamageInformation info) { - MyLog.Default.Info(target.ToString()); - IMyEntity ent = MyAPIGateway.Entities.GetEntityById(info.AttackerId); if (ent == null) return; // End: Must be a player character diff --git a/ThermalDynamics/Data/Scripts/Thermodynamics/PlanetManager.cs b/ThermalDynamics/Data/Scripts/Thermodynamics/PlanetManager.cs index 4a87bd8..c39fc0e 100644 --- a/ThermalDynamics/Data/Scripts/Thermodynamics/PlanetManager.cs +++ b/ThermalDynamics/Data/Scripts/Thermodynamics/PlanetManager.cs @@ -129,51 +129,5 @@ public static Planet GetClosestPlanet(Vector3D position) return current; } - - public static bool IsSolarOccluded(Vector3D observer, Vector3 solarDirection, MyPlanet planet) - { - Vector3D local = observer - planet.PositionComp.WorldMatrixRef.Translation; - double distance = local.Length(); - Vector3D localNorm = local / distance; - - double dot = Vector3.Dot(localNorm, solarDirection); - return dot < GetLargestOcclusionDotProduct(GetVisualSize(distance, planet.AverageRadius)); - } - - - /// - /// a number between 0 and 1 representing the side object based on distance - /// - /// the local vector between the observer and the target - /// the size of the target - //public static double GetVisualSize(Vector3D observer, double radius) - //{ - // return 2 * Math.Atan(radius / (2 * observer.Length())); - //} - - /// - /// a number between 0 and 1 representing the side object based on distance - /// - /// the distance between the observer and the target - /// the size of the target - public static double GetVisualSize(double distance, double radius) - { - return 2 * Math.Atan(radius / (2 * distance)); - } - - /// - /// an equation made by plotting the edge most angle of the occluded sun - /// takes in the current visual size of the planet and produces a number between 0 and -1 - /// if the dot product of the planet and sun directions is less than this number it is occluded - /// - /// - /// - public static double GetLargestOcclusionDotProduct(double visualSize) - { - return -1 + (0.85 * visualSize * visualSize * visualSize); - } - } - - } diff --git a/ThermalDynamics/Data/Scripts/Thermodynamics/Session.cs b/ThermalDynamics/Data/Scripts/Thermodynamics/Session.cs index 71f737e..05a96b5 100644 --- a/ThermalDynamics/Data/Scripts/Thermodynamics/Session.cs +++ b/ThermalDynamics/Data/Scripts/Thermodynamics/Session.cs @@ -7,6 +7,7 @@ using Sandbox.ModAPI; using System; using System.Collections.Generic; +using System.Net; using System.Text; using VRage.Game; using VRage.Game.Components; @@ -56,12 +57,15 @@ public Color GetTemperatureColor(float temp) return new Color(red, 0, blue, 255); } + + public override void Simulate() - { + { if (Settings.Debug && !MyAPIGateway.Utilities.IsDedicated) { //MyAPIGateway.Utilities.ShowNotification($"[Grid] Frequency: {Settings.Instance.Frequency}", 1, "White"); MatrixD matrix = MyAPIGateway.Session.Camera.WorldMatrix; + Vector3D start = matrix.Translation; Vector3D end = start + (matrix.Forward * 15); @@ -82,32 +86,6 @@ public override void Simulate() if (c == null) return; - Vector3D blockPosition; - Matrix blockRotation; - - block.ComputeWorldCenter(out blockPosition); - block.Orientation.GetMatrix(out blockRotation); - - MatrixD gridRotationMatrix = block.CubeGrid.WorldMatrix; - gridRotationMatrix.Translation = Vector3D.Zero; - blockRotation *= gridRotationMatrix; - MatrixD blockWorldMatrix = MatrixD.CreateWorld(blockPosition, blockRotation.Forward, blockRotation.Up); - - float unit = block.CubeGrid.GridSize * 0.5f; - Vector3 halfExtents = new Vector3((float)unit, (float)unit, (float)unit); - BoundingBoxD box = new BoundingBoxD(-halfExtents, halfExtents); - - //GetTemperatureColor(c.Temperature); - - Color color = ColorExtensions.HSVtoColor(Tools.GetTemperatureColor(c.Temperature)); - - - MySimpleObjectDraw.DrawTransparentBox(ref blockWorldMatrix, ref box, ref color, MySimpleObjectRasterizer.Solid, 1, 0.01f, null, null, true, -1, BlendTypeEnum.AdditiveTop, 1000f); - - - //MyAPIGateway.Utilities.ShowNotification($"[Grid] {tGrid.Entity.EntityId} Count: {tGrid.Thermals.Count}", 1, "White"); - - MyAPIGateway.Utilities.ShowNotification($"[Env] " + $"sim: {Settings.Instance.SimulationSpeed.ToString("n2")} " + $"freq: {Settings.Instance.Frequency.ToString("n2")} " + @@ -154,5 +132,65 @@ public override void Simulate() //MyAPIGateway.Utilities.ShowNotification($"[External] {tGrid.Mapper.Blocks.Count} EComplete: {tGrid.Mapper.ExternalRoomUpdateComplete} BComplete: {tGrid.ThermalCellUpdateComplete}", 1, "White"); } } - } + + public override void Draw() + { + if (Settings.Debug && !MyAPIGateway.Utilities.IsDedicated) + { + //MyAPIGateway.Utilities.ShowNotification($"[Grid] Frequency: {Settings.Instance.Frequency}", 1, "White"); + MatrixD matrix = MyAPIGateway.Session.Camera.WorldMatrix; + + Vector3D start = matrix.Translation; + Vector3D end = start + (matrix.Forward * 15); + + IHitInfo hit; + MyAPIGateway.Physics.CastRay(start, end, out hit); + MyCubeGrid grid = hit?.HitEntity as MyCubeGrid; + if (grid == null) return; + + Vector3I position = grid.WorldToGridInteger(hit.Position + (matrix.Forward * 0.005f)); + + ThermalGrid g = grid.GameLogic.GetAs(); + + IMySlimBlock block = grid.GetCubeBlock(position); + + if (block == null) return; + + ThermalCell c = g.Get(block.Position); + + if (c == null) return; + + DrawBillboard(c, matrix); + for (int i = 0; i < c.Neighbors.Count; i++) + { + ThermalCell n = c.Neighbors[i]; + DrawBillboard(n, matrix); + } + } + } + + public void DrawBillboard(ThermalCell c, MatrixD cameraMatrix) + { + Vector3D position; + c.Block.ComputeWorldCenter(out position); + + float averageBlockLength = Vector3I.DistanceManhattan(c.Block.Max + 1, c.Block.Min) * 0.33f; + + Color color = ColorExtensions.HSVtoColor(Tools.GetTemperatureColor(c.Temperature)); + + float distance = 0.01f; + position = cameraMatrix.Translation + (position - cameraMatrix.Translation) * distance; + float scaler = 1.2f * c.Grid.Grid.GridSizeHalf * averageBlockLength * distance; + + MyTransparentGeometry.AddBillboardOriented( + MyStringId.GetOrCompute("GaugeThermalTexture"), // Texture or material name for the billboard + color, // Color of the billboard + position, + cameraMatrix.Left, // Left direction of the billboard + cameraMatrix.Up, // Up direction of the billboard + scaler, // Width of the billboard + scaler // Height of the billboard + ); + } + } } diff --git a/ThermalDynamics/Data/Scripts/Thermodynamics/Settings.cs b/ThermalDynamics/Data/Scripts/Thermodynamics/Settings.cs index b7e2598..f01e362 100644 --- a/ThermalDynamics/Data/Scripts/Thermodynamics/Settings.cs +++ b/ThermalDynamics/Data/Scripts/Thermodynamics/Settings.cs @@ -16,6 +16,7 @@ public class Settings public const string Filename = "ThermodynamicsConfig.cfg"; public const string Name = "Thermodynamics"; public const bool Debug = true; + public const bool DebugBlockColors = true; public static Settings Instance; diff --git a/ThermalDynamics/Data/Scripts/Thermodynamics/ThermalCell.cs b/ThermalDynamics/Data/Scripts/Thermodynamics/ThermalCell.cs index f6c70f0..cb5bd29 100644 --- a/ThermalDynamics/Data/Scripts/Thermodynamics/ThermalCell.cs +++ b/ThermalDynamics/Data/Scripts/Thermodynamics/ThermalCell.cs @@ -49,13 +49,11 @@ public class ThermalCell public IMySlimBlock Block; public ThermalCellDefinition Definition; - private List Neighbors = new List(); + public List Neighbors = new List(); private List TouchingSerfacesByNeighbor = new List(); public int ExposedSurfaces = 0; - private List ExposedSurfaceDirections = new List(); - - + public List ExposedSurfaceDirections = new List(); public ThermalCell(ThermalGrid g, IMySlimBlock b) { diff --git a/ThermalDynamics/Data/Scripts/Thermodynamics/ThermalGrid.cs b/ThermalDynamics/Data/Scripts/Thermodynamics/ThermalGrid.cs index f673d01..9326240 100644 --- a/ThermalDynamics/Data/Scripts/Thermodynamics/ThermalGrid.cs +++ b/ThermalDynamics/Data/Scripts/Thermodynamics/ThermalGrid.cs @@ -10,6 +10,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Reflection; using System.Text; using System.Transactions; @@ -371,6 +372,7 @@ public override void UpdateBeforeSimulation() { if (!ThermalCellUpdateComplete) { + //MyLog.Default.Info($"[Thermals] updating serfaces {ExteriorNodes.Count}"); cell.UpdateSurfaces(ref ExteriorNodes, ref neighbors); } @@ -449,7 +451,7 @@ private void PrepareNextSimulationStep() Vector3D planetDirection = planetLocal / distance; double dot = Vector3D.Dot(planetDirection, FrameSolarDirection); - double occlusionDot = PlanetManager.GetLargestOcclusionDotProduct(PlanetManager.GetVisualSize(distance, myPlanet.AverageRadius)); + double occlusionDot = Tools.GetLargestOcclusionDotProduct(Tools.GetVisualSize(distance, myPlanet.AverageRadius)); if (dot < occlusionDot) { diff --git a/ThermalDynamics/Data/Scripts/Thermodynamics/ThermalGridMapper.cs b/ThermalDynamics/Data/Scripts/Thermodynamics/ThermalGridMapper.cs index dfa4634..76179fd 100644 --- a/ThermalDynamics/Data/Scripts/Thermodynamics/ThermalGridMapper.cs +++ b/ThermalDynamics/Data/Scripts/Thermodynamics/ThermalGridMapper.cs @@ -47,6 +47,16 @@ private void MapBlocks(IMySlimBlock block, bool isNew = false, IMySlimBlock remo Vector3I min = block.Min; Vector3I max = block.Max + 1; + if (isNew) + { + if (Vector3I.Min(Grid.Min - 1, this.min) != this.min || + Vector3I.Max(Grid.Max + 1, this.max) != this.max) + ResetMapper(); + } + + HashSet processedNeighbours = new HashSet(); + processedNeighbours.Add(removed); + MyCubeBlockDefinition def = block.BlockDefinition as MyCubeBlockDefinition; Matrix blockMatrix; block.Orientation.GetMatrix(out blockMatrix); @@ -55,30 +65,81 @@ private void MapBlocks(IMySlimBlock block, bool isNew = false, IMySlimBlock remo bool isAirTight = def?.IsAirTight == true; if (isAirTight) { - state = 63; // All sides airtight + state = 63; } - // Iterate over the block's volume for (int x = min.X; x < max.X; x++) { for (int y = min.Y; y < max.Y; y++) { for (int z = min.Z; z < max.Z; z++) { + Vector3I node = new Vector3I(x, y, z); - // Update state based on neighbors - UpdateNodeState(ref state, node, block, def, blockMatrix); + for (int i = 0; i < neighbors.Length; i++) + { + Vector3I n = node + neighbors[i]; + Vector3 direction1 = node - n; + Vector3 direction2 = n - node; + + // neighbour is the same block + if (n.X >= min.X && n.Y >= min.Y && n.Z >= min.Z && + n.X < max.X && n.Y < max.Y && n.Z < max.Z) + { + + if (IsAirtight(ref block, ref def, ref node, ref direction2, ref blockMatrix)) + { + state |= 1 << i; + } - // Safely add or update nodes in the dictionary - if (BlockNodes.ContainsKey(node)) + if (IsAirtight(ref block, ref def, ref n, ref direction1, ref blockMatrix)) + { + state |= 1 << i + 6; + } + } + else + { + IMySlimBlock nblock = Grid.GetCubeBlock(n); + if (nblock == null) + { + continue; + } + + // update all neighbor blocks if this block was just added to the grid + if (isNew && !processedNeighbours.Contains(nblock)) + { + MapBlocks(nblock); + processedNeighbours.Add(nblock); + } + + MyCubeBlockDefinition ndef = nblock.BlockDefinition as MyCubeBlockDefinition; + Matrix nMatrix; + nblock.Orientation.GetMatrix(out nMatrix); + nMatrix.TransposeRotationInPlace(); + + if (IsAirtight(ref block, ref def, ref node, ref direction2, ref blockMatrix)) + { + state |= 1 << i; + } + + if (ndef?.IsAirTight == true || + IsAirtight(ref nblock, ref ndef, ref n, ref direction1, ref nMatrix)) + { + state |= 1 << i + 6; + } + } + } + + if (isNew) { - BlockNodes[node] = state; // Update the existing node + BlockNodes.Add(node, state); } else { - BlockNodes.Add(node, state); // Add new node + BlockNodes[node] = state; } + } } } diff --git a/ThermalDynamics/Data/Scripts/Thermodynamics/Tools.cs b/ThermalDynamics/Data/Scripts/Thermodynamics/Tools.cs index 37308c7..c270f5f 100644 --- a/ThermalDynamics/Data/Scripts/Thermodynamics/Tools.cs +++ b/ThermalDynamics/Data/Scripts/Thermodynamics/Tools.cs @@ -1,6 +1,9 @@ -using System; +using Sandbox.Game.Entities; +using Sandbox.ModAPI; +using System; using System.Collections.Generic; using System.Text; +using VRage.ModAPI; using VRageMath; namespace Thermodynamics @@ -96,16 +99,72 @@ public static Vector3 GetTemperatureColor(float temp, float max = 2000, float lo /// public static int FindTouchingSurfaceArea(Vector3I minA, Vector3I maxA, Vector3I minB, Vector3I maxB) { - int deltaX = Math.Min(maxA.X, maxB.X) - Math.Max(minA.X, minB.X); - int deltaY = Math.Min(maxA.Y, maxB.Y) - Math.Max(minA.Y, minB.Y); - int deltaZ = Math.Min(maxA.Z, maxB.Z) - Math.Max(minA.Z, minB.Z); + // Check if they touch on the X face + if (minA.X == maxB.X || maxA.X == minB.X) + { + int overlapY = Math.Min(maxA.Y, maxB.Y) - Math.Max(minA.Y, minB.Y); + int overlapZ = Math.Min(maxA.Z, maxB.Z) - Math.Max(minA.Z, minB.Z); + if (overlapY > 0 && overlapZ > 0) + { + return overlapY * overlapZ; + } + } + + // Check if they touch on the Y face + if (minA.Y == maxB.Y || maxA.Y == minB.Y) + { + int overlapX = Math.Min(maxA.X, maxB.X) - Math.Max(minA.X, minB.X); + int overlapZ = Math.Min(maxA.Z, maxB.Z) - Math.Max(minA.Z, minB.Z); + if (overlapX > 0 && overlapZ > 0) + { + return overlapX * overlapZ; + } + } - if (deltaX <= 0 || deltaY <= 0 || deltaZ <= 0) + // Check if they touch on the Z face + if (minA.Z == maxB.Z || maxA.Z == minB.Z) { - return 0; + int overlapX = Math.Min(maxA.X, maxB.X) - Math.Max(minA.X, minB.X); + int overlapY = Math.Min(maxA.Y, maxB.Y) - Math.Max(minA.Y, minB.Y); + if (overlapX > 0 && overlapY > 0) + { + return overlapX * overlapY; + } } - return deltaX * deltaY * deltaZ; + return 0; + } + + public static bool IsSolarOccluded(Vector3D observer, Vector3 solarDirection, MyPlanet planet) + { + Vector3D local = observer - planet.PositionComp.WorldMatrixRef.Translation; + double distance = local.Length(); + Vector3D localNorm = local / distance; + + double dot = Vector3.Dot(localNorm, solarDirection); + return dot < GetLargestOcclusionDotProduct(GetVisualSize(distance, planet.AverageRadius)); + } + + /// + /// a number between 0 and 1 representing the side object based on distance + /// + /// the distance between the observer and the target + /// the size of the target + public static double GetVisualSize(double distance, double radius) + { + return 2 * Math.Atan(radius / (2 * distance)); + } + + /// + /// an equation made by plotting the edge most angle of the occluded sun + /// takes in the current visual size of the planet and produces a number between 0 and -1 + /// if the dot product of the planet and sun directions is less than this number it is occluded + /// + /// + /// + public static double GetLargestOcclusionDotProduct(double visualSize) + { + return -1 + (0.85 * visualSize * visualSize * visualSize); } } } diff --git a/ThermalDynamics/Data/TransparentMaterials.sbc b/ThermalDynamics/Data/TransparentMaterials.sbc new file mode 100644 index 0000000..2085fba --- /dev/null +++ b/ThermalDynamics/Data/TransparentMaterials.sbc @@ -0,0 +1,18 @@ + + + + + + TransparentMaterialDefinition + GaugeThermalTexture + + false + 1 + false + false + 0.1 + Textures\Particles\GaugeThermalTexture.dds + false + + + \ No newline at end of file diff --git a/ThermalDynamics/Textures/Particles/GaugeThermalTexture.dds b/ThermalDynamics/Textures/Particles/GaugeThermalTexture.dds new file mode 100644 index 0000000..48e49ab Binary files /dev/null and b/ThermalDynamics/Textures/Particles/GaugeThermalTexture.dds differ