Starsector API
Loading...
Searching...
No Matches
ThreatShipConstructionScript.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.combat.threat;
2
3import java.util.ArrayList;
4import java.util.List;
5
6import java.awt.Color;
7
8import org.lwjgl.util.vector.Vector2f;
9
10import com.fs.starfarer.api.Global;
11import com.fs.starfarer.api.campaign.FactionAPI;
12import com.fs.starfarer.api.combat.BaseEveryFrameCombatPlugin;
13import com.fs.starfarer.api.combat.CollisionClass;
14import com.fs.starfarer.api.combat.CombatEngineAPI;
15import com.fs.starfarer.api.combat.CombatFleetManagerAPI;
16import com.fs.starfarer.api.combat.DamageType;
17import com.fs.starfarer.api.combat.ShipAPI;
18import com.fs.starfarer.api.combat.ShipCommand;
19import com.fs.starfarer.api.combat.WeaponGroupAPI;
20import com.fs.starfarer.api.impl.campaign.ids.Factions;
21import com.fs.starfarer.api.impl.combat.RiftLanceEffect;
22import com.fs.starfarer.api.impl.combat.threat.RoilingSwarmEffect.SwarmMember;
23import com.fs.starfarer.api.input.InputEventAPI;
24import com.fs.starfarer.api.util.IntervalUtil;
25import com.fs.starfarer.api.util.Misc;
26
28
29 public static String SWARM_CONSTRUCTING_SHIP = "swarm_constructing_ship";
30 public static String SHIP_UNDER_CONSTRUCTION = "ship_under_construction";
31
32 public static float FADE_IN_RATE_MULT_WHEN_DESTROYED = 10f;
33
34 protected float elapsed = 0f;
35 protected ShipAPI ship = null;
37
38 protected String variantId;
39 protected ShipAPI source;
40 protected float delay;
41 protected float fadeInTime;
42 protected float origMaxSpeed = 500f;
43 protected List<ShipAPI> explodedPieces = new ArrayList<>();
44
45 protected IntervalUtil interval = new IntervalUtil(0.075f, 0.125f);
46
48 this.variantId = variantId;
49 this.source = source;
50 this.delay = delay;
51 this.fadeInTime = fadeInTime;
52
54
55 spawnShip();
56 }
57
58 public ShipAPI getShip() {
59 return ship;
60 }
61
62 protected void spawnShip() {
63 float facing = source.getFacing() + 15f * ((float) Math.random() - 0.5f);
64
65 Vector2f loc = new Vector2f(source.getLocation());
66
69 boolean wasSuppressed = fleetManager.isSuppressDeploymentMessages();
70 fleetManager.setSuppressDeploymentMessages(true);
71
72 ship = engine.getFleetManager(source.getOriginalOwner()).spawnShipOrWing(variantId, loc, facing, 0f, null);
75 if (faction != null) {
76 String name = faction.pickRandomShipName();
77 ship.setName(name);
78 }
79 }
80 fleetManager.setSuppressDeploymentMessages(wasSuppressed);
82
83
86 if (swarm != null) {
87 swarm.params.withInitialMembers = false;
88 swarm.params.withRespawn = false;
89 }
90 if (sourceSwarm != null) {
91 origMaxSpeed = sourceSwarm.params.maxSpeed;
92// sourceSwarm.params.maxSpeed *= 0.25f;
93 sourceSwarm.params.outspeedAttachedEntityBy = 0f;
94 if (swarm != null) {
95 swarm.params.withInitialMembers = false;
96 swarm.params.flashFringeColor = sourceSwarm.params.flashFringeColor;
97 }
98 }
99
103 source.getMutableStats().getHullDamageTakenMult().modifyMult("ThreatShipConstructionScript", 0f);
104
105 ship.setShipAI(null);
107 g.toggleOff();
108 }
109 }
110
111 protected float hulkFor = 0f;
112
113 @Override
114 public void advance(float amount, List<InputEventAPI> events) {
115 if (Global.getCombatEngine().isPaused()) return;
116
117 if (ship.isHulk()) {
118 hulkFor += amount;
120 // ship splitting into pieces doesn't happen immediately
121 if (explodedPieces.isEmpty() || hulkFor < 0.25f) {
122 explodedPieces.clear();
123 for (ShipAPI curr : Global.getCombatEngine().getShips()) {
124 if (curr.getFleetMember() == ship.getFleetMember() ||
125 (curr.getParentPieceId() != null && curr.getParentPieceId().equals(ship.getId()))) {
126 explodedPieces.add(curr);
127 }
128 }
129 }
130 //elapsed += delay + fadeInTime; // instant fade in while hidden by the explosion
131 }
132 elapsed += amount;
133 if (elapsed < delay) return;
134
136
137 float progress = (elapsed - delay) / fadeInTime;
138 if (progress > 1f) progress = 1f;
139
140 float remaining = fadeInTime - (elapsed - delay);
141
142 ship.setAlphaMult(progress);
143// if (!explodedPieces.isEmpty()) {
144// System.out.println("Pieces: " + explodedPieces.size());
145// }
146 for (ShipAPI curr : explodedPieces) {
147 curr.setAlphaMult(progress);
148 }
149 ship.getMutableStats().getEffectiveArmorBonus().modifyMult("ThreatShipConstructionScript", progress * progress);
150
151 Global.getSoundPlayer().playLoop("construction_swarm_loop", ship, 1f, 1f, ship.getLocation(), ship.getVelocity());
152
153
154
155 if (remaining > 1f) {
156 Vector2f deltaLoc = Vector2f.sub(ship.getLocation(), source.getLocation(), new Vector2f());
159 if (sourceSwarm != null) {
160 for (SwarmMember p : sourceSwarm.members) {
161 Vector2f.add(p.loc, deltaLoc, p.loc);
162 }
163 }
165 }
166
167 float jitterLevel = progress;
168 if (fadeInTime <= 4f) {
169 if (jitterLevel < 0.5f) {
170 jitterLevel *= 2f;
171 } else {
172 jitterLevel = (1f - jitterLevel) * 2f;
173 }
174 } else {
175 if (jitterLevel < 0.5f) {
176 jitterLevel *= 2f;
177 } else if (remaining <= 2f) {
178 jitterLevel = remaining / 2f;
179 } else {
180 jitterLevel = 1f;
181 }
182 }
183 jitterLevel = (float) Math.sqrt(jitterLevel);
184
185 //float jitterRange = 1f - progress;
186 float jitterRange = 1f;
187 if (remaining < 2f) {
188 jitterRange = remaining / 2f;
189 } else {
190 jitterRange = (elapsed - delay) / Math.max(1f, fadeInTime - 2f);
191 }
192 float maxRangeBonus = 25f;
193 float jitterRangeBonus = jitterRange * maxRangeBonus;
194
196 c = Misc.setAlpha(c, 127);
197
198 ship.setJitter(this, c, jitterLevel, 3, 0f, jitterRangeBonus);
200
201
203 if (sourceSwarm != null) {
204 float speedMult = 0.25f + 0.75f * Math.max(0f, 1f - (elapsed - delay) / 2f);
205 sourceSwarm.params.maxSpeed = origMaxSpeed * speedMult;
206
207 if (remaining > 3f) {
208 float numFragMult = sourceSwarm.params.initialMembers / 150f;
209 if (numFragMult < 0.25f) numFragMult = 0.25f;
210 if (numFragMult > 1f) numFragMult = 1f;
211 sourceSwarm.params.flashFrequency = 5f * progress * 2f * numFragMult;
212 sourceSwarm.params.flashProbability = 1f;
213 sourceSwarm.params.flashFringeColor = VoltaicDischargeOnFireEffect.EMP_FRINGE_COLOR;
214 sourceSwarm.params.flashFringeColor = Misc.setAlpha(sourceSwarm.params.flashFringeColor, 200);
215 //sourceSwarm.params.flashCoreRadiusMult = 0f;
216 sourceSwarm.params.flashCoreRadiusMult = 1.5f;
217 sourceSwarm.params.flashRadius = 50f;
218 sourceSwarm.params.renderFlashOnSameLayer = true;
219 } else {
220 sourceSwarm.params.flashFrequency = 1f;
221 sourceSwarm.params.flashProbability = 0f;
222 }
223 }
224
225
226 spawnParticles(amount);
227
228
229 if (elapsed > fadeInTime + delay) {
230 ship.setDefaultAI(null);
232 ship.setAlphaMult(1f);
233 ship.setHoldFire(false);
235 ship.getMutableStats().getEffectiveArmorBonus().unmodifyMult("ThreatShipConstructionScript");
236 engine.removePlugin(this);
237
238 if (sourceSwarm != null) {
239 sourceSwarm.getParams().despawnSound = null;
240 }
241
243 //RoilingSwarmEffect sourceSwarm = RoilingSwarmEffect.getSwarmFor(source);
244 if (swarm != null && sourceSwarm != null) {
245 int transfer = Math.min(swarm.params.baseMembersToMaintain, sourceSwarm.getNumActiveMembers());
246 sourceSwarm.transferMembersTo(swarm, transfer);
247 }
248 if (swarm != null) {
249 swarm.params.withRespawn = true;
250 swarm.params.withInitialMembers = true;
251 }
252
254 source.setSpawnDebris(false);
255 engine.applyDamage(source, source.getLocation(), 100f, DamageType.ENERGY, 0f, true, false, source, false);
256 }
257 }
258
259 protected void spawnParticles(float amount) {
260 if (ship == null) return;
261
262 float remaining = fadeInTime - (elapsed - delay);
263
264 interval.advance(amount);
265 if (interval.intervalElapsed() && remaining > 1f) {
266
268 if (swarm != null) {
269 for (SwarmMember p : swarm.members) {
270 if ((float) Math.random() > 0.9f) {
271 p.rollOffset(swarm.params, ship);
272 }
273 }
274 }
275
277
279 c = Misc.setAlpha(c, 50);
280 float baseDuration = 2f;
281 Vector2f vel = new Vector2f(ship.getVelocity());
282 //float size = ship.getCollisionRadius() * 0.35f;
283 float size = ship.getCollisionRadius() * 0.33f;
284
285 float extraDur = 0f;
286 if (remaining < 1f) extraDur = 1f;
287
288 //for (int i = 0; i < 3; i++) {
289 for (int i = 0; i < 11; i++) {
290 Vector2f point = new Vector2f(ship.getLocation());
292 float dur = baseDuration + baseDuration * (float) Math.random();
293 dur += extraDur;
294 float nSize = size;
295 Vector2f pt = Misc.getPointWithinRadius(point, nSize * 0.5f);
296 Vector2f v = Misc.getUnitVectorAtDegreeAngle((float) Math.random() * 360f);
297 v.scale(nSize + nSize * (float) Math.random() * 0.5f);
298 v.scale(0.2f);
299 Vector2f.add(vel, v, v);
300
301 float maxSpeed = nSize * 1.5f * 0.2f;
302 float minSpeed = nSize * 1f * 0.2f;
303 float overMin = v.length() - minSpeed;
304 if (overMin > 0) {
305 float durMult = 1f - overMin / (maxSpeed - minSpeed);
306 if (durMult < 0.1f) durMult = 0.1f;
307 dur *= 0.5f + 0.5f * durMult;
308 }
309 engine.addNegativeNebulaParticle(pt, v, nSize * 1f, 2f,
310 0.5f / dur, 0f, dur, c);
311 }
312 }
313 }
314
315
316}
static SoundPlayerAPI getSoundPlayer()
Definition Global.java:49
static CombatEngineAPI getCombatEngine()
Definition Global.java:69
static SectorAPI getSector()
Definition Global.java:65
void modifyMult(String source, float value)
void modifyMult(String source, float value)
void transferMembersTo(RoilingSwarmEffect other, float fraction)
static RoilingSwarmEffect getSwarmFor(CombatEntityAPI entity)
ThreatShipConstructionScript(String variantId, ShipAPI source, float delay, float fadeInTime)
static Vector2f getUnitVectorAtDegreeAngle(float degrees)
Definition Misc.java:1196
static Color setAlpha(Color color, int alpha)
Definition Misc.java:1316
static Vector2f getPointWithinRadius(Vector2f from, float r)
Definition Misc.java:711
static Vector2f getPointWithinRadiusUniform(Vector2f from, float r, Random random)
Definition Misc.java:722
void playLoop(String id, Object playingEntity, float pitch, float volume, Vector2f loc, Vector2f vel)
FactionAPI getFaction(String factionId)
CombatFleetManagerAPI getFleetManager(FleetSide side)
void applyDamage(CombatEntityAPI entity, Vector2f point, float damageAmount, DamageType damageType, float empAmount, boolean bypassShields, boolean dealsSoftFlux, Object source, boolean playSound)
void removePlugin(EveryFrameCombatPlugin plugin)
void addNegativeNebulaParticle(Vector2f loc, Vector2f vel, float size, float endSizeMult, float rampUpFraction, float fullBrightnessFraction, float totalDuration, Color color)
void setCollisionClass(CollisionClass collisionClass)
ShipAPI spawnShipOrWing(String specId, Vector2f location, float facing)
void setSuppressDeploymentMessages(boolean suppressDeploymentMessages)
void setAlphaMult(float alphaMult)
void setDefaultAI(FleetMemberAPI member)
void setSpawnDebris(boolean spawnDebris)
void setHoldFire(boolean holdFire)
MutableShipStatsAPI getMutableStats()
void setShipAI(ShipAIPlugin ai)
List< WeaponGroupAPI > getWeaponGroupsCopy()
void setJitter(Object source, Color color, float intensity, int copies, float range)
ShipEngineControllerAPI getEngineController()
void giveCommand(ShipCommand command, Object param, int groupNumber)
void fadeToOtherColor(Object key, Color other, Color contrailColor, float effectLevel, float maxBlend)