private static void SpawnEncounter(MyEncounterId encounterPosition, Vector3D placePosition, List <MySpawnGroupDefinition> candidates, int selectedEncounter) { var spawnGroup = candidates[selectedEncounter]; long ownerId = 0; // 0 means that the owner won't be changed if (spawnGroup.IsPirate) { ownerId = MyPirateAntennas.GetPiratesId(); } foreach (var selectedPrefab in spawnGroup.Prefabs) { List <MyCubeGrid> createdGrids = new List <MyCubeGrid>(); Vector3D direction = Vector3D.Forward; Vector3D upVector = Vector3D.Up; var spawningOptions = spawnGroup.ReactorsOn ? VRage.Game.ModAPI.SpawningOptions.None : VRage.Game.ModAPI.SpawningOptions.TurnOffReactors; if (selectedPrefab.Speed > 0.0f) { spawningOptions = VRage.Game.ModAPI.SpawningOptions.RotateFirstCockpitTowardsDirection | VRage.Game.ModAPI.SpawningOptions.SpawnRandomCargo | VRage.Game.ModAPI.SpawningOptions.DisableDampeners; float centerArcRadius = (float)Math.Atan(MyNeutralShipSpawner.NEUTRAL_SHIP_FORBIDDEN_RADIUS / placePosition.Length()); direction = -Vector3D.Normalize(placePosition); float theta = m_random.NextFloat(centerArcRadius, centerArcRadius + MyNeutralShipSpawner.NEUTRAL_SHIP_DIRECTION_SPREAD); float phi = m_random.NextFloat(0, 2 * MathHelper.Pi); 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; upVector = Vector3D.CalculatePerpendicularVector(direction); } spawningOptions |= VRage.Game.ModAPI.SpawningOptions.DisableSave; if (selectedPrefab.PlaceToGridOrigin) { spawningOptions |= SpawningOptions.UseGridOrigin; } Stack <Action> callback = new Stack <Action>(); callback.Push(delegate() { ProcessCreatedGrids(ref encounterPosition, selectedPrefab.Speed, createdGrids); }); MyPrefabManager.Static.SpawnPrefab( resultList: createdGrids, prefabName: selectedPrefab.SubtypeId, position: placePosition + selectedPrefab.Position, forward: direction, up: upVector, beaconName: selectedPrefab.BeaconText, initialLinearVelocity: direction * selectedPrefab.Speed, spawningOptions: spawningOptions | SpawningOptions.UseGridOrigin, ownerId: ownerId, updateSync: true, callbacks: callback); } }
private bool OwnedBy(MyCubeGrid grid, string str) { long identityId; if (string.Compare(str, "nobody", StringComparison.InvariantCultureIgnoreCase) == 0) { return(grid.BigOwners.Count == 0); } if (string.Compare(str, "pirates", StringComparison.InvariantCultureIgnoreCase) == 0) { identityId = MyPirateAntennas.GetPiratesId(); } else { var player = Utilities.GetPlayerByNameOrId(str); if (player == null) { return(false); } identityId = player.IdentityId; } return(grid.BigOwners.Contains(identityId)); }
void UpdatePirateAntenna(bool forceRemove = false) { bool isActive = IsWorking && Sync.Players.GetNPCIdentities().Contains(OwnerId); bool doRemove = !isActive || forceRemove; MyPirateAntennas.UpdatePirateAntenna(this.EntityId, doRemove, this.CustomName); }
public bool IsExcluded(ConcealGroup group) { var pirateId = MyPirateAntennas.GetPiratesId(); foreach (var grid in group.Grids) { if (_keepAliveTimers.ContainsKey(grid.EntityId)) { Log.Trace($"{group.GridNames} is kept alive by PB action"); return(true); } if (!Settings.Data.ConcealPirates && grid.BigOwners.Contains(pirateId)) { Log.Trace($"{group.GridNames} is kept alive by pirate ownership"); return(true); } } var exclude = false; Parallel.ForEach(group.Grids, grid => { foreach (var block in grid.CubeBlocks.Select(x => x.FatBlock)) { if (block == null) { continue; } if (block is IMyProductionBlock p && !Settings.Data.ConcealProduction && p.IsProducing) { Log.Trace($"{group.GridNames} exempted production ({p.CustomName} active)"); exclude = true; break; } if (Settings.Data.ExcludedSubtypes.Contains(block.BlockDefinition.Id.SubtypeName)) { Log.Trace($"{group.GridNames} exempted subtype {block.BlockDefinition.Id.SubtypeName}"); exclude = true; break; } }
public void UpdatePirateAntenna(bool remove = false) { bool isActive = IsWorking && Sync.Players.GetNPCIdentities().Contains(OwnerId); MyPirateAntennas.UpdatePirateAntenna(this.EntityId, remove, isActive, this.CustomName); }
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( ); } }); }
public void UpdatePirateAntenna(bool remove = false) { bool activeState = base.IsWorking && Sync.Players.GetNPCIdentities().Contains(base.OwnerId); MyPirateAntennas.UpdatePirateAntenna(base.EntityId, remove, activeState, (this.HudText.Length > 0) ? this.HudText : base.CustomName); }