1package com.fs.starfarer.api.impl.campaign.terrain;
4import java.util.Random;
6import com.fs.starfarer.api.Global;
7import com.fs.starfarer.api.campaign.AsteroidAPI;
8import com.fs.starfarer.api.campaign.CampaignEngineLayers;
9import com.fs.starfarer.api.campaign.CampaignFleetAPI;
10import com.fs.starfarer.api.campaign.LocationAPI;
11import com.fs.starfarer.api.campaign.SectorEntityToken;
12import com.fs.starfarer.api.campaign.TerrainAIFlags;
13import com.fs.starfarer.api.campaign.rules.MemoryAPI;
14import com.fs.starfarer.api.combat.ViewportAPI;
15import com.fs.starfarer.api.loading.Description.Type;
16import com.fs.starfarer.api.ui.Alignment;
17import com.fs.starfarer.api.ui.TooltipMakerAPI;
18import com.fs.starfarer.api.util.Misc;
25 public static class AsteroidBeltParams
extends RingParams {
26 public int numAsteroids;
29 public float minOrbitDays;
30 public float maxOrbitDays;
33 public AsteroidBeltParams(
int numAsteroids,
float orbitRadius,
34 float width,
float minOrbitDays,
float maxOrbitDays,
35 float minSize,
float maxSize, String name) {
36 super(width, orbitRadius,
null, name);
37 this.numAsteroids = numAsteroids;
40 this.minOrbitDays = minOrbitDays;
41 this.maxOrbitDays = maxOrbitDays;
42 this.minSize = minSize;
43 this.maxSize = maxSize;
56 if (
params ==
null)
return;
61 float bandWidth =
params.bandWidthInEngine;
64 params.middleRadius - bandWidth * 0.5f,
65 params.middleRadius + bandWidth * 0.5f,
67 false, factor, alphaMult);
76 if (!(
params instanceof AsteroidBeltParams))
return;
80 LocationAPI location =
entity.getContainingLocation();
81 for (
int i = 0; i <
params.numAsteroids; i++) {
83 float size = params.minSize + rand.nextFloat() * (params.maxSize -
params.minSize);
84 AsteroidAPI asteroid = location.addAsteroid(size);
86 asteroid.setFacing(rand.nextFloat() * 360f);
87 float currRadius = params.middleRadius -
params.bandWidthInEngine/2f + rand.nextFloat() *
params.bandWidthInEngine;
88 float angle = rand.nextFloat() * 360f;
89 float orbitDays = params.minOrbitDays + rand.nextFloat() * (params.maxOrbitDays -
params.minOrbitDays);
90 asteroid.setCircularOrbit(this.
entity, angle, currRadius, orbitDays);
91 Misc.setAsteroidSource(asteroid,
this);
100 super.advance(amount);
132 if (param instanceof AsteroidBeltParams) {
133 params = (AsteroidBeltParams) param;
136 name =
"Asteroid Belt";
142 public void render(CampaignEngineLayers layer, ViewportAPI viewport) {
143 super.render(layer, viewport);
148 if (
entity instanceof CampaignFleetAPI) {
149 CampaignFleetAPI fleet = (CampaignFleetAPI)
entity;
156 if (Misc.isSlowMoving(fleet)) {
157 fleet.getStats().addTemporaryModMult(0.1f,
getModId() +
"_2",
159 fleet.getStats().getDetectedRangeMod());
164 if (!fleet.isInHyperspaceTransition()) {
165 String key =
"$asteroidImpactTimeout";
166 String sKey =
"$skippedImpacts";
167 String recentKey =
"$recentImpact";
168 float probPerSkip = 0.15f;
170 float maxSkipsToTrack = 7;
171 float durPerSkip = 0.2f;
172 MemoryAPI mem = fleet.getMemoryWithoutUpdate();
173 if (!mem.contains(key)) {
174 float expire = mem.getExpire(sKey);
175 if (expire < 0) expire = 0;
177 float hitProb = Misc.getFleetRadiusTerrainEffectMult(fleet) * 0.5f;
181 hitProb = expire / durPerSkip * probPerSkip;
182 if (hitProb > maxProb) hitProb = maxProb;
183 if ((
float) Math.random() < hitProb) {
184 boolean hadRecent = mem.is(recentKey,
true);
185 hadRecent &= (float) Math.random() > 0.5f;
187 mem.set(sKey,
true, 0);
188 mem.set(recentKey,
true, 0.5f + 1f * (
float) Math.random());
190 mem.set(sKey,
true, Math.min(expire + durPerSkip, maxSkipsToTrack * durPerSkip));
192 mem.set(key,
true, (
float) (0.05f + 0.1f * Math.random()));
239 return "Asteroid Belt";
249 Color gray = Misc.getGrayColor();
250 Color highlight = Misc.getHighlightColor();
252 Color bad = Misc.getNegativeHighlightColor();
260 tooltip.addSectionHeading(
"Travel", Alignment.MID, pad);
280 tooltip.addPara(
"Chance of asteroid impacts that briefly knock the fleet off course and " +
281 "may occasionally impact ships directly, dealing moderate damage.", nextPad);
287 tooltip.addPara(
"Smaller fleets are usually able to avoid the heavier impacts, " +
288 "and slow-moving fleets do not risk impacts at all.", pad,
299 tooltip.addPara(
"Reduces the range at which stationary or slow-moving* fleets inside it can be detected by %s.", nextPad,
303 tooltip.addPara(
"*Press and hold %s to stop; combine with holding the left mouse button down to move slowly. " +
304 "A slow-moving fleet moves at a burn level of half that of its slowest ship.", nextPad,
305 Misc.getGrayColor(), highlight,
318 tooltip.addSectionHeading(
"Combat", Alignment.MID, pad);
319 tooltip.addPara(
"Numerous asteroids present on the battlefield. Large enough to be an in-combat navigational hazard.", small);
334 return "asteroid_belt";
338 return flag == TerrainAIFlags.REDUCES_SPEED_LARGE || flag == TerrainAIFlags.DANGEROUS_UNLESS_GO_SLOW ||
339 flag == TerrainAIFlags.NOT_SUPER_DANGEROUS_UNLESS_GO_SLOW;
344 if (Misc.getAsteroidSource(asteroid) ==
this) {
static SettingsAPI getSettings()
static SectorAPI getSector()
AsteroidBeltParams params
void renderOnMap(float factor, float alphaMult)
void createTooltip(TooltipMakerAPI tooltip, boolean expanded)
String getNameForTooltip()
void applyEffect(SectorEntityToken entity, float days)
boolean isTooltipExpandable()
void regenerateAsteroids()
void init(String terrainId, SectorEntityToken entity, Object param)
void reportAsteroidPersisted(SectorEntityToken asteroid)
void render(CampaignEngineLayers layer, ViewportAPI viewport)
void advance(float amount)
String getEffectCategory()
boolean needToCreateAsteroids
boolean hasAIFlag(Object flag)
void render(Vector2f loc, float minR, float maxR, Color color, boolean spiral, float factor, float alphaMult)
static float getVisibilityMult(CampaignFleetAPI fleet)
Description getDescription(String id, Type type)
String getControlStringForEnumName(String name)
Color getColor(String id)