-
-
Save Rseding91/aecc426adc32039844f6d43bf3f3c63f to your computer and use it in GitHub Desktop.
| void SpacePlatform::spawnAsteroids() | |
| { | |
| const bool randomOrientation = this->speed < 0.2; | |
| if (SpaceLocationID locationID = this->position.getCurrentLocation()) | |
| for (auto& spawnDefinition : locationID->asteroidSpawnDefinitions) | |
| this->trySpawnAsteroid(spawnDefinition.asteroid, spawnDefinition.chunk, spawnDefinition, randomOrientation); | |
| else | |
| { | |
| const PointOnSpaceConnection& pointOnConnection = this->position.getPointOnConnection(); | |
| for (auto& spawnDefinition : pointOnConnection.connection->asteroidSpawnDefinitions) | |
| this->trySpawnAsteroid(spawnDefinition.asteroid, spawnDefinition.asteroidChunk, spawnDefinition.interpolate(pointOnConnection.distance), randomOrientation); | |
| // Spawn SpaceLocation asteroids on space connections if the platform is in the location's sphere of influence. | |
| this->spawnAsteroidsOnConnectionNearEndPoint(**pointOnConnection.connection->from, pointOnConnection.distance); | |
| this->spawnAsteroidsOnConnectionNearEndPoint(**pointOnConnection.connection->to, 1 - pointOnConnection.distance); | |
| } | |
| } | |
| void SpacePlatform::spawnAsteroidsOnConnectionNearEndPoint(const SpaceLocationPrototype& endPoint, double distanceFromEndPoint) | |
| { | |
| if (distanceFromEndPoint < endPoint.asteroidSpawnInfluence) | |
| for (const SpaceLocationAsteroidSpawnDefinition& spawnDefinition : endPoint.asteroidSpawnDefinitions) | |
| this->trySpawnAsteroid(spawnDefinition.asteroid, | |
| spawnDefinition.chunk, | |
| Math::lerp<AsteroidSpawnPoint>(spawnDefinition, | |
| AsteroidSpawnPoint(0, 0, spawnDefinition.angleWhenStopped), | |
| Math::inverseLerp(0.0, endPoint.asteroidSpawnInfluence, distanceFromEndPoint)), | |
| !this->isMoving()); | |
| } | |
| void SpacePlatform::trySpawnAsteroid(EntityID entityID, AsteroidChunkID asteroidChunkID, const AsteroidSpawnPoint& data, bool randomOrientation) | |
| { | |
| static constexpr uint32_t BASE_SPAWNING_AREA = 1024; | |
| double probability = this->getAsteroidSpawningArea().getWidth().getDouble() + this->getAsteroidSpawningArea().getHeight().getDouble(); | |
| if (!randomOrientation) | |
| probability += this->getAsteroidSpawningArea().getWidth().getDouble() * this->speed * 10; | |
| else if (!this->position.getCurrentLocation()) | |
| probability *= 0.1; // Reduce asteroid spawning for platforms which stopped mid-route. | |
| probability *= *this->map.mapSettings->asteroidSettings.spawningRate / BASE_SPAWNING_AREA * data.probability; | |
| randomOrientation |= this->speed < UtilityConstants::instance().asteroidSpawningWithRandomOrientationMaxSpeed; | |
| for (; probability > 1; --probability) | |
| this->spawnAsteroid(entityID, asteroidChunkID, data, randomOrientation); | |
| if (this->map.getRandomGenerator().testChance(probability)) | |
| this->spawnAsteroid(entityID, asteroidChunkID, data, randomOrientation); | |
| } | |
| SimpleBoundingBox SpacePlatform::getAsteroidSpawningArea() | |
| { | |
| const SimpleBoundingBox& asteroidSpawningOffset = UtilityConstants::instance().asteroidSpawningOffset; | |
| return SimpleBoundingBox(this->platformBoundingBox.leftTop.x + asteroidSpawningOffset.leftTop.x, | |
| this->platformBoundingBox.leftTop.y + asteroidSpawningOffset.leftTop.y, | |
| this->platformBoundingBox.rightBottom.x + asteroidSpawningOffset.rightBottom.x, | |
| this->platformBoundingBox.rightBottom.y + asteroidSpawningOffset.rightBottom.y); | |
| } |
Yes, km per tick.
Thanks!
When an asteroid spawns at a stationary platform, does it strictly spawn on the edges of the square defined by asteroidSpawningOffset?
Also, does it spawn with a fully random direction of travel, or is it restricted to some cone such that it won't immediately exit the active area? Is it possible, for example, to spawn an asteroid near the bottom-left corner and have it travel at -45 degrees and exit almost immediately? Could it spawn traveling at +180 degrees exit immediately?
Thanks so much!
FYI, I did some testing. I found that it is possible to capture ALL (or at least, nearly all) asteroids that spawn. Using the formula for asteroid spawn rate (where L and W are the length and width of your space platform):
asteroid_rate_per_minute = 90 * (L + W + 72 + 48*3) / 1024
I get a theoretical asteroid spawn rate for Nauvis orbit. (Note: the '90' is the sum of metal/carbon/oxide asteroids from the wiki, https://wiki.factorio.com/Nauvis)
I made a "+ shaped" station that just collected asteroids and tossed them overboard. I used L=48 and W=48.

Then I ran a 10 hour sped-up test in the editor, and I got 17.8 metal/min, 12.1 coal/min, and 6.0 ice/min, or a total of 35.9/min. the the asteroid_rate_per_minute calculation is 38.86/min. So this means I am probably capturing every asteroid that spawns, and that therefore the random velocity that asteroids get is set in some way such that they head "generally" toward the space station.
Finally, I ran a test where I had a long line of collectors on one axis (W=96, L=4). In this config I captured only 91.4% of the theoretical asteroids over 10 hours, and I could see many asteroids crossing the full width of the screen without ever getting close enough to the station.
So it seems that it is possible to capture all asteroids as long as the station is large enough on two axes. It's not clear to me if symmetry is important or not.
Thanks to u/ahydra447 for the post on https://www.reddit.com/r/factorio/comments/1jnzf44/indepth_details_about_asteroid_spawning/ which was very helpful in doing this experiment.
In what unit is the platform speed? km per tick?
Trying to get a grasp on asteroid rates