public GroupInfo() { m_cost = 0; m_spawnClass = SpawnerClass.ANY; m_spawnType = SpawnerType.ANY; m_spawnGroupDef = null; }
public static NPCTerritory GetOldTerritoryDetails(MySpawnGroupDefinition spawnGroup) { var territory = new NPCTerritory(); territory.Name = spawnGroup.Id.SubtypeName; territory.TagOld = spawnGroup.Prefabs[0].BeaconText; territory.Position = (Vector3D)spawnGroup.Prefabs[0].Position; territory.Radius = (double)spawnGroup.Prefabs[0].Speed; return(territory); }
public GroupInfo( int cost, SpawnerClass spawnClass, SpawnerType spawnType, MySpawnGroupDefinition spawnGroup) { m_cost = cost; m_spawnClass = spawnClass; m_spawnType = spawnType; m_spawnGroupDef = spawnGroup; }
private static BoundingBox GetEncounterBoundingBox(MySpawnGroupDefinition selectedEncounter) { BoundingBox encouterBoundingBox = new BoundingBox(Vector3.Zero, Vector3.Zero); selectedEncounter.ReloadPrefabs(); foreach (var selectedPrefab in selectedEncounter.Prefabs) { var prefabDefinition = MyDefinitionManager.Static.GetPrefabDefinition(selectedPrefab.SubtypeId); encouterBoundingBox.Include(prefabDefinition.BoundingSphere); } return(encouterBoundingBox); }
public static void SpawnSpawmGroup(string spawnGroup, MatrixD spawnOrigin, Options options = null) { MyAPIGateway.Parallel.Start(delegate { List <MySpawnGroupDefinition> spawnGroupDefinitions = new List <MySpawnGroupDefinition>(MyDefinitionManager.Static.GetSpawnGroupDefinitions()); MySpawnGroupDefinition spawnGroupDefinition = spawnGroupDefinitions.Find(x => x.Id.SubtypeName == spawnGroup); foreach (MySpawnGroupDefinition.SpawnGroupPrefab spawnGroupPrefab in spawnGroupDefinition.Prefabs) { Vector3D prefabSpawnPos = Vector3D.Transform(spawnGroupPrefab.Position, spawnOrigin); MatrixD prefabSpawnMatrix = spawnOrigin; prefabSpawnMatrix.Translation = prefabSpawnPos; SpawnPrefab(spawnGroupPrefab.SubtypeId, prefabSpawnMatrix, options); MyAPIGateway.Parallel.Sleep(1000); } }); }
public static bool IsSpawnGroupATerritory(MySpawnGroupDefinition spawnGroup) { if (spawnGroup.DescriptionText != null) { if (spawnGroup.DescriptionText.Contains("[Modular Encounters Territory]") == true) { return(true); } } if (spawnGroup.Prefabs.Count > 0) { if (spawnGroup.Prefabs[0].SubtypeId == "TerritoryPlaceholder") { return(true); } } return(false); }
public static NPCTerritory GetNewTerritoryDetails(MySpawnGroupDefinition spawnGroup) { var territory = new NPCTerritory(); var descSplit = spawnGroup.DescriptionText.Split('\n'); var tempCoords = Vector3D.Zero; foreach (var tag in descSplit) { //Name if (tag.Contains("[Name") == true) { bool badParse = false; territory.Name = SpawnGroupManager.TagStringCheck(tag, spawnGroup.Id.SubtypeName, out badParse); if (territory.BadTerritory == false && badParse == true) { territory.BadTerritory = true; } } //Type if (tag.Contains("[Type") == true) { bool badParse = false; territory.Type = SpawnGroupManager.TagStringCheck(tag, spawnGroup.Id.SubtypeName, out badParse); if (territory.BadTerritory == false && badParse == true) { territory.BadTerritory = true; } } //Active if (tag.Contains("[Active") == true) { bool badParse = false; territory.Active = SpawnGroupManager.TagBoolCheck(tag, spawnGroup.Id.SubtypeName, out badParse); if (territory.BadTerritory == false && badParse == true) { territory.BadTerritory = true; } } //Radius if (tag.Contains("[Radius") == true) { bool badParse = false; territory.Radius = SpawnGroupManager.TagDoubleCheck(tag, spawnGroup.Id.SubtypeName, territory.Radius, out badParse); if (territory.BadTerritory == false && badParse == true) { territory.BadTerritory = true; } } //ScaleRadiusWithPlanetSize if (tag.Contains("[ScaleRadiusWithPlanetSize") == true) { bool badParse = false; territory.ScaleRadiusWithPlanetSize = SpawnGroupManager.TagBoolCheck(tag, spawnGroup.Id.SubtypeName, out badParse); if (territory.BadTerritory == false && badParse == true) { territory.BadTerritory = true; } } //NoSpawnZone if (tag.Contains("[NoSpawnZone") == true) { bool badParse = false; territory.NoSpawnZone = SpawnGroupManager.TagBoolCheck(tag, spawnGroup.Id.SubtypeName, out badParse); if (territory.BadTerritory == false && badParse == true) { territory.BadTerritory = true; } } //StrictTerritory if (tag.Contains("[StrictTerritory") == true) { bool badParse = false; territory.StrictTerritory = SpawnGroupManager.TagBoolCheck(tag, spawnGroup.Id.SubtypeName, out badParse); if (territory.BadTerritory == false && badParse == true) { territory.BadTerritory = true; } } //FactionTagWhitelist if (tag.Contains("[FactionTagWhitelist") == true) { bool badParse = false; territory.FactionTagWhitelist = SpawnGroupManager.TagStringListCheck(tag, spawnGroup.Id.SubtypeName, out badParse); if (territory.BadTerritory == false && badParse == true) { territory.BadTerritory = true; } } //FactionTagBlacklist if (tag.Contains("[FactionTagBlacklist") == true) { bool badParse = false; territory.FactionTagBlacklist = SpawnGroupManager.TagStringListCheck(tag, spawnGroup.Id.SubtypeName, out badParse); if (territory.BadTerritory == false && badParse == true) { territory.BadTerritory = true; } } //CoordsX if (tag.Contains("[CoordsX") == true) { bool badParse = false; tempCoords.X = SpawnGroupManager.TagDoubleCheck(tag, spawnGroup.Id.SubtypeName, territory.Position.X, out badParse); if (territory.BadTerritory == false && badParse == true) { territory.BadTerritory = true; } } //CoordsY if (tag.Contains("[CoordsY") == true) { bool badParse = false; tempCoords.Y = SpawnGroupManager.TagDoubleCheck(tag, spawnGroup.Id.SubtypeName, territory.Position.Y, out badParse); if (territory.BadTerritory == false && badParse == true) { territory.BadTerritory = true; } } //CoordsZ if (tag.Contains("[CoordsZ") == true) { bool badParse = false; tempCoords.Z = SpawnGroupManager.TagDoubleCheck(tag, spawnGroup.Id.SubtypeName, territory.Position.Z, out badParse); if (territory.BadTerritory == false && badParse == true) { territory.BadTerritory = true; } } //AnnounceArriveDepart if (tag.Contains("[AnnounceArriveDepart") == true) { bool badParse = false; territory.AnnounceArriveDepart = SpawnGroupManager.TagBoolCheck(tag, spawnGroup.Id.SubtypeName, out badParse); if (territory.BadTerritory == false && badParse == true) { territory.BadTerritory = true; } } //CustomArriveMessage if (tag.Contains("[CustomArriveMessage") == true) { bool badParse = false; territory.CustomArriveMessage = SpawnGroupManager.TagStringCheck(tag, spawnGroup.Id.SubtypeName, out badParse); if (territory.BadTerritory == false && badParse == true) { territory.BadTerritory = true; } } //CustomDepartMessage if (tag.Contains("[CustomDepartMessage") == true) { bool badParse = false; territory.CustomDepartMessage = SpawnGroupManager.TagStringCheck(tag, spawnGroup.Id.SubtypeName, out badParse); if (territory.BadTerritory == false && badParse == true) { territory.BadTerritory = true; } } //PlanetGeneratorName if (tag.Contains("[PlanetGeneratorName") == true) { bool badParse = false; territory.PlanetGeneratorName = SpawnGroupManager.TagStringCheck(tag, spawnGroup.Id.SubtypeName, out badParse); if (territory.BadTerritory == false && badParse == true) { territory.BadTerritory = true; } } } territory.Position = tempCoords; return(territory); }
public static void OnGlobalSpawnEvent(object senderEvent) { // Select a spawn group to spawn MySpawnGroupDefinition spawnGroup = PickRandomSpawnGroup(); if (spawnGroup == null) { return; } spawnGroup.ReloadPrefabs(); ProfilerShort.Begin("Generate position and direction"); double spawnDistance = NEUTRAL_SHIP_SPAWN_DISTANCE; Vector3D playerPosition = Vector3D.Zero; bool isWorldLimited = MyEntities.IsWorldLimited(); int numPlayers = 0; if (isWorldLimited) { spawnDistance = Math.Min(spawnDistance, MyEntities.WorldSafeHalfExtent() - spawnGroup.SpawnRadius); } else { // In infinite worlds players can be thousands of kilometers away, so spawn ship around random player // so cargo ships will be spawned around every player at some time var players = MySession.Static.Players.GetOnlinePlayers(); // In DS there can be no players connected numPlayers = Math.Max(0, players.Count - 1); int randomPlayerPosition = MyUtils.GetRandomInt(0, numPlayers); int i = 0; foreach (var player in players) { if (i == randomPlayerPosition) { if (player.Character != null) { playerPosition = player.GetPosition(); } break; } i++; } } if (spawnDistance < 0.0f) { MySandboxGame.Log.WriteLine("Not enough space in the world to spawn such a huge spawn group!"); return; } double forbiddenRadius = NEUTRAL_SHIP_FORBIDDEN_RADIUS; BoundingBoxD spawnBox; if (isWorldLimited) { spawnBox = new BoundingBoxD(new Vector3D(playerPosition - spawnDistance), new Vector3D(playerPosition + spawnDistance)); } else { // We need to extend bouding box so cargo ships aren't spawned near other players GetSafeBoundingBoxForPlayers(playerPosition, spawnDistance, out spawnBox); // Forbidden radius is sphere around all players in box. // Bounding box is generated from players positions so their distance to center shall be same for all players forbiddenRadius += spawnBox.HalfExtents.Max() - NEUTRAL_SHIP_FORBIDDEN_RADIUS; } // Get the direction to the center and deviate it randomly Vector3D?origin = MyUtils.GetRandomBorderPosition(ref spawnBox); origin = MyEntities.TestPlaceInSpace(origin.Value, spawnGroup.SpawnRadius); if (!origin.HasValue) { if (++m_eventSpawnTry <= EVENT_SPAWN_TRY_MAX) { MySandboxGame.Log.WriteLine("Could not spawn neutral ships - no free place found. Try " + m_eventSpawnTry + " of " + EVENT_SPAWN_TRY_MAX); MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME); ProfilerShort.End(); return; } else { m_eventSpawnTry = 0; return; } } m_eventSpawnTry = 0; // Radius in arc units of the forbidden sphere in the center, when viewed from origin float centerArcRadius = (float)Math.Atan(forbiddenRadius / (origin.Value - spawnBox.Center).Length()); // Generate direction with elevation from centerArcRadius radians to (cAR + N_S_D_S) radians Vector3D direction = -Vector3D.Normalize(origin.Value); float theta = MyUtils.GetRandomFloat(centerArcRadius, centerArcRadius + NEUTRAL_SHIP_DIRECTION_SPREAD); float phi = MyUtils.GetRandomRadian(); Vector3D cosVec = Vector3D.CalculatePerpendicularVector(direction); Vector3D sinVec = Vector3D.Cross(direction, cosVec); cosVec *= (Math.Sin(theta) * Math.Cos(phi)); sinVec *= (Math.Sin(theta) * Math.Sin(phi)); direction = direction * Math.Cos(theta) + cosVec + sinVec; Vector3D destination = Vector3D.Zero; RayD ray = new RayD(origin.Value, direction); double? intersection = ray.Intersects(spawnBox); Vector3D directionMult; if (!intersection.HasValue || intersection.Value < NEUTRAL_SHIP_MINIMAL_ROUTE_LENGTH) { directionMult = direction * NEUTRAL_SHIP_MINIMAL_ROUTE_LENGTH; } else { directionMult = direction * intersection.Value; } destination = origin.Value + directionMult; Vector3D upVector = Vector3D.CalculatePerpendicularVector(direction); Vector3D rightVector = Vector3D.Cross(direction, upVector); MatrixD originMatrix = MatrixD.CreateWorld(origin.Value, direction, upVector); ProfilerShort.End(); ProfilerShort.Begin("Check free space"); // CH:TODO: Convex cast to detect collision // Check ships' path to avoid possible collisions. (TODO: But only if it is said in the definitions) m_raycastHits.Clear(); foreach (var shipPrefab in spawnGroup.Prefabs) { var prefabDef = MyDefinitionManager.Static.GetPrefabDefinition(shipPrefab.SubtypeId); Debug.Assert(prefabDef != null); Vector3D shipPosition = Vector3.Transform(shipPrefab.Position, originMatrix); Vector3D shipDestination = shipPosition + directionMult; float radius = prefabDef == null ? 10.0f : prefabDef.BoundingSphere.Radius; //these point checks could be done in the trajectory intersect, but checking points is faster than ray intersect if (MyGravityProviderSystem.IsPositionInNaturalGravity(shipPosition, spawnGroup.SpawnRadius)) { if (!MyFinalBuildConstants.IS_OFFICIAL) { MySandboxGame.Log.WriteLine("Could not spawn neutral ships: spawn point is inside gravity well"); } MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME); ProfilerShort.End(); return; } if (MyGravityProviderSystem.IsPositionInNaturalGravity(shipDestination, spawnGroup.SpawnRadius)) { if (!MyFinalBuildConstants.IS_OFFICIAL) { MySandboxGame.Log.WriteLine("Could not spawn neutral ships: destination point is inside gravity well"); } MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME); ProfilerShort.End(); return; } if (MyGravityProviderSystem.DoesTrajectoryIntersectNaturalGravity(shipPosition, shipDestination, spawnGroup.SpawnRadius + NEUTRAL_SHIP_SPAWN_OFFSET)) { if (!MyFinalBuildConstants.IS_OFFICIAL) { MySandboxGame.Log.WriteLine("Could not spawn neutral ships: flight path intersects gravity well"); } MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME); ProfilerShort.End(); return; } MyPhysics.CastRay(shipPosition, shipDestination, m_raycastHits, MyPhysics.CollisionLayers.ObjectDetectionCollisionLayer); if (m_raycastHits.Count > 0) { if (!MyFinalBuildConstants.IS_OFFICIAL) { MySandboxGame.Log.WriteLine("Could not spawn neutral ships due to collision"); } MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME); ProfilerShort.End(); return; } for (int i = 0; i < 4; ++i) { Vector3D shiftVector = upVector * m_upVecMultipliers[i] * radius + rightVector * m_rightVecMultipliers[i] * radius; MyPhysics.CastRay(shipPosition + shiftVector, shipDestination + shiftVector, m_raycastHits, MyPhysics.CollisionLayers.ObjectDetectionCollisionLayer); if (m_raycastHits.Count > 0) { if (!MyFinalBuildConstants.IS_OFFICIAL) { MySandboxGame.Log.WriteLine("Could not spawn neutral ships due to collision"); } MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME); ProfilerShort.End(); return; } } } ProfilerShort.End(); ProfilerShort.Begin("Spawn ships"); long spawnGroupId = MyPirateAntennas.GetPiratesId(); // The ships were collision-free. Now spawn them foreach (var shipPrefab in spawnGroup.Prefabs) { ProfilerShort.Begin(shipPrefab.BeaconText); // Yes, this could have been saved in the previous loop, but compared to (e.g.) raycasts, this does not take too much time to recalculate Vector3D shipPosition = Vector3D.Transform((Vector3D)shipPrefab.Position, originMatrix); Vector3D shipDestination = shipPosition + directionMult; Vector3D up = Vector3D.CalculatePerpendicularVector(-direction); List <MyCubeGrid> tmpGridList = new List <MyCubeGrid>(); // CH: We don't want a new identity for each ship anymore. We should handle that in a better way... /*if (shipPrefab.ResetOwnership) * { * if (spawnGroupId == 0) * { * //This is not an NPC so that it doesn't show up in assign ownership drop down menu * MyIdentity spawnGroupIdentity = Sync.Players.CreateNewIdentity("Neutral NPC"); * spawnGroupId = spawnGroupIdentity.IdentityId; * } * }*/ // Deploy ship ProfilerShort.Begin("Spawn cargo ship"); Stack <Action> callbacks = new Stack <Action>(); callbacks.Push(delegate() { InitAutopilot(tmpGridList, shipDestination, direction); foreach (var grid in tmpGridList) { Debug.Assert(grid.Physics.Enabled); grid.ActivatePhysics(); //last chance to activate physics } }); MyPrefabManager.Static.SpawnPrefab( resultList: tmpGridList, prefabName: shipPrefab.SubtypeId, position: shipPosition, forward: direction, up: up, initialLinearVelocity: shipPrefab.Speed * direction, beaconName: shipPrefab.BeaconText, spawningOptions: VRage.Game.ModAPI.SpawningOptions.RotateFirstCockpitTowardsDirection | VRage.Game.ModAPI.SpawningOptions.SpawnRandomCargo | VRage.Game.ModAPI.SpawningOptions.DisableDampeners, ownerId: shipPrefab.ResetOwnership ? spawnGroupId : 0, callbacks: callbacks); ProfilerShort.End(); ProfilerShort.End(); } ProfilerShort.End(); }
private bool SpawnDrone(MyRadioAntenna antenna, long ownerId, Vector3D position, MySpawnGroupDefinition spawnGroup, Vector3?spawnUp = null, Vector3?spawnForward = null) { long antennaEntityId = antenna.EntityId; Vector3D antennaPos = antenna.PositionComp.GetPosition(); Vector3D upVector; var planet = MyGamePruningStructure.GetClosestPlanet(position); if (planet != null) { 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 = position - planet.PositionComp.GetPosition(); upVector.Normalize(); } else { var totalGravityInPoint = MyGravityProviderSystem.CalculateTotalGravityInPoint(position); if (totalGravityInPoint != Vector3.Zero) { upVector = -totalGravityInPoint; upVector.Normalize(); } else if (spawnUp != null) { upVector = spawnUp.Value; } else { upVector = MyUtils.GetRandomVector3Normalized(); } } Vector3D direction = MyUtils.GetRandomPerpendicularVector(ref upVector); if (spawnForward != null) { // Align forward to up vector. Vector3 forward = spawnForward.Value; if (Math.Abs(Vector3.Dot(forward, upVector)) >= 0.98f) { forward = Vector3.CalculatePerpendicularVector(upVector); } else { Vector3 right = Vector3.Cross(forward, upVector); right.Normalize(); forward = Vector3.Cross(upVector, right); forward.Normalize(); } direction = forward; } MatrixD originMatrix = MatrixD.CreateWorld(position, direction, upVector); foreach (var shipPrefab in spawnGroup.Prefabs) { Vector3D shipPosition = Vector3D.Transform((Vector3D)shipPrefab.Position, originMatrix); List <MyCubeGrid> tmpGridList = new List <MyCubeGrid>(); Stack <Action> callback = new Stack <Action>(); callback.Push(delegate() { ChangeDroneOwnership(tmpGridList, ownerId, antennaEntityId); }); MyPrefabManager.Static.SpawnPrefab( resultList: 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, callbacks: callback); } return(true); }
public static bool CalculateRegularTravelPath(MySpawnGroupDefinition spawnGroup, Vector3D startCoords, out Vector3D startPathCoords, out Vector3D endPathCoords) { startPathCoords = Vector3D.Zero; endPathCoords = Vector3D.Zero; SpawnResources.RefreshEntityLists(); MyPlanet planet = SpawnResources.GetNearestPlanet(startCoords); List <IMyEntity> nearbyEntities = new List <IMyEntity>(); for (int i = 0; i < Settings.SpaceCargoShips.MaxSpawnAttempts; i++) { var randDir = Vector3D.Normalize(MyUtils.GetRandomVector3D()); var closestPathDist = (double)SpawnResources.rnd.Next((int)Settings.SpaceCargoShips.MinPathDistanceFromPlayer, (int)Settings.SpaceCargoShips.MaxPathDistanceFromPlayer); var closestPathPoint = randDir * closestPathDist + startCoords; bool tryInvertedDir = SpawnResources.IsPositionInGravity(closestPathPoint, planet); if (tryInvertedDir == true) { randDir = randDir * -1; closestPathPoint = randDir * closestPathDist + startCoords; if (SpawnResources.IsPositionInGravity(closestPathPoint, planet) == true) { continue; } } var pathDist = (double)SpawnResources.rnd.Next((int)Settings.SpaceCargoShips.MinPathDistance, (int)Settings.SpaceCargoShips.MaxPathDistance); var pathDir = Vector3D.Normalize(MyUtils.GetRandomPerpendicularVector(ref randDir)); var pathHalfDist = pathDist / 2; var tempPathStart = pathDir * pathHalfDist + closestPathPoint; pathDir = pathDir * -1; var tempPathEnd = pathDir * pathHalfDist + closestPathPoint; bool badPath = false; IHitInfo hitInfo = null; if (MyAPIGateway.Physics.CastLongRay(tempPathStart, tempPathEnd, out hitInfo, true) == true) { continue; } foreach (var entity in SpawnResources.EntityList) { if (Vector3D.Distance(tempPathStart, entity.GetPosition()) < Settings.SpaceCargoShips.MinSpawnDistFromEntities) { badPath = true; break; } } if (badPath == true) { continue; } var upDir = Vector3D.CalculatePerpendicularVector(pathDir); var pathMatrix = MatrixD.CreateWorld(tempPathStart, pathDir, upDir); foreach (var prefab in spawnGroup.Prefabs) { double stepDistance = 0; var tempPrefabStart = Vector3D.Transform((Vector3D)prefab.Position, pathMatrix); while (stepDistance < pathDist) { stepDistance += Settings.SpaceCargoShips.PathCheckStep; var pathCheckCoords = pathDir * stepDistance + tempPrefabStart; if (SpawnResources.IsPositionInSafeZone(pathCheckCoords) == true || SpawnResources.IsPositionInGravity(pathCheckCoords, planet) == true) { badPath = true; break; } } if (badPath == true) { break; } } if (badPath == true) { continue; } startPathCoords = tempPathStart; endPathCoords = tempPathEnd; return(true); } return(false); }
public ImprovedSpawnGroup() { SpawnGroupEnabled = true; SpawnGroupName = ""; SpawnGroup = null; SpaceCargoShip = false; LunarCargoShip = false; AtmosphericCargoShip = false; SpaceRandomEncounter = false; PlanetaryInstallation = false; PlanetaryInstallationType = "Small"; SkipTerrainCheck = false; RotateInstallations = new List <Vector3D>(); ReverseForwardDirections = new List <bool>(); CutVoxelsAtAirtightCells = false; BossEncounterSpace = false; BossEncounterAtmo = false; BossEncounterAny = false; RivalAiSpawn = false; RivalAiSpaceSpawn = false; RivalAiAtmosphericSpawn = false; RivalAiAnySpawn = false; Frequency = 0; UniqueEncounter = false; FactionOwner = "SPRT"; UseRandomMinerFaction = false; UseRandomBuilderFaction = false; UseRandomTraderFaction = false; IgnoreCleanupRules = false; ReplenishSystems = false; UseNonPhysicalAmmo = false; RemoveContainerContents = false; InitializeStoreBlocks = false; ContainerTypesForStoreOrders = new List <string>(); ForceStaticGrid = false; AdminSpawnOnly = false; SandboxVariables = new List <string>(); FalseSandboxVariables = new List <string>(); RandomNumberRoll = 1; UseCommonConditions = true; UseAutoPilotInSpace = false; PauseAutopilotAtPlayerDistance = -1; PreventOwnershipChange = false; RandomizeWeapons = false; IgnoreWeaponRandomizerMod = false; IgnoreWeaponRandomizerTargetGlobalBlacklist = false; IgnoreWeaponRandomizerTargetGlobalWhitelist = false; IgnoreWeaponRandomizerGlobalBlacklist = false; IgnoreWeaponRandomizerGlobalWhitelist = false; WeaponRandomizerTargetBlacklist = new List <string>(); WeaponRandomizerTargetWhitelist = new List <string>(); WeaponRandomizerBlacklist = new List <string>(); WeaponRandomizerWhitelist = new List <string>(); AddDefenseShieldBlocks = false; IgnoreShieldProviderMod = false; UseBlockReplacer = false; ReplaceBlockReference = new Dictionary <MyDefinitionId, MyDefinitionId>(); UseBlockReplacerProfile = false; BlockReplacerProfileNames = new List <string>(); RelaxReplacedBlocksSize = false; AlwaysRemoveBlock = false; IgnoreGlobalBlockReplacer = false; ConvertToHeavyArmor = false; UseRandomNameGenerator = false; RandomGridNamePrefix = ""; RandomGridNamePattern = ""; ReplaceAntennaNameWithRandomizedName = ""; UseBlockNameReplacer = false; BlockNameReplacerReference = new Dictionary <string, string>(); AssignContainerTypesToAllCargo = new List <string>(); UseContainerTypeAssignment = false; ContainerTypeAssignmentReference = new Dictionary <string, string>(); OverrideBlockDamageModifier = false; BlockDamageModifier = 1; GridsAreEditable = true; GridsAreDestructable = true; ShiftBlockColorsHue = false; RandomHueShift = false; ShiftBlockColorAmount = 0; AssignGridSkin = new List <string>(); RecolorGrid = false; ColorReferencePairs = new Dictionary <Vector3, Vector3>(); ColorSkinReferencePairs = new Dictionary <Vector3, string>(); ReduceBlockBuildStates = false; AffectNonFunctionalBlock = true; AffectFunctionalBlock = false; MinimumBlocksPercent = 10; MaximumBlocksPercent = 40; MinimumBuildPercent = 10; MaximumBuildPercent = 75; UseRivalAi = false; RivalAiReplaceRemoteControl = false; EraseIngameScripts = false; DisableTimerBlocks = false; DisableSensorBlocks = false; DisableWarheads = false; DisableThrustOverride = false; DisableGyroOverride = false; EraseLCDs = false; UseTextureLCD = new List <string>(); EnableBlocksWithName = new List <string>(); DisableBlocksWithName = new List <string>(); AllowPartialNames = false; ChangeTurretSettings = false; TurretRange = 800; TurretIdleRotation = false; TurretTargetMeteors = true; TurretTargetMissiles = true; TurretTargetCharacters = true; TurretTargetSmallGrids = true; TurretTargetLargeGrids = true; TurretTargetStations = true; TurretTargetNeutrals = true; ClearAuthorship = false; MinSpawnFromWorldCenter = -1; MaxSpawnFromWorldCenter = -1; DirectionFromWorldCenter = Vector3D.Zero; MinAngleFromDirection = -1; MaxAngleFromDirection = -1; MinSpawnFromPlanetSurface = -1; MaxSpawnFromPlanetSurface = -1; UseDayOrNightOnly = false; SpawnOnlyAtNight = false; UseWeatherSpawning = false; AllowedWeatherSystems = new List <string>(); UseTerrainTypeValidation = false; AllowedTerrainTypes = new List <string>(); MinAirDensity = -1; MaxAirDensity = -1; MinGravity = -1; MaxGravity = -1; PlanetBlacklist = new List <string>(); PlanetWhitelist = new List <string>(); PlanetRequiresVacuum = false; PlanetRequiresAtmo = false; PlanetRequiresOxygen = false; PlanetMinimumSize = -1; PlanetMaximumSize = -1; UsePlayerCountCheck = false; PlayerCountCheckRadius = -1; MinimumPlayers = -1; MaximumPlayers = -1; UseThreatLevelCheck = false; ThreatLevelCheckRange = 5000; ThreatIncludeOtherNpcOwners = false; ThreatScoreMinimum = -1; ThreatScoreMaximum = -1; UsePCUCheck = false; PCUCheckRadius = 5000; PCUMinimum = -1; PCUMaximum = -1; UsePlayerCredits = false; IncludeAllPlayersInRadius = false; IncludeFactionBalance = false; PlayerCreditsCheckRadius = 15000; MinimumPlayerCredits = -1; MaximumPlayerCredits = -1; UsePlayerFactionReputation = false; PlayerReputationCheckRadius = 15000; CheckReputationAgainstOtherNPCFaction = ""; MinimumReputation = -1501; MaximumReputation = 1501; RequireAllMods = new List <ulong>(); RequireAnyMods = new List <ulong>(); ExcludeAllMods = new List <ulong>(); ExcludeAnyMods = new List <ulong>(); ModBlockExists = new List <string>(); RequiredPlayersOnline = new List <ulong>(); AttachModStorageComponentToGrid = false; StorageKey = new Guid("00000000-0000-0000-0000-000000000000"); StorageValue = ""; UseKnownPlayerLocations = false; KnownPlayerLocationMustMatchFaction = false; KnownPlayerLocationMinSpawnedEncounters = -1; KnownPlayerLocationMaxSpawnedEncounters = -1; Territory = ""; MinDistanceFromTerritoryCenter = -1; MaxDistanceFromTerritoryCenter = -1; BossCustomAnnounceEnable = false; BossCustomAnnounceAuthor = ""; BossCustomAnnounceMessage = ""; BossCustomGPSLabel = "Dangerous Encounter"; BossMusicId = ""; RotateFirstCockpitToForward = true; PositionAtFirstCockpit = false; SpawnRandomCargo = true; DisableDampeners = false; ReactorsOn = true; UseBoundingBoxCheck = false; RemoveVoxelsIfGridRemoved = true; }
public static void SpawnCargoShip(bool checkGravity) { Init( ); Wrapper.GameAction(() => { if (ExtenderOptions.IsDebugging) { Essentials.Log.Info("Spawn cargo ship"); } // Select a spawn group to spawn MySpawnGroupDefinition spawnGroup = PickRandomSpawnGroup( ); if (spawnGroup == null) { return; } spawnGroup.ReloadPrefabs( ); double spawnDistance = NEUTRAL_SHIP_SPAWN_DISTANCE; Vector3D playerPosition = Vector3D.Zero; bool isWorldLimited = MyEntities.IsWorldLimited( ); int numPlayers = 0; if (isWorldLimited) { spawnDistance = Math.Min(spawnDistance, MyEntities.WorldSafeHalfExtent( ) - spawnGroup.SpawnRadius); } else { // In infinite worlds players can be thousands of kilometers away, so spawn ship around random player // so cargo ships will be spawned around every player at some time var players = MySession.Static.Players.GetOnlinePlayers( ); // In DS there can be no players connected numPlayers = Math.Max(0, players.Count - 1); int randomPlayerPosition = MyUtils.GetRandomInt(0, numPlayers); int i = 0; foreach (var player in players) { if (i == randomPlayerPosition) { if (player.Character != null) { playerPosition = player.GetPosition( ); } break; } i++; } } if (spawnDistance < 0.0f) { if (ExtenderOptions.IsDebugging) { Essentials.Log.Info("Not enough space in the world to spawn such a huge spawn group!"); } return; } double forbiddenRadius = NEUTRAL_SHIP_FORBIDDEN_RADIUS; BoundingBoxD spawnBox; if (isWorldLimited) { spawnBox = new BoundingBoxD(new Vector3D(playerPosition - spawnDistance), new Vector3D(playerPosition + spawnDistance)); } else { // We need to extend bouding box so cargo ships aren't spawned near other players GetSafeBoundingBoxForPlayers(playerPosition, spawnDistance, out spawnBox); // Forbidden radius is sphere around all players in box. // Bounding box is generated from players positions so their distance to center shall be same for all players forbiddenRadius += spawnBox.HalfExtents.Max( ) - NEUTRAL_SHIP_FORBIDDEN_RADIUS; } // Get the direction to the center and deviate it randomly Vector3D?origin = MyUtils.GetRandomBorderPosition(ref spawnBox); origin = MyEntities.FindFreePlace(origin.Value, spawnGroup.SpawnRadius); if (!origin.HasValue) { if (ExtenderOptions.IsDebugging) { Essentials.Log.Info("Couldn't find free place for cargo spawn"); } return; } // Radius in arc units of the forbidden sphere in the center, when viewed from origin float centerArcRadius = (float)Math.Atan(forbiddenRadius / (origin.Value - spawnBox.Center).Length( )); // Generate direction with elevation from centerArcRadius radians to (cAR + N_S_D_S) radians Vector3D direction = -Vector3D.Normalize(origin.Value); float theta = MyUtils.GetRandomFloat(centerArcRadius, centerArcRadius + NEUTRAL_SHIP_DIRECTION_SPREAD); float phi = MyUtils.GetRandomRadian( ); Vector3D cosVec = Vector3D.CalculatePerpendicularVector(direction); Vector3D sinVec = Vector3D.Cross(direction, cosVec); cosVec *= (Math.Sin(theta) * Math.Cos(phi)); sinVec *= (Math.Sin(theta) * Math.Sin(phi)); direction = direction * Math.Cos(theta) + cosVec + sinVec; Vector3D destination = Vector3D.Zero; RayD ray = new RayD(origin.Value, direction); double?intersection = ray.Intersects(spawnBox); Vector3D directionMult; if (!intersection.HasValue || intersection.Value < NEUTRAL_SHIP_MINIMAL_ROUTE_LENGTH) { directionMult = direction * NEUTRAL_SHIP_MINIMAL_ROUTE_LENGTH; } else { directionMult = direction * intersection.Value; } destination = origin.Value + directionMult; Vector3D upVector = Vector3D.CalculatePerpendicularVector(direction); Vector3D rightVector = Vector3D.Cross(direction, upVector); MatrixD originMatrix = MatrixD.CreateWorld(origin.Value, direction, upVector); // CH:TODO: Convex cast to detect collision // Check ships' path to avoid possible collisions. (TODO: But only if it is said in the definitions) m_raycastHits.Clear( ); foreach (var shipPrefab in spawnGroup.Prefabs) { var prefabDef = MyDefinitionManager.Static.GetPrefabDefinition(shipPrefab.SubtypeId); Debug.Assert(prefabDef != null); Vector3D shipPosition = Vector3.Transform(shipPrefab.Position, originMatrix); Vector3D shipDestination = shipPosition + directionMult; float radius = prefabDef == null ? 10.0f : prefabDef.BoundingSphere.Radius; if (checkGravity) { //these point checks could be done in the trajectory intersect, but checking points is faster than ray intersect if (MyGravityProviderSystem.IsPositionInNaturalGravity(shipPosition, spawnGroup.SpawnRadius)) { if (ExtenderOptions.IsDebugging) { Essentials.Log.Info("Failed to spawn cargo ship: Spawn location is in gravity well"); } return; } if (MyGravityProviderSystem.IsPositionInNaturalGravity(shipDestination, spawnGroup.SpawnRadius)) { if (ExtenderOptions.IsDebugging) { Essentials.Log.Info("Failed to spawn cargo ship: Destination is in gravity well"); } } if (MyGravityProviderSystem.DoesTrajectoryIntersectNaturalGravity(shipPosition, shipDestination, spawnGroup.SpawnRadius + 500)) { if (ExtenderOptions.IsDebugging) { Essentials.Log.Info("Failed to spawn cargo ship: Ship path intersects gravity well"); } return; } } MyPhysics.CastRay(shipPosition, shipDestination, m_raycastHits, MyPhysics.CollisionLayers.ObjectDetectionCollisionLayer); if (m_raycastHits.Count > 0) { if (ExtenderOptions.IsDebugging) { Essentials.Log.Info("Failed to spawn cargo ship: Ship path intersects another object"); } return; } for (int i = 0; i < 4; ++i) { Vector3D shiftVector = upVector * m_upVecMultipliers[i] * radius + rightVector * m_rightVecMultipliers[i] * radius; MyPhysics.CastRay(shipPosition + shiftVector, shipDestination + shiftVector, m_raycastHits, MyPhysics.CollisionLayers.ObjectDetectionCollisionLayer); if (m_raycastHits.Count > 0) { if (ExtenderOptions.IsDebugging) { Essentials.Log.Info("Failed to spawn cargo ship: Ship path intersects another object"); } return; } } } long spawnGroupId = MyPirateAntennas.GetPiratesId( ); // The ships were collision-free. Now spawn them foreach (var shipPrefab in spawnGroup.Prefabs) { // Yes, this could have been saved in the previous loop, but compared to (e.g.) raycasts, this does not take too much time to recalculate Vector3D shipPosition = Vector3D.Transform((Vector3D)shipPrefab.Position, originMatrix); Vector3D shipDestination = shipPosition + directionMult; Vector3D up = Vector3D.CalculatePerpendicularVector(-direction); m_tmpGridList.Clear( ); // CH: We don't want a new identity for each ship anymore. We should handle that in a better way... /*if (shipPrefab.ResetOwnership) * { * if (spawnGroupId == 0) * { * //This is not an NPC so that it doesn't show up in assign ownership drop down menu * MyIdentity spawnGroupIdentity = Sync.Players.CreateNewIdentity("Neutral NPC"); * spawnGroupId = spawnGroupIdentity.IdentityId; * } * }*/ // Deploy ship MyPrefabManager.Static.SpawnPrefab( resultList: m_tmpGridList, prefabName: shipPrefab.SubtypeId, position: shipPosition, forward: direction, up: up, initialLinearVelocity: shipPrefab.Speed * direction, beaconName: shipPrefab.BeaconText, spawningOptions: VRage.Game.ModAPI.SpawningOptions.RotateFirstCockpitTowardsDirection | VRage.Game.ModAPI.SpawningOptions.SpawnRandomCargo | VRage.Game.ModAPI.SpawningOptions.DisableDampeners, ownerId: shipPrefab.ResetOwnership ? spawnGroupId : 0, updateSync: true); /* * foreach (var grid in m_tmpGridList) * { * var cockpit = grid.GetFirstBlockOfType<MyCockpit>(); * if (cockpit != null) * { * MySimpleAutopilot ai = new MySimpleAutopilot(shipDestination, (Vector3)direction); * cockpit.AttachAutopilot(ai); * break; * } * } */ m_tmpGridList.Clear( ); } }); }
private bool SpawnDrone(long antennaEntityId, long ownerId, Vector3D position, MySpawnGroupDefinition spawnGroup) { Vector3D direction = MyUtils.GetRandomVector3Normalized(); Vector3D upVector = Vector3D.CalculatePerpendicularVector(direction); 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: Sandbox.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 void SpawnCargoShipGroup(Vector3 startPosition, Vector3 stopPosition, ulong remoteUserId = 0) { try { //Calculate lowest and highest frequencies float lowestFrequency = 999999; float highestFrequency = 0; foreach (MySpawnGroupDefinition entry in MyDefinitionManager.Static.GetSpawnGroupDefinitions()) { if (entry.Frequency < lowestFrequency) { lowestFrequency = entry.Frequency; } if (entry.Frequency > highestFrequency) { highestFrequency = entry.Frequency; } } if (lowestFrequency <= 0) { lowestFrequency = 1; } //Get a list of which groups *could* spawn Random random = new Random((int)DateTime.Now.ToBinary()); double randomChance = random.NextDouble(); randomChance = randomChance * (highestFrequency / lowestFrequency); List <MySpawnGroupDefinition> possibleGroups = new List <MySpawnGroupDefinition>(); foreach (MySpawnGroupDefinition entry in MyDefinitionManager.Static.GetSpawnGroupDefinitions()) { if (entry.Frequency >= randomChance) { possibleGroups.Add(entry); } } //Determine which group *will* spawn randomChance = random.NextDouble(); int randomShipIndex = Math.Max(0, Math.Min((int)Math.Round(randomChance * possibleGroups.Count, 0), possibleGroups.Count - 1)); MySpawnGroupDefinition randomSpawnGroup = possibleGroups[randomShipIndex]; ChatManager.Instance.SendPrivateChatMessage(remoteUserId, "Spawning cargo group '" + randomSpawnGroup.DisplayNameText.ToString() + "' ..."); //Spawn the ships in the group Matrix orientation = Matrix.CreateLookAt(startPosition, stopPosition, new Vector3(0, 1, 0)); foreach (MySpawnGroupDefinition.SpawnGroupPrefab entry in randomSpawnGroup.Prefabs) { MyPrefabDefinition matchedPrefab = null; foreach (var prefabEntry in MyDefinitionManager.Static.GetPrefabDefinitions()) { MyPrefabDefinition prefabDefinition = prefabEntry.Value; if (prefabDefinition.Id.SubtypeId.ToString() == entry.SubtypeId) { matchedPrefab = prefabDefinition; break; } } if (matchedPrefab == null) { continue; } //TODO - Build this to iterate through all cube grids in the prefab MyObjectBuilder_CubeGrid objectBuilder = matchedPrefab.CubeGrids[0]; //Create the ship CubeGridEntity cubeGrid = new CubeGridEntity(objectBuilder); //Set the ship position and orientation Vector3 shipPosition = Vector3.Transform(entry.Position, orientation) + startPosition; orientation.Translation = shipPosition; MyPositionAndOrientation newPositionOrientation = new MyPositionAndOrientation(orientation); cubeGrid.PositionAndOrientation = newPositionOrientation; //Set the ship velocity //Speed is clamped between 1.0f and the max cube grid speed Vector3 travelVector = stopPosition - startPosition; travelVector.Normalize(); Vector3 shipVelocity = travelVector * (float)Math.Min(cubeGrid.MaxLinearVelocity, Math.Max(1.0f, entry.Speed)); cubeGrid.LinearVelocity = shipVelocity; cubeGrid.IsDampenersEnabled = false; foreach (MyObjectBuilder_CubeBlock cubeBlock in cubeGrid.BaseCubeBlocks) { //Set the beacon names if (cubeBlock.TypeId == typeof(MyObjectBuilder_Beacon)) { MyObjectBuilder_Beacon beacon = (MyObjectBuilder_Beacon)cubeBlock; beacon.CustomName = entry.BeaconText; } //Set the owner of every block //TODO - Find out if setting to an arbitrary non-zero works for this //cubeBlock.Owner = PlayerMap.Instance.GetServerVirtualPlayerId(); cubeBlock.Owner = 0; cubeBlock.ShareMode = MyOwnershipShareModeEnum.Faction; } //And add the ship to the world SectorObjectManager.Instance.AddEntity(cubeGrid); } ChatManager.Instance.SendPrivateChatMessage(remoteUserId, "Cargo group '" + randomSpawnGroup.DisplayNameText.ToString() + "' spawned with " + randomSpawnGroup.Prefabs.Count.ToString() + " ships at " + startPosition.ToString()); } catch (Exception ex) { LogManager.ErrorLog.WriteLine(ex); } }
public static bool CalculateLunarTravelPath(MySpawnGroupDefinition spawnGroup, Vector3D startCoords, out Vector3D startPathCoords, out Vector3D endPathCoords) { startPathCoords = Vector3D.Zero; endPathCoords = Vector3D.Zero; SpawnResources.RefreshEntityLists(); MyPlanet planet = SpawnResources.GetNearestPlanet(startCoords); if (planet == null) { return(false); } var planetEntity = planet as IMyEntity; for (int i = 0; i < Settings.SpaceCargoShips.MaxSpawnAttempts; i++) { var spawnAltitude = (double)SpawnResources.rnd.Next((int)Settings.SpaceCargoShips.MinLunarSpawnHeight, (int)Settings.SpaceCargoShips.MaxLunarSpawnHeight); var abovePlayer = SpawnResources.CreateDirectionAndTarget(planetEntity.GetPosition(), startCoords, startCoords, spawnAltitude); var midpointDist = (double)SpawnResources.rnd.Next((int)Settings.SpaceCargoShips.MinPathDistanceFromPlayer, (int)Settings.SpaceCargoShips.MaxPathDistanceFromPlayer); var pathMidpoint = SpawnResources.GetRandomCompassDirection(abovePlayer, planet) * midpointDist + abovePlayer; var pathDist = (double)SpawnResources.rnd.Next((int)Settings.SpaceCargoShips.MinPathDistance, (int)Settings.SpaceCargoShips.MaxPathDistance); var pathDir = SpawnResources.GetRandomCompassDirection(abovePlayer, planet); var pathHalfDist = pathDist / 2; var tempPathStart = pathDir * pathHalfDist + pathMidpoint; pathDir = pathDir * -1; var tempPathEnd = pathDir * pathHalfDist + pathMidpoint; bool badPath = false; IHitInfo hitInfo = null; if (MyAPIGateway.Physics.CastLongRay(tempPathStart, tempPathEnd, out hitInfo, true) == true) { continue; } foreach (var entity in SpawnResources.EntityList) { if (Vector3D.Distance(tempPathStart, entity.GetPosition()) < Settings.SpaceCargoShips.MinSpawnDistFromEntities) { badPath = true; break; } } if (badPath == true) { continue; } var upDir = Vector3D.CalculatePerpendicularVector(pathDir); var pathMatrix = MatrixD.CreateWorld(tempPathStart, pathDir, upDir); foreach (var prefab in spawnGroup.Prefabs) { double stepDistance = 0; var tempPrefabStart = Vector3D.Transform((Vector3D)prefab.Position, pathMatrix); while (stepDistance < pathDist) { stepDistance += Settings.SpaceCargoShips.PathCheckStep; var pathCheckCoords = pathDir * stepDistance + tempPrefabStart; if (SpawnResources.IsPositionInSafeZone(pathCheckCoords) == true || SpawnResources.IsPositionInGravity(pathCheckCoords, planet) == true) { badPath = true; break; } } if (badPath == true) { break; } } if (badPath == true) { continue; } startPathCoords = tempPathStart; endPathCoords = tempPathEnd; return(true); } return(false); }
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 void SpawnCargoShipGroup(Vector3 startPosition, Vector3 stopPosition, ulong remoteUserId = 0) { try { //Calculate lowest and highest frequencies double lowestFrequency = double.MaxValue; double highestFrequency = 0d; foreach (MySpawnGroupDefinition entry in MyDefinitionManager.Static.GetSpawnGroupDefinitions( )) { if (entry.Frequency < lowestFrequency) { lowestFrequency = entry.Frequency; } if (entry.Frequency > highestFrequency) { highestFrequency = entry.Frequency; } } if (lowestFrequency <= 0d) { lowestFrequency = 1d; } //Get a list of which groups *could* spawn Random random = new Random( ); double randomChance = random.NextDouble( ); randomChance = randomChance * (highestFrequency / lowestFrequency); List <MySpawnGroupDefinition> possibleGroups = MyDefinitionManager.Static.GetSpawnGroupDefinitions( ).Where(entry => entry.Frequency >= randomChance).ToList( ); //Determine which group *will* spawn randomChance = random.NextDouble( ); int randomShipIndex = Math.Max(0, Math.Min((int)Math.Round(randomChance * possibleGroups.Count, 0), possibleGroups.Count - 1)); MySpawnGroupDefinition randomSpawnGroup = possibleGroups[randomShipIndex]; ChatManager.Instance.SendPrivateChatMessage(remoteUserId, string.Format("Spawning cargo group '{0}' ...", randomSpawnGroup.DisplayNameText)); //Spawn the ships in the group Matrix orientation = Matrix.CreateLookAt(startPosition, stopPosition, new Vector3(0, 1, 0)); foreach (MySpawnGroupDefinition.SpawnGroupPrefab entry in randomSpawnGroup.Prefabs) { MyPrefabDefinition matchedPrefab = MyDefinitionManager.Static.GetPrefabDefinitions( ).Select(prefabEntry => prefabEntry.Value).FirstOrDefault(prefabDefinition => prefabDefinition.Id.SubtypeId.ToString( ) == entry.SubtypeId); if (matchedPrefab == null) { continue; } foreach (MyObjectBuilder_CubeGrid objectBuilder in matchedPrefab.CubeGrids) { //Create the ship CubeGridEntity cubeGrid = new CubeGridEntity(objectBuilder); //Set the ship position and orientation Vector3 shipPosition = Vector3.Transform(entry.Position, orientation) + startPosition; orientation.Translation = shipPosition; MyPositionAndOrientation newPositionOrientation = new MyPositionAndOrientation(orientation); cubeGrid.PositionAndOrientation = newPositionOrientation; //Set the ship velocity //Speed is clamped between 1.0f and the max cube grid speed Vector3 travelVector = stopPosition - startPosition; travelVector.Normalize( ); Vector3 shipVelocity = travelVector * Math.Min(cubeGrid.MaxLinearVelocity, Math.Max(1.0f, entry.Speed)); cubeGrid.LinearVelocity = shipVelocity; //cubeGrid.IsDampenersEnabled = false; foreach (MyObjectBuilder_CubeBlock cubeBlock in cubeGrid.BaseCubeBlocks) { //Set the beacon names MyObjectBuilder_Beacon beacon = cubeBlock as MyObjectBuilder_Beacon; if (beacon != null) { beacon.CustomName = entry.BeaconText; } //Set the owner of every block //TODO - Find out if setting to an arbitrary non-zero works for this //cubeBlock.Owner = PlayerMap.Instance.GetServerVirtualPlayerId(); cubeBlock.Owner = 0; cubeBlock.ShareMode = MyOwnershipShareModeEnum.Faction; } //And add the ship to the world SectorObjectManager.Instance.AddEntity(cubeGrid); } } ChatManager.Instance.SendPrivateChatMessage(remoteUserId, string.Format("Cargo group '{0}' spawned with {1} ships at {2}", randomSpawnGroup.DisplayNameText, randomSpawnGroup.Prefabs.Count, startPosition)); } catch (ArgumentOutOfRangeException ex) { ApplicationLog.BaseLog.Error(ex); } catch (ArgumentNullException ex) { ApplicationLog.BaseLog.Error(ex); } catch (FormatException ex) { ApplicationLog.BaseLog.Error(ex); } catch (Exception ex) { ApplicationLog.BaseLog.Error(ex); } }
public static void OnGlobalSpawnEvent(object senderEvent) { // Select a spawn group to spawn MySpawnGroupDefinition spawnGroup = PickRandomSpawnGroup(); if (spawnGroup == null) { return; } spawnGroup.ReloadPrefabs(); ProfilerShort.Begin("Generate position and direction"); double spawnDistance = NEUTRAL_SHIP_SPAWN_DISTANCE; Vector3D playerPosition = Vector3D.Zero; bool isWorldLimited = MyEntities.IsWorldLimited(); int numPlayers = 0; if (isWorldLimited) { spawnDistance = Math.Min(spawnDistance, MyEntities.WorldSafeHalfExtent() - spawnGroup.SpawnRadius); } else { // In infinite worlds players can be thousands of kilometers away, so spawn ship around random player // so cargo ships will be spawned around every player at some time var players = MySession.Static.Players.GetOnlinePlayers(); // In DS there can be no players connected numPlayers = Math.Max(0, players.Count - 1); int randomPlayerPosition = MyUtils.GetRandomInt(0, numPlayers); int i = 0; foreach (var player in players) { if (i == randomPlayerPosition) { if (player.Character != null) { playerPosition = player.GetPosition(); } break; } i++; } } if (spawnDistance < 0.0f) { MySandboxGame.Log.WriteLine("Not enough space in the world to spawn such a huge spawn group!"); return; } double forbiddenRadius = NEUTRAL_SHIP_FORBIDDEN_RADIUS; BoundingBoxD spawnBox; if (isWorldLimited) { spawnBox = new BoundingBoxD(new Vector3D(playerPosition - spawnDistance), new Vector3D(playerPosition + spawnDistance)); } else { // We need to extend bouding box so cargo ships aren't spawned near other players GetSafeBoundingBoxForPlayers(playerPosition, spawnDistance, out spawnBox); // Forbidden radius is sphere around all players in box. // Bounding box is generated from players positions so their distance to center shall be same for all players forbiddenRadius += spawnBox.HalfExtents.Max() - NEUTRAL_SHIP_FORBIDDEN_RADIUS; } // Get the direction to the center and deviate it randomly Vector3D?origin = MyUtils.GetRandomBorderPosition(ref spawnBox); origin = MyEntities.FindFreePlace(origin.Value, spawnGroup.SpawnRadius); if (!origin.HasValue) { MySandboxGame.Log.WriteLine("Could not spawn neutral ships - no free place found"); MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME); ProfilerShort.End(); return; } // Radius in arc units of the forbidden sphere in the center, when viewed from origin float centerArcRadius = (float)Math.Atan(forbiddenRadius / (origin.Value - spawnBox.Center).Length()); // Generate direction with elevation from centerArcRadius radians to (cAR + N_S_D_S) radians Vector3D direction = -Vector3D.Normalize(origin.Value); float theta = MyUtils.GetRandomFloat(centerArcRadius, centerArcRadius + NEUTRAL_SHIP_DIRECTION_SPREAD); float phi = MyUtils.GetRandomRadian(); Vector3D cosVec = Vector3D.CalculatePerpendicularVector(direction); Vector3D sinVec = Vector3D.Cross(direction, cosVec); cosVec *= (Math.Sin(theta) * Math.Cos(phi)); sinVec *= (Math.Sin(theta) * Math.Sin(phi)); direction = direction * Math.Cos(theta) + cosVec + sinVec; Vector3D destination = Vector3D.Zero; RayD ray = new RayD(origin.Value, direction); double? intersection = ray.Intersects(spawnBox); Vector3D directionMult; if (!intersection.HasValue || intersection.Value < NEUTRAL_SHIP_MINIMAL_ROUTE_LENGTH) { directionMult = direction * NEUTRAL_SHIP_MINIMAL_ROUTE_LENGTH; } else { directionMult = direction * intersection.Value; } destination = origin.Value + directionMult; Vector3D upVector = Vector3D.CalculatePerpendicularVector(direction); Vector3D rightVector = Vector3D.Cross(direction, upVector); MatrixD originMatrix = MatrixD.CreateWorld(origin.Value, direction, upVector); ProfilerShort.End(); ProfilerShort.Begin("Check free space"); // CH:TODO: Convex cast to detect collision // Check ships' path to avoid possible collisions. (TODO: But only if it is said in the definitions) m_raycastHits.Clear(); foreach (var shipPrefab in spawnGroup.Prefabs) { var prefabDef = MyDefinitionManager.Static.GetPrefabDefinition(shipPrefab.SubtypeId); Debug.Assert(prefabDef != null); Vector3D shipPosition = Vector3.Transform(shipPrefab.Position, originMatrix); Vector3D shipDestination = shipPosition + directionMult; float radius = prefabDef == null ? 10.0f : prefabDef.BoundingSphere.Radius; MyPhysics.CastRay(shipPosition, shipDestination, m_raycastHits, MyPhysics.ObjectDetectionCollisionLayer); if (m_raycastHits.Count() > 0) { MySandboxGame.Log.WriteLine("Could not spawn neutral ships due to collision"); MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME); ProfilerShort.End(); return; } for (int i = 0; i < 4; ++i) { Vector3D shiftVector = upVector * m_upVecMultipliers[i] * radius + rightVector * m_rightVecMultipliers[i] * radius; MyPhysics.CastRay(shipPosition + shiftVector, shipDestination + shiftVector, m_raycastHits, MyPhysics.ObjectDetectionCollisionLayer); if (m_raycastHits.Count() > 0) { MySandboxGame.Log.WriteLine("Could not spawn neutral ships due to collision"); MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME); ProfilerShort.End(); return; } } } ProfilerShort.End(); ProfilerShort.Begin("Spawn ships"); //This is not an NPC so that it doesn't show up in assign ownership drop down menu MyIdentity spawnGroupIdentity = Sync.Players.CreateNewIdentity("Neutral NPC"); long spawnGroupId = spawnGroupIdentity.IdentityId; // The ships were collision-free. Now spawn them foreach (var shipPrefab in spawnGroup.Prefabs) { ProfilerShort.Begin(shipPrefab.BeaconText); // Yes, this could have been saved in the previous loop, but compared to (e.g.) raycasts, this does not take too much time to recalculate Vector3D shipPosition = Vector3D.Transform((Vector3D)shipPrefab.Position, originMatrix); Vector3D shipDestination = shipPosition + directionMult; Vector3D up = Vector3D.CalculatePerpendicularVector(-direction); m_tmpGridList.Clear(); // Deploy ship ProfilerShort.Begin("Spawn cargo ship"); MyPrefabManager.Static.SpawnPrefab( resultList: m_tmpGridList, prefabName: shipPrefab.SubtypeId, position: shipPosition, forward: direction, up: up, initialLinearVelocity: shipPrefab.Speed * direction, beaconName: shipPrefab.BeaconText, spawningOptions: Sandbox.ModAPI.SpawningOptions.RotateFirstCockpitTowardsDirection | Sandbox.ModAPI.SpawningOptions.SpawnRandomCargo | Sandbox.ModAPI.SpawningOptions.DisableDampeners, updateSync: true); ProfilerShort.End(); foreach (var grid in m_tmpGridList) { grid.ChangeGridOwnership(spawnGroupId, MyOwnershipShareModeEnum.None); var cockpit = grid.GetFirstBlockOfType <MyCockpit>(); if (cockpit != null) { MySimpleAutopilot ai = new MySimpleAutopilot(shipDestination, (Vector3)direction); cockpit.AttachAutopilot(ai); break; } } m_tmpGridList.Clear(); ProfilerShort.End(); } ProfilerShort.End(); }
private bool SpawnDrone(MyRadioAntenna antenna, long ownerId, Vector3D position, MySpawnGroupDefinition spawnGroup, Vector3?spawnUp = null, Vector3?spawnForward = null) { long antennaEntityId = antenna.EntityId; Vector3D antennaPos = antenna.PositionComp.GetPosition(); Vector3D upVector; var planet = MyGamePruningStructure.GetClosestPlanet(position); if (planet != null) { 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 = position - planet.PositionComp.GetPosition(); upVector.Normalize(); } else { var totalGravityInPoint = MyGravityProviderSystem.CalculateTotalGravityInPoint(position); if (totalGravityInPoint != Vector3.Zero) { upVector = -totalGravityInPoint; upVector.Normalize(); } else if (spawnUp != null) { upVector = spawnUp.Value; } else { upVector = MyUtils.GetRandomVector3Normalized(); } } Vector3D direction = MyUtils.GetRandomPerpendicularVector(ref upVector); if (spawnForward != null) { // Align forward to up vector. Vector3 forward = spawnForward.Value; if (Math.Abs(Vector3.Dot(forward, upVector)) >= 0.98f) { forward = Vector3.CalculatePerpendicularVector(upVector); } else { Vector3 right = Vector3.Cross(forward, upVector); right.Normalize(); forward = Vector3.Cross(upVector, right); forward.Normalize(); } direction = forward; } 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); }