public static void GetSpawnPosition(float collisionRadius, out Vector3 direction, out Vector3D position) { float distance = 0; foreach (var entity in MyEntities.GetEntities()) { // Include only voxels if (entity is MyVoxelMap) { distance = (float)MathHelper.Max(distance, entity.PositionComp.WorldVolume.Center.Length() + entity.PositionComp.WorldVolume.Radius); } } // 500 - 650m from last voxel distance += MyUtils.GetRandomFloat(500, 650); if (MyEntities.IsWorldLimited()) { distance = Math.Min(distance, MyEntities.WorldSafeHalfExtent()); } else { distance = Math.Min(distance, 20000); // limited spawn area in infinite worlds } direction = MyUtils.GetRandomVector3Normalized(); var searchPosition = MyEntities.FindFreePlace((Vector3D)(direction * distance), collisionRadius); if (!searchPosition.HasValue) { searchPosition = (Vector3D)(direction * distance); // Spawn in existing place (better than crash) } Vector3D globalPoint = (Vector3D)searchPosition; position = globalPoint; if (MyGravityProviderSystem.CalculateNaturalGravityInPoint(globalPoint) != null && MyGravityProviderSystem.CalculateNaturalGravityInPoint(globalPoint).Length() != 0) { MyPlanet planet = MyGravityProviderSystem.GetStrongestGravityWell(globalPoint); double multiplier = planet.MaximumRadius / globalPoint.Length(); globalPoint *= multiplier; Vector3D closestPoint = planet.GetClosestSurfacePointGlobal(ref globalPoint) * 1.25; searchPosition = MyEntities.FindFreePlace(closestPoint, collisionRadius); if (searchPosition.HasValue) { position = searchPosition.Value; } } else { position = searchPosition.Value; } }
private bool SpawnDrone(MyRadioAntenna antenna, long ownerId, Vector3D position, MySpawnGroupDefinition spawnGroup) { long antennaEntityId = antenna.EntityId; Vector3D antennaPos = antenna.PositionComp.GetPosition(); var planet = MyGravityProviderSystem.GetStrongestGravityWell(position); Vector3D upVector; if (planet != null && planet.IsPositionInGravityWell(position)) { if (!MyGravityProviderSystem.IsPositionInNaturalGravity(antennaPos)) { MySandboxGame.Log.WriteLine("Couldn't spawn drone; antenna is not in natural gravity but spawn location is."); return(false); } planet.CorrectSpawnLocation(ref position, spawnGroup.SpawnRadius * 2.0); upVector = -planet.GetWorldGravityNormalized(ref position); } else { upVector = MyUtils.GetRandomVector3Normalized(); } Vector3D direction = MyUtils.GetRandomPerpendicularVector(ref upVector); MatrixD originMatrix = MatrixD.CreateWorld(position, direction, upVector); foreach (var shipPrefab in spawnGroup.Prefabs) { Vector3D shipPosition = Vector3D.Transform((Vector3D)shipPrefab.Position, originMatrix); m_tmpGridList.Clear(); MyPrefabManager.Static.SpawnPrefab( resultList: m_tmpGridList, prefabName: shipPrefab.SubtypeId, position: shipPosition, forward: direction, up: upVector, initialLinearVelocity: default(Vector3), beaconName: null, spawningOptions: VRage.Game.ModAPI.SpawningOptions.None, ownerId: ownerId, updateSync: true); foreach (var grid in m_tmpGridList) { grid.ChangeGridOwnership(ownerId, MyOwnershipShareModeEnum.None); MyRemoteControl firstRemote = null; foreach (var block in grid.CubeBlocks) { if (block.FatBlock == null) { continue; } var pb = block.FatBlock as MyProgrammableBlock; if (pb != null) { pb.SendRecompile(); } var remote = block.FatBlock as MyRemoteControl; if (firstRemote == null) { firstRemote = remote; } } // If there's no remote control on the grid, we have to register it as is RegisterDrone(antennaEntityId, (MyEntity)firstRemote ?? (MyEntity)grid); } m_tmpGridList.Clear(); } return(true); }
public override void UpdateBeforeSimulation() { base.UpdateBeforeSimulation(); if (!MyFakes.ENABLE_PLANET_FIREFLIES) { return; } if (m_particleSpawnCounter-- > 0) { return; } m_particleSpawnCounter = 0; var entity = MySession.Static.ControlledEntity as MyEntity; if (entity == null) { return; } var controlledEntity = entity.GetTopMostParent(); if (controlledEntity == null) { return; } try { ProfilerShort.Begin("Fireflies.Spawn"); m_particleSpawnCounter = (int)Math.Round(m_particleSpawnCounter + m_particleSpawnCounter * m_particleSpawnIntervalRandomness * (MyRandom.Instance.NextFloat() * 2.0f - 1.0f)); float normalVar = (MyRandom.Instance.FloatNormal() + 3.0f) / 6.0f; if (normalVar > m_particleDensity) { return; } var naturalGravity = MyGravityProviderSystem.CalculateNaturalGravityInPoint(MySector.MainCamera.Position); if (naturalGravity.Dot(MySector.DirectionToSunNormalized) <= 0) // Only spawn at night and on planets { return; } var velocity = (MySession.Static.GetCameraControllerEnum() != MyCameraControllerEnum.Entity && MySession.Static.GetCameraControllerEnum() != MyCameraControllerEnum.ThirdPersonSpectator ? Vector3.Zero : controlledEntity.Physics.LinearVelocity); var speed = velocity.Length(); var currentCharacter = controlledEntity as MyCharacter; float characterFlyingMaxSpeed = MyGridPhysics.ShipMaxLinearVelocity(); if (currentCharacter != null && currentCharacter.Physics != null && currentCharacter.Physics.CharacterProxy != null) { characterFlyingMaxSpeed = currentCharacter.Physics.CharacterProxy.CharacterFlyingMaxLinearVelocity(); } Vector3 halfExtents = Vector3.One * m_particleSpawnDistance; if (speed / characterFlyingMaxSpeed > 1.0f) { halfExtents += 10.0f * velocity / characterFlyingMaxSpeed; } var entityTranslation = MySector.MainCamera.Position; var searchPosition = entityTranslation + velocity; MyPlanet planet = MyGravityProviderSystem.GetStrongestGravityWell(MySector.MainCamera.Position); if (planet == null || !planet.IsPositionInGravityWell(MySector.MainCamera.Position)) { return; } Vector3D cameraPosition = MySector.MainCamera.Position; var foundEnvironmentItems = planet.GetEnvironmentItemsAtPosition(ref cameraPosition); foreach (var environmentItems in foundEnvironmentItems) { environmentItems.GetAllItemsInRadius(searchPosition, m_particleSpawnDistance, m_tmpItemInfos); } var spawnPosition = default(Vector3D); bool spawnPositionFound = m_tmpItemInfos.Count != 0; if (spawnPositionFound) { int selectedTreeIndex = MyRandom.Instance.Next(0, m_tmpItemInfos.Count - 1); spawnPosition = m_tmpItemInfos[selectedTreeIndex].Transform.Position; spawnPositionFound = true; } else { return; } var spawnedParticle = Spawn(spawnPosition); if (spawnedParticle == null) { return; } InitializePath(spawnedParticle); } finally { m_bodyCollisions.Clear(); m_tmpItemInfos.Clear(); ProfilerShort.End(); } }
/// <summary> /// Returns a position that should be safe to spawn at given the radius and position. /// </summary> /// <param name="collisionRadius">The radius of the object that is trying to spawn.</param> /// <param name="position">The position the object would like to spawn at.</param> /// <param name="forward">(Out) The forward vector the object should spawn with.</param> /// <param name="up">(Out) The up vector the object should spawn with.</param> /// <param name="planetSpawnHeightRatio">The ratio within the planet's max radius and atmosphere radius you are positioned in.</param> /// <param name="randomRangeMin">The minimum randomized distance that is added.</param> /// <param name="randomRangeMax">The minimum randomized distance that is added.</param> public static void GetSpawnPosition(float collisionRadius, ref Vector3D position, out Vector3D forward, out Vector3D up, float planetSpawnHeightRatio = 0.3f, float randomRangeMin = 500, float randomRangeMax = 650) { // Are we spawning near a planet? Vector3 gravity = MyGravityProviderSystem.CalculateNaturalGravityInPoint(position); if (gravity.LengthSquared() > 0) { MyPlanet planet = MyGravityProviderSystem.GetStrongestGravityWell(position); if (planet != null) { GetSpawnPositionNearPlanet(planet, collisionRadius, ref position, out forward, out up, planetSpawnHeightRatio, randomRangeMin, randomRangeMax); return; } } // Old logic, testing for asteroids and other objects double distance = 0; foreach (var entity in MyEntities.GetEntities()) { MyVoxelMap voxelMap = entity as MyVoxelMap; // Only test against voxels if (entity == null) { continue; } distance = MathHelper.Max(distance, entity.PositionComp.WorldVolume.Center.Length() + entity.PositionComp.WorldVolume.Radius); } // Random range from last voxel distance += MyUtils.GetRandomFloat(randomRangeMin, randomRangeMax); if (MyEntities.IsWorldLimited()) { distance = Math.Min(distance, MyEntities.WorldSafeHalfExtent()); } else { distance = Math.Min(distance, 20000); // limited spawn area in infinite worlds } // Compute random position forward = MyUtils.GetRandomVector3Normalized(); up = Vector3D.CalculatePerpendicularVector(forward); Vector3D randomizedPosition = position + (forward * distance); // Test if we can spawn here Vector3D?searchPosition = MyEntities.FindFreePlace(randomizedPosition, collisionRadius); if (searchPosition.HasValue) { randomizedPosition = searchPosition.Value; } // Make sure we didn't randomize into a planet gravity = MyGravityProviderSystem.CalculateNaturalGravityInPoint(randomizedPosition); if (gravity.LengthSquared() > 0) { MyPlanet planet = MyGravityProviderSystem.GetStrongestGravityWell(randomizedPosition); if (planet != null) { GetSpawnPositionNearPlanet(planet, collisionRadius, ref position, out forward, out up, planetSpawnHeightRatio, randomRangeMin, randomRangeMax); } else { position = randomizedPosition; } } else { position = randomizedPosition; } }