Starsector API
Loading...
Searching...
No Matches
ShroudedMantleHullmod.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.combat.dweller;
2
3import org.lwjgl.util.vector.Vector2f;
4
5import com.fs.starfarer.api.Global;
6import com.fs.starfarer.api.campaign.CargoAPI.CargoItemType;
7import com.fs.starfarer.api.campaign.CargoStackAPI;
8import com.fs.starfarer.api.campaign.SpecialItemData;
9import com.fs.starfarer.api.combat.CombatEngineAPI;
10import com.fs.starfarer.api.combat.MutableShipStatsAPI;
11import com.fs.starfarer.api.combat.ShipAPI;
12import com.fs.starfarer.api.combat.ShipAPI.HullSize;
13import com.fs.starfarer.api.combat.ShipCommand;
14import com.fs.starfarer.api.impl.campaign.ids.Items;
15import com.fs.starfarer.api.impl.combat.threat.RoilingSwarmEffect.SwarmMember;
16import com.fs.starfarer.api.util.IntervalUtil;
17import com.fs.starfarer.api.util.Misc;
18
23
24 public static float HEAL_MULT = 0.5f;
25
26 public static float LUNGE_COOLDOWN = 10f;
27 public static float LUNGE_DUR = 4f;
28 public static float LUNGE_SPEED = 250f;
29
30 @Override
31 public void applyEffectsBeforeShipCreation(HullSize hullSize, MutableShipStatsAPI stats, String id) {
32 super.applyEffectsBeforeShipCreation(hullSize, stats, id);
33
34 boolean sMod = isSMod(stats);
35 if (sMod) {
37 }
38 }
39
40 public String getDescriptionParam(int index, HullSize hullSize) {
41 if (index == 0) return "" + (int) CREW_CASUALTIES + "%";
42 return null;
43 }
44
45 @Override
46 public String getSModDescriptionParam(int index, HullSize hullSize, ShipAPI ship) {
47 if (index == 0) return "" + (int) Math.round(HEAL_MULT * 100f) + "%";
48 return null;
49 }
50
51 @Override
53 return Global.getSettings().createCargoStack(CargoItemType.SPECIAL,
54 new SpecialItemData(Items.SHROUDED_MANTLE, null), null);
55 }
56
57
58 public static String DATA_KEY = "core_ShroudedMantleHullmod_data_key";
59 public static class ShroudedMantleHullmodData {
60 IntervalUtil interval = new IntervalUtil(0.75f, 1.25f);
61 float hullAtPrevLunge = 1f;
62 float cooldown = 0f;
63 boolean lunging = false;
64 Vector2f lungeDest;
65 float lungeElapsed = 0f;
66 boolean fadedFlash = false;
67 }
68
69 @Override
70 public void advanceInCombat(ShipAPI ship, float amount) {
71 super.advanceInCombat(ship, amount);
72
73 if (!ship.isAlive()) return;
74 if (amount <= 0f) return;
75
77
78 String key = DATA_KEY + "_" + ship.getId();
79 ShroudedMantleHullmodData data = (ShroudedMantleHullmodData) engine.getCustomData().get(key);
80 if (data == null) {
81 data = new ShroudedMantleHullmodData();
82 engine.getCustomData().put(key, data);
83 }
84
85 boolean forceUse = false;
86
87// if (Keyboard.isKeyDown(Keyboard.KEY_K)) {
88// forceUse = true;
89// data.cooldown = 0f;
90// }
91
92 if (data.cooldown > 0) {
93 data.cooldown -= amount;
94 if (data.cooldown < 0) data.cooldown = 0;
95 if (data.cooldown > 0) {
96 return;
97 }
98 }
99
100 if (ship.getFluxLevel() > 0.95f && ship.getHullLevel() > 0.25f &&
101 ship.getShield() != null && ship.getShield().isOn()) {
102 forceUse = true;
103 }
104 if (ship.getFluxTracker().isOverloaded()) {
105 forceUse = true;
106 }
107
108 data.interval.advance(amount * 2f);
109 if ((data.interval.intervalElapsed() || forceUse) && !data.lunging) {
110 float hull = ship.getHullLevel();
111 data.hullAtPrevLunge = Math.max(hull, data.hullAtPrevLunge);
112 if (hull <= data.hullAtPrevLunge - ConvulsiveLungeSystemAI.HULL_LOSS_FOR_PULLBACK || forceUse) {
113 data.lunging = true;
114 data.lungeElapsed = 0f;
115 data.lungeDest = null;
116 data.fadedFlash = false;
117 data.hullAtPrevLunge = hull;
118 }
119 }
120
121 doLunge(data, ship, amount);
122 }
123
124 protected void doLunge(ShroudedMantleHullmodData data, ShipAPI ship, float amount) {
125 if (!data.lunging) return;
126 //if (ship.getFluxTracker().isOverloadedOrVenting()) return;
127
129
130 if (data.lungeElapsed < 1f || data.lungeDest == null) {
131 if (data.lungeDest == null) {
133 data.lungeDest.scale(ConvulsiveLungeSystemScript.PULL_DIST);
134 Vector2f.add(data.lungeDest, ship.getLocation(), data.lungeDest);
135 }
136
137 if (data.lungeDest != null) {
138 if (shroud != null) {
139 Vector2f dir = Misc.getUnitVector(ship.getLocation(), data.lungeDest);
140 float accel = ConvulsiveLungeSystemScript.PARTICLE_WINDUP_ACCEL * amount * 1f;
141 if (!ship.isFrigate()) accel *= 2f;
142 boolean affect = true;
143 for (SwarmMember p : shroud.getMembers()) {
144 if (affect) {
145 p.vel.x += dir.x * accel;
146 p.vel.y += dir.y * accel;
147 }
148 if (ship.isFrigate()) {
149 affect = !affect;
150 }
151 }
152 }
153 }
154 } else if (data.lungeDest != null) {
155 Vector2f dir = Misc.getUnitVectorAtDegreeAngle(Misc.getAngleInDegrees(ship.getLocation(), data.lungeDest));
156
157 boolean slowdown = data.lungeElapsed > LUNGE_DUR - 1f;
158 if (slowdown) {
159 dir = Misc.normalise(new Vector2f(ship.getVelocity()));
160 dir.negate();
161 }
162
163 if (!data.fadedFlash) {
164 if (shroud != null) {
165 for (SwarmMember p : shroud.getMembers()) {
166 if (p.flash != null) {
167 p.flash.fadeOut();
168 }
169 }
170 }
171 data.fadedFlash = true;
172 }
173
174 Vector2f loc = ship.getLocation();
175 float dist = Misc.getDistance(loc, data.lungeDest);
176
177 //Vector2f perp = new Vector2f(-dir.y, dir.x);
178
179 float friction = ConvulsiveLungeSystemScript.FRICTION;
181 float freeLength = 0f;
182 float stretch = dist - freeLength;
183
184 float forceMag = k * Math.abs(stretch);
185
186 float speedInDir = Vector2f.dot(dir, ship.getVelocity());
187 if (speedInDir > LUNGE_SPEED) {
188 float mult = 1f - Math.min(1f, (speedInDir - LUNGE_SPEED) / 100f);
189 forceMag *= mult;
190 }
191
192
193 float forceMagReduction = Math.min(Math.abs(forceMag), friction);
194 forceMag -= forceMagReduction;
195 friction -= forceMagReduction;
196
197 Vector2f force = new Vector2f(dir);
198 if (slowdown) {
199 forceMag = ship.getVelocity().length() * 2f;
200 force.scale(forceMag);
201 } else {
202 force.scale(forceMag * Math.signum(stretch));
203 }
204
205 Vector2f acc = new Vector2f(force);
206 acc.scale(amount);
207 Vector2f.add(ship.getVelocity(), acc, ship.getVelocity());
208 }
209
210 ship.giveCommand(ShipCommand.DECELERATE, null, 0);
211
212 data.lungeElapsed += amount;
213 if (data.lungeElapsed > LUNGE_DUR) {
214 data.lunging = false;
215 data.cooldown = LUNGE_COOLDOWN;
216 }
217 }
218
219}
220
221
222
223
224
225
226
227
228
229
230
231
232
233
static SettingsAPI getSettings()
Definition Global.java:57
static CombatEngineAPI getCombatEngine()
Definition Global.java:69
boolean isSMod(MutableShipStatsAPI stats)
void modifyFlat(String source, float value)
static DwellerShroud getShroudFor(CombatEntityAPI entity)
void doLunge(ShroudedMantleHullmodData data, ShipAPI ship, float amount)
String getSModDescriptionParam(int index, HullSize hullSize, ShipAPI ship)
void applyEffectsBeforeShipCreation(HullSize hullSize, MutableShipStatsAPI stats, String id)
static Vector2f getUnitVectorAtDegreeAngle(float degrees)
Definition Misc.java:1196
static float getDistance(SectorEntityToken from, SectorEntityToken to)
Definition Misc.java:599
static Vector2f getUnitVector(Vector2f from, Vector2f to)
Definition Misc.java:1191
static float getAngleInDegrees(Vector2f v)
Definition Misc.java:1126
static Vector2f normalise(Vector2f v)
Definition Misc.java:1134
float getSafeMovementDir(ShipAPI ship)
CargoStackAPI createCargoStack(CargoItemType type, Object data, CargoAPI cargo)
void giveCommand(ShipCommand command, Object param, int groupNumber)