Starsector API
Loading...
Searching...
No Matches
BattleCreationPluginImpl.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.combat;
2
3import java.util.ArrayList;
4import java.util.Arrays;
5import java.util.List;
6import java.util.Random;
7
8import java.awt.Color;
9
10import org.lwjgl.util.vector.Vector2f;
11
12import com.fs.starfarer.api.Global;
13import com.fs.starfarer.api.campaign.BattleCreationPlugin;
14import com.fs.starfarer.api.campaign.CampaignFleetAPI;
15import com.fs.starfarer.api.campaign.CampaignTerrainAPI;
16import com.fs.starfarer.api.campaign.CustomCampaignEntityAPI;
17import com.fs.starfarer.api.campaign.LocationAPI;
18import com.fs.starfarer.api.campaign.PlanetAPI;
19import com.fs.starfarer.api.campaign.SectorEntityToken;
20import com.fs.starfarer.api.campaign.StarSystemAPI;
21import com.fs.starfarer.api.combat.BaseEveryFrameCombatPlugin;
22import com.fs.starfarer.api.combat.BattleCreationContext;
23import com.fs.starfarer.api.combat.CombatEngineAPI;
24import com.fs.starfarer.api.combat.MissileAPI;
25import com.fs.starfarer.api.combat.ShipAPI;
26import com.fs.starfarer.api.fleet.FleetGoal;
27import com.fs.starfarer.api.fleet.FleetMemberAPI;
28import com.fs.starfarer.api.impl.campaign.ids.Planets;
29import com.fs.starfarer.api.impl.campaign.ids.Tags;
30import com.fs.starfarer.api.impl.campaign.ids.Terrain;
31import com.fs.starfarer.api.impl.campaign.terrain.HyperspaceAbyssPluginImpl;
32import com.fs.starfarer.api.impl.campaign.terrain.PulsarBeamTerrainPlugin;
33import com.fs.starfarer.api.impl.campaign.terrain.StarCoronaTerrainPlugin;
34import com.fs.starfarer.api.input.InputEventAPI;
35import com.fs.starfarer.api.mission.FleetSide;
36import com.fs.starfarer.api.mission.MissionDefinitionAPI;
37import com.fs.starfarer.api.util.Misc;
38import com.fs.starfarer.api.util.WeightedRandomPicker;
39
41
42 public interface NebulaTextureProvider {
43 String getNebulaTex();
45 }
46
47
48 public static float ABYSS_SHIP_SPEED_PENALTY = 20f;
49 public static float ABYSS_MISSILE_SPEED_PENALTY = 20f;
50 //public static float ABYSS_MISSILE_FLIGHT_TIME_MULT = 1.25f;
51 public static float ABYSS_OVERLAY_ALPHA = 0.2f;
52
53 protected float width, height;
54
55 protected float xPad = 2000;
56 protected float yPad = 2000;
57
58 protected List<String> objs = null;
59
60 protected float prevXDir = 0;
61 protected float prevYDir = 0;
62 protected boolean escape;
63
66
68
69 this.context = context;
70 this.loader = loader;
73 FleetGoal playerGoal = context.getPlayerGoal();
74 FleetGoal enemyGoal = context.getOtherGoal();
75
76 // doesn't work for consecutive engagements; haven't investigated why
77 //Random random = Misc.getRandom(Misc.getNameBasedSeed(otherFleet), 23);
78
79 Random random = Misc.getRandom(Misc.getSalvageSeed(otherFleet) *
80 (long)otherFleet.getFleetData().getNumMembers(), 23);
81 //System.out.println("RNG: " + random.nextLong());
82 //random = new Random(1213123L);
83 //Random random = Misc.random;
84
85 escape = playerGoal == FleetGoal.ESCAPE || enemyGoal == FleetGoal.ESCAPE;
86
87 int maxFP = (int) Global.getSettings().getFloat("maxNoObjectiveBattleSize");
88 int fpOne = 0;
89 int fpTwo = 0;
90 for (FleetMemberAPI member : playerFleet.getFleetData().getMembersListCopy()) {
91 if (member.canBeDeployedForCombat() || playerGoal == FleetGoal.ESCAPE) {
92 fpOne += member.getUnmodifiedDeploymentPointsCost();
93 }
94 }
95 for (FleetMemberAPI member : otherFleet.getFleetData().getMembersListCopy()) {
96 if (member.canBeDeployedForCombat() || playerGoal == FleetGoal.ESCAPE) {
97 fpTwo += member.getUnmodifiedDeploymentPointsCost();
98 }
99 }
100
101 int smaller = Math.min(fpOne, fpTwo);
102
103 boolean withObjectives = smaller > maxFP;
104 //withObjectives = true;
106 withObjectives = false;
107 } else if (context.forceObjectivesOnMap) {
108 withObjectives = true;
109 }
110
111 int numObjectives = 0;
112 if (withObjectives) {
113// if (fpOne + fpTwo > maxFP + 70) {
114// numObjectives = 3
115// numObjectives = 3 + (int)(Math.random() * 2.0);
116// } else {
117// numObjectives = 2 + (int)(Math.random() * 2.0);
118// }
119 if (fpOne + fpTwo > maxFP + 70) {
120 numObjectives = 4;
121 //numObjectives = 3 + (int)(Math.random() * 2.0);
122 } else {
123 numObjectives = 3 + random.nextInt(2);
124 //numObjectives = 2 + (int)(Math.random() * 2.0);
125 }
126 }
127
128 // shouldn't be possible, but..
129 if (numObjectives > 4) {
130 numObjectives = 4;
131 }
132
133 int baseCommandPoints = (int) Global.getSettings().getFloat("startingCommandPoints");
134
135 //
136 loader.initFleet(FleetSide.PLAYER, "ISS", playerGoal, false,
137 context.getPlayerCommandPoints() - baseCommandPoints,
138 (int) playerFleet.getCommanderStats().getCommandPoints().getModifiedValue() - baseCommandPoints);
139 loader.initFleet(FleetSide.ENEMY, "", enemyGoal, true,
140 (int) otherFleet.getCommanderStats().getCommandPoints().getModifiedValue() - baseCommandPoints);
141
142 List<FleetMemberAPI> playerShips = playerFleet.getFleetData().getCombatReadyMembersListCopy();
143 if (playerGoal == FleetGoal.ESCAPE) {
144 playerShips = playerFleet.getFleetData().getMembersListCopy();
145 }
146 for (FleetMemberAPI member : playerShips) {
148 }
149
150
151 List<FleetMemberAPI> enemyShips = otherFleet.getFleetData().getCombatReadyMembersListCopy();
152 if (enemyGoal == FleetGoal.ESCAPE) {
153 enemyShips = otherFleet.getFleetData().getMembersListCopy();
154 }
155 for (FleetMemberAPI member : enemyShips) {
157 }
158
159 width = 18000f;
160 height = 18000f;
161
162 if (escape) {
163 width = 18000f;
164 //height = 24000f;
165 height = 18000f;
166 } else if (withObjectives) {
167 width = 24000f;
168 if (numObjectives == 2) {
169 height = 14000f;
170 } else {
171 height = 18000f;
172 }
173 }
174
175 createMap(random);
176
180
181 xPad = 2000f;
182 yPad = 3000f;
183
184 if (escape) {
185// addEscapeObjectives(loader, 4);
186// context.setInitialEscapeRange(7000f);
187// context.setFlankDeploymentDistance(9000f);
188 addEscapeObjectives(loader, 2, random);
189// context.setInitialEscapeRange(4000f);
190// context.setFlankDeploymentDistance(8000f);
191
192 context.setInitialEscapeRange(Global.getSettings().getFloat("escapeStartDistance"));
194
196 } else {
197 if (withObjectives) {
198 addObjectives(loader, numObjectives, random);
200 } else {
202 }
203
204 context.setFlankDeploymentDistance(height/2f); // matters for Force Concentration
205 }
206 }
207
208 public void afterDefinitionLoad(final CombatEngineAPI engine) {
209 if (coronaIntensity > 0 && (corona != null || pulsar != null)) {
210 String name = "Corona";
211 if (pulsar != null) name = pulsar.getTerrainName();
212 else if (corona != null) name = corona.getTerrainName();
213
214 final String name2 = name;
215
216// CombatFleetManagerAPI manager = engine.getFleetManager(FleetSide.PLAYER);
217// for (FleetMemberAPI member : manager.getReservesCopy()) {
218// }
219 final Object key1 = new Object();
220 final Object key2 = new Object();
221 final String icon = Global.getSettings().getSpriteName("ui", "icon_tactical_cr_penalty");
223 @Override
224 public void advance(float amount, List<InputEventAPI> events) {
225 engine.maintainStatusForPlayerShip(key1, icon, name2, "reduced peak time", true);
226 engine.maintainStatusForPlayerShip(key2, icon, name2, "faster CR degradation", true);
227 }
228 });
229 }
230
231 if (abyssalDepth > 0) {
232 Color color = Misc.scaleColor(Color.white, 1f - abyssalDepth);
233 engine.setBackgroundColor(color);
234
235 color = Misc.scaleAlpha(Color.black, abyssalDepth * ABYSS_OVERLAY_ALPHA);
236 engine.setBackgroundGlowColor(color);
238
240 engine.setRenderStarfield(false);
241 }
242
243 final Object key1 = new Object();
244 final Object key2 = new Object();
245 final String icon = Global.getSettings().getSpriteName("ui", "icon_tactical_engine_damage");
246 final String name = "Abyssal hyperspace";
248 @Override
249 public void advance(float amount, List<InputEventAPI> events) {
250 String percentSpeed = "-" + (int)Math.round(ABYSS_SHIP_SPEED_PENALTY) + "%";
251 String percentMissile = "-" + (int)Math.round(ABYSS_MISSILE_SPEED_PENALTY) + "%";
252 engine.maintainStatusForPlayerShip(key1, icon, name, percentSpeed + " top speed", true);
253 engine.maintainStatusForPlayerShip(key2, icon, name, percentMissile + " missle speed / range", true);
254
255 String modId = "abyssal";
256 float modW = -0.0f * abyssalDepth;
257 float modL = -0.33f * abyssalDepth;
258 float modG = -0.5f * abyssalDepth;
259
260 for (ShipAPI curr : engine.getShips()) {
261 if (curr.isHulk()) continue;
262
263 curr.getEngineController().fadeToOtherColor(this, Color.black, null, 1f, abyssalDepth * 0.4f);
264 curr.getEngineController().extendFlame(this, modL, modW, modG);
265
266 curr.getMutableStats().getMaxSpeed().modifyMult(modId,
268 curr.getMutableStats().getMissileWeaponRangeBonus().modifyMult(modId,
270 curr.getMutableStats().getMissileMaxSpeedBonus().modifyMult(modId,
272 }
273
274 for (MissileAPI missile : engine.getMissiles()) {
275 missile.getEngineController().fadeToOtherColor(this, Color.black, null, 1f, abyssalDepth * 0.4f);
276 missile.getEngineController().extendFlame(this, modL, modW, 0f);
277 }
278
279 }
280 });
281
282 }
283 }
284
285
286 protected float abyssalDepth = 0f;
287 protected float coronaIntensity = 0f;
290 protected void createMap(Random random) {
291 loader.initMap((float)-width/2f, (float)width/2f, (float)-height/2f, (float)height/2f);
292
294 String nebulaTex = null;
295 String nebulaMapTex = null;
296 boolean inNebula = false;
297
298 boolean protectedFromCorona = false;
300 if (Misc.getDistance(curr.getLocation(), playerFleet.getLocation()) <= curr.getRadius() + Global.getSector().getPlayerFleet().getRadius() + 10f) {
301 protectedFromCorona = true;
302 break;
303 }
304 }
305
306 abyssalDepth = Misc.getAbyssalDepth(playerFleet);
307
308 float numRings = 0;
309
310 Color coronaColor = null;
311 // this assumes that all nebula in a system are of the same color
312 for (CampaignTerrainAPI terrain : playerFleet.getContainingLocation().getTerrainCopy()) {
313 //if (terrain.getType().equals(Terrain.NEBULA)) {
314 if (terrain.getPlugin() instanceof NebulaTextureProvider) {
315 if (terrain.getPlugin().containsEntity(playerFleet)) {
316 inNebula = true;
317 if (terrain.getPlugin() instanceof NebulaTextureProvider) {
318 NebulaTextureProvider provider = (NebulaTextureProvider) terrain.getPlugin();
319 nebulaTex = provider.getNebulaTex();
320 nebulaMapTex = provider.getNebulaMapTex();
321 }
322 } else {
323 if (nebulaTex == null) {
324 if (terrain.getPlugin() instanceof NebulaTextureProvider) {
325 NebulaTextureProvider provider = (NebulaTextureProvider) terrain.getPlugin();
326 nebulaTex = provider.getNebulaTex();
327 nebulaMapTex = provider.getNebulaMapTex();
328 }
329 }
330 }
331 } else if (terrain.getPlugin() instanceof StarCoronaTerrainPlugin && pulsar == null && !protectedFromCorona) {
332 StarCoronaTerrainPlugin plugin = (StarCoronaTerrainPlugin) terrain.getPlugin();
333 if (plugin.containsEntity(playerFleet)) {
334 float angle = Misc.getAngleInDegrees(terrain.getLocation(), playerFleet.getLocation());
335 Color color = plugin.getAuroraColorForAngle(angle);
336 float intensity = plugin.getIntensityAtPoint(playerFleet.getLocation());
337 intensity = 0.4f + 0.6f * intensity;
338 int alpha = (int)(80f * intensity);
339 color = Misc.setAlpha(color, alpha);
340 if (coronaColor == null || coronaColor.getAlpha() < alpha) {
341 coronaColor = color;
342 coronaIntensity = intensity;
343 corona = plugin;
344 }
345 }
346 } else if (terrain.getPlugin() instanceof PulsarBeamTerrainPlugin && !protectedFromCorona) {
347 PulsarBeamTerrainPlugin plugin = (PulsarBeamTerrainPlugin) terrain.getPlugin();
348 if (plugin.containsEntity(playerFleet)) {
349 float angle = Misc.getAngleInDegreesStrict(terrain.getLocation(), playerFleet.getLocation());
350 Color color = plugin.getPulsarColorForAngle(angle);
351 float intensity = plugin.getIntensityAtPoint(playerFleet.getLocation());
352 intensity = 0.4f + 0.6f * intensity;
353 int alpha = (int)(80f * intensity);
354 color = Misc.setAlpha(color, alpha);
355 if (coronaColor == null || coronaColor.getAlpha() < alpha) {
356 coronaColor = color;
357 coronaIntensity = intensity;
358 pulsar = plugin;
359 corona = null;
360 }
361 }
362 } else if (terrain.getType().equals(Terrain.RING)) {
363 if (terrain.getPlugin().containsEntity(playerFleet)) {
364 numRings++;
365 }
366 }
367 }
368 if (nebulaTex != null) {
369 loader.setNebulaTex(nebulaTex);
370 loader.setNebulaMapTex(nebulaMapTex);
371 }
372
373 if (coronaColor != null) {
374 loader.setBackgroundGlowColor(coronaColor);
375 }
376
377 int numNebula = 15;
378 if (inNebula) {
379 numNebula = 100;
380 }
381 if (!inNebula && playerFleet.isInHyperspace()) {
382 numNebula = 0;
383 }
384
385 for (int i = 0; i < numNebula; i++) {
386 float x = random.nextFloat() * width - width/2;
387 float y = random.nextFloat() * height - height/2;
388 float radius = 100f + random.nextFloat() * 400f;
389 if (inNebula) {
390 radius += 100f + 500f * random.nextFloat();
391 }
392 loader.addNebula(x, y, radius);
393 }
394
395 if (!playerFleet.isInHyperspace()) {
396 float numAsteroidsWithinRange = countNearbyAsteroids(playerFleet);
397
398 int numAsteroids = Math.min(400, (int)((numAsteroidsWithinRange + 1f) * 20f));
399
400 loader.addAsteroidField(0, 0, random.nextFloat() * 360f, width,
401 20f, 70f, numAsteroids);
402
403 if (numRings > 0) {
404 int numRingAsteroids = (int) (numRings * 300 + (numRings * 600f) * random.nextFloat());
405 //int numRingAsteroids = (int) (numRings * 1600 + (numRings * 600f) * (float) Math.random());
406 if (numRingAsteroids > 1500) {
407 numRingAsteroids = 1500;
408 }
409 loader.addRingAsteroids(0, 0, random.nextFloat() * 360f, width,
410 100f, 200f, numRingAsteroids);
411 }
412 }
413
414 //setRandomBackground(loader);
416// loader.setBackgroundSpriteName("graphics/backgrounds/hyperspace_bg_cool.jpg");
417// loader.setBackgroundSpriteName("graphics/ships/onslaught/onslaught_base.png");
418
419 if (playerFleet.getContainingLocation() == Global.getSector().getHyperspace()) {
421 } else {
423 }
424
425 //addMultiplePlanets();
427 }
428
429 protected void addClosestPlanet() {
430 float bgWidth = 2048f;
431 float bgHeight = 2048f;
432
434 if (planet == null) return;
435
436 float dist = Vector2f.sub(context.getPlayerFleet().getLocation(), planet.getLocation(), new Vector2f()).length() - planet.getRadius();
437 if (dist < 0) dist = 0;
438 float baseRadius = planet.getRadius();
439 float scaleFactor = 1.5f;
440 float maxRadius = 500f;
441 float minRadius = 100f;
442
443// if (planet.isStar()) {
444// scaleFactor = 0.01f;
445// maxRadius = 20f;
446// }
447
448 float maxDist = SINGLE_PLANET_MAX_DIST - planet.getRadius();
449 if (maxDist < 1) maxDist = 1;
450
451
452 boolean playerHasStation = false;
453 boolean enemyHasStation = false;
454
456 if (curr.isStation()) {
457 playerHasStation = true;
458 break;
459 }
460 }
461
463 if (curr.isStation()) {
464 enemyHasStation = true;
465 break;
466 }
467 }
468
469 float planetYOffset = 0;
470
471 if (playerHasStation) {
472 planetYOffset = -bgHeight / 2f * 0.5f;
473 }
474 if (enemyHasStation) {
475 planetYOffset = bgHeight / 2f * 0.5f;
476 }
477
478
479 float f = (maxDist - dist) / maxDist * 0.65f + 0.35f;
480 float radius = baseRadius * f * scaleFactor;
481 if (radius > maxRadius) radius = maxRadius;
482 if (radius < minRadius) radius = minRadius;
483 loader.setPlanetBgSize(bgWidth * f, bgHeight * f);
484 loader.addPlanet(0f, planetYOffset, radius, planet, 0f, true);
485 }
486
487 protected void addMultiplePlanets() {
488 float bgWidth = 2048f;
489 float bgHeight = 2048f;
490 loader.setPlanetBgSize(bgWidth, bgHeight);
491
492
493 List<NearbyPlanetData> planets = getNearbyPlanets(context.getPlayerFleet());
494 if (!planets.isEmpty()) {
495 float maxDist = PLANET_MAX_DIST;
496 for (NearbyPlanetData data : planets) {
497 float dist = Vector2f.sub(context.getPlayerFleet().getLocation(), data.planet.getLocation(), new Vector2f()).length();
498 float baseRadius = data.planet.getRadius();
499 float scaleFactor = 1.5f;
500 float maxRadius = 500f;
501
502 if (data.planet.isStar()) {
503 // skip stars in combat, bright and annoying
504 continue;
505// scaleFactor = 0.1f;
506// maxRadius = 50f;
507 }
508
509 float f = (maxDist - dist) / maxDist * 0.65f + 0.35f;
510 float radius = baseRadius * f * scaleFactor;
511 if (radius > maxRadius) radius = maxRadius;
512
513 loader.addPlanet(data.offset.x * bgWidth / PLANET_AREA_WIDTH * scaleFactor,
514 data.offset.y * bgHeight / PLANET_AREA_HEIGHT * scaleFactor,
515 radius, data.planet.getTypeId(), 0f, true);
516 }
517
518 }
519 }
520
521
522 protected void setRandomBackground(MissionDefinitionAPI loader, Random random) {
523 // these have to be loaded using the graphics section in settings.json
524 String [] bgs = new String [] {
525 "graphics/backgrounds/background1.jpg",
526 "graphics/backgrounds/background2.jpg",
527 "graphics/backgrounds/background3.jpg",
528 "graphics/backgrounds/background4.jpg"
529 };
530 String pick = bgs[Math.min(bgs.length - 1, (int)(random.nextDouble() * bgs.length))];
532 }
533
534 protected static String COMM = "comm_relay";
535 protected static String SENSOR = "sensor_array";
536 protected static String NAV = "nav_buoy";
537
538 protected void addObjectives(MissionDefinitionAPI loader, int num, Random random) {
539 //if (true) return;
540
541 objs = new ArrayList<String>(Arrays.asList(new String [] {
542 SENSOR,
543 SENSOR,
544 NAV,
545 NAV,
546 //COMM,
547 //COMM,
548 }));
549
550 if (num == 2) { // minimum is 3 now, so this shouldn't happen
551 objs = new ArrayList<String>(Arrays.asList(new String [] {
552 SENSOR,
553 SENSOR,
554 NAV,
555 NAV,
556 COMM,
557 }));
558 addObjectiveAt(0.25f, 0.5f, 0f, 0f, random);
559 addObjectiveAt(0.75f, 0.5f, 0f, 0f, random);
560 } else if (num == 3) {
561 float r = random.nextFloat();
562 if (r < 0.33f) {
563 addObjectiveAt(0.25f, 0.7f, 1f, 1f, random);
564 addObjectiveAt(0.25f, 0.3f, 1f, 1f, random);
565 addObjectiveAt(0.75f, 0.5f, 1f, 1f, COMM, random);
566 } else if (r < 0.67f) {
567 addObjectiveAt(0.75f, 0.7f, 1f, 1f, random);
568 addObjectiveAt(0.75f, 0.3f, 1f, 1f, random);
569 addObjectiveAt(0.25f, 0.5f, 1f, 1f, COMM, random);
570 } else {
571 if (random.nextFloat() < 0.5f) {
572 addObjectiveAt(0.22f, 0.7f, 1f, 1f, random);
573 addObjectiveAt(0.5f, 0.5f, 1f, 1f, COMM, random);
574 addObjectiveAt(0.78f, 0.3f, 1f, 1f, random);
575 } else {
576 addObjectiveAt(0.22f, 0.3f, 1f, 1f, random);
577 addObjectiveAt(0.5f, 0.5f, 1f, 1f, COMM, random);
578 addObjectiveAt(0.78f, 0.7f, 1f, 1f, random);
579 }
580 }
581 } else if (num == 4) {
582 float r = random.nextFloat();
583 if (r < 0.33f) {
584 String [] maybeRelays = pickCommRelays(2, 2, false, true, true, false, random);
585 addObjectiveAt(0.25f, 0.25f, 2f, 1f, maybeRelays[0], random);
586 addObjectiveAt(0.25f, 0.75f, 2f, 1f, maybeRelays[1], random);
587 addObjectiveAt(0.75f, 0.25f, 2f, 1f, maybeRelays[2], random);
588 addObjectiveAt(0.75f, 0.75f, 2f, 1f, maybeRelays[3], random);
589 } else if (r < 0.67f) {
590 String [] maybeRelays = pickCommRelays(1, 2, true, false, true, false, random);
591 addObjectiveAt(0.25f, 0.5f, 1f, 1f, maybeRelays[0], random);
592 addObjectiveAt(0.5f, 0.75f, 1f, 1f, maybeRelays[1], random);
593 addObjectiveAt(0.75f, 0.5f, 1f, 1f, maybeRelays[2], random);
594 addObjectiveAt(0.5f, 0.25f, 1f, 1f, maybeRelays[3], random);
595 } else {
596 if (random.nextFloat() < 0.5f) {
597 String [] maybeRelays = pickCommRelays(1, 2, true, false, true, false, random);
598 addObjectiveAt(0.25f, 0.25f, 1f, 0f, maybeRelays[0], random);
599 addObjectiveAt(0.4f, 0.6f, 1f, 0f, maybeRelays[1], random);
600 addObjectiveAt(0.6f, 0.4f, 1f, 0f, maybeRelays[2], random);
601 addObjectiveAt(0.75f, 0.75f, 1f, 0f, maybeRelays[3], random);
602 } else {
603 String [] maybeRelays = pickCommRelays(1, 2, false, true, false, true, random);
604 addObjectiveAt(0.25f, 0.75f, 1f, 0f, maybeRelays[0], random);
605 addObjectiveAt(0.4f, 0.4f, 1f, 0f, maybeRelays[1], random);
606 addObjectiveAt(0.6f, 0.6f, 1f, 0f, maybeRelays[2], random);
607 addObjectiveAt(0.75f, 0.25f, 1f, 0f, maybeRelays[3], random);
608 }
609 }
610 }
611 }
612
613 protected String [] pickCommRelays(int min, int max, boolean comm1, boolean comm2, boolean comm3, boolean comm4, Random random) {
614 String [] result = new String [4];
615
617 if (comm1) picker.add(0);
618 if (comm2) picker.add(1);
619 if (comm3) picker.add(2);
620 if (comm4) picker.add(3);
621
622 int num = min + random.nextInt(max - min + 1);
623
624 for (int i = 0; i < num && !picker.isEmpty(); i++) {
625 result[picker.pickAndRemove()] = COMM;
626 }
627 return result;
628 }
629
630
631 protected void addEscapeObjectives(MissionDefinitionAPI loader, int num, Random random) {
632 objs = new ArrayList<String>(Arrays.asList(new String [] {
633 SENSOR,
634 SENSOR,
635 NAV,
636 NAV,
637 COMM,
638 }));
639
640 if (num == 2) {
641 float r = random.nextFloat();
642 if (r < 0.33f) {
643 addObjectiveAt(0.25f, 0.25f, 1f, 1f, random);
644 addObjectiveAt(0.75f, 0.75f, 1f, 1f, random);
645 } else if (r < 0.67f) {
646 addObjectiveAt(0.75f, 0.25f, 1f, 1f, random);
647 addObjectiveAt(0.25f, 0.75f, 1f, 1f, random);
648 } else {
649 addObjectiveAt(0.5f, 0.25f, 4f, 2f, random);
650 addObjectiveAt(0.5f, 0.75f, 4f, 2f, random);
651 }
652 } else if (num == 3) {
653 float r = random.nextFloat();
654 if (r < 0.33f) {
655 addObjectiveAt(0.25f, 0.75f, 1f, 1f, random);
656 addObjectiveAt(0.25f, 0.25f, 1f, 1f, random);
657 addObjectiveAt(0.75f, 0.5f, 1f, 6f, random);
658 } else if (r < 0.67f) {
659 addObjectiveAt(0.25f, 0.5f, 1f, 6f, random);
660 addObjectiveAt(0.75f, 0.75f, 1f, 1f, random);
661 addObjectiveAt(0.75f, 0.25f, 1f, 1f, random);
662 } else {
663 addObjectiveAt(0.5f, 0.25f, 4f, 1f, random);
664 addObjectiveAt(0.5f, 0.5f, 4f, 1f, random);
665 addObjectiveAt(0.5f, 0.75f, 4f, 1f, random);
666 }
667 } else if (num == 4) {
668 float r = random.nextFloat();
669 if (r < 0.33f) {
670 addObjectiveAt(0.25f, 0.25f, 1f, 1f, random);
671 addObjectiveAt(0.25f, 0.75f, 1f, 1f, random);
672 addObjectiveAt(0.75f, 0.25f, 1f, 1f, random);
673 addObjectiveAt(0.75f, 0.75f, 1f, 1f, random);
674 } else if (r < 0.67f) {
675 addObjectiveAt(0.35f, 0.25f, 2f, 0f, random);
676 addObjectiveAt(0.65f, 0.35f, 2f, 0f, random);
677 addObjectiveAt(0.5f, 0.6f, 4f, 1f, random);
678 addObjectiveAt(0.5f, 0.8f, 4f, 1f, random);
679 } else {
680 addObjectiveAt(0.65f, 0.25f, 2f, 0f, random);
681 addObjectiveAt(0.35f, 0.35f, 2f, 0f, random);
682 addObjectiveAt(0.5f, 0.6f, 4f, 1f, random);
683 addObjectiveAt(0.5f, 0.8f, 4f, 1f, random);
684 }
685 }
686 }
687
688 protected void addObjectiveAt(float xMult, float yMult, float xOff, float yOff, Random random) {
689 addObjectiveAt(xMult, yMult, xOff, yOff, null, random);
690 }
691 protected void addObjectiveAt(float xMult, float yMult, float xOff, float yOff, String type, Random random) {
692 //String type = pickAny();
693 if (type == null) {
694 type = pickAny(random);
695 if (objs != null && objs.size() > 0) {
696 int index = (int) (random.nextDouble() * objs.size());
697 type = objs.remove(index);
698 }
699 }
700
701 float minX = -width/2 + xPad;
702 float minY = -height/2 + yPad;
703
704 float x = (width - xPad * 2f) * xMult + minX;
705 float y = (height - yPad * 2f) * yMult + minY;
706
707 x = ((int) x / 1000) * 1000f;
708 y = ((int) y / 1000) * 1000f;
709
710 float offsetX = Math.round((random.nextFloat() - 0.5f) * xOff * 1f) * 1000f;
711 float offsetY = Math.round((random.nextFloat() - 0.5f) * yOff * 1f) * 1000f;
712
713// offsetX = 0;
714// offsetY = 0;
715
716 float xDir = (float) Math.signum(offsetX);
717 float yDir = (float) Math.signum(offsetY);
718
719 if (xDir == prevXDir && xOff > 0) {
720 xDir = -xDir;
721 offsetX = Math.abs(offsetX) * -prevXDir;
722 }
723
724 if (yDir == prevYDir && yOff > 0) {
725 yDir = -yDir;
726 offsetY = Math.abs(offsetY) * -prevYDir;
727 }
728
729 prevXDir = xDir;
730 prevYDir = yDir;
731
732 x += offsetX;
733 y += offsetY;
734
735 loader.addObjective(x, y, type);
736
737 if (random.nextFloat() > 0.6f && loader.hasNebula()) {
738 float nebulaSize = random.nextFloat() * 1500f + 500f;
739 loader.addNebula(x, y, nebulaSize);
740 }
741 }
742
743 protected String pickAny(Random random) {
744 float r = random.nextFloat();
745 if (r < 0.33f) return "nav_buoy";
746 else if (r < 0.67f) return "sensor_array";
747 else return "comm_relay";
748 }
749
750 protected float countNearbyAsteroids(CampaignFleetAPI playerFleet) {
751 float numAsteroidsWithinRange = 0;
752 LocationAPI loc = playerFleet.getContainingLocation();
753 if (loc instanceof StarSystemAPI) {
754 StarSystemAPI system = (StarSystemAPI) loc;
755 List<SectorEntityToken> asteroids = system.getAsteroids();
756 for (SectorEntityToken asteroid : asteroids) {
757 float range = Vector2f.sub(playerFleet.getLocation(), asteroid.getLocation(), new Vector2f()).length();
758 if (range < 300) numAsteroidsWithinRange ++;
759 }
760 }
761 return numAsteroidsWithinRange;
762 }
763
764 protected static class NearbyPlanetData {
765 protected Vector2f offset;
766 protected PlanetAPI planet;
767 public NearbyPlanetData(Vector2f offset, PlanetAPI planet) {
768 this.offset = offset;
769 this.planet = planet;
770 }
771 }
772
773 protected static float PLANET_AREA_WIDTH = 2000;
774 protected static float PLANET_AREA_HEIGHT = 2000;
775 protected static float PLANET_MAX_DIST = (float) Math.sqrt(PLANET_AREA_WIDTH/2f * PLANET_AREA_WIDTH/2f + PLANET_AREA_HEIGHT/2f * PLANET_AREA_WIDTH/2f);
776
777 protected static float SINGLE_PLANET_MAX_DIST = 1000f;
778
779 protected List<NearbyPlanetData> getNearbyPlanets(CampaignFleetAPI playerFleet) {
780 LocationAPI loc = playerFleet.getContainingLocation();
781 List<NearbyPlanetData> result = new ArrayList<NearbyPlanetData>();
782 if (loc instanceof StarSystemAPI) {
783 StarSystemAPI system = (StarSystemAPI) loc;
784 List<PlanetAPI> planets = system.getPlanets();
785 for (PlanetAPI planet : planets) {
786 float diffX = planet.getLocation().x - playerFleet.getLocation().x;
787 float diffY = planet.getLocation().y - playerFleet.getLocation().y;
788
789 if (Math.abs(diffX) < PLANET_AREA_WIDTH/2f && Math.abs(diffY) < PLANET_AREA_HEIGHT/2f) {
790 result.add(new NearbyPlanetData(new Vector2f(diffX, diffY), planet));
791 }
792 }
793 }
794 return result;
795 }
796
798 LocationAPI loc = playerFleet.getContainingLocation();
799 PlanetAPI closest = null;
800 float minDist = Float.MAX_VALUE;
801 if (loc instanceof StarSystemAPI) {
802 StarSystemAPI system = (StarSystemAPI) loc;
803 List<PlanetAPI> planets = system.getPlanets();
804 for (PlanetAPI planet : planets) {
805 if (planet.isStar()) continue;
806 if (Planets.PLANET_LAVA.equals(planet.getTypeId())) continue;
807 if (Planets.PLANET_LAVA_MINOR.equals(planet.getTypeId())) continue;
808 if (planet.getSpec().isDoNotShowInCombat()) continue;
809
810 float dist = Vector2f.sub(context.getPlayerFleet().getLocation(), planet.getLocation(), new Vector2f()).length();
811 if (dist < minDist && dist < SINGLE_PLANET_MAX_DIST) {
812 closest = planet;
813 minDist = dist;
814 }
815 }
816 }
817 return closest;
818 }
819}
820
821
822
823
static SettingsAPI getSettings()
Definition Global.java:57
static SectorAPI getSector()
Definition Global.java:65
void setInitialDeploymentBurnDuration(float initialDeploymentBurnDuration)
void setNormalDeploymentBurnDuration(float normalDeploymentBurnDuration)
void setEscapeDeploymentBurnDuration(float escapeDeploymentBurnDuration)
void setFlankDeploymentDistance(float sideDeploymentDistance)
static final String PROTECTS_FROM_CORONA_IN_BATTLE
Definition Tags.java:381
List< NearbyPlanetData > getNearbyPlanets(CampaignFleetAPI playerFleet)
void addEscapeObjectives(MissionDefinitionAPI loader, int num, Random random)
void addObjectiveAt(float xMult, float yMult, float xOff, float yOff, String type, Random random)
void addObjectives(MissionDefinitionAPI loader, int num, Random random)
void addObjectiveAt(float xMult, float yMult, float xOff, float yOff, Random random)
String[] pickCommRelays(int min, int max, boolean comm1, boolean comm2, boolean comm3, boolean comm4, Random random)
void initBattle(final BattleCreationContext context, MissionDefinitionAPI loader)
void setRandomBackground(MissionDefinitionAPI loader, Random random)
static Random getRandom(long seed, int level)
Definition Misc.java:2973
static Color setAlpha(Color color, int alpha)
Definition Misc.java:1316
static float getDistance(SectorEntityToken from, SectorEntityToken to)
Definition Misc.java:599
static long getSalvageSeed(SectorEntityToken entity)
Definition Misc.java:4129
static Color scaleAlpha(Color color, float factor)
Definition Misc.java:1309
static float getAbyssalDepth(Vector2f loc)
Definition Misc.java:2330
static float getAngleInDegreesStrict(Vector2f v)
Definition Misc.java:1115
static float getAngleInDegrees(Vector2f v)
Definition Misc.java:1126
static Color scaleColor(Color color, float factor)
Definition Misc.java:1296
String getSpriteName(String category, String id)
MutableCharacterStatsAPI getCommanderStats()
List< FleetMemberAPI > getCombatReadyMembersListCopy()
List< FleetMemberAPI > getMembersListCopy()
List< CustomCampaignEntityAPI > getCustomEntitiesWithTag(String tag)
List< CampaignTerrainAPI > getTerrainCopy()
List< SectorEntityToken > getAsteroids()
void maintainStatusForPlayerShip(Object key, String spriteName, String title, String data, boolean isDebuff)
void setBackgroundGlowColor(Color backgroundGlowColor)
void addPlugin(EveryFrameCombatPlugin plugin)
void setBackgroundColor(Color backgroundColor)
void setRenderStarfield(boolean renderStarfield)
void setBackgroundGlowColorNonAdditive(boolean backgroundGlowColorNonAdditive)
void setBackgroundGlowColor(Color backgroundGlowColor)
void addObjective(float x, float y, String type, BattleObjectiveAPI.Importance importance)
void setHyperspaceMode(boolean hyperspaceMode)
void addRingAsteroids(float x, float y, float angle, float width, float minSpeed, float maxSpeed, int quantity)
void setPlanetBgSize(float bgWidth, float bgHeight)
void addPlanet(float x, float y, float radius, String type, float gravity)
void addAsteroidField(float x, float y, float angle, float width, float minSpeed, float maxSpeed, int quantity)
void addFleetMember(FleetSide side, FleetMemberAPI member)
void initMap(float minX, float maxX, float minY, float maxY)
void initFleet(FleetSide side, String shipNamePrefix, FleetGoal goal, boolean useDefaultAI)
void addPlugin(EveryFrameCombatPlugin plugin)
void addNebula(float x, float y, float radius)