Starsector API
Loading...
Searching...
No Matches
SwarmLauncherEffect.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.combat.threat;
2
3import java.util.HashMap;
4import java.util.Map;
5
6import org.lwjgl.util.vector.Vector2f;
7
8import com.fs.starfarer.api.GameState;
9import com.fs.starfarer.api.Global;
10import com.fs.starfarer.api.combat.CombatEngineAPI;
11import com.fs.starfarer.api.combat.CombatFleetManagerAPI;
12import com.fs.starfarer.api.combat.DamagingProjectileAPI;
13import com.fs.starfarer.api.combat.EveryFrameWeaponEffectPlugin;
14import com.fs.starfarer.api.combat.FighterWingAPI;
15import com.fs.starfarer.api.combat.OnFireEffectPlugin;
16import com.fs.starfarer.api.combat.ShipAPI;
17import com.fs.starfarer.api.combat.WeaponAPI;
18import com.fs.starfarer.api.impl.campaign.ids.HullMods;
19import com.fs.starfarer.api.impl.campaign.ids.Stats;
20import com.fs.starfarer.api.util.Misc;
21
23
24 public static String CONSTRUCTION_SWARM_WING = "construction_swarm_wing";
25 public static String CONSTRUCTION_SWARM_VARIANT = "attack_swarm_Construction";
26 public static String RECLAMATION_SWARM_WING = "reclamation_swarm_wing";
27 public static String RECLAMATION_SWARM_VARIANT = "attack_swarm_Reclamation";
28
29 public static String ATTACK_SWARM_HULL = "attack_swarm";
30 public static String ATTACK_SWARM_WING = "attack_swarm_wing";
31 public static String ATTACK_SWARM_VARIANT = "attack_swarm_Attack";
32 public static String SWARM_LAUNCHER = "swarm_launcher";
33 public static float IMPACT_VOLUME_MULT = 0.33f;
34
35 public static float INITIAL_SPAWN_DELAY = 1f;
36
37 public static Map<String, Integer> FRAGMENT_NUM = new HashMap<>();
38 public static Map<String, Integer> SWARM_RADIUS = new HashMap<>();
39 public static Map<String, Integer> WING_SIZE = new HashMap<>();
40 public static Map<String, String> WING_IDS = new HashMap<>();
41
42 static {
47
50 }
51
52 protected FighterWingAPI currWing = null;
53 protected boolean waitUntilOneLeft = false;
54 protected float elapsed = 0f;
55
57
58 }
59
60 @Override
61 public void advance(float amount, CombatEngineAPI engine, WeaponAPI weapon) {
62 ShipAPI ship = weapon.getShip();
63 if (ship == null) return;
64
65 elapsed += amount;
67 weapon.setForceDisabled(true);
68 return;
69 }
70
72 int active = swarm == null ? 0 : swarm.getNumActiveMembers();
73 int required = FRAGMENT_NUM.get(getWingId(weapon));
74 boolean disable = active < required;
75 //disable = false;
76 int max = getWingSize(weapon);
77 int swarmsActive = 0;
78 if (currWing != null) swarmsActive = currWing.getWingMembers().size();
79 waitUntilOneLeft |= currWing != null && swarmsActive >= max;
80 if (currWing != null && currWing.getWingMembers().size() == 1 && currWing.getLeader() != null) {
81 float dist = Misc.getDistance(currWing.getLeader().getLocation(), weapon.getLocation());
82 if (dist > 1000f) {
83 waitUntilOneLeft = true;
84 }
85 }
86 if (waitUntilOneLeft) {
87 if (currWing != null && ((swarmsActive <= 1 && max > 1) || swarmsActive <= 0 && max <= 1)) {
88 waitUntilOneLeft = false;
89 currWing = null;
90 } else {
91 disable = true;
92 }
93 }
94
95 if (currWing == null && swarm != null) {
97 preferred = (int) Math.min(preferred, swarm.params.baseMembersToMaintain * 0.9f);
98 if (active < preferred ) {
99 disable = true;
100 }
101 }
102
103 weapon.setForceDisabled(disable);
104
105 boolean playerShip = Global.getCurrentState() == GameState.COMBAT &&
107 if (playerShip) {
109 Global.getSettings().getSpriteName("ui", "icon_tactical_swarm_launcher"),
110 weapon.getDisplayName(),
111 "SWARMS ACTIVE: " + swarmsActive, // + " / " + max,
112 swarmsActive <= 0);
113 }
114
115 weapon.setCustom(currWing);
116
118 weapon.setAmmo(weapon.getMaxAmmo());
119 }
120
121 if (disable) {
122 return;
123 }
124
125 weapon.setForceFireOneFrame(true);
126 }
127
128 public String getWingId(WeaponAPI weapon) {
129 //String wingId = WING_IDS.get(SWARM_LAUNCHER);
130 String wingId = WING_IDS.get(weapon.getId());
131 if (wingId != null) return wingId;
132 return ATTACK_SWARM_WING;
133 }
134
135 public int getWingSize(WeaponAPI weapon) {
136 float wingSize = WING_SIZE.get(getWingId(weapon));
137 if (weapon.getShip() != null) {
138 wingSize = weapon.getShip().getMutableStats().getDynamic().getValue(
140 }
141 //wingSize = 20;
142 //wingSize = 1;
143 return (int) Math.round(wingSize);
144 }
145
146 public void onFire(DamagingProjectileAPI projectile, WeaponAPI weapon, CombatEngineAPI engine) {
147
148 //FighterWingSpecAPI spec = Global.getSettings().getFighterWingSpec(ATTACK_SWARM_WING);
149
150 CombatFleetManagerAPI manager = engine.getFleetManager(projectile.getOwner());
151 manager.setSuppressDeploymentMessages(true);
152 ShipAPI leader = manager.spawnShipOrWing(getWingId(weapon),
153 projectile.getLocation(), projectile.getFacing(), 0f, null);
154 leader.getWing().setSourceShip(projectile.getSource());
155 manager.setSuppressDeploymentMessages(false);
156
157 Vector2f takeoffVel = Misc.getUnitVectorAtDegreeAngle(projectile.getFacing());
158 takeoffVel.scale(leader.getMaxSpeed() * 1f);
159
160 //Global.getSoundPlayer().playSound("threat_swarm_launched", 1f, 1f, projectile.getLocation(), takeoffVel);
161
162 for (ShipAPI curr : leader.getWing().getWingMembers()) {
163 curr.setDoNotRender(true);
164 curr.setExplosionScale(0f);
165 curr.setHulkChanceOverride(0f);
166 curr.setImpactVolumeMult(IMPACT_VOLUME_MULT);
167 curr.getArmorGrid().clearComponentMap(); // no damage to weapons/engines
168
169 if (currWing != null) {
170 if (curr.getWing() != null) {
171 curr.getWing().removeMember(curr);
172 // really important, otherwise this doesn't get cleaned up
173 manager.removeDeployed(curr.getWing(), false);
174 }
175 curr.setWing(currWing);
176 currWing.addMember(curr);
177 }
178
179 Vector2f.add(curr.getVelocity(), takeoffVel, curr.getVelocity());
180 }
181
182 currWing = leader.getWing();
183
185 if (sourceSwarm != null) {
187
188 int required = FRAGMENT_NUM.get(getWingId(weapon));
189 int transfer = required;
190
191 if (transfer > 0) {
192 Vector2f loc = new Vector2f(takeoffVel);
193 loc.scale(0.5f);
194 Vector2f.add(loc, leader.getLocation(), loc);
195 sourceSwarm.transferMembersTo(swarm, transfer, loc, 100f);
196 }
197
198 }
199
200// if (currWing.getWingMembers().size() >= getWingSize(weapon)) {
201// currWing = null;
202// }
203
204 engine.removeEntity(projectile);
205 }
206
209 if (swarm == null) return 0;
210
211 int req = 0;
212 for (WeaponAPI w : ship.getAllWeapons()) {
213 if (w.getEffectPlugin() instanceof SwarmLaunchingWeapon) {
214 if (w.isFiring()) continue;
215 SwarmLaunchingWeapon effect = (SwarmLaunchingWeapon) w.getEffectPlugin();
216 req += effect.getPreferredNumFragmentsToFire(w);
217 }
218 }
219 return req;
220 }
221
222 @Override
224 Integer required = FRAGMENT_NUM.get(getWingId(weapon));
225 if (required == null) return 0;
226 int wingSize = getWingSize(weapon);
227 int num = Math.min(wingSize, 2);
228 return required * num;
229 }
230
231
232//
233// public static RoilingSwarmEffect createTestDwellerSwarmFor(ShipAPI ship) {
234// RoilingSwarmEffect existing = RoilingSwarmEffect.getSwarmFor(ship);
235// if (existing != null) {
236// if (!"dweller_pieces".equals(existing.params.spriteKey)) {
237// existing.setForceDespawn(true);
238// }
239// //return existing;
240// }
241//
242// RoilingSwarmParams params = new RoilingSwarmParams();
243// float radius = 20f;
244// int numMembers = 50;
245//
246//
252//
254// params.spriteKey = "fx_particles1";
255// params.spriteKey = "nebula_particles";
256// params.spriteKey = "dweller_pieces";
257//
258// params.baseDur = 1f;
259// params.durRange = 2f;
260// params.memberRespawnRate = 100f;
261//
262// params.memberExchangeClass = null;
263// params.flockingClass = null;
264// params.maxSpeed = ship.getMaxSpeedWithoutBoost() +
265// Math.max(ship.getMaxSpeedWithoutBoost() * 0.25f + 50f, 100f);
266//
267// params.baseSpriteSize = 256f;
268// params.baseSpriteSize = 128f * 1.5f * 0.67f;
269// params.maxTurnRate = 120f;
270//
271// radius = 100f;
272// numMembers = 100;
273//
274// params.flashCoreRadiusMult = 0f;
275// //params.flashRadius = 0f;
276// params.flashRadius = 200f;
277// params.flashRateMult = 0.1f;
278// params.flashFrequency = 10f;
279// params.flashProbability = 1f;
280//
281//
282// params.alphaMult = 1f;
283// params.alphaMultBase = 0.1f;
284// params.alphaMultFlash = 1f;
285// params.color = RiftCascadeEffect.STANDARD_RIFT_COLOR;
286// params.color = Misc.setAlpha(RiftCascadeEffect.EXPLOSION_UNDERCOLOR, 255);
287// params.color = Misc.setBrightness(params.color, 155);
288// params.flashFringeColor = params.color;
289// params.flashCoreColor = params.color;
290//
291// params.color = new Color(100, 50, 255, 255);
292// params.flashFringeColor = new Color(100, 100, 255, 255);
293// params.flashCoreColor = new Color(100, 100, 255, 255);
294//
295// //params.renderFlashOnSameLayer = true;
296//
297// params.maxOffset = radius;
298//
299// //params.despawnDist = params.maxOffset + 300f;
300//
301// params.initialMembers = numMembers;
302// params.baseMembersToMaintain = params.initialMembers;
303//
304// //params.springStretchMult = 1f;
305//
306//
307// return new RoilingSwarmEffect(ship, params) {
308// protected IntervalUtil interval = new IntervalUtil(0.075f, 0.125f);
309//
310// @Override
311// public int getNumMembersToMaintain() {
312// return super.getNumMembersToMaintain();
313// }
314//
315// @Override
316// public void advance(float amount) {
317// super.advance(amount);
318//
319// interval.advance(amount);
320// if (interval.intervalElapsed() && false) {
321//
322// CombatEngineAPI engine = Global.getCombatEngine();
323//
324// //Color c = RiftLanceEffect.getColorForDarkening(VoltaicDischargeOnFireEffect.EMP_FRINGE_COLOR);
325// Color c = RiftLanceEffect.getColorForDarkening(params.color);
326// c = Misc.setAlpha(c, 50);
327// float baseDuration = 2f;
328// Vector2f vel = new Vector2f(ship.getVelocity());
329//
330// float baseSize = params.maxOffset * 2f;
331//
332// //float size = ship.getCollisionRadius() * 0.35f;
333// float size = baseSize * 0.33f;
334//
335// float extraDur = 0f;
336//
337// //for (int i = 0; i < 3; i++) {
338// for (int i = 0; i < 11; i++) {
339// Vector2f point = new Vector2f(ship.getLocation());
340// point = Misc.getPointWithinRadiusUniform(point, baseSize * 0.75f, Misc.random);
341// float dur = baseDuration + baseDuration * (float) Math.random();
342// dur += extraDur;
343// float nSize = size;
344// Vector2f pt = Misc.getPointWithinRadius(point, nSize * 0.5f);
345// Vector2f v = Misc.getUnitVectorAtDegreeAngle((float) Math.random() * 360f);
346// v.scale(nSize + nSize * (float) Math.random() * 0.5f);
347// v.scale(0.2f);
348// Vector2f.add(vel, v, v);
349//
350// float maxSpeed = nSize * 1.5f * 0.2f;
351// float minSpeed = nSize * 1f * 0.2f;
352// float overMin = v.length() - minSpeed;
353// if (overMin > 0) {
354// float durMult = 1f - overMin / (maxSpeed - minSpeed);
355// if (durMult < 0.1f) durMult = 0.1f;
356// dur *= 0.5f + 0.5f * durMult;
357// }
358// engine.addNegativeNebulaParticle(pt, v, nSize * 1f, 2f,
359// 0.5f / dur, 0f, dur, c);
360// }
361// }
362//
363// }
364//
365// };
366// }
367}
368
369
370
371
372
373
374
375
static SettingsAPI getSettings()
Definition Global.java:57
static CombatEngineAPI getCombatEngine()
Definition Global.java:69
static GameState getCurrentState()
Definition Global.java:27
static final String SWARM_LAUNCHER_WING_SIZE_MOD
Definition Stats.java:152
void transferMembersTo(RoilingSwarmEffect other, float fraction)
static RoilingSwarmEffect getSwarmFor(CombatEntityAPI entity)
void onFire(DamagingProjectileAPI projectile, WeaponAPI weapon, CombatEngineAPI engine)
void advance(float amount, CombatEngineAPI engine, WeaponAPI weapon)
static Vector2f getUnitVectorAtDegreeAngle(float degrees)
Definition Misc.java:1196
static float getDistance(SectorEntityToken from, SectorEntityToken to)
Definition Misc.java:599
String getSpriteName(String category, String id)
void maintainStatusForPlayerShip(Object key, String spriteName, String title, String data, boolean isDebuff)
CombatFleetManagerAPI getFleetManager(FleetSide side)
void removeEntity(CombatEntityAPI entity)
ShipAPI spawnShipOrWing(String specId, Vector2f location, float facing)
void removeDeployed(ShipAPI ship, boolean retreated)
void setSuppressDeploymentMessages(boolean suppressDeploymentMessages)
void setSourceShip(ShipAPI sourceShip)
MutableShipStatsAPI getMutableStats()
List< WeaponAPI > getAllWeapons()
void setForceDisabled(boolean forceDisabled)
void setForceFireOneFrame(boolean forceFire)