Starsector API
Loading...
Searching...
No Matches
ShroudedLensHullmod.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.combat.dweller;
2
3import java.util.Iterator;
4
5import java.awt.Color;
6
7import org.lwjgl.util.vector.Vector2f;
8
9import com.fs.starfarer.api.Global;
10import com.fs.starfarer.api.campaign.CargoAPI.CargoItemType;
11import com.fs.starfarer.api.campaign.CargoStackAPI;
12import com.fs.starfarer.api.campaign.SpecialItemData;
13import com.fs.starfarer.api.combat.CollisionClass;
14import com.fs.starfarer.api.combat.CombatEngineAPI;
15import com.fs.starfarer.api.combat.CombatEntityAPI;
16import com.fs.starfarer.api.combat.DamageType;
17import com.fs.starfarer.api.combat.DamagingProjectileAPI;
18import com.fs.starfarer.api.combat.EmpArcEntityAPI;
19import com.fs.starfarer.api.combat.EmpArcEntityAPI.EmpArcParams;
20import com.fs.starfarer.api.combat.MissileAPI;
21import com.fs.starfarer.api.combat.ShipAPI;
22import com.fs.starfarer.api.combat.ShipAPI.HullSize;
23import com.fs.starfarer.api.impl.campaign.ids.Items;
24import com.fs.starfarer.api.impl.combat.NegativeExplosionVisual.NEParams;
25import com.fs.starfarer.api.impl.combat.RiftCascadeMineExplosion;
26import com.fs.starfarer.api.impl.combat.dweller.DwellerShroud.DwellerShroudParams;
27import com.fs.starfarer.api.loading.DamagingExplosionSpec;
28import com.fs.starfarer.api.ui.Alignment;
29import com.fs.starfarer.api.ui.TooltipMakerAPI;
30import com.fs.starfarer.api.util.Misc;
31import com.fs.starfarer.api.util.WeightedRandomPicker;
32
34
35 public static float MAX_RANGE = 400f;
36 public static float RADIUS = 50f;
37
38 public static float MIN_REFIRE_DELAY = 0.9f;
39 public static float MAX_REFIRE_DELAY = 1.1f;
40
41 public static float FLUX_PER_DAMAGE = 1f;
42
43 public static float DAMAGE = 75f;
44 public static float MIN_ROF_MULT = 1f;
45 public static float MAX_ROF_MULT = 4f;
46
47 public String getDescriptionParam(int index, HullSize hullSize) {
48 return null;
49 }
50
51 @Override
53 return Global.getSettings().createCargoStack(CargoItemType.SPECIAL,
54 new SpecialItemData(Items.SHROUDED_LENS, null), null);
55 }
56
57 public static String DATA_KEY = "core_ShroudedLensHullmod_data_key";
58
59 public static class ShroudedLensHullmodData {
60 //IntervalUtil interval = new IntervalUtil(0.75f, 1.25f);
61 float untilAttack = 0f;
62 float sinceAttack = 1000f;
63 }
64
65 public static ShroudedLensHullmodData getData(ShipAPI ship) {
67 String key = DATA_KEY + "_" + ship.getId();
68 ShroudedLensHullmodData data = (ShroudedLensHullmodData) engine.getCustomData().get(key);
69 if (data == null) {
70 data = new ShroudedLensHullmodData();
71 engine.getCustomData().put(key, data);
72 }
73 return data;
74 }
75
76 @Override
77 public void advanceInCombat(ShipAPI ship, float amount) {
78 super.advanceInCombat(ship, amount);
79
80 if (!ship.isAlive()) return;
81 if (amount <= 0f) return;
82
83 ShroudedLensHullmodData data = getData(ship);
84 data.untilAttack -= amount * getRoF(ship.getHullSize());
85 if (data.untilAttack <= 0f) {
86 CombatEntityAPI target = findTarget(ship);
87 if (target != null) {
88 spawnExplosion(ship, target);
89 }
90 data.untilAttack = MIN_REFIRE_DELAY + (float) Math.random() * (MAX_REFIRE_DELAY - MIN_REFIRE_DELAY);
91 }
92 }
93
94 public static float getPowerMult(HullSize size) {
95 switch (size) {
96 case CAPITAL_SHIP: return 1f;
97 case CRUISER: return 0.6666666667f;
98 case DESTROYER: return 0.3333333333f;
99 case FIGHTER:
100 case FRIGATE:
101 return 0f;
102 }
103 return 1f;
104 }
105
106 public static float getRoF(HullSize size) {
107 float mult = getPowerMult(size);
108 return MIN_ROF_MULT + (MAX_ROF_MULT - MIN_ROF_MULT) * mult;
109 }
110 public static float getFluxCost(HullSize size) {
111 return DAMAGE * FLUX_PER_DAMAGE;
112 }
113 public static float getDamage(HullSize size) {
114 return DAMAGE;
115 }
116
117 public void spawnExplosion(ShipAPI ship, CombatEntityAPI target) {
119
120
121 float angle = Misc.getAngleInDegrees(target.getLocation(), ship.getLocation());
122 angle += 45f - 90f * (float) Math.random();
123 Vector2f from = Misc.getUnitVectorAtDegreeAngle(angle);
124 from.scale(10000f);
125
126 float targetRadius = Misc.getTargetingRadius(from, target, false);
127 Vector2f point = Misc.getUnitVector(target.getLocation(), from);
128 point.scale(targetRadius * (0.8f + (float) Math.random() * 0.4f));
129 Vector2f.add(target.getLocation(), point, point);
130
131 float dist = Misc.getDistance(from, point);
132
133 //float mult = getPowerMult(ship.getHullSize());
134 float damage = getDamage(ship.getHullSize());
135
136 if (FLUX_PER_DAMAGE > 0f) {
137 float fluxCost = getFluxCost(ship.getHullSize());
138 //if (!ship.getFluxTracker().increaseFlux(fluxCost, false)) {
139 if (!deductFlux(ship, fluxCost)) {
140 return;
141 }
142 }
143
145 if (shroud != null) {
146 angle = Misc.getAngleInDegrees(ship.getLocation(), point);
147 from = Misc.getUnitVectorAtDegreeAngle(angle + 90f - 180f * (float) Math.random());
148 from.scale((0.5f + (float) Math.random() * 0.25f) * shroud.getShroudParams().maxOffset * shroud.getShroudParams().overloadArcOffsetMult);
149 Vector2f.add(ship.getLocation(), from, from);
150 }
151
153
154 if (shroud != null) {
155 DwellerShroudParams shroudParams = shroud.getShroudParams();
156 EmpArcParams params = new EmpArcParams();
157 params.segmentLengthMult = 4f;
158 params.glowSizeMult = 4f;
159 params.flickerRateMult = 0.5f + (float) Math.random() * 0.5f;
160 params.flickerRateMult *= 1.5f;
161
162 //Color fringe = shroudParams.overloadArcFringeColor;
163 Color fringe = color;
164 Color core = Color.white;
165
166 float thickness = shroudParams.overloadArcThickness;
167
168 //Vector2f to = Misc.getPointAtRadius(from, 1f);
169
170 angle = Misc.getAngleInDegrees(from, ship.getLocation());
171 angle = angle + 90f * ((float) Math.random() - 0.5f);
172 Vector2f dir = Misc.getUnitVectorAtDegreeAngle(angle);
173 dist = shroudParams.maxOffset * shroud.getShroudParams().overloadArcOffsetMult;
174 dist = dist * 0.5f + dist * 0.5f * (float) Math.random();
175 //dist *= 1.5f;
176 dist *= 0.5f;
177 dir.scale(dist);
178 Vector2f to = Vector2f.add(from, dir, new Vector2f());
179
181 from, ship, to, ship, thickness, fringe, core, params);
182
183 arc.setCoreWidthOverride(shroudParams.overloadArcCoreThickness);
184 arc.setSingleFlickerMode(false);
185 //arc.setRenderGlowAtStart(false);
186 }
187
188 //float explosionRadius = 40f + mult * 40f;
189 float explosionRadius = RADIUS;
190
192 0.1f, // duration
193 explosionRadius, // radius
194 explosionRadius * 0.5f, // coreRadius
195 damage, // maxDamage
196 damage, // / 2f, // minDamage - no damage dropoff with range
197 CollisionClass.PROJECTILE_NO_FF, // collisionClass
198 CollisionClass.PROJECTILE_FIGHTER, // collisionClassByFighter - using to flag it as from this effect
199 3f, // particleSizeMin
200 3f, // particleSizeRange
201 0.5f, // particleDuration
202 0, // particleCount
203 new Color(255,255,255,0), // particleColor
204 new Color(255,100,100,0) // explosionColor
205 );
206
207 spec.setDamageType(DamageType.ENERGY);
208 spec.setUseDetailedExplosion(false);
209 spec.setSoundSetId("abyssal_glare_explosion");
210 //spec.setSoundVolume(0.5f + 0.5f * mult);
211 spec.setSoundVolume(0.33f);
212
213 DamagingProjectileAPI explosion = engine.spawnDamagingExplosion(spec, ship, point);
214
215 //explosion.addDamagedAlready(target);
216 //color = new Color(255,75,75,255);
217
218 float baseSize = 7f;
219
221 color, baseSize);
222 //p.hitGlowSizeMult = 0.5f;
223 p.noiseMult = 6f;
224 p.thickness = 25f;
225 p.fadeOut = 0.5f;
226 p.spawnHitGlowAt = 1f;
227 p.additiveBlend = true;
228 p.blackColor = Color.white;
229 p.underglow = null;
230 p.withNegativeParticles = false;
231 p.withHitGlow = false;
232 p.fadeIn = 0f;
233 //p.numRiftsToSpawn = 1;
234
236
237
238 // the "beam"
239
240 float thickness = 30f;
241 //Color color = weapon.getSpec().getGlowColor();
242 Color coreColor = Color.white;
243 coreColor = Misc.zeroColor;
244 coreColor = color;
245
246 color = new Color(255,0,30,255);
247 coreColor = new Color(255,10,255,255);
248
250 coreColor = color;
251 //coreColor = Color.white;
252
253 float coreWidthMult = 1f;
254
255
256// from = ship.getLocation();
257// if (shroud != null) {
258// angle = Misc.getAngleInDegrees(ship.getLocation(), target.getLocation());
259// from = Misc.getUnitVectorAtDegreeAngle(angle + 90f - 180f * (float) Math.random());
260// from.scale((0.5f + (float) Math.random() * 0.25f) * shroud.getShroudParams().maxOffset);
261// Vector2f.add(ship.getLocation(), from, from);
262// }
263
264 EmpArcParams params = new EmpArcParams();
265 //params.segmentLengthMult = 10000f;
266 params.segmentLengthMult = 4f;
267
268// params.maxZigZagMult = 0f;
269// params.zigZagReductionFactor = 1f;
270
271 params.maxZigZagMult = 0.25f;
272 //params.maxZigZagMult = 0f;
273 params.zigZagReductionFactor = 1f;
274
275 //params.glowColorOverride = new Color(255,10,155,255);
276
277 //params.zigZagReductionFactor = 0.25f;
278 //params.maxZigZagMult = 0f;
279 //params.flickerRateMult = 0.75f;
280// params.flickerRateMult = 1f;
281// params.flickerRateMult = 0.75f;
282 params.flickerRateMult = 0.75f + 0.25f * (float) Math.random();
283
284 params.fadeOutDist = 150f;
285 params.minFadeOutMult = 5f;
286
287 params.glowSizeMult = 0.5f;
288
289 //params.glowAlphaMult = 0.5f;
290 //params.flamesOutMissiles = false;
291
292// params.movementDurOverride = 0.1f;
293// params.flickerRateMult = 0.5f;
294// params.glowSizeMult = 1f;
295// params.brightSpotFadeFraction = 0.1f;
296// params.brightSpotFullFraction = 0.9f;
297
298// params.maxZigZagMult = 1f;
299// params.zigZagReductionFactor = 0f;
300// params.flickerRateMult = 0.25f;
301
302 Vector2f to = point;
303 EmpArcEntityAPI arc = engine.spawnEmpArcVisual(from, ship, to, explosion, thickness, color, coreColor, params);
304 arc.setCoreWidthOverride(thickness * coreWidthMult);
306 arc.setRenderGlowAtStart(false);
307 if (shroud != null) {
308 arc.setFadedOutAtStart(true);
309 }
310 arc.setWarping(0.2f);
311
312 }
313
314 @Override
315 public boolean shouldAddDescriptionToTooltip(HullSize hullSize, ShipAPI ship, boolean isForModSpec) {
316 return false;
317 }
318
319 @Override
320 public void addPostDescriptionSection(TooltipMakerAPI tooltip, HullSize hullSize, final ShipAPI ship, float width, boolean isForModSpec) {
321 float pad = 3f;
322 float opad = 10f;
323 Color h = Misc.getHighlightColor();
324 Color bad = Misc.getNegativeHighlightColor();
325
326
327 tooltip.addPara("The \"lens\" (in the loosest sense of the word) focuses on nearby objects, "
328 + "seemingly at random. Deals %s damage and generates %s flux.", opad, h,
329 "" + (int) getDamage(hullSize) + " Energy", "" + (int) getFluxCost(hullSize));
330
331 tooltip.addPara("The rate of fire depends on the size of the ship the "
332 + "hullmod is installed on. Can not be turned off during combat operations, and continues to "
333 + "function even if the ship is venting flux or overloaded.", opad);
334
335 //tooltip.addSectionHeading("Reload capacity", Alignment.MID, opad);
336
337 if (isForModSpec || (ship == null && !Global.CODEX_TOOLTIP_MODE)) return;
338
339 tooltip.setBgAlpha(0.9f);
340
341 HullSize [] sizes = new HullSize[] {HullSize.FRIGATE, HullSize.DESTROYER, HullSize.CRUISER, HullSize.CAPITAL_SHIP};
342
343 float rofW = 130f;
344 float fluxW = 130f;
345 float sizeW = width - rofW - fluxW - 10f;
347 20f, true, true,
348 new Object [] {"Ship size", sizeW, "Attacks / sec", rofW, "Flux / sec", fluxW});
349
350 for (HullSize size : sizes) {
351 float rof = getRoF(size);
352 float flux = getFluxCost(size) * rof;
353 Color c = Misc.getGrayColor();
354 if (size == hullSize || Global.CODEX_TOOLTIP_MODE) {
356 }
357 tooltip.addRow(Alignment.MID, c, Misc.getHullSizeStr(size),
358 Alignment.MID, c, "" + (int) Misc.getRoundedValueFloat(rof) + "",
359 Alignment.MID, c, "" + (int) Misc.getRoundedValueFloat(flux) + "");
360 }
361 tooltip.addTable("", 0, opad);
362
363 tooltip.addSpacer(5f);
364
365 addCrewCasualties(tooltip, opad);
366
367// if (Global.CODEX_TOOLTIP_MODE) {
368// return;
369// }
370 }
371
372
373// @Override
374// public String getSModDescriptionParam(int index, HullSize hullSize, ShipAPI ship) {
375// if (index == 0) return "" + (int) Math.round(SMOD_CR_PENALTY * 100f) + "%";
376// if (index == 1) return "" + (int) Math.round(SMOD_MAINTENANCE_PENALTY) + "%";
377// return null;
378// }
379//
380// @Override
381// public boolean isSModEffectAPenalty() {
382// return true;
383// }
384
385
387 float range = MAX_RANGE;
388 Vector2f from = ship.getLocation();
389
390 Iterator<Object> iter = Global.getCombatEngine().getAllObjectGrid().getCheckIterator(from,
391 range * 2f, range * 2f);
392 int owner = ship.getOwner();
393 CombatEntityAPI best = null;
394 float minScore = Float.MAX_VALUE;
395
396 //boolean ignoreFlares = ship != null && ship.getMutableStats().getDynamic().getValue(Stats.PD_IGNORES_FLARES, 0) >= 1;
397 //ignoreFlares |= weapon.hasAIHint(AIHints.IGNORES_FLARES);
398 boolean ignoreFlares = false; // doesn't care one way or another
399
401
402 while (iter.hasNext()) {
403 Object o = iter.next();
404 if (!(o instanceof MissileAPI) &&
406 !(o instanceof ShipAPI)) continue;
408 if (other.getOwner() == owner) continue;
409
410 if (other instanceof ShipAPI) {
411 ShipAPI otherShip = (ShipAPI) other;
412 //if (otherShip.isHulk()) continue;
413 //if (!otherShip.isAlive()) continue;
414 if (otherShip.isPhased()) continue;
415 if (!otherShip.isTargetable()) continue;
416 }
417
418 if (other.getCollisionClass() == CollisionClass.NONE) continue;
419
420 if (ignoreFlares && other instanceof MissileAPI) {
421 MissileAPI missile = (MissileAPI) other;
422 if (missile.isFlare()) continue;
423 }
424
425 float targetRadius = Misc.getTargetingRadius(from, other, false);
426 float shipRadius = Misc.getTargetingRadius(other.getLocation(), ship, false);
427 float dist = Misc.getDistance(from, other.getLocation()) - targetRadius - shipRadius;
428 if (dist > range) continue;
429
430 float score = dist;
431
432 if (score < minScore) {
433 minScore = score;
434 best = other;
435 }
436
437 picker.add(other, 100f / Math.max(100f, score));
438 }
439
440 //return best;
441 return picker.pick();
442 }
443}
444
445
446
447
448
449
450
451
452
453
454
455
456
457
static SettingsAPI getSettings()
Definition Global.java:57
static boolean CODEX_TOOLTIP_MODE
Definition Global.java:15
static CombatEngineAPI getCombatEngine()
Definition Global.java:69
static void spawnStandardRift(DamagingProjectileAPI explosion, NEParams params)
static NEParams createStandardRiftParams(String minelayerId, float baseRadius)
static DwellerShroud getShroudFor(CombatEntityAPI entity)
void addPostDescriptionSection(TooltipMakerAPI tooltip, HullSize hullSize, final ShipAPI ship, float width, boolean isForModSpec)
boolean shouldAddDescriptionToTooltip(HullSize hullSize, ShipAPI ship, boolean isForModSpec)
static Vector2f getUnitVectorAtDegreeAngle(float degrees)
Definition Misc.java:1196
static Color getNegativeHighlightColor()
Definition Misc.java:802
static String getHullSizeStr(HullSize size)
Definition Misc.java:6665
static float getRoundedValueFloat(float value)
Definition Misc.java:661
static Color getBasePlayerColor()
Definition Misc.java:833
static Color getGrayColor()
Definition Misc.java:826
static Color getBrightPlayerColor()
Definition Misc.java:830
static float getDistance(SectorEntityToken from, SectorEntityToken to)
Definition Misc.java:599
static Vector2f getUnitVector(Vector2f from, Vector2f to)
Definition Misc.java:1191
static Color getHighlightColor()
Definition Misc.java:792
static float getTargetingRadius(Vector2f from, CombatEntityAPI target, boolean considerShield)
Definition Misc.java:1349
static Color getDarkPlayerColor()
Definition Misc.java:836
static float getAngleInDegrees(Vector2f v)
Definition Misc.java:1126
CargoStackAPI createCargoStack(CargoItemType type, Object data, CargoAPI cargo)
Iterator< Object > getCheckIterator(Vector2f loc, float checkWidth, float checkHeight)
EmpArcEntityAPI spawnEmpArcVisual(Vector2f from, CombatEntityAPI fromAnchor, Vector2f to, CombatEntityAPI toAnchor, float thickness, Color fringe, Color core)
DamagingProjectileAPI spawnDamagingExplosion(DamagingExplosionSpec spec, ShipAPI source, Vector2f location)
void setFadedOutAtStart(boolean fadedOutAtStart)
void setRenderGlowAtStart(boolean renderGlowAtStart)
void setCoreWidthOverride(float coreWidthOverride)
void addTable(String emptyText, int andMore, float pad)
UIPanelAPI beginTable(FactionAPI faction, float itemHeight, Object ... columns)
LabelAPI addPara(String format, float pad, Color hl, String... highlights)
UIComponentAPI addSpacer(float height)