Skip to content

Commit

Permalink
Merge pull request #38 from InvalidArgument3/cores
Browse files Browse the repository at this point in the history
asteroid models
  • Loading branch information
InvalidArgument3 authored Jun 8, 2024
2 parents 13b11f8 + 723cf58 commit c4b9a8d
Show file tree
Hide file tree
Showing 25 changed files with 193 additions and 71 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System;
using System.IO;
using Sandbox.Definitions;
using Sandbox.Engine.Physics;
using Sandbox.Game.Entities;
using Sandbox.ModAPI;
using SC.SUGMA;
using VRage;
using VRage.Game;
using VRage.Game.Components;
Expand All @@ -18,70 +20,105 @@

namespace DynamicAsteroids.AsteroidEntities
{
public enum AsteroidType
{
Ice,
Stone,
Ore // We'll define specific ore types as needed
}

public class AsteroidEntity : MyEntity, IMyDestroyableObject
{
private const double VelocityVariability = 10;
private const double AngularVelocityVariability = 0.1;

private static readonly string[] AvailableModels = {
@"Models\Components\Sphere.mwm"
private static readonly string[] IceAsteroidModels = {
@"Models\IceAsteroid_1.mwm",
@"Models\IceAsteroid_2.mwm",
@"Models\IceAsteroid_3.mwm",
@"Models\IceAsteroid_4.mwm"
};

public static AsteroidEntity CreateAsteroid(Vector3D position, float size, Vector3D initialVelocity)
private static readonly string[] StoneAsteroidModels = {
@"Models\StoneAsteroid_1.mwm",
@"Models\StoneAsteroid_2.mwm",
@"Models\StoneAsteroid_3.mwm",
@"Models\StoneAsteroid_4.mwm",
@"Models\StoneAsteroid_5.mwm",
@"Models\StoneAsteroid_6.mwm",
@"Models\StoneAsteroid_7.mwm",
@"Models\StoneAsteroid_8.mwm",
@"Models\StoneAsteroid_9.mwm",
@"Models\StoneAsteroid_10.mwm",
@"Models\StoneAsteroid_11.mwm",
@"Models\StoneAsteroid_12.mwm",
@"Models\StoneAsteroid_13.mwm",
@"Models\StoneAsteroid_14.mwm",
@"Models\StoneAsteroid_15.mwm",
@"Models\StoneAsteroid_16.mwm"
};

// Placeholder for Ore Asteroids
private static readonly string[] OreAsteroidModels = {
// @"Models\OreAsteroid_Iron.mwm",
// @"Models\OreAsteroid_Nickel.mwm",
// @"Models\OreAsteroid_Cobalt.mwm",
// @"Models\OreAsteroid_Magnesium.mwm",
// @"Models\OreAsteroid_Silicon.mwm",
// @"Models\OreAsteroid_Silver.mwm",
// @"Models\OreAsteroid_Gold.mwm",
// @"Models\OreAsteroid_Platinum.mwm",
// @"Models\OreAsteroid_Uraninite.mwm"
};

public static AsteroidEntity CreateAsteroid(Vector3D position, float size, Vector3D initialVelocity, AsteroidType type)
{
var ent = new AsteroidEntity();
ent.Init(position, size, initialVelocity);
ent.Init(position, size, initialVelocity, type);
return ent;
}

public float Size = 3;
public string ModelString = "";
public AsteroidType Type;
private float _integrity = 1;

public void SplitAsteroid()
{
int splits = MainSession.I.Rand.Next(2, 5);

if (splits > Size)
splits = (int) Math.Ceiling(Size);
splits = (int)Math.Ceiling(Size);

float newSize = Size / splits;
MyAPIGateway.Utilities.ShowNotification($"NS: {newSize}");

if (newSize <= 1)
{
MyPhysicalItemDefinition item =
MyDefinitionManager.Static.GetPhysicalItemDefinition(new MyDefinitionId(typeof(MyObjectBuilder_Ore),
"Stone"));
MyPhysicalItemDefinition item = MyDefinitionManager.Static.GetPhysicalItemDefinition(new MyDefinitionId(typeof(MyObjectBuilder_Ore), "Stone"));
var newObject = MyObjectBuilderSerializer.CreateNewObject(item.Id.TypeId, item.Id.SubtypeId.ToString()) as MyObjectBuilder_PhysicalObject;
for (int i = 0; i < splits; i++)
{

//MyFloatingObjects.Spawn(item, PositionComp.GetPosition() + RandVector*Size*4, Vector3D.Forward, Vector3D.Up);

//MyObjectBuilder_PhysicalObject newObject = MyObjectBuilderSerializerKeen.CreateNewObject(item.Id.TypeId, item.Id.SubtypeName) as MyObjectBuilder_PhysicalObject;
MyFloatingObjects.Spawn(new MyPhysicalInventoryItem(1000, newObject), PositionComp.GetPosition() + RandVector()*Size, Vector3D.Forward, Vector3D.Up, Physics);
MyFloatingObjects.Spawn(new MyPhysicalInventoryItem(1000, newObject), PositionComp.GetPosition() + RandVector() * Size, Vector3D.Forward, Vector3D.Up, Physics);
}
Close();
return;
}

for (int i = 0; i < splits; i++)
{
Vector3D newPos = this.PositionComp.GetPosition() + RandVector() * Size;
CreateAsteroid(newPos, newSize, this.Physics.GetVelocityAtPoint(newPos));
Vector3D newPos = PositionComp.GetPosition() + RandVector() * Size;
CreateAsteroid(newPos, newSize, Physics.GetVelocityAtPoint(newPos), Type);
}
Close();
}


public void OnDestroy()
{
SplitAsteroid();
}

public bool DoDamage(float damage, MyStringHash damageSource, bool sync, MyHitInfo? hitInfo = null, long attackerId = 0,
long realHitEntityId = 0, bool shouldDetonateAmmo = true, MyStringHash? extraInfo = null)
public bool DoDamage(float damage, MyStringHash damageSource, bool sync, MyHitInfo? hitInfo = null, long attackerId = 0, long realHitEntityId = 0, bool shouldDetonateAmmo = true, MyStringHash? extraInfo = null)
{
_integrity -= damage;
if (Integrity < 0)
Expand All @@ -93,33 +130,56 @@ public bool DoDamage(float damage, MyStringHash damageSource, bool sync, MyHitIn

public bool UseDamageSystem => true;


private void Init(Vector3D position, float size, Vector3D initialVelocity)
private void Init(Vector3D position, float size, Vector3D initialVelocity, AsteroidType type)
{
ModelString = AvailableModels[MainSession.I.Rand.Next(0, AvailableModels.Length - 1)];
Size = size;
try
{
Log.Info("Initializing asteroid entity");
string modPath = Path.Combine(MainSession.I.ModContext.ModPath, "");
Type = type;
switch (type)
{
case AsteroidType.Ice:
ModelString = Path.Combine(modPath, IceAsteroidModels[MainSession.I.Rand.Next(IceAsteroidModels.Length)]);
break;
case AsteroidType.Stone:
ModelString = Path.Combine(modPath, StoneAsteroidModels[MainSession.I.Rand.Next(StoneAsteroidModels.Length)]);
break;
case AsteroidType.Ore:
// Placeholder logic for ore asteroids, use the correct models when ready
// ModelString = Path.Combine(modPath, OreAsteroidModels[MainSession.I.Rand.Next(OreAsteroidModels.Length)]);
break;
}
Size = size;

Init(null, ModelString, null, Size);
Log.Info($"Attempting to load model: {ModelString}");

if (string.IsNullOrEmpty(ModelString))
Flags &= ~EntityFlags.Visible;
Init(null, ModelString, null, Size);

if (string.IsNullOrEmpty(ModelString))
Flags &= ~EntityFlags.Visible;

Save = false;
NeedsWorldMatrix = true;
Save = false;
NeedsWorldMatrix = true;

//Flags |= EntityFlags.Visible;
//Flags |= EntityFlags.Near;
//Flags |= EntityFlags.Sync;
//Flags |= EntityFlags.NeedsDraw;
PositionComp.LocalAABB = new BoundingBox(-Vector3.Half*Size, Vector3.Half*Size);
PositionComp.LocalAABB = new BoundingBox(-Vector3.Half * Size, Vector3.Half * Size);

WorldMatrix = MatrixD.CreateWorld(position, Vector3D.Forward, Vector3D.Up);
WorldMatrix = MatrixD.CreateWorld(position, Vector3D.Forward, Vector3D.Up);
WorldMatrix.Orthogonalize(); // Normalize the matrix to prevent rotation spazzing

MyEntities.Add(this);
MyEntities.Add(this);

CreatePhysics();
Physics.LinearVelocity = initialVelocity + RandVector() * VelocityVariability;
Physics.AngularVelocity = RandVector() * AngularVelocityVariability;
CreatePhysics();
Physics.LinearVelocity = initialVelocity + RandVector() * VelocityVariability;
Physics.AngularVelocity = RandVector() * AngularVelocityVariability; // Set initial angular velocity

Log.Info($"Asteroid model {ModelString} loaded successfully with initial angular velocity: {Physics.AngularVelocity}");
}
catch (Exception ex)
{
Log.Exception(ex, typeof(AsteroidEntity), $"Failed to load model: {ModelString}");
Flags &= ~EntityFlags.Visible;
}
}

private void CreatePhysics()
Expand All @@ -129,18 +189,14 @@ private void CreatePhysics()
this,
WorldMatrix,
Vector3.Zero,
linearDamping: 0,
angularDamping: 0,
linearDamping: 0f, // Remove damping
angularDamping: 0f, // Remove damping
collisionLayer: CollisionLayers.DefaultCollisionLayer,
//rigidBodyFlags: RigidBodyFlag.RBF_UNLOCKED_SPEEDS,
isPhantom: false,
mass: new ModAPIMass(PositionComp.LocalAABB.Volume(), mass, Vector3.Zero, mass * PositionComp.LocalAABB.Height * PositionComp.LocalAABB.Height / 6 * Matrix.Identity)
);

//settings.DetectorColliderCallback += HitCallback;
//settings.Entity.Flags |= EntityFlags.IsGamePrunningStructureObject;
MyAPIGateway.Physics.CreateBoxPhysics(settings, PositionComp.LocalAABB.HalfExtents, 0);

Physics.Enabled = true;
Physics.Activate();
}
Expand All @@ -150,7 +206,7 @@ private Vector3D RandVector()
var theta = MainSession.I.Rand.NextDouble() * 2.0 * Math.PI;
var phi = Math.Acos(2.0 * MainSession.I.Rand.NextDouble() - 1.0);
var sinPhi = Math.Sin(phi);
return Math.Pow(MainSession.I.Rand.NextDouble(), 1/3d) * new Vector3D(sinPhi * Math.Cos(theta), sinPhi * Math.Sin(theta), Math.Cos(phi));
return Math.Pow(MainSession.I.Rand.NextDouble(), 1 / 3d) * new Vector3D(sinPhi * Math.Cos(theta), sinPhi * Math.Sin(theta), Math.Cos(phi));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,63 +1,116 @@
using System;
using System.Collections.Generic;
using Sandbox.ModAPI;
using SC.SUGMA;
using VRage.Game.ModAPI;
using VRage.ModAPI;
using VRageMath;

namespace DynamicAsteroids.AsteroidEntities
{
internal class AsteroidSpawner
{
private List<AsteroidEntity> _asteroids;
private const double MinDistanceFromVanillaAsteroids = 1000; // 1 km

public void Init()
{
Log.Info("Initializing AsteroidSpawner");
_asteroids = new List<AsteroidEntity>(AsteroidSettings.MaxAsteroidCount);
}

public void Close()
{
Log.Info("Closing AsteroidSpawner");
_asteroids.Clear();
}

public void UpdateTick()
{
Vector3D playerPosition = MyAPIGateway.Session?.Player?.GetPosition() ?? Vector3D.MaxValue;
try
{
Vector3D playerPosition = MyAPIGateway.Session?.Player?.GetPosition() ?? Vector3D.MaxValue;

if (playerPosition == Vector3D.MaxValue || !AsteroidSettings.PlayerCanSeeRings(playerPosition))
return;
if (playerPosition == Vector3D.MaxValue || !AsteroidSettings.PlayerCanSeeRings(playerPosition))
return;

foreach (var asteroid in _asteroids.ToArray())
{
if (Vector3D.DistanceSquared(asteroid.PositionComp.GetPosition(), playerPosition) >
AsteroidSettings.AsteroidSpawnRadius * AsteroidSettings.AsteroidSpawnRadius * 1.1)
foreach (var asteroid in _asteroids.ToArray())
{
_asteroids.Remove(asteroid);
asteroid.Close();
continue;
if (Vector3D.DistanceSquared(asteroid.PositionComp.GetPosition(), playerPosition) >
AsteroidSettings.AsteroidSpawnRadius * AsteroidSettings.AsteroidSpawnRadius * 1.1)
{
_asteroids.Remove(asteroid);
asteroid.Close();
continue;
}
}
}

int asteroidsSpawned = 0;
while (_asteroids.Count < AsteroidSettings.MaxAsteroidCount && asteroidsSpawned < 10)
int asteroidsSpawned = 0;
while (_asteroids.Count < AsteroidSettings.MaxAsteroidCount && asteroidsSpawned < 10)
{
Vector3D newPosition = playerPosition + RandVector() * AsteroidSettings.AsteroidSpawnRadius;
Vector3D newVelocity;
if (!AsteroidSettings.CanSpawnAsteroidAtPoint(newPosition, out newVelocity))
continue;

if (IsNearVanillaAsteroid(newPosition))
{
Log.Info("Skipped spawning asteroid due to proximity to vanilla asteroid.");
continue;
}

// Determine asteroid type to spawn
AsteroidType type = DetermineAsteroidType();

_asteroids.Add(AsteroidEntity.CreateAsteroid(newPosition, RandAsteroidSize, newVelocity, type));
asteroidsSpawned++;
}

// Show a notification with the number of active asteroids
MyAPIGateway.Utilities.ShowNotification($"Active Asteroids: {_asteroids.Count}", 1000 / 60);

// Log the number of active asteroids for debugging purposes
Log.Info($"Active Asteroids: {_asteroids.Count}");
}
catch (Exception ex)
{
Vector3D newPosition = playerPosition + RandVector()*AsteroidSettings.AsteroidSpawnRadius;
Vector3D newVelocity;
if (!AsteroidSettings.CanSpawnAsteroidAtPoint(newPosition, out newVelocity))
continue;
_asteroids.Add(AsteroidEntity.CreateAsteroid(newPosition, RandAsteroidSize, newVelocity));
Log.Exception(ex, typeof(AsteroidSpawner));
}
}

private bool IsNearVanillaAsteroid(Vector3D position)
{
List<IMyVoxelBase> voxelMaps = new List<IMyVoxelBase>();
MyAPIGateway.Session.VoxelMaps.GetInstances(voxelMaps, v => v is IMyVoxelMap && !v.StorageName.StartsWith("mod_"));

asteroidsSpawned++;
foreach (var voxelMap in voxelMaps)
{
if (Vector3D.DistanceSquared(position, voxelMap.GetPosition()) < MinDistanceFromVanillaAsteroids * MinDistanceFromVanillaAsteroids)
{
return true;
}
}

return false;
}

private Vector3D RandVector()
{
var theta = MainSession.I.Rand.NextDouble() * 2.0 * Math.PI;
var phi = Math.Acos(2.0 * MainSession.I.Rand.NextDouble() - 1.0);
var sinPhi = Math.Sin(phi);
return Math.Pow(MainSession.I.Rand.NextDouble(), 1/3d) * new Vector3D(sinPhi * Math.Cos(theta), sinPhi * Math.Sin(theta), Math.Cos(phi));
return Math.Pow(MainSession.I.Rand.NextDouble(), 1 / 3d) * new Vector3D(sinPhi * Math.Cos(theta), sinPhi * Math.Sin(theta), Math.Cos(phi));
}

private float RandAsteroidSize => (float) (MainSession.I.Rand.NextDouble()*MainSession.I.Rand.NextDouble()*MainSession.I.Rand.NextDouble()*500) + 1.5f;
private float RandAsteroidSize => (float)(MainSession.I.Rand.NextDouble() * MainSession.I.Rand.NextDouble() * MainSession.I.Rand.NextDouble() * 500) + 1.5f;

// This function determines the type of asteroid to spawn
private AsteroidType DetermineAsteroidType()
{
// Here you can add logic to determine the type of asteroid.
// For example, randomly selecting a type or using some other logic.
int randValue = MainSession.I.Rand.Next(0, 2); // Adjust as needed for more types
return (AsteroidType)randValue;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ internal static class AsteroidSettings
{
public static int MaxAsteroidCount = 1000;
public static int AsteroidSpawnRadius = 10000;
public static int AsteroidVelocityBase = 80;
public static int AsteroidVelocityBase = 0;

public static SpawnableArea[] ValidSpawnLocations =
{
Expand Down
Loading

0 comments on commit c4b9a8d

Please sign in to comment.