1package com.fs.starfarer.api.impl.campaign.abilities;
3import java.util.LinkedHashMap;
5import java.util.Random;
9import org.lwjgl.util.vector.Vector2f;
11import com.fs.starfarer.api.EveryFrameScript;
12import com.fs.starfarer.api.Global;
13import com.fs.starfarer.api.campaign.CampaignFleetAPI;
14import com.fs.starfarer.api.campaign.CampaignTerrainAPI;
15import com.fs.starfarer.api.campaign.FactionAPI;
16import com.fs.starfarer.api.campaign.JumpPointAPI;
17import com.fs.starfarer.api.campaign.PlanetAPI;
18import com.fs.starfarer.api.campaign.PlanetSpecAPI;
19import com.fs.starfarer.api.campaign.SectorEntityToken;
20import com.fs.starfarer.api.characters.AbilityPlugin;
21import com.fs.starfarer.api.fleet.FleetMemberViewAPI;
22import com.fs.starfarer.api.impl.campaign.ids.Abilities;
23import com.fs.starfarer.api.impl.campaign.ids.Factions;
24import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
25import com.fs.starfarer.api.impl.campaign.ids.Pings;
26import com.fs.starfarer.api.impl.campaign.ids.StarTypes;
27import com.fs.starfarer.api.impl.campaign.ids.Tags;
28import com.fs.starfarer.api.impl.campaign.ids.Terrain;
29import com.fs.starfarer.api.impl.campaign.terrain.HyperspaceTerrainPlugin;
30import com.fs.starfarer.api.impl.campaign.velfield.SlipstreamTerrainPlugin2;
31import com.fs.starfarer.api.impl.campaign.velfield.SlipstreamTerrainPlugin2.SlipstreamParams2;
32import com.fs.starfarer.api.impl.campaign.velfield.SlipstreamTerrainPlugin2.SlipstreamSegment;
33import com.fs.starfarer.api.ui.Alignment;
34import com.fs.starfarer.api.ui.TooltipMakerAPI;
35import com.fs.starfarer.api.util.Misc;
36import com.fs.starfarer.api.util.Misc.FleetMemberDamageLevel;
82 protected boolean done =
false;
83 protected int index = 0;
84 protected float elapsed = 0f;
85 protected float maxElapsed = 0f;
89 float fadeInLength = 300f;
90 float lengthSoFar = 0f;
92 maxElapsed = durIn * plugin.
getSegments().size() * 0.34f + 3f;
93 for (SlipstreamSegment seg : plugin.
getSegments()) {
94 seg.fader.setDurationIn(durIn);
97 seg.bMult = Math.min(1f, lengthSoFar / fadeInLength);
98 lengthSoFar += seg.lengthToNext;
101 public void advance(
float amount) {
108 for (SlipstreamSegment curr : plugin.
getSegments()) {
117 if (index >= plugin.
getSegments().size() || elapsed > maxElapsed) {
121 SlipstreamSegment curr = plugin.
getSegments().get(index);
128 plugin.
getSegments().get(index + 1).fader.fadeIn();
131 plugin.
getSegments().get(index + 2).fader.fadeIn();
135 public boolean isDone() {
138 public boolean runWhilePaused() {
144 protected float elapsed = 0f;
145 protected float extraRadius;
146 public ExpandStormRadiusScript(
float extraRadius) {
147 this.extraRadius = extraRadius;
149 public void advance(
float amount) {
153 if (terrain !=
null) {
160 public boolean isDone() {
161 return elapsed >= 10f;
163 public boolean runWhilePaused() {
168 public static class SlipsurgeEffectScript
implements EveryFrameScript {
169 protected CampaignFleetAPI fleet;
170 protected boolean triggered =
false;
171 protected boolean done =
false;
172 protected boolean didTempCleanup =
false;
173 protected float elapsed = 0f;
174 protected SlipstreamTerrainPlugin2 plugin;
175 public SlipsurgeEffectScript(CampaignFleetAPI fleet, SlipstreamTerrainPlugin2 plugin) {
177 this.plugin = plugin;
180 public void abort() {
182 didTempCleanup =
true;
184 fleet.setNoEngaging(0f);
185 fleet.getStats().getSensorRangeMod().unmodifyMult(
SENSOR_MOD_ID);
186 for (FleetMemberViewAPI view : fleet.getViews()) {
189 if (fleet.isPlayerFleet()) {
190 Global.getSector().getCampaignUI().setFollowingDirectCommand(
false);
195 public void advance(
float amount) {
198 if (fleet.isInHyperspaceTransition() ||
199 plugin.getEntity().getContainingLocation() != fleet.getContainingLocation()) {
200 if (!didTempCleanup) {
210 if (elapsed >= 30f ||
211 !plugin.getEntity().isAlive()) {
217 float burn = Misc.getBurnLevelForSpeed(fleet.getVelocity().length());
218 if (burn > 50 && plugin.containsEntity(fleet)) {
224 plugin.despawn(0, 0.2f,
new Random());
229 AbilityPlugin gs = fleet.getAbility(Abilities.GENERATE_SLIPSURGE);
230 if (gs instanceof BaseAbilityPlugin) {
231 BaseAbilityPlugin base = (BaseAbilityPlugin) gs;
232 for (AbilityPlugin curr : fleet.getAbilities().values()) {
233 if (curr ==
this)
continue;
234 if (!base.isCompatible(curr)) {
235 if (curr.isActiveOrInProgress()) {
243 float decelMult = Misc.getAbyssalDepth(fleet) * 1f;
244 if (fleet.getGoSlowOneFrame()) decelMult = 1f;
246 if (decelMult > 0f && !plugin.containsEntity(fleet)) {
247 float angle = Misc.getAngleInDegrees(fleet.getVelocity());
248 Vector2f decelDir = Misc.getUnitVectorAtDegreeAngle(angle + 180f);
250 float targetDecelSeconds = 0.5f;
251 float speed = fleet.getVelocity().length();
252 float decelAmount = amount * speed / targetDecelSeconds;
253 decelDir.scale(decelAmount * decelMult);
255 Vector2f vel = fleet.getVelocity();
256 fleet.setVelocity(vel.x + decelDir.x, vel.y + decelDir.y);
260 fleet.fadeOutIndicator();
261 fleet.setNoEngaging(0.1f);
262 fleet.setInteractionTarget(
null);
263 if (fleet.isPlayerFleet()) {
264 Global.getSector().getCampaignUI().setFollowingDirectCommand(
true);
266 fleet.getMemoryWithoutUpdate().set(MemFlags.NO_HIGH_BURN_TOPOGRAPHY_READINGS,
true, 0.1f);
268 didTempCleanup =
false;
270 float angle = Misc.getAngleInDegrees(fleet.getVelocity());
271 Vector2f jitterDir = Misc.getUnitVectorAtDegreeAngle(angle + 180f);
272 Vector2f windDir = Misc.getUnitVectorAtDegreeAngle(angle);
273 float windIntensity = (burn - 50f) / 250f;
274 if (windIntensity < 0) windIntensity = 0;
277 float b = (burn - 50f) / 450f;
282 if (fleet.isPlayerFleet()) {
285 Global.getSoundPlayer().setNextLoopFadeInAndOut(0.05f, 0.5f);
288 fleet.getLocation(), fleet.getVelocity());
293 for (FleetMemberViewAPI view : fleet.getViews()) {
294 Color c = view.getMember().getHullSpec().getHyperspaceJitterColor();
300 c = Misc.setAlpha(c, 60);
301 view.setJitter(0.1f, 1f, c, 10 + Math.round(40f * b), 20f);
302 view.setUseCircularJitter(
true);
303 view.setJitterDirection(jitterDir);
304 view.setJitterLength(30f * b);
305 view.setJitterBrightness(b);
309 for (FleetMemberViewAPI view : fleet.getViews()) {
317 public boolean isDone() {
320 public boolean runWhilePaused() {
337 return FleetMemberDamageLevel.MEDIUM;
347 if (fleet ==
null)
return;
351 if (
well ==
null)
return;
374 if (fleet ==
null)
return;
393 if (fleet ==
null)
return;
397 if (jp ==
null)
return;
409 SlipstreamParams2 params =
new SlipstreamParams2();
411 params.enteringSlipstreamTextOverride =
"Entering slipsurge";
412 params.enteringSlipstreamTextDurationOverride = 0.1f;
413 params.forceNoWindVisualEffectOnFleets =
true;
416 float length = 1000f;
418 length += strength * 500f;
419 params.burnLevel = Math.round(400f + strength * strength * 500f);
420 params.accelerationMult = 20f + strength * strength * 280f;
424 params.baseWidth = width;
425 params.widthForMaxSpeed = 400f;
426 params.widthForMaxSpeedMinMult = 0.34f;
428 params.slowDownInWiderSections =
true;
436 params.lineLengthFractionOfSpeed = 2000f / ((params.maxSpeed + params.minSpeed) * 0.5f);
438 float lineFactor = 0.1f;
439 params.minSpeed *= lineFactor;
440 params.maxSpeed *= lineFactor;
443 params.maxBurnLevelForTextureScroll = (int) (params.burnLevel * 0.1f);
445 params.particleFadeInTime = 0.01f;
446 params.areaPerParticle = 1000f;
449 to.scale(offset + fleet.
getRadius() + length);
458 float spacing = 100f;
459 float incr = spacing / length;
461 Vector2f diff = Vector2f.sub(to, from,
new Vector2f());
462 for (
float f = 0; f <= 1f; f += incr) {
463 Vector2f curr =
new Vector2f(diff);
465 Vector2f.add(curr, from, curr);
466 plugin.
addSegment(curr, width - Math.min(300f, 300f * (
float)Math.sqrt(f)));
472 plugin.
despawn(1.5f, 0.2f,
new Random());
474 slipstream.
addScript(
new SlipsurgeFadeInScript(plugin));
475 fleet.
addScript(
new SlipsurgeEffectScript(fleet, plugin));
482 if (fleet ==
null)
return;
492 if (!super.isUsable())
return false;
493 return super.isUsable() &&
505 if (fleet ==
null)
return;
517 extra =
"and availability ";
522 tooltip.
addPara(
"Overload and modulate the fleet's drive field "
523 +
"to induce an extremely powerful, "
524 +
"short-duration slipstream flowing away from the nearest gravity well, its strength " + extra
525 +
"based on the stellar object's mass, density, and some other poorly-understood factors. "
526 +
"Largely ineffective inside abyssal hyperspace.", pad);
541 tooltip.
beginTable(player, 20f,
"Stellar object type", tw - strW,
"Surge strength", strW);
570 float xOff = (int)((tw2 - tw) / 2f);
577 tooltip.
addPara(
"A stronger surge can allow the fleet to rapidly travel up to %s light-years. "
578 +
"Attempting to %s "
579 +
"during the transit will decelerate the fleet quickly. Fleet sensor range is "
580 +
"reduced by %s during the transit.", pad, highlight,
589 if (fleet ==
null)
return false;
596 tooltip.
addPara(
"Can only be used in hyperspace.", bad, pad);
602 tooltip.
addPara(
"Must be near a powerful gravity well.", bad, pad);
604 tooltip.
addPara(
"Must be near a gravity well.", bad, pad);
615 if (fleet ==
null)
return null;
618 float minDist = Float.MAX_VALUE;
627 if (str <= min)
continue;
631 if (dist > jp.
getRadius() + 150f)
continue;
632 if (dist < minDist) {
645 if (!(
object instanceof
PlanetAPI))
return 0f;
649 if (val !=
null)
return val;
651 if (
spec.isGasGiant())
return 0f;
659 if (name.contains(
"neutron") ||
spec.isPulsar()) {
661 }
else if (name.contains(
"dwarf")) {
663 }
else if (name.contains(
"supergiant")) {
665 }
else if (name.contains(
"giant")) {
667 }
else if (name.contains(
" hole")) {
669 }
else if (name.contains(
"brown")) {
674 if (val !=
null)
return val;
static boolean CODEX_TOOLTIP_MODE
static SectorAPI getSector()
transient AbilitySpecAPI spec
CampaignFleetAPI getFleet()
static String TRANSIT_SOUND_LOOP
void applyStatsEffect(float amount, float level)
void unapplyStatsEffect()
static String SENSOR_MOD_ID
float getStrengthForGravityWell(JumpPointAPI jp)
float getStrengthForStellarObject(SectorEntityToken object)
void addInitialDescription(TooltipMakerAPI tooltip, boolean expanded)
boolean canRecoverCRWhileActive()
static float SENSOR_RANGE_MULT
static float SLIPSURGE_STRENGTH_MULT
static float FUEL_COST_MULT
JumpPointAPI findGravityWell()
static float CR_COST_MULT
void generateSlipstream()
static Map< String, Float > SLIPSURGE_STRENGTH
static boolean REQUIRE_GIANT_STARS_OR_STRONGER
boolean addNotUsableReasonBeforeFuelCost(TooltipMakerAPI tooltip, boolean expanded)
static float TRANSIT_MUSIC_SUPPRESSION
FleetMemberDamageLevel getActivationDamageLevel()
static final String PLAYER
static final String SLIPSURGE
static final String BLUE_SUPERGIANT
static final String BLUE_GIANT
static final String NEUTRON_STAR
static final String ORANGE
static final String ORANGE_GIANT
static final String BROWN_DWARF
static final String RED_DWARF
static final String ICE_GIANT
static final String BLACK_HOLE
static final String GAS_GIANT
static final String WHITE_DWARF
static final String RED_GIANT
static final String YELLOW
static final String RED_SUPERGIANT
static final String SLIPSTREAM
SectorEntityToken getEntity()
void setStormCellTimeMultOutsideBaseArea(float stormCellTimeMultOutsideBaseArea)
void setExtraDistanceAroundPlayerToAdvanceStormCells(float extraDistanceAroundPlayerToAdvanceStormCells)
void addSegment(Vector2f loc, float width)
void despawn(float despawnDelay, float despawnDays, Random random)
List< SlipstreamSegment > getSegments()
static Color getTextColor()
static Vector2f getUnitVectorAtDegreeAngle(float degrees)
static Color getNegativeHighlightColor()
static Color getBasePlayerColor()
static Color getGrayColor()
static float getDistance(SectorEntityToken from, SectorEntityToken to)
static CampaignTerrainAPI getHyperspaceTerrain()
static Color getHighlightColor()
static float getSpeedForBurnLevel(float burnLevel)
static float getAngleInDegrees(Vector2f v)
LocationAPI getContainingLocation()
void goSlowOneFrame(boolean stop)
CampaignTerrainPlugin getPlugin()
SectorEntityToken getDestinationVisualEntity()
boolean isGasGiantAnchor()
SectorEntityToken addTerrain(String terrainId, Object param)
List< SectorEntityToken > getJumpPoints()
void addScript(EveryFrameScript script)
SectorEntityToken createToken(float x, float y)
EveryFrameScript addPing(SectorEntityToken entity, String pingType)
FactionAPI getFaction(String factionId)
LocationAPI getContainingLocation()
boolean isInCurrentLocation()
void addScript(EveryFrameScript script)
void setLocation(float x, float y)
PositionAPI setXAlignOffset(float xAlignOffset)
PositionAPI getPosition()