private void SpawnBot(SpawnInfo spawnInfo, MyPlanet planet, MyPlanetAnimalSpawnInfo animalSpawnInfo) { PlanetAIInfo planetInfo = null; if (!m_planets.TryGetValue(planet.EntityId, out planetInfo)) { Debug.Assert(false, "Could not get planet info!"); return; } if (planetInfo.BotNumber >= MAX_BOTS_PER_PLANET) { return; } Debug.Assert(animalSpawnInfo != null); double spawnDistMin = animalSpawnInfo.SpawnDistMin; double spawnDistMax = animalSpawnInfo.SpawnDistMax; Vector3D center = spawnInfo.Position; Vector3D planetGravityVec = MyGravityProviderSystem.CalculateNaturalGravityInPoint(center); //GR: if gravity is zero provide a random Vector to normalize if (planetGravityVec == Vector3D.Zero) { planetGravityVec = Vector3D.Up; } planetGravityVec.Normalize(); Vector3D planetTangent = Vector3D.CalculatePerpendicularVector(planetGravityVec); Vector3D planetBitangent = Vector3D.Cross(planetGravityVec, planetTangent); planetTangent.Normalize(); planetBitangent.Normalize(); Vector3D spawnPos = MyUtils.GetRandomDiscPosition(ref center, spawnDistMin, spawnDistMax, ref planetTangent, ref planetBitangent); spawnPos = planet.GetClosestSurfacePointGlobal(ref spawnPos); Vector3D?spawnPosCorrected = MyEntities.FindFreePlace(spawnPos, 2.0f); if (spawnPosCorrected.HasValue) { spawnPos = spawnPosCorrected.Value; } planet.CorrectSpawnLocation(ref spawnPos, 2.0f); MyAgentDefinition botBehavior = GetAnimalDefinition(animalSpawnInfo) as MyAgentDefinition; if (botBehavior != null) { if (botBehavior.Id.SubtypeName == Wolf_SUBTYPE_ID && MySession.Static.EnableWolfs) { MyAIComponent.Static.SpawnNewBot(botBehavior, spawnPos); } else if (botBehavior.Id.SubtypeName != Wolf_SUBTYPE_ID && MySession.Static.EnableSpiders) { MyAIComponent.Static.SpawnNewBot(botBehavior, spawnPos); } } }
public override void UpdateAfterSimulation() { base.UpdateAfterSimulation(); if (!Sync.IsServer) { return; } if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW && MyDebugDrawSettings.DEBUG_DRAW_FAUNA_COMPONENT) { DebugDraw(); } ProfilerShort.Begin("MySpaceFaunaComponent.UpdateAfter"); m_waitForUpdate--; if (m_waitForUpdate > 0) { return; } m_waitForUpdate = UPDATE_DELAY; var players = Sync.Players.GetOnlinePlayers(); m_tmpPlayerPositions.Capacity = Math.Max(m_tmpPlayerPositions.Capacity, players.Count); m_tmpPlayerPositions.Clear(); // Reset bot numbers foreach (var planet in m_planets) { planet.Value.BotNumber = 0; } // Update bot numbers and save player positions foreach (var player in players) { // Human player if (player.Id.SerialId == 0) { if (player.Controller.ControlledEntity == null) { continue; } var pos = player.GetPosition(); m_tmpPlayerPositions.Add(pos); } // Bot else { if (player.Controller.ControlledEntity == null) { continue; } var pos = player.GetPosition(); var planet = MyGamePruningStructure.GetClosestPlanet(pos); if (planet != null) { PlanetAIInfo planetInfo; if (m_planets.TryGetValue(planet.EntityId, out planetInfo)) { planetInfo.BotNumber++; } } } } int currentTime = MySandboxGame.TotalGamePlayTimeInMilliseconds; // Spawn bots near players on planets, only if in survival/myfakes macro set if (MyFakes.SPAWN_SPACE_FAUNA_IN_CREATIVE) { foreach (var player in players) { if (player.Controller.ControlledEntity == null) { continue; } var pos = player.GetPosition(); var planet = MyGamePruningStructure.GetClosestPlanet(pos); if (planet == null || !PlanetHasFauna(planet)) { continue; } PlanetAIInfo planetInfo = null; if (!m_planets.TryGetValue(planet.EntityId, out planetInfo)) { continue; } // Human player - spawn spiders if (player.Id.SerialId == 0) { // Distance to surface check Vector3D toSurface = planet.GetClosestSurfacePointGlobal(ref pos) - pos; if (toSurface.LengthSquared() >= PROXIMITY_DIST * PROXIMITY_DIST && planetInfo.BotNumber >= MAX_BOTS_PER_PLANET) { continue; } int spawnPointCount = 0; var pointEnum = m_spawnInfoGrid.GetPointsCloserThan(ref pos, SPHERE_SPAWN_DIST); while (pointEnum.MoveNext()) { var spawnPoint = pointEnum.Current; spawnPointCount++; if (spawnPoint.SpawnDone) { continue; // Don't take not-yet cleaned spawn info into consideration } if (spawnPoint.ShouldSpawn(currentTime)) { spawnPoint.SpawnDone = true; var timeouts = m_timeoutInfoGrid.GetPointsCloserThan(ref pos, TIMEOUT_DIST); bool timeoutPresent = false; while (timeouts.MoveNext()) { if (timeouts.Current.IsTimedOut(currentTime)) { continue; } timeoutPresent = true; break; } if (timeoutPresent) { continue; } var animalSpawnInfo = MySpaceBotFactory.GetDayOrNightAnimalSpawnInfo(planet, spawnPoint.Position); if (animalSpawnInfo == null) { continue; } int numBots = MyUtils.GetRandomInt(animalSpawnInfo.WaveCountMin, animalSpawnInfo.WaveCountMax); for (int i = 0; i < numBots; ++i) { SpawnBot(spawnPoint, planet, animalSpawnInfo); } } else { spawnPoint.UpdateAbandoned(currentTime); } } if (spawnPointCount == 0) // we dont have any spawn points near human players position { var spawnInfo = new SpawnInfo(pos, currentTime, planet); m_spawnInfoGrid.AddPoint(ref pos, spawnInfo); m_allSpawnInfos.Add(spawnInfo); } } // Despawn bots that are too far from all players else //if (player.Id.SteamId == Sync.MyId) { double closestDistSq = double.MaxValue; foreach (Vector3D playerPosition in m_tmpPlayerPositions) { closestDistSq = Math.Min(Vector3D.DistanceSquared(pos, playerPosition), closestDistSq); } if (closestDistSq > DESPAWN_DIST * DESPAWN_DIST) { MyAIComponent.Static.RemoveBot(player.Id.SerialId, removeCharacter: true); } } } } m_tmpPlayerPositions.Clear(); m_waitForClean -= UPDATE_DELAY; if (m_waitForClean <= 0) { MyAIComponent.Static.CleanUnusedIdentities(); m_waitForClean = CLEAN_DELAY; for (int i = 0; i < m_allSpawnInfos.Count; ++i) { var spawnInfo = m_allSpawnInfos[i]; if (spawnInfo.IsAbandoned(currentTime) || spawnInfo.SpawnDone) { m_allSpawnInfos.RemoveAtFast(i); Vector3D point = spawnInfo.Position; m_spawnInfoGrid.RemovePoint(ref point); --i; } } for (int i = 0; i < m_allTimeoutInfos.Count; ++i) { var timeoutInfo = m_allTimeoutInfos[i]; if (timeoutInfo.IsTimedOut(currentTime)) { m_allTimeoutInfos.RemoveAtFast(i); Vector3D point = timeoutInfo.Position; m_timeoutInfoGrid.RemovePoint(ref point); --i; } } } ProfilerShort.End(); }