Starsector API
Loading...
Searching...
No Matches
PhaseAnchor.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.hullmods;
2
3import java.awt.Color;
4
5import org.lwjgl.util.vector.Vector2f;
6
7import com.fs.starfarer.api.Global;
8import com.fs.starfarer.api.combat.BaseHullMod;
9import com.fs.starfarer.api.combat.MutableShipStatsAPI;
10import com.fs.starfarer.api.combat.ShipAPI;
11import com.fs.starfarer.api.combat.ShipAPI.HullSize;
12import com.fs.starfarer.api.combat.ShipCommand;
13import com.fs.starfarer.api.combat.ShipSystemAPI.SystemState;
14import com.fs.starfarer.api.combat.listeners.AdvanceableListener;
15import com.fs.starfarer.api.combat.listeners.HullDamageAboutToBeTakenListener;
16import com.fs.starfarer.api.impl.campaign.ids.HullMods;
17import com.fs.starfarer.api.impl.campaign.ids.Strings;
18import com.fs.starfarer.api.impl.campaign.skills.NeuralLinkScript;
19import com.fs.starfarer.api.util.FaderUtil;
20import com.fs.starfarer.api.util.Misc;
21
22public class PhaseAnchor extends BaseHullMod {
23
24 public static float PHASE_DISSIPATION_MULT = 2f;
25 public static float ACTIVATION_COST_MULT = 0f;
26
27 public static float CR_LOSS_MULT_FOR_EMERGENCY_DIVE = 1f;
28
29 public static class PhaseAnchorScript implements AdvanceableListener, HullDamageAboutToBeTakenListener {
30 public ShipAPI ship;
31 public boolean emergencyDive = false;
32 public float diveProgress = 0f;
33 public FaderUtil diveFader = new FaderUtil(1f, 1f);
34 public PhaseAnchorScript(ShipAPI ship) {
35 this.ship = ship;
36 }
37
38 public boolean notifyAboutToTakeHullDamage(Object param, ShipAPI ship, Vector2f point, float damageAmount) {
39 //if (ship.getCurrentCR() <= 0) return false;
40
41 if (!emergencyDive) {
42 String key = "phaseAnchor_canDive";
43 boolean canDive = !Global.getCombatEngine().getCustomData().containsKey(key);
44 float depCost = 0f;
45 if (ship.getFleetMember() != null) {
46 depCost = ship.getFleetMember().getDeployCost();
47 }
48 float crLoss = CR_LOSS_MULT_FOR_EMERGENCY_DIVE * depCost;
49 canDive &= ship.getCurrentCR() >= crLoss;
50
51 float hull = ship.getHitpoints();
52 if (damageAmount >= hull && canDive) {
53 ship.setHitpoints(1f);
54
55 //ship.setCurrentCR(Math.max(0f, ship.getCurrentCR() - crLoss));
56 if (ship.getFleetMember() != null) { // fleet member is fake during simulation, so this is fine
57 ship.getFleetMember().getRepairTracker().applyCREvent(-crLoss, "Emergency phase dive");
58 //ship.getFleetMember().getRepairTracker().setCR(ship.getFleetMember().getRepairTracker().getBaseCR() + crLoss);
59 }
60 emergencyDive = true;
61 Global.getCombatEngine().getCustomData().put(key, true);
62
63 if (!ship.isPhased()) {
64 Global.getSoundPlayer().playSound("system_phase_cloak_activate", 1f, 1f, ship.getLocation(), ship.getVelocity());
65 }
66 }
67 }
68
69 if (emergencyDive) {
70 return true;
71 }
72
73 return false;
74 }
75
76 public void advance(float amount) {
77 String id = "phase_anchor_modifier";
78 if (emergencyDive) {
79 Color c = ship.getPhaseCloak().getSpecAPI().getEffectColor2();
80 c = Misc.setAlpha(c, 255);
81 c = Misc.interpolateColor(c, Color.white, 0.5f);
82
83 if (diveProgress == 0f) {
84 if (ship.getFluxTracker().showFloaty()) {
85 float timeMult = ship.getMutableStats().getTimeMult().getModifiedValue();
86 Global.getCombatEngine().addFloatingTextAlways(ship.getLocation(),
87 "Emergency dive!",
88 NeuralLinkScript.getFloatySize(ship), c, ship, 16f * timeMult, 3.2f/timeMult, 1f/timeMult, 0f, 0f,
89 1f);
90 }
91 }
92
93 diveFader.advance(amount);
94 ship.setRetreating(true, false);
95
96 ship.blockCommandForOneFrame(ShipCommand.USE_SYSTEM);
97 diveProgress += amount * ship.getPhaseCloak().getChargeUpDur();
98 float curr = ship.getExtraAlphaMult();
99 ship.getPhaseCloak().forceState(SystemState.IN, Math.min(1f, Math.max(curr, diveProgress)));
100 ship.getMutableStats().getHullDamageTakenMult().modifyMult(id, 0f);
101
102 if (diveProgress >= 1f) {
103 if (diveFader.isIdle()) {
104 Global.getSoundPlayer().playSound("phase_anchor_vanish", 1f, 1f, ship.getLocation(), ship.getVelocity());
105 }
106 diveFader.fadeOut();
107 diveFader.advance(amount);
108 float b = diveFader.getBrightness();
109 ship.setExtraAlphaMult2(b);
110
111 float r = ship.getCollisionRadius() * 5f;
112 ship.setJitter(this, c, b, 20, r * (1f - b));
113
114 if (diveFader.isFadedOut()) {
115 ship.getLocation().set(0, -1000000f);
116 }
117 }
118 }
119
120
121 boolean phased = ship.isPhased();
122 if (ship.getPhaseCloak() != null && ship.getPhaseCloak().isChargedown()) {
123 phased = false;
124 }
125
126 MutableShipStatsAPI stats = ship.getMutableStats();
127 if (phased) {
128 stats.getFluxDissipation().modifyMult(id, PHASE_DISSIPATION_MULT);
129 stats.getBallisticRoFMult().modifyMult(id, PHASE_DISSIPATION_MULT);
130 stats.getEnergyRoFMult().modifyMult(id, PHASE_DISSIPATION_MULT);
131 stats.getMissileRoFMult().modifyMult(id, PHASE_DISSIPATION_MULT);
132 stats.getBallisticAmmoRegenMult().modifyMult(id, PHASE_DISSIPATION_MULT);
133 stats.getEnergyAmmoRegenMult().modifyMult(id, PHASE_DISSIPATION_MULT);
134 stats.getMissileAmmoRegenMult().modifyMult(id, PHASE_DISSIPATION_MULT);
135
136 // doesn't actually work, needs to update the ammo tracker in the system and this isn't handled
137 // probably overpowered anyway...
138 //stats.getSystemRegenBonus().modifyMult(id, PHASE_DISSIPATION_MULT);
139 } else {
140 stats.getFluxDissipation().unmodifyMult(id);
141 stats.getBallisticRoFMult().unmodifyMult(id);
142 stats.getEnergyRoFMult().unmodifyMult(id);
143 stats.getMissileRoFMult().unmodifyMult(id);
144 stats.getBallisticAmmoRegenMult().unmodifyMult(id);
145 stats.getEnergyAmmoRegenMult().unmodifyMult(id);
146 stats.getMissileAmmoRegenMult().unmodifyMult(id);
147 //stats.getSystemRegenBonus().unmodifyMult(id);
148 }
149 }
150
151 }
152
153 @Override
154 public void applyEffectsAfterShipCreation(ShipAPI ship, String id) {
155 ship.addListener(new PhaseAnchorScript(ship));
156 }
157
158 public void applyEffectsBeforeShipCreation(HullSize hullSize, MutableShipStatsAPI stats, String id) {
159 stats.getPhaseCloakActivationCostBonus().modifyMult(id, 0f);
160 }
161
162 public String getDescriptionParam(int index, HullSize hullSize) {
163 if (index == 0) return "zero";
164 if (index == 1) return "" + (int)PHASE_DISSIPATION_MULT + Strings.X;
165 if (index == 2) return "" + (int)CR_LOSS_MULT_FOR_EMERGENCY_DIVE + Strings.X;
166
167 // if (index == 1) return "" + (int) Math.round(PHASE_TIME_BONUS) + "%";
168// float multWithoutMod = PhaseCloakStats.MAX_TIME_MULT;
169// float multWithMod = 1f + (multWithoutMod - 1f) * (1f + PHASE_TIME_BONUS/100f);
170// if (index == 2) return "" + (int) Math.round(multWithoutMod) + Strings.X;
171// if (index == 3) return "" + (int) Math.round(multWithMod) + Strings.X;
172//
173// if (index == 4) return "" + (int) Math.round((1f - FLUX_THRESHOLD_DECREASE_MULT) * 100f) + "%";
174// if (index == 5) return "" + (int) Math.round(PhaseCloakStats.BASE_FLUX_LEVEL_FOR_MIN_SPEED * 100f) + "%";
175// if (index == 6) return "" + (int)Math.round(
176// PhaseCloakStats.BASE_FLUX_LEVEL_FOR_MIN_SPEED * 100f * FLUX_THRESHOLD_DECREASE_MULT) + "%";
177//
178 //if (index == 0) return "" + (int) Math.round(PHASE_COOLDOWN_REDUCTION) + "%";
179 return null;
180 }
181
182 @Override
183 public boolean isApplicableToShip(ShipAPI ship) {
184 if (ship.getVariant().hasHullMod(HullMods.ADAPTIVE_COILS)) return false;
185 return ship.getHullSpec().isPhase();
186 }
187
188 @Override
189 public String getUnapplicableReason(ShipAPI ship) {
190 if (ship.getVariant().hasHullMod(HullMods.ADAPTIVE_COILS)) {
191 return "Incompatible with Adaptive Phase Coils";
192 }
193 if (!ship.getHullSpec().isPhase()) {
194 return "Can only be installed on phase ships";
195 }
196 return super.getUnapplicableReason(ship);
197 }
198
199}
200
static SoundPlayerAPI getSoundPlayer()
Definition Global.java:43
static CombatEngineAPI getCombatEngine()
Definition Global.java:63
void applyEffectsBeforeShipCreation(HullSize hullSize, MutableShipStatsAPI stats, String id)
void applyEffectsAfterShipCreation(ShipAPI ship, String id)
String getDescriptionParam(int index, HullSize hullSize)
SoundAPI playSound(String id, float pitch, float volume, Vector2f loc, Vector2f vel)