diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs index b730978..2ac35d1 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidEntity.cs @@ -91,7 +91,6 @@ public static AsteroidEntity CreateAsteroid(Vector3D position, float size, Vecto ent.EntityId = entityId.Value; var massRange = AsteroidSettings.MinMaxMassByType[type]; - string ringDebugInfo; float distanceScale = AsteroidSettings.CalculateMassScaleByDistance(position, MainSession.I.RealGasGiantsApi, out ringDebugInfo); @@ -99,6 +98,7 @@ public static AsteroidEntity CreateAsteroid(Vector3D position, float size, Vecto float finalMass = MathHelper.Lerp(massRange.MinMass, massRange.MaxMass, distanceScale + randomFactor); finalMass = MathHelper.Clamp(finalMass, massRange.MinMass, massRange.MaxMass); + // Create physical properties first ent.Properties = AsteroidPhysicalProperties.CreateFromMass(finalMass, AsteroidPhysicalProperties.DEFAULT_DENSITY, ent); if (!rotation.HasValue && MyAPIGateway.Session.IsServer) { @@ -110,7 +110,8 @@ public static AsteroidEntity CreateAsteroid(Vector3D position, float size, Vecto rotation = Quaternion.Identity; } - ent.Init(position, size, initialVelocity, type, rotation); + // Pass the calculated diameter instead of the input size + ent.Init(position, ent.Properties.Diameter, initialVelocity, type, rotation); MyEntities.Add(ent); if (!MyEntities.EntityExists(ent.EntityId)) { @@ -118,11 +119,11 @@ public static AsteroidEntity CreateAsteroid(Vector3D position, float size, Vecto return null; } - // Detailed spawn logging Log.Info($"Spawned ring asteroid {ent.EntityId}:" + $"\nType: {type}" + $"\nMass Range: {massRange.MinMass:N0}kg - {massRange.MaxMass:N0}kg" + $"\nFinal Mass: {finalMass:N0}kg" + + $"\nFinal Diameter: {ent.Properties.Diameter:F2}m" + $"\nRandom Factor: {randomFactor:F3}" + $"\nPosition: {position}" + $"\nVelocity: {initialVelocity.Length():F1}m/s" + @@ -135,15 +136,18 @@ public static AsteroidEntity CreateAsteroid(Vector3D position, float size, Vecto return null; } } + private void Init(Vector3D position, float size, Vector3D initialVelocity, AsteroidType type, Quaternion? rotation) { try { Type = type; ModelString = SelectModelForAsteroidType(type); - Properties = new AsteroidPhysicalProperties(size, AsteroidPhysicalProperties.DEFAULT_DENSITY, this); + // Don't create new Properties here, use the one created in CreateAsteroid Log.Info($"Initializing asteroid at {position} with size {size} and type {type}"); - Init(null, ModelString, null, Properties.Diameter); + // Set up the model with the proper scale + float modelScale = size; // dividing by 2 is a bit too small when compared to the hitbox but would make an ok bounding sphere + Init(null, ModelString, null, modelScale); if (string.IsNullOrEmpty(ModelString)) { Log.Warning($"Failed to assign model for asteroid type {type}"); @@ -151,7 +155,6 @@ private void Init(Vector3D position, float size, Vector3D initialVelocity, Aster PositionComp.SetPosition(position); - // Apply the rotation to the world matrix if (rotation.HasValue) { MatrixD worldMatrix = MatrixD.CreateFromQuaternion(rotation.Value); worldMatrix.Translation = position; @@ -170,7 +173,11 @@ private void Init(Vector3D position, float size, Vector3D initialVelocity, Aster SyncFlag = true; } - Log.Info($"Asteroid {EntityId} initialized with position {PositionComp.GetPosition()} and velocity {initialVelocity}"); + Log.Info($"Asteroid {EntityId} initialized:" + + $"\n - Position: {PositionComp.GetPosition()}" + + $"\n - Velocity: {initialVelocity}" + + $"\n - Model Scale: {modelScale}" + + $"\n - Physics Radius: {Properties.Radius}"); } catch (Exception ex) { Log.Exception(ex, typeof(AsteroidEntity), "Failed to initialize AsteroidEntity"); @@ -296,13 +303,17 @@ public void CreatePhysics() { Physics = null; } - // Reduced angular dampening to allow more natural rotation + Log.Info($"Creating physics for asteroid {EntityId}:" + + $"\n - Mass: {Properties.Mass:N0}kg" + + $"\n - Volume: {Properties.Volume:N0}m³" + + $"\n - Radius: {Properties.Radius:F2}m"); + PhysicsSettings settings = MyAPIGateway.Physics.CreateSettingsForPhysics( this, MatrixD.CreateTranslation(this.PositionComp.GetPosition()), Vector3.Zero, linearDamping: 0f, - angularDamping: 0.01f, // Very light dampening just to prevent extreme cases + angularDamping: 0.01f, rigidBodyFlags: RigidBodyFlag.RBF_DEFAULT, collisionLayer: CollisionLayers.NoVoxelCollisionLayer, isPhantom: false, @@ -312,21 +323,17 @@ public void CreatePhysics() { MyAPIGateway.Physics.CreateSpherePhysics(settings, Properties.Radius); - // Give it an initial spin if we're on the server if (MyAPIGateway.Session.IsServer) { - const float initialMaxSpin = 0.2f; // radians per second + const float initialMaxSpin = 0.2f; Vector3D randomSpin = RandVector() * initialMaxSpin; this.Physics.AngularVelocity = randomSpin; Log.Info($"Server: Set initial spin for asteroid {EntityId}: {randomSpin}"); } - - Log.Info($"Created physics for asteroid {EntityId} at position {this.PositionComp.GetPosition()}"); } catch (Exception ex) { Log.Exception(ex, typeof(AsteroidEntity), $"Error creating physics for asteroid {EntityId}"); } } - private static Vector3D RandVector() { var theta = MainSession.I.Rand.NextDouble() * 2.0 * Math.PI; var phi = Math.Acos(2.0 * MainSession.I.Rand.NextDouble() - 1.0); diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidPhysicalProperties.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidPhysicalProperties.cs index 8d1830c..2a43a94 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidPhysicalProperties.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidPhysicalProperties.cs @@ -33,12 +33,18 @@ public AsteroidPhysicalProperties(float diameter, float density = DEFAULT_DENSIT Radius = diameter / 2.0f; Density = density; + // Calculate volume and mass from diameter Volume = (4.0f / 3.0f) * MathHelper.Pi * (float)Math.Pow(Radius, 3); Mass = Volume * Density; MaxInstability = Mass * AsteroidSettings.InstabilityPerMass; InstabilityThreshold = MaxInstability * AsteroidSettings.InstabilityThresholdPercent; CurrentInstability = 0; + + Log.Info($"Created asteroid with:" + + $"\n - Diameter: {Diameter:F2}m" + + $"\n - Mass: {Mass:N0}kg" + + $"\n - Volume: {Volume:N0}m³"); } public void AddInstability(float amount) { @@ -67,9 +73,21 @@ public void ReduceMass(float damageAmount) { } public static AsteroidPhysicalProperties CreateFromMass(float targetMass, float density = DEFAULT_DENSITY, AsteroidEntity parentEntity = null) { + // Calculate volume from mass and density float volume = targetMass / density; + + // Calculate radius from volume (V = 4/3 * π * r³) float radius = (float)Math.Pow((3.0f * volume) / (4.0f * MathHelper.Pi), 1.0f / 3.0f); - return new AsteroidPhysicalProperties(radius * 2.0f, density, parentEntity); + + // Create new properties with calculated diameter + float diameter = radius * 2.0f; + + Log.Info($"Creating asteroid from mass:" + + $"\n - Target Mass: {targetMass:N0}kg" + + $"\n - Calculated Diameter: {diameter:F2}m" + + $"\n - Calculated Volume: {volume:N0}m³"); + + return new AsteroidPhysicalProperties(diameter, density, parentEntity); } public bool ShouldSpawnChunk() { diff --git a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSettings.cs b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSettings.cs index d2f9a61..7132039 100644 --- a/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSettings.cs +++ b/Dynamic Asteroids/Data/Scripts/DynamicAsteroids/AsteroidEntities/AsteroidSettings.cs @@ -32,23 +32,23 @@ public static class AsteroidSettings public static double ZoneRadius = 10000.0; public static int AsteroidVelocityBase = 0; public static double VelocityVariability = 0; - public static double AngularVelocityVariability = 0; + public static double AngularVelocityVariability = 0; //TODO: this gets corrected during runtime and doesnt actually work public static double MinDistanceFromVanillaAsteroids = 1000; - public static double MinDistanceFromPlayer = 3000; + public static double MinDistanceFromPlayer = 3000; //TODO: this might only be checking form the center of a zone. lets not make zones move with players yet public static int Seed = 69420; public static bool IgnorePlanets = true; - public static double IceWeight = 99; - public static double StoneWeight = 0.5; - public static double IronWeight = 0.25; - public static double NickelWeight = 0.05; - public static double CobaltWeight = 0.05; - public static double MagnesiumWeight = 0.05; - public static double SiliconWeight = 0.05; - public static double SilverWeight = 0.05; - public static double GoldWeight = 0.05; - public static double PlatinumWeight = 0.05; - public static double UraniniteWeight = 0.05; - public static float MinAsteroidSize = 50f; + public static double IceWeight = 97.4; + public static double StoneWeight = 1.0; + public static double IronWeight = 0.4; + public static double NickelWeight = 0.2; + public static double CobaltWeight = 0.2; //TODO: spawning weights might be way to proportionally out of whack for videogames gamplay + public static double MagnesiumWeight = 0.2; + public static double SiliconWeight = 0.2; + public static double SilverWeight = 0.1; + public static double GoldWeight = 0.1; + public static double PlatinumWeight = 0.1; + public static double UraniniteWeight = 0.1; + public static float MinAsteroidSize = 50f; //TODO: depreciate min and max since we have reasonable volumes (sphere) public static float MaxAsteroidSize = 250f; public static float InstabilityPerMass = 0.1f; public static float InstabilityThresholdPercent = 0.8f; @@ -76,18 +76,18 @@ public MassRange(float minMass, float maxMass) public static readonly Dictionary MinMaxMassByType = new Dictionary { - //TODO: put thse into confings, gradient toward gasgiant in ring for bigger roids - { AsteroidType.Ice, new MassRange(10000f, 5000000f) }, - { AsteroidType.Stone, new MassRange(8000f, 4000000f) }, - { AsteroidType.Iron, new MassRange(5000f, 3000000f) }, - { AsteroidType.Nickel, new MassRange(4000f, 2500000f) }, - { AsteroidType.Cobalt, new MassRange(3000f, 2000000f) }, - { AsteroidType.Magnesium, new MassRange(2000f, 1500000f) }, - { AsteroidType.Silicon, new MassRange(5000f, 3500000f) }, - { AsteroidType.Silver, new MassRange(2000f, 1000000f) }, - { AsteroidType.Gold, new MassRange(1000f, 800000f) }, - { AsteroidType.Platinum, new MassRange(500f, 500000f) }, - { AsteroidType.Uraninite, new MassRange(300f, 200000f) } + //TODO: think about how you'd make clusters of this stuff. maybe conglomerate rocks first + { AsteroidType.Ice, new MassRange(10000f, 5000000000f) }, + { AsteroidType.Stone, new MassRange(8000f, 4000000000f) }, + { AsteroidType.Iron, new MassRange(5000f, 3000000000f) }, + { AsteroidType.Nickel, new MassRange(4000f, 2500000000f) }, + { AsteroidType.Cobalt, new MassRange(3000f, 2000000000f) }, + { AsteroidType.Magnesium, new MassRange(2000f, 1500000000f) }, + { AsteroidType.Silicon, new MassRange(5000f, 3500000000f) }, + { AsteroidType.Silver, new MassRange(2000f, 1000000000f) }, + { AsteroidType.Gold, new MassRange(1000f, 800000000f) }, + { AsteroidType.Platinum, new MassRange(500f, 500000000f) }, + { AsteroidType.Uraninite, new MassRange(300f, 200000000f) } }; public static List ValidSpawnLocations = new List();