Starsector API
Loading...
Searching...
No Matches
Misc.java
Go to the documentation of this file.
1package com.fs.starfarer.api.util;
2
3import java.awt.Color;
4import java.awt.image.BufferedImage;
5import java.awt.image.Raster;
6import java.io.IOException;
7import java.lang.reflect.Method;
8import java.nio.Buffer;
9import java.text.DecimalFormat;
10import java.text.DecimalFormatSymbols;
11import java.util.ArrayList;
12import java.util.Arrays;
13import java.util.Collection;
14import java.util.Collections;
15import java.util.Comparator;
16import java.util.HashMap;
17import java.util.HashSet;
18import java.util.LinkedHashSet;
19import java.util.List;
20import java.util.Locale;
21import java.util.Map;
22import java.util.Random;
23import java.util.Set;
24import java.util.UUID;
25import java.util.concurrent.atomic.AtomicLong;
26import java.util.regex.Matcher;
27import java.util.regex.Pattern;
28
29import javax.imageio.ImageIO;
30
31import org.json.JSONArray;
32import org.json.JSONException;
33import org.json.JSONObject;
34import org.lwjgl.opengl.ATIMeminfo;
35import org.lwjgl.opengl.GL11;
36import org.lwjgl.opengl.NVXGpuMemoryInfo;
37import org.lwjgl.util.vector.Vector2f;
38import org.lwjgl.util.vector.Vector3f;
39
40import com.fs.starfarer.api.EveryFrameScript;
41import com.fs.starfarer.api.Global;
42import com.fs.starfarer.api.MusicPlayerPlugin;
43import com.fs.starfarer.api.campaign.AICoreAdminPlugin;
44import com.fs.starfarer.api.campaign.AICoreOfficerPlugin;
45import com.fs.starfarer.api.campaign.BattleAPI;
46import com.fs.starfarer.api.campaign.CampaignClockAPI;
47import com.fs.starfarer.api.campaign.CampaignFleetAPI;
48import com.fs.starfarer.api.campaign.CampaignTerrainAPI;
49import com.fs.starfarer.api.campaign.CampaignUIAPI.CoreUITradeMode;
50import com.fs.starfarer.api.campaign.CargoAPI;
51import com.fs.starfarer.api.campaign.CargoAPI.CargoItemType;
52import com.fs.starfarer.api.campaign.CargoStackAPI;
53import com.fs.starfarer.api.campaign.CommDirectoryEntryAPI;
54import com.fs.starfarer.api.campaign.CommDirectoryEntryAPI.EntryType;
55import com.fs.starfarer.api.campaign.CustomCampaignEntityAPI;
56import com.fs.starfarer.api.campaign.FactionAPI;
57import com.fs.starfarer.api.campaign.FactionAPI.ShipPickMode;
58import com.fs.starfarer.api.campaign.FleetAssignment;
59import com.fs.starfarer.api.campaign.FleetInflater;
60import com.fs.starfarer.api.campaign.InteractionDialogAPI;
61import com.fs.starfarer.api.campaign.JumpPointAPI;
62import com.fs.starfarer.api.campaign.JumpPointAPI.JumpDestination;
63import com.fs.starfarer.api.campaign.LocationAPI;
64import com.fs.starfarer.api.campaign.ParticleControllerAPI;
65import com.fs.starfarer.api.campaign.PlanetAPI;
66import com.fs.starfarer.api.campaign.RepLevel;
67import com.fs.starfarer.api.campaign.ReputationActionResponsePlugin.ReputationAdjustmentResult;
68import com.fs.starfarer.api.campaign.ResourceCostPanelAPI;
69import com.fs.starfarer.api.campaign.SectorEntityToken;
70import com.fs.starfarer.api.campaign.SectorEntityToken.VisibilityLevel;
71import com.fs.starfarer.api.campaign.StarSystemAPI;
72import com.fs.starfarer.api.campaign.SubmarketPlugin;
73import com.fs.starfarer.api.campaign.SubmarketPlugin.OnClickAction;
74import com.fs.starfarer.api.campaign.TextPanelAPI;
75import com.fs.starfarer.api.campaign.ai.CampaignFleetAIAPI.EncounterOption;
76import com.fs.starfarer.api.campaign.ai.FleetAIFlags;
77import com.fs.starfarer.api.campaign.ai.ModularFleetAIAPI;
78import com.fs.starfarer.api.campaign.comm.CommMessageAPI.MessageClickAction;
79import com.fs.starfarer.api.campaign.econ.AbandonMarketPlugin;
80import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
81import com.fs.starfarer.api.campaign.econ.CommoditySpecAPI;
82import com.fs.starfarer.api.campaign.econ.ImmigrationPlugin;
83import com.fs.starfarer.api.campaign.econ.Industry;
84import com.fs.starfarer.api.campaign.econ.MarketAPI;
85import com.fs.starfarer.api.campaign.econ.MarketAPI.SurveyLevel;
86import com.fs.starfarer.api.campaign.econ.MarketConditionAPI;
87import com.fs.starfarer.api.campaign.econ.StabilizeMarketPlugin;
88import com.fs.starfarer.api.campaign.econ.SubmarketAPI;
89import com.fs.starfarer.api.campaign.events.CampaignEventManagerAPI;
90import com.fs.starfarer.api.campaign.events.CampaignEventPlugin;
91import com.fs.starfarer.api.campaign.events.CampaignEventTarget;
92import com.fs.starfarer.api.campaign.rules.MemKeys;
93import com.fs.starfarer.api.campaign.rules.MemoryAPI;
94import com.fs.starfarer.api.characters.AbilityPlugin;
95import com.fs.starfarer.api.characters.MutableCharacterStatsAPI;
96import com.fs.starfarer.api.characters.MutableCharacterStatsAPI.SkillLevelAPI;
97import com.fs.starfarer.api.characters.OfficerDataAPI;
98import com.fs.starfarer.api.characters.PersonAPI;
99import com.fs.starfarer.api.combat.CombatEngineAPI;
100import com.fs.starfarer.api.combat.CombatEntityAPI;
101import com.fs.starfarer.api.combat.DamageType;
102import com.fs.starfarer.api.combat.MissileAPI;
103import com.fs.starfarer.api.combat.MutableShipStatsAPI;
104import com.fs.starfarer.api.combat.ShipAPI;
105import com.fs.starfarer.api.combat.ShipAPI.HullSize;
106import com.fs.starfarer.api.combat.ShipCommand;
107import com.fs.starfarer.api.combat.ShipHullSpecAPI;
108import com.fs.starfarer.api.combat.ShipHullSpecAPI.ShipTypeHints;
109import com.fs.starfarer.api.combat.ShipVariantAPI;
110import com.fs.starfarer.api.combat.WeaponAPI;
111import com.fs.starfarer.api.combat.listeners.ApplyDamageResultAPI;
112import com.fs.starfarer.api.combat.listeners.CombatListenerUtil;
113import com.fs.starfarer.api.fleet.FleetMemberAPI;
114import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.CustomRepImpact;
115import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActionEnvelope;
116import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActions;
117import com.fs.starfarer.api.impl.campaign.DModManager;
118import com.fs.starfarer.api.impl.campaign.JumpPointInteractionDialogPluginImpl;
119import com.fs.starfarer.api.impl.campaign.RuleBasedInteractionDialogPluginImpl;
120import com.fs.starfarer.api.impl.campaign.WarningBeaconEntityPlugin;
121import com.fs.starfarer.api.impl.campaign.abilities.ReversePolarityToggle;
122import com.fs.starfarer.api.impl.campaign.econ.impl.ConstructionQueue.ConstructionQueueItem;
123import com.fs.starfarer.api.impl.campaign.econ.impl.ShipQuality;
124import com.fs.starfarer.api.impl.campaign.econ.impl.ShipQuality.QualityData;
125import com.fs.starfarer.api.impl.campaign.events.BaseEventPlugin.MarketFilter;
126import com.fs.starfarer.api.impl.campaign.fleets.FleetFactoryV3;
127import com.fs.starfarer.api.impl.campaign.ids.Conditions;
128import com.fs.starfarer.api.impl.campaign.ids.Difficulties;
129import com.fs.starfarer.api.impl.campaign.ids.Drops;
130import com.fs.starfarer.api.impl.campaign.ids.Entities;
131import com.fs.starfarer.api.impl.campaign.ids.Factions;
132import com.fs.starfarer.api.impl.campaign.ids.HullMods;
133import com.fs.starfarer.api.impl.campaign.ids.Industries;
134import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
135import com.fs.starfarer.api.impl.campaign.ids.Personalities;
136import com.fs.starfarer.api.impl.campaign.ids.Stats;
137import com.fs.starfarer.api.impl.campaign.ids.Strings;
138import com.fs.starfarer.api.impl.campaign.ids.Submarkets;
139import com.fs.starfarer.api.impl.campaign.ids.Tags;
140import com.fs.starfarer.api.impl.campaign.ids.Terrain;
141import com.fs.starfarer.api.impl.campaign.intel.FactionCommissionIntel;
142import com.fs.starfarer.api.impl.campaign.intel.MessageIntel;
143import com.fs.starfarer.api.impl.campaign.intel.contacts.ContactIntel;
144import com.fs.starfarer.api.impl.campaign.plog.PlaythroughLog;
145import com.fs.starfarer.api.impl.campaign.plog.SModRecord;
146import com.fs.starfarer.api.impl.campaign.population.CoreImmigrationPluginImpl;
147import com.fs.starfarer.api.impl.campaign.procgen.DefenderDataOverride;
148import com.fs.starfarer.api.impl.campaign.procgen.PlanetConditionGenerator;
149import com.fs.starfarer.api.impl.campaign.procgen.SalvageEntityGenDataSpec.DropData;
150import com.fs.starfarer.api.impl.campaign.procgen.StarAge;
151import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator;
152import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.OrbitGap;
153import com.fs.starfarer.api.impl.campaign.rulecmd.AddRemoveCommodity;
154import com.fs.starfarer.api.impl.campaign.rulecmd.unsetAll;
155import com.fs.starfarer.api.impl.campaign.submarkets.BaseSubmarketPlugin;
156import com.fs.starfarer.api.impl.campaign.submarkets.StoragePlugin;
157import com.fs.starfarer.api.impl.campaign.terrain.AsteroidSource;
158import com.fs.starfarer.api.impl.campaign.terrain.BaseTiledTerrain.TileParams;
159import com.fs.starfarer.api.impl.campaign.terrain.DebrisFieldTerrainPlugin;
160import com.fs.starfarer.api.impl.campaign.terrain.DebrisFieldTerrainPlugin.DebrisFieldParams;
161import com.fs.starfarer.api.impl.campaign.terrain.HyperspaceTerrainPlugin;
162import com.fs.starfarer.api.impl.campaign.terrain.MagneticFieldTerrainPlugin;
163import com.fs.starfarer.api.impl.campaign.terrain.NebulaTerrainPlugin;
164import com.fs.starfarer.api.impl.campaign.terrain.PulsarBeamTerrainPlugin;
165import com.fs.starfarer.api.impl.campaign.terrain.StarCoronaTerrainPlugin;
166import com.fs.starfarer.api.impl.campaign.velfield.SlipstreamTerrainPlugin2;
167import com.fs.starfarer.api.impl.campaign.velfield.SlipstreamTerrainPlugin2.SlipstreamSegment;
168import com.fs.starfarer.api.loading.HullModSpecAPI;
169import com.fs.starfarer.api.loading.IndustrySpecAPI;
170import com.fs.starfarer.api.plugins.FactionPersonalityPickerPlugin;
171import com.fs.starfarer.api.plugins.SurveyPlugin;
172import com.fs.starfarer.api.ui.Alignment;
173import com.fs.starfarer.api.ui.LabelAPI;
174import com.fs.starfarer.api.ui.TooltipMakerAPI;
175
176import sun.misc.Cleaner;
177import sun.nio.ch.DirectBuffer;
178
179
180public class Misc {
181
182 public static boolean CAN_SMOD_BUILT_IN = true;
183
184 public static String SIR = "Sir";
185 public static String MAAM = "Ma'am";
186 public static String CAPTAIN = "Captain";
187
188
189 public static float FLUX_PER_CAPACITOR = Global.getSettings().getFloat("fluxPerCapacitor");
190 public static float DISSIPATION_PER_VENT = Global.getSettings().getFloat("dissipationPerVent");
191
192 private static boolean cbMode = Global.getSettings().getBoolean("colorblindMode");
193
194 public static Color MOUNT_BALLISTIC = Global.getSettings().getColor("mountYellowColor");
195 public static Color MOUNT_MISSILE = Global.getSettings().getColor("mountGreenColor");
196 public static Color MOUNT_ENERGY = cbMode ? new Color(155,155,155,255) : Global.getSettings().getColor("mountBlueColor");
197 public static Color MOUNT_UNIVERSAL = Global.getSettings().getColor("mountGrayColor");
198 public static Color MOUNT_HYBRID = Global.getSettings().getColor("mountOrangeColor");
199 public static Color MOUNT_SYNERGY = Global.getSettings().getColor("mountCyanColor");
200 public static Color MOUNT_COMPOSITE = Global.getSettings().getColor("mountCompositeColor");
201
202 // for combat entities
203 public static final int OWNER_NEUTRAL = 100;
204 public static final int OWNER_PLAYER = 0;
205
206 public static Color FLOATY_EMP_DAMAGE_COLOR = new Color(255,255,255,255);
207 public static Color FLOATY_ARMOR_DAMAGE_COLOR = new Color(255,255,0,220);
208 public static Color FLOATY_SHIELD_DAMAGE_COLOR = new Color(200,200,255,220);
209 public static Color FLOATY_HULL_DAMAGE_COLOR = new Color(255,50,0,220);
210
211// public static final String SUPPLY_ACCESSIBILITY = "Supply Accessibility";
212
213 public static float GATE_FUEL_COST_MULT = Global.getSettings().getFloat("gateTransitFuelCostMult");
214
215 public static int MAX_COLONY_SIZE = Global.getSettings().getInt("maxColonySize");
216 public static int OVER_MAX_INDUSTRIES_PENALTY = Global.getSettings().getInt("overMaxIndustriesPenalty");
217
218
219 public static float FP_TO_BOMBARD_COST_APPROX_MULT = 12f;
220 public static float FP_TO_GROUND_RAID_STR_APPROX_MULT = 6f;
221
222 public static String UNKNOWN = " ";
223 public static String UNSURVEYED = "??";
224 public static String PRELIMINARY = "?";
225 public static String FULL = "X";
226
230 public static String STORY = "story";
231
232 public static float MAX_OFFICER_LEVEL = Global.getSettings().getFloat("officerMaxLevel");
233
234 public static Random random = new Random();
235
236 public static enum TokenType {
237 VARIABLE,
238 LITERAL,
239 OPERATOR,
240 }
241
242 public static final Vector2f ZERO = new Vector2f(0, 0);
243
244 public static class VarAndMemory {
245 public String name;
246 public MemoryAPI memory;
247 }
248 public static class Token {
249 public String string;
250 public TokenType type;
251 public String varNameWithoutMemoryKeyIfKeyIsValid = null;
252 public String varMemoryKey = null;
253 public Token(String string, TokenType type) {
254 this.string = string;
255 this.type = type;
256
257 if (isVariable()) {
258 int index = string.indexOf(".");
259 if (index > 0 && index < string.length() - 1) {
260 varMemoryKey = string.substring(1, index);
261 varNameWithoutMemoryKeyIfKeyIsValid = "$" + string.substring(index + 1);
262 }
263 }
264 }
265
266 public VarAndMemory getVarNameAndMemory(Map<String, MemoryAPI> memoryMap) {
267 String varName = varNameWithoutMemoryKeyIfKeyIsValid;
268 MemoryAPI memory = memoryMap.get(varMemoryKey);
269 if (memory == null) {
270 varName = string;
271 memory = memoryMap.get(MemKeys.LOCAL);
272 }
273 if (memory == null) {
274 throw new RuleException("No memory found for keys: " + varMemoryKey + ", " + MemKeys.LOCAL);
275 }
276
277 VarAndMemory result = new VarAndMemory();
278 result.name = varName;
279 result.memory = memory;
280 return result;
281 }
282
283 public String getStringWithTokenReplacement(String ruleId, InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap) {
284 String text = getString(memoryMap);
285 if (text == null) return null;
286 text = Global.getSector().getRules().performTokenReplacement(ruleId, text, dialog.getInteractionTarget(), memoryMap);
287// Map<String, String> tokens = Global.getSector().getRules().getTokenReplacements(ruleId, dialog.getInteractionTarget(), memoryMap);
288// for (String token : tokens.keySet()) {
289// String value = tokens.get(token);
290// text = text.replaceAll("(?s)\\" + token, value);
291// }
292// text = Misc.replaceTokensFromMemory(text, memoryMap);
293 return text;
294 }
295 public String getString(Map<String, MemoryAPI> memoryMap) {
296 String string = null;
297 if (isVariable()) {
298 VarAndMemory var = getVarNameAndMemory(memoryMap);
299 string = var.memory.getString(var.name);
300 } else {
301 string = this.string;
302 }
303 return string;
304 }
305
306 public Object getObject(Map<String, MemoryAPI> memoryMap) {
307 Object o = null;
308 if (isVariable()) {
309 VarAndMemory var = getVarNameAndMemory(memoryMap);
310 o = var.memory.get(var.name);
311 }
312 return o;
313 }
314
315 public boolean getBoolean(Map<String, MemoryAPI> memoryMap) {
316 String str = getString(memoryMap);
317 return Boolean.parseBoolean(str);
318 }
319
320 public boolean isBoolean(Map<String, MemoryAPI> memoryMap) {
321 String str = getString(memoryMap);
322 return str.toLowerCase().equals("true") || str.toLowerCase().equals("false");
323 }
324
325 public boolean isFloat(Map<String, MemoryAPI> memoryMap) {
326 String str = null;
327 if (isVariable()) {
328 VarAndMemory var = getVarNameAndMemory(memoryMap);
329 str = var.memory.getString(var.name);
330 } else {
331 str = string;
332 }
333 try {
334 Float.parseFloat(str);
335 return true;
336 } catch (NumberFormatException e) {
337 return false;
338 }
339 }
340
341 public float getFloat(Map<String, MemoryAPI> memoryMap) {
342 float result = 0f;
343 if (isVariable()) {
344 VarAndMemory var = getVarNameAndMemory(memoryMap);
345 result = var.memory.getFloat(var.name);
346 } else {
347 result = Float.parseFloat(string);
348 }
349 return result;
350 }
351
352 public int getInt(Map<String, MemoryAPI> memoryMap) {
353 return (int) Math.round(getFloat(memoryMap));
354 }
355
356 public Color getColor(Map<String, MemoryAPI> memoryMap) {
357 Object object = null;
358 if (isVariable()) {
359 VarAndMemory var = getVarNameAndMemory(memoryMap);
360 object = var.memory.get(var.name);
361 }
362 if (object instanceof Color) {
363 return (Color) object;
364 }
365
366 String string = getString(memoryMap);
367 try {
368 String [] parts = string.split(Pattern.quote(","));
369 return new Color(Integer.parseInt(parts[0]),
370 Integer.parseInt(parts[1]),
371 Integer.parseInt(parts[2]),
372 Integer.parseInt(parts[3]));
373 } catch (Exception e) {
374 if ("bad".equals(string)) {
375 string = "textEnemyColor";
376 } else if ("good".equals(string)) {
377 string = "textFriendColor";
378 } else if ("highlight".equals(string)) {
379 string = "buttonShortcut";
380 } else if ("h".equals(string)) {
381 string = "buttonShortcut";
382 } else if ("story".equals(string)) {
383 return Misc.getStoryOptionColor();
384 } else if ("gray".equals(string)) {
385 return Misc.getGrayColor();
386 } else if ("grey".equals(string)) {
387 return Misc.getGrayColor();
388 } else {
389 FactionAPI faction = Global.getSector().getFaction(string);
390 if (faction != null) {
391 return faction.getBaseUIColor();
392 }
393 }
394
395 return Global.getSettings().getColor(string);
396 }
397 }
398
399 public boolean isLiteral() {
400 return type == TokenType.LITERAL;
401 }
402 public boolean isVariable() {
403 return type == TokenType.VARIABLE;
404 }
405 public boolean isOperator() {
406 return type == TokenType.OPERATOR;
407 }
408 @Override
409 public String toString() {
410 if (isVariable()) {
411 return string + " (" + type.name() + ", memkey: " + varMemoryKey + ", name: " + varNameWithoutMemoryKeyIfKeyIsValid + ")";
412 } else {
413 return string + " (" + type.name() + ")";
414 }
415 }
416 }
417
418 public static List<Token> tokenize(String string) {
419 List<Token> result = new ArrayList<Token>();
420 boolean inQuote = false;
421 boolean inOperator = false;
422
424 for (int i = 0; i < string.length(); i++) {
425 char curr = string.charAt(i);
426 char next = 0;
427 if (i + 1 < string.length()) next = string.charAt(i + 1);
428 boolean charEscaped = false;
429 if (curr == '\\') {
430 i++;
431 if (i >= string.length()) {
432 throw new RuleException("Escape character at end of string in: [" + string + "]");
433 }
434 curr = string.charAt(i);
435 if (i + 1 < string.length()) next = string.charAt(i + 1);
436 charEscaped = true;
437 }
438// if (charEscaped) {
439// System.out.println("dfsdfs");
440// }
441
442 if (curr == '"' && !charEscaped) {
443 inQuote = !inQuote;
444 if (!inQuote && currToken.length() <= 0) {
445 result.add(new Token("", TokenType.LITERAL));
446 } else if (currToken.length() > 0) {
447 String str = currToken.toString();
448 if (!inQuote) {
449 result.add(new Token(str, TokenType.LITERAL));
450 } else {
451 if (str.startsWith("$")) {
452 result.add(new Token(str, TokenType.VARIABLE));
453 } else if (inOperator) {
454 result.add(new Token(str, TokenType.OPERATOR));
455 } else {
456 result.add(new Token(str, TokenType.LITERAL));
457 }
458 }
459 }
460 inOperator = false;
461 currToken.delete(0, 1000000);
462 continue;
463 }
464
465 if (!inQuote && (curr == ' ' || curr == '\t')) {
466 if (currToken.length() > 0) {
467 String str = currToken.toString();
468 if (str.startsWith("$")) {
469 result.add(new Token(str, TokenType.VARIABLE));
470 } else if (inOperator) {
471 result.add(new Token(str, TokenType.OPERATOR));
472 } else {
473 result.add(new Token(str, TokenType.LITERAL));
474 }
475 }
476 inOperator = false;
477 currToken.delete(0, 1000000);
478 continue;
479 }
480
481 if (!inQuote && !inOperator && isOperatorChar(curr) && (curr != '-' || !isDigit(next))) {
482 if (currToken.length() > 0) {
483 String str = currToken.toString();
484 if (str.startsWith("$")) {
485 result.add(new Token(str, TokenType.VARIABLE));
486 } else {
487 result.add(new Token(str, TokenType.LITERAL));
488 }
489 }
490 currToken.delete(0, 1000000);
491 inOperator = true;
492 if (charEscaped && curr == 'n') {
493 currToken.append("\n");
494 } else {
495 currToken.append(curr);
496 }
497 continue;
498 }
499
500 if (!inQuote && inOperator && !isOperatorChar(curr)) {
501 if (currToken.length() > 0) {
502 String str = currToken.toString();
503 result.add(new Token(str, TokenType.OPERATOR));
504 }
505 currToken.delete(0, 1000000);
506 inOperator = false;
507 if (charEscaped && curr == 'n') {
508 currToken.append("\n");
509 } else {
510 currToken.append(curr);
511 }
512 continue;
513 }
514
515 if (charEscaped && curr == 'n') {
516 currToken.append("\n");
517 } else {
518 currToken.append(curr);
519 }
520 }
521
522 if (inQuote) {
523 throw new RuleException("Unmatched quotes in string: " + string + "]");
524 }
525
526 if (currToken.length() > 0) {
527 String str = currToken.toString();
528 if (str.startsWith("$")) {
529 result.add(new Token(str, TokenType.VARIABLE));
530 } else if (inOperator) {
531 result.add(new Token(str, TokenType.OPERATOR));
532 } else {
533 result.add(new Token(str, TokenType.LITERAL));
534 }
535 }
536
537 return result;
538 }
539
540
541 private static boolean isDigit(char c) {
542 if (c == 0) return false;
543 String digits = "1234567890";
544 return digits.contains("" + c);
545 }
546 private static boolean isOperatorChar(char c) {
547 String operatorChars = "=<>!+-";
548 return operatorChars.contains("" + c);
549 }
550
551
552 public static String ucFirst(String str) {
553 if (str == null) return "Null";
554 if (str.isEmpty()) return "";
555 return ("" + str.charAt(0)).toUpperCase() + str.substring(1);
556 }
557
558 public static String lcFirst(String str) {
559 if (str == null) return "Null";
560 if (str.isEmpty()) return "";
561 return ("" + str.charAt(0)).toLowerCase() + str.substring(1);
562 }
563
564
566 List<String> keySet = new ArrayList<String>(memoryMap.keySet());
567 if (keySet.contains(MemKeys.LOCAL)) {
568 keySet.remove(MemKeys.LOCAL);
569 keySet.add(0, MemKeys.LOCAL);
570 }
571 for (String key : keySet) {
572 MemoryAPI memory = memoryMap.get(key);
573 List<String> keys = new ArrayList<String>(memory.getKeys());
575 public int compare(String o1, String o2) {
576 return o2.length() - o1.length();
577 }
578 });
579 for (String token : keys) {
580 Object value = memory.get(token);
581 if (value == null) value = "null";
582 if (value instanceof String || value instanceof Boolean || value instanceof Float || value instanceof Integer) {
583 text = text.replaceAll("(?s)\\$" + Pattern.quote(key) + "\\." + Pattern.quote(token.substring(1)), value.toString());
584 text = text.replaceAll("(?s)\\$" + Pattern.quote(token.substring(1)), value.toString());
585 }
586 }
587 }
588 return text;
589 }
590
591
592 public static float getDistance(SectorEntityToken from, SectorEntityToken to) {
593 return getDistance(from.getLocation(), to.getLocation());
594 }
595 public static float getDistanceLY(SectorEntityToken from, SectorEntityToken to) {
596 return getDistanceLY(from.getLocationInHyperspace(), to.getLocationInHyperspace());
597 }
598
599
600 private static Vector2f temp3 = new Vector2f();
601 public static float getDistance(Vector2f v1, Vector2f v2) {
602 //return Vector2f.sub(v1, v2, temp3).length();
603 return (float) Math.sqrt((v1.x - v2.x) * (v1.x - v2.x) + (v1.y - v2.y) * (v1.y - v2.y));
604 }
605
606 public static float getDistanceSq(Vector2f v1, Vector2f v2) {
607 //return Vector2f.sub(v1, v2, temp3).lengthSquared();
608 return (v1.x - v2.x) * (v1.x - v2.x) + (v1.y - v2.y) * (v1.y - v2.y);
609 }
610
611 public static float getDistance(float x1, float y1, float x2, float y2) {
612// float xDiff = Math.abs(x1 - x2);
613// float yDiff = Math.abs(y1 - y2);
614// return (float) Math.sqrt(xDiff * xDiff + yDiff * yDiff);
615 return (float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
616
617 }
618
619 public static float getDistanceToPlayerLY(Vector2f locInHyper) {
620 if (Global.getSector().getPlayerFleet() == null) return 100000f;
621 return getDistanceLY(Global.getSector().getPlayerFleet().getLocationInHyperspace(), locInHyper);
622 }
623 public static float getDistanceToPlayerLY(SectorEntityToken other) {
624 if (Global.getSector().getPlayerFleet() == null) return 100000f;
625 return getDistanceLY(Global.getSector().getPlayerFleet().getLocationInHyperspace(), other.getLocationInHyperspace());
626 }
627
628 public static float getDistanceLY(Vector2f v1, Vector2f v2) {
629 return Vector2f.sub(v1, v2, temp3).length() / getUnitsPerLightYear();
630 }
631
632 public static float getRounded(float in) {
633 if (in <= 10) return Math.max(1, (int) in);
634 float pow = (int) Math.log10(in);
635 float div = (float) Math.pow(10, Math.max(0, pow - 1));
636 if (pow == 1) div = 10;
637 return (int) Math.round(in / div) * div;
638 }
639
640 public static String getRoundedValue(float value) {
641 if (Math.abs((float)Math.round(value) - value) < 0.0001f) {
642 //if (value > 10 || value < -10) {
643 return String.format("%d", (int) Math.round(value));
644 //} else {
645 //return String.format("%.1f", value);
646 //}
647 } else if ((int) Math.round((value * 100f)) == (int) Math.round((value * 10f)) * 10) {
648 return (value > 10 || value < -10) ? "" + (int) Math.round(value) : String.format("%.1f", value);
649 } else {
650 return (value > 10 || value < -10) ? "" + (int) Math.round(value) : String.format("%.2f", value);
651 }
652 }
653
654 public static float getRoundedValueFloat(float value) {
655 if (Math.abs((float)Math.round(value) - value) < 0.0001f) {
656 return (int) Math.round(value);
657 } else if ((int) Math.round((value * 100f)) == (int) Math.round((value * 10f)) * 10) {
658 return (value > 10 || value < -10) ? (int) Math.round(value) :
659 (Math.round(value * 10f) / 10f);
660 } else {
661 return (value > 10 || value < -10) ? (int) Math.round(value) :
662 (Math.round(value * 100f) / 100f);
663 }
664 }
665
666 public static String getRoundedValueMaxOneAfterDecimal(float value) {
667 if (Math.abs((float)Math.round(value) - value) < 0.0001f) {
668 return String.format("%d", (int) Math.round(value));
669 } else if ((int) Math.round((value * 100f)) == (int) Math.round((value * 10f)) * 10) {
670 return (value >= 10 || value <= -10) ? "" + (int) Math.round(value) : String.format("%.1f", value);
671 } else {
672 return (value >= 10 || value <= -10) ? "" + (int) Math.round(value) : String.format("%.1f", value);
673 }
674 }
675
677 if (Math.abs((float)Math.round(value) - value) < 0.0001f) {
678 return String.format("%d", (int) Math.round(value));
679 } else {
680 return String.format("%.1f", value);
681 }
682 }
683
684
685
686 public static float logOfBase(float base, float num) {
687 return (float) (Math.log(num) / Math.log(base));
688 }
689
690 public static Vector2f getPointAtRadius(Vector2f from, float r) {
691 float angle = (float) ((float) Math.random() * Math.PI * 2f);
692 float x = (float) (Math.cos(angle) * r) + from.x;
693 float y = (float) (Math.sin(angle) * r) + from.y;
694 return new Vector2f(x, y);
695 }
696
697 public static Vector2f getPointAtRadius(Vector2f from, float r, Random random) {
698 float angle = (float) (random.nextFloat() * Math.PI * 2f);
699 float x = (float) (Math.cos(angle) * r) + from.x;
700 float y = (float) (Math.sin(angle) * r) + from.y;
701 return new Vector2f(x, y);
702 }
703
704 public static Vector2f getPointWithinRadius(Vector2f from, float r) {
705 return getPointWithinRadius(from, r, random);
706 }
707 public static Vector2f getPointWithinRadius(Vector2f from, float r, Random random) {
708 r = r * random.nextFloat();
709 float angle = (float) (random.nextFloat() * Math.PI * 2f);
710 float x = (float) (Math.cos(angle) * r) + from.x;
711 float y = (float) (Math.sin(angle) * r) + from.y;
712 return new Vector2f(x, y);
713 }
714
716 r = (float) (r * Math.sqrt(random.nextFloat()));
717 float angle = (float) (random.nextFloat() * Math.PI * 2f);
718 float x = (float) (Math.cos(angle) * r) + from.x;
719 float y = (float) (Math.sin(angle) * r) + from.y;
720 return new Vector2f(x, y);
721 }
722
724 float r = (float) (minR + (maxR - minR) * Math.sqrt(random.nextFloat()));
725 float angle = (float) (random.nextFloat() * Math.PI * 2f);
726 float x = (float) (Math.cos(angle) * r) + from.x;
727 float y = (float) (Math.sin(angle) * r) + from.y;
728 return new Vector2f(x, y);
729 }
730
731 public static float getSnapshotFPLost(CampaignFleetAPI fleet) {
732 float fp = fleet.getFleetPoints();
733 float before = 0;
734 for (FleetMemberAPI member : fleet.getFleetData().getSnapshot()) {
735 before += member.getFleetPointCost();
736 }
737
738 return before - fp;
739 }
740
741 public static List<FleetMemberAPI> getSnapshotMembersLost(CampaignFleetAPI fleet) {
743 List<FleetMemberAPI> curr = fleet.getFleetData().getMembersListCopy();
744 for (FleetMemberAPI member : fleet.getFleetData().getSnapshot()) {
745 if (!curr.contains(member)) {
746 lost.add(member);
747 }
748 }
749
750 return lost;
751 }
752
753
754 public static CampaignEventPlugin startEvent(CampaignEventTarget eventTarget, String eventId, Object params) {
755 CampaignEventManagerAPI manager = Global.getSector().getEventManager();
756 CampaignEventPlugin event = manager.getOngoingEvent(eventTarget, eventId);
757 if (event == null) {
758 event = manager.startEvent(eventTarget, eventId, params);
759 }
760 return event;
761 }
762
764 return setAlpha(scaleColorOnly(getStoryOptionColor(), 0.65f), 255);
765 }
766 public static Color getStoryDarkColor() {
767 return setAlpha(scaleColorOnly(getStoryOptionColor(), 0.4f), 175);
768 }
769 public static Color getStoryBrightColor() {
771 setAlpha(Color.white, 255),
772 0.35f);
773 return bright;
774 }
775 public static Color getStoryOptionColor() {
776 //return Misc.interpolateColor(Misc.getButtonTextColor(), Misc.getPositiveHighlightColor(), 0.5f);
777 return Global.getSettings().getColor("storyOptionColor");
778 //return Global.getSettings().getColor("tooltipTitleAndLightHighlightColor");
779 }
780
782 return Global.getSettings().getColor("buttonShortcut");
783 }
784
785 public static Color getHighlightColor() {
786 return Global.getSettings().getColor("buttonShortcut");
787 }
788 public static Color getDarkHighlightColor() {
790 return Misc.setAlpha(hc, 255);
791 }
793 return Global.getSettings().getColor("tooltipTitleAndLightHighlightColor");
794 }
796 if (Global.getSettings().getBoolean("colorblindMode")) {
797 return new Color(0, 100, 255);
798 }
799 return Global.getSettings().getColor("textEnemyColor");
800 }
801
803 return Global.getSettings().getColor("mountYellowColor");
804 }
805 public static Color getMissileMountColor() {
806 return Global.getSettings().getColor("mountGreenColor");
807 }
808 public static Color getEnergyMountColor() {
809 if (Global.getSettings().getBoolean("colorblindMode")) {
810 return new Color(155,155,155,255);
811 }
812 return Global.getSettings().getColor("mountBlueColor");
813 }
814
816 return Global.getSettings().getColor("textFriendColor");
817 }
818
819 public static Color getGrayColor() {
820 return Global.getSettings().getColor("textGrayColor");
821 }
822
823 public static Color getBrightPlayerColor() {
824 return Global.getSector().getPlayerFaction().getBrightUIColor();
825 }
826 public static Color getBasePlayerColor() {
827 return Global.getSector().getPlayerFaction().getBaseUIColor();
828 }
829 public static Color getDarkPlayerColor() {
830 return Global.getSector().getPlayerFaction().getDarkUIColor();
831 }
832 public static Color getTextColor() {
833 return Global.getSettings().getColor("standardTextColor");
834 }
835 public static Color getButtonTextColor() {
836 return Global.getSettings().getColor("buttonText");
837 }
838
839 public static float getUnitsPerLightYear() {
840 return Global.getSettings().getFloat("unitsPerLightYear");
841 }
842
843 public static float getProfitMarginFlat() {
844 return Global.getSettings().getFloat("profitMarginFlat");
845 }
846
847 public static float getProfitMarginMult() {
848 return Global.getSettings().getFloat("profitMarginMult");
849 }
850
851 public static float getEconomyInterval() {
852 return Global.getSettings().getFloat("economyIntervalnGameDays");
853 }
854
855 public static float getGenericRollingAverageFactor() {
856 return Global.getSettings().getFloat("genericRollingAverageFactor");
857 }
858
860 float interval = getEconomyInterval();
861 return new IntervalUtil(interval * 0.75f, interval * 1.25f);
862 }
863
865 return getAndJoined(strings.toArray(new String [0]));
866 }
867
868 public static String getAndJoined(String ... strings) {
869 return getJoined("and", strings);
870 }
871
873 return getJoined(joiner, strings.toArray(new String [0]));
874 }
876 if (strings.length == 1) return strings[0];
877
878 String result = "";
879 for (int i = 0; i < strings.length - 1; i++) {
880 result += strings[i] + ", ";
881 }
882 if (!result.isEmpty()) {
883 result = result.substring(0, result.length() - 2);
884 }
885 if (strings.length > 2) {
886 if (joiner.isEmpty()) {
887 result += ", " + strings[strings.length - 1];
888 } else {
889 result += ", " + joiner + " " + strings[strings.length - 1];
890 }
891 } else if (strings.length == 2) {
892 if (joiner.isEmpty()) {
893 result += ", " + strings[strings.length - 1];
894 } else {
895 result += " " + joiner + " " + strings[strings.length - 1];
896 }
897 }
898 return result;
899 }
900
901 public static interface FleetFilter {
902 boolean accept(CampaignFleetAPI curr);
903 }
904
905 public static List<CampaignFleetAPI> findNearbyFleets(SectorEntityToken from, float maxRange, FleetFilter filter) {
907 for (CampaignFleetAPI fleet : from.getContainingLocation().getFleets()) {
908 if (fleet == from) continue;
909 float dist = Misc.getDistance(fleet.getLocation(), from.getLocation());
910 if (dist > maxRange) continue;
911
912 if (filter == null || filter.accept(fleet)) {
913 result.add(fleet);
914 }
915 }
916 return result;
917 }
918
919 public static List<CampaignFleetAPI> getFleetsInOrNearSystem(StarSystemAPI system) {
920 List<CampaignFleetAPI> result = new ArrayList<CampaignFleetAPI>(system.getFleets());
921 for (CampaignFleetAPI fleet : Global.getSector().getHyperspace().getFleets()) {
922 if (!fleet.isInOrNearSystem(system)) continue;
923 result.add(fleet);
924 }
925 return result;
926 }
927
928
929 public static List<MarketAPI> getMarketsInLocation(LocationAPI location, String factionId) {
931 for (MarketAPI curr : getMarketsInLocation(location)) {
932 if (curr.getFactionId().equals(factionId)) {
933 result.add(curr);
934 }
935 }
936 return result;
937 }
938
939 public static MarketAPI getBiggestMarketInLocation(LocationAPI location) {
940 int max = 0;
941 MarketAPI best = null;
942 for (MarketAPI curr : getMarketsInLocation(location)) {
943 int size = curr.getSize();
944 if (size > max || (size == max && curr.getFaction().isPlayerFaction())) {
945 max = size;
946 best = curr;
947 }
948 }
949 return best;
950 }
951
952
953 public static List<MarketAPI> getMarketsInLocation(LocationAPI location) {
954 if (location == null) return new ArrayList<MarketAPI>();
955 return Global.getSector().getEconomy().getMarkets(location);
956// List<MarketAPI> result = new ArrayList<MarketAPI>();
957// for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
958// if (market.getContainingLocation() != location) continue;
959// result.add(market);
960// }
961// return result;
962 }
963
964 public static List<MarketAPI> getFactionMarkets(FactionAPI faction, String econGroup) {
966 for (MarketAPI market : Global.getSector().getEconomy().getMarketsInGroup(econGroup)) {
967 if (market.getFaction() == faction) {
968 result.add(market);
969 }
970 }
971 return result;
972 }
974 FactionAPI player = Global.getSector().getFaction(Factions.PLAYER);
976 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
977 if (market.getFaction() == player) {
978 result.add(market);
979 } else if (includeNonPlayerFaction && market.isPlayerOwned()) {
980 result.add(market);
981 }
982 }
983 return result;
984 }
985
992 for (MarketAPI market : markets) {
993 StarSystemAPI system = market.getStarSystem();
994 if (system != null && !systems.contains(system)) {
995 systems.add(system);
996 }
997 }
998 return systems;
999 }
1000
1001 public static List<MarketAPI> getFactionMarkets(String factionId) {
1002 return getFactionMarkets(Global.getSector().getFaction(factionId));
1003 }
1004 public static List<MarketAPI> getFactionMarkets(FactionAPI faction) {
1005 //Global.getSector().getEconomy().get
1007 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
1008 if (market.getFaction() == faction) {
1009 result.add(market);
1010 }
1011 }
1012 return result;
1013 }
1014
1015 public static List<MarketAPI> getNearbyMarkets(Vector2f locInHyper, float distLY) {
1017 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
1018 float dist = getDistanceLY(market.getLocationInHyperspace(), locInHyper);
1019 if (dist > distLY) continue;
1020 result.add(market);
1021 }
1022 return result;
1023 }
1024
1025 public static int getNumHostileMarkets(FactionAPI faction, SectorEntityToken from, float maxDist) {
1027 for (MarketAPI market : Misc.getMarketsInLocation(from.getContainingLocation())) {
1028 SectorEntityToken primary = market.getPrimaryEntity();
1029 float dist = getDistance(primary.getLocation(), from.getLocation());
1030 if (dist > maxDist) continue;
1031 if (market.getFaction() != null && market.getFaction().isHostileTo(faction)) {
1033 }
1034 }
1036 }
1037
1038 public static List<StarSystemAPI> getNearbyStarSystems(SectorEntityToken token, float maxRangeLY) {
1040
1041 for (StarSystemAPI system : Global.getSector().getStarSystems()) {
1042 float dist = Misc.getDistanceLY(token.getLocationInHyperspace(), system.getLocation());
1043 if (dist > maxRangeLY) continue;
1044 result.add(system);
1045 }
1046 return result;
1047 }
1048
1049 public static StarSystemAPI getNearbyStarSystem(SectorEntityToken token, float maxRangeLY) {
1050 if (token.getContainingLocation() instanceof StarSystemAPI) {
1051 return (StarSystemAPI) token.getContainingLocation();
1052 }
1053
1054 StarSystemAPI closest = null;
1055 float minDist = Float.MAX_VALUE;
1056 for (StarSystemAPI system : Global.getSector().getStarSystems()) {
1057 float dist = Misc.getDistanceLY(token.getLocationInHyperspace(), system.getLocation());
1058 if (dist > maxRangeLY) continue;
1059 if (dist < minDist) {
1060 minDist = dist;
1061 closest = system;
1062 }
1063 //return system;
1064 }
1065 return closest;
1066 }
1067
1068 public static StarSystemAPI getNearestStarSystem(SectorEntityToken token) {
1069 if (token.getContainingLocation() instanceof StarSystemAPI) {
1070 return (StarSystemAPI) token.getContainingLocation();
1071 }
1072
1073 float minDist = Float.MAX_VALUE;
1074 StarSystemAPI closest = null;
1075 for (StarSystemAPI system : Global.getSector().getStarSystems()) {
1076 float dist = Misc.getDistanceLY(token.getLocationInHyperspace(), system.getLocation());
1077 if (dist < minDist) {
1078 minDist = dist;
1079 closest = system;
1080 }
1081 }
1082 return closest;
1083 }
1084
1085 public static StarSystemAPI getNearbyStarSystem(SectorEntityToken token) {
1086 if (token.getContainingLocation() instanceof StarSystemAPI) {
1087 return (StarSystemAPI) token.getContainingLocation();
1088 }
1089 for (StarSystemAPI system : Global.getSector().getStarSystems()) {
1090 if (token.isInOrNearSystem(system)) return system;
1091 }
1092 return null;
1093 }
1094
1095
1096 public static boolean showRuleDialog(SectorEntityToken entity, String initialTrigger) {
1097 RuleBasedInteractionDialogPluginImpl plugin;
1098 if (initialTrigger != null) {
1099 plugin = new RuleBasedInteractionDialogPluginImpl(initialTrigger);
1100 } else {
1101 plugin = new RuleBasedInteractionDialogPluginImpl();
1102 }
1103 return Global.getSector().getCampaignUI().showInteractionDialog(plugin, entity);
1104 }
1105
1106 public static float DEG_PER_RAD = 180f / 3.1415926f;
1107
1108 public static float getAngleInDegreesStrict(Vector2f v) {
1109 float angle = (float) Math.atan2(v.y, v.x) * DEG_PER_RAD;
1110 return angle;
1111 }
1112
1113 public static float getAngleInDegreesStrict(Vector2f from, Vector2f to) {
1114 float dx = to.x - from.x;
1115 float dy = to.y - from.y;
1116 float angle = (float) Math.atan2(dy, dx) * DEG_PER_RAD;
1117 return angle;
1118 }
1119 public static float getAngleInDegrees(Vector2f v) {
1121 }
1122
1123 public static float getAngleInDegrees(Vector2f from, Vector2f to) {
1124 return Global.getSettings().getAngleInDegreesFast(from, to);
1125 }
1126
1127 public static Vector2f normalise(Vector2f v) {
1128 if (v.lengthSquared() > Float.MIN_VALUE) {
1129 return (Vector2f)v.normalise();
1130 }
1131 //return v;
1132 return new Vector2f(1, 0);
1133 }
1134
1135 public static float normalizeAngle(float angleDeg) {
1136 return (angleDeg % 360f + 360f) % 360f;
1137 }
1138
1139 public static MarketAPI findNearestLocalMarket(SectorEntityToken token, float maxDist, MarketFilter filter) {
1140 List<MarketAPI> localMarkets = getMarketsInLocation(token.getContainingLocation());
1141 float distToLocalMarket = Float.MAX_VALUE;
1142 MarketAPI closest = null;
1143 for (MarketAPI market : localMarkets) {
1144 if (filter != null && !filter.acceptMarket(market)) continue;
1145
1146 if (market.getPrimaryEntity() == null) continue;
1147 if (market.getPrimaryEntity().getContainingLocation() != token.getContainingLocation()) continue;
1148
1149 float currDist = Misc.getDistance(market.getPrimaryEntity().getLocation(), token.getLocation());
1150 if (currDist > maxDist) continue;
1153 closest = market;
1154 }
1155 }
1156 return closest;
1157 }
1158 public static List<MarketAPI> findNearbyLocalMarkets(SectorEntityToken token, float maxDist, MarketFilter filter) {
1159 List<MarketAPI> localMarkets = getMarketsInLocation(token.getContainingLocation());
1161
1162 for (MarketAPI market : localMarkets) {
1163 if (filter != null && !filter.acceptMarket(market)) continue;
1164 if (market.getPrimaryEntity() == null) continue;
1165 if (market.getPrimaryEntity().getContainingLocation() != token.getContainingLocation()) continue;
1166
1167 float currDist = Misc.getDistance(market.getPrimaryEntity().getLocation(), token.getLocation());
1168 if (currDist > maxDist) continue;
1169
1170 result.add(market);
1171
1172 }
1173 return result;
1174 }
1175
1176 public static MarketAPI findNearestLocalMarketWithSameFaction(final SectorEntityToken token, float maxDist) {
1177 return findNearestLocalMarket(token, maxDist, new MarketFilter() {
1178 public boolean acceptMarket(MarketAPI curr) {
1179 return curr.getFaction() == token.getFaction();
1180 }
1181 });
1182 }
1183
1184 public static Vector2f getUnitVector(Vector2f from, Vector2f to) {
1186 }
1187
1188 public static float RAD_PER_DEG = 0.01745329251f;
1190 Vector2f result = new Vector2f();
1191 float radians = degrees * RAD_PER_DEG;
1192 result.x = (float)Math.cos(radians);
1193 result.y = (float)Math.sin(radians);
1194
1195 return result;
1196 }
1197
1198 public static Vector2f rotateAroundOrigin(Vector2f v, float angle) {
1199 float cos = (float) Math.cos(angle * RAD_PER_DEG);
1200 float sin = (float) Math.sin(angle * RAD_PER_DEG);
1201 Vector2f r = new Vector2f();
1202 r.x = v.x * cos - v.y * sin;
1203 r.y = v.x * sin + v.y * cos;
1204 return r;
1205 }
1206
1207 public static Vector2f rotateAroundOrigin(Vector2f v, float angle, Vector2f origin) {
1208 float cos = (float) Math.cos(angle * RAD_PER_DEG);
1209 float sin = (float) Math.sin(angle * RAD_PER_DEG);
1210 Vector2f r = Vector2f.sub(v, origin, new Vector2f());
1211 Vector2f r2 = new Vector2f();
1212 r2.x = r.x * cos - r.y * sin;
1213 r2.y = r.x * sin + r.y * cos;
1214 Vector2f.add(r2, origin, r2);
1215 return r2;
1216 }
1217
1225 public static boolean isBetween(float one, float two, float check) {
1226 one = normalizeAngle(one);
1227 two = normalizeAngle(two);
1228 check = normalizeAngle(check);
1229
1230 //System.out.println(one + "," + two + "," + check);
1231 if (check >= one && check <= two) return true;
1232
1233 if (one > two) {
1234 if (check <= two) return true;
1235 if (check >= one) return true;
1236 }
1237 return false;
1238 }
1239
1240 public static float getShieldedCargoFraction(CampaignFleetAPI fleet) {
1241 float shielded = 0f;
1242 for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) {
1243 if (member.isMothballed()) continue;
1244 if (member.getVariant().hasHullMod(HullMods.SHIELDED_CARGO_HOLDS)) {
1245 shielded += member.getCargoCapacity();
1246 }
1247 }
1248 float max = fleet.getCargo().getMaxCapacity();
1249 if (max < 1) return 0f;
1250 return shielded / max;
1251 }
1252
1253
1254 public static Color interpolateColor(Color from, Color to, float progress) {
1255 float red = (float)from.getRed() + ((float)to.getRed() - (float)from.getRed()) * progress;
1256 float green = (float)from.getGreen() + ((float)to.getGreen() - (float)from.getGreen()) * progress;
1257 float blue = (float)from.getBlue() + ((float)to.getBlue() - (float)from.getBlue()) * progress;
1258 float alpha = (float)from.getAlpha() + ((float)to.getAlpha() - (float)from.getAlpha()) * progress;
1259 red = Math.round(red);
1260 green = Math.round(green);
1261 blue = Math.round(blue);
1262 alpha = Math.round(alpha);
1263 return new Color((int)red, (int)green, (int)blue, (int)alpha);
1264 }
1265
1266 public static Color genColor(Color min, Color max, Random random) {
1267 Color color = new Color((int) (min.getRed() + (max.getRed() - min.getRed()) * random.nextDouble()),
1268 (int) (min.getGreen() + (max.getGreen() - min.getGreen()) * random.nextDouble()),
1269 (int) (min.getBlue() + (max.getBlue() - min.getBlue()) * random.nextDouble()),
1270 255);
1271
1272 return color;
1273 }
1274
1275 public static Vector2f interpolateVector(Vector2f from, Vector2f to, float progress) {
1276 Vector2f v = new Vector2f(from);
1277
1278 v.x += (to.x - from.x) * progress;
1279 v.y += (to.y - from.y) * progress;
1280
1281 return v;
1282 }
1283
1284 public static float interpolate(float from, float to, float progress) {
1285 to = from + (to - from) * progress;
1286 return to;
1287 }
1288
1289 public static Color scaleColor(Color color, float factor) {
1290 return new Color((int) (color.getRed() * factor),
1291 (int) (color.getGreen() * factor),
1292 (int) (color.getBlue() * factor),
1293 (int) (color.getAlpha() * factor));
1294 }
1295 public static Color scaleColorOnly(Color color, float factor) {
1296 return new Color((int) (color.getRed() * factor),
1297 (int) (color.getGreen() * factor),
1298 (int) (color.getBlue() * factor),
1299 (int) (color.getAlpha()));
1300 }
1301
1302 public static Color scaleAlpha(Color color, float factor) {
1303 return new Color((int) (color.getRed() * 1f),
1304 (int) (color.getGreen() * 1f),
1305 (int) (color.getBlue() * 1f),
1306 (int) (color.getAlpha() * factor));
1307 }
1308
1309 public static Color setAlpha(Color color, int alpha) {
1310 if (alpha < 0) alpha = 0;
1311 if (alpha > 255) alpha = 255;
1312 return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);
1313 }
1314
1315 public static float getSizeNum(HullSize size) {
1316 if (size == null) {
1317 return 1;
1318 }
1319 switch (size) {
1320 case CAPITAL_SHIP:
1321 return 5;
1322 case CRUISER:
1323 return 3;
1324 case DESTROYER:
1325 return 2;
1326 case FIGHTER:
1327 case FRIGATE:
1328 case DEFAULT:
1329 return 1;
1330 }
1331 return 1;
1332 }
1333
1334 public static void unsetAll(String prefix, String memKey, MemoryAPI memory) {
1336 memoryMap.put(memKey, memory);
1337 new unsetAll().execute(null, null, Misc.tokenize(prefix), memoryMap);
1338 }
1339
1340
1341
1342 public static float getTargetingRadius(Vector2f from, CombatEntityAPI target, boolean considerShield) {
1343 return Global.getSettings().getTargetingRadius(from, target, considerShield);
1344 }
1345
1346
1347 public static float getClosingSpeed(Vector2f p1, Vector2f p2, Vector2f v1, Vector2f v2) {
1348 // direction from target to shooter
1349 Vector2f dir = Vector2f.sub(p1, p2, new Vector2f());
1350 normalise(dir);
1351 // velocity of target relative to shooter
1352 Vector2f relVel = Vector2f.sub(v2, v1, new Vector2f());
1353 float closingSpeed = Vector2f.dot(dir, relVel);
1354 return closingSpeed;
1355 }
1356
1357
1358 protected static DecimalFormat format = null;
1359 public static DecimalFormat getFormat() {
1360 if (format == null) {
1362// symbols.setDecimalSeparator('.');
1363// symbols.setGroupingSeparator(',');
1364 format = new DecimalFormat("###,###,###,###,###", symbols);
1365 }
1366 return format;
1367 }
1368
1374 public static String getWithDGS(float num) {
1375 return getFormat().format(num);
1376 }
1377
1383 public static String getDGSCredits(float num) {
1384 return getFormat().format((int)num) + Strings.C;
1385 }
1386
1387
1388
1389 public static Vector2f getInterceptPointBasic(SectorEntityToken from, SectorEntityToken to) {
1390 float dist = getDistance(from.getLocation(), to.getLocation()) - from.getRadius() - to.getRadius();
1391 if (dist <= 0) return new Vector2f(to.getLocation());
1392
1393 float closingSpeed = getClosingSpeed(from.getLocation(), to.getLocation(), from.getVelocity(), to.getVelocity());
1394 if (closingSpeed <= 10) return new Vector2f(to.getLocation());
1395
1396 Vector2f toTarget = getUnitVectorAtDegreeAngle(Misc.getAngleInDegrees(from.getLocation(), to.getLocation()));
1397 Vector2f vel = new Vector2f(from.getVelocity());
1398 normalise(vel);
1399 float dot = Vector2f.dot(toTarget, vel);
1400 if (dot < 0) return new Vector2f(to.getLocation());
1401// if (to.isPlayerFleet()) {
1402// System.out.println("23rwefe");
1403// }
1404 float time = dist / closingSpeed;
1405
1406 Vector2f point = new Vector2f(to.getVelocity());
1407 point.scale(time);
1408 Vector2f.add(point, to.getLocation(), point);
1409 return point;
1410 }
1411
1412
1413
1432 public static boolean setFlagWithReason(MemoryAPI memory, String flagKey, String reason, boolean value, float expire) {
1433 String requiredKey = flagKey + "_" + reason;
1434
1435 if (value) {
1436 memory.set(flagKey, true);
1437 memory.set(requiredKey, value, expire);
1438 memory.addRequired(flagKey, requiredKey);
1439 } else {
1440 memory.unset(requiredKey);
1441 }
1442
1443 return memory.contains(flagKey);
1444 }
1445
1446 public static boolean flagHasReason(MemoryAPI memory, String flagKey, String reason) {
1447 String requiredKey = flagKey + "_" + reason;
1448
1449 return memory.getBoolean(requiredKey);
1450 }
1451
1452 public static void clearFlag(MemoryAPI memory, String flagKey) {
1453 for (String req : memory.getRequired(flagKey)) {
1454 memory.unset(req);
1455 }
1456 }
1457
1458 public static void makeLowRepImpact(CampaignFleetAPI fleet, String reason) {
1459 setFlagWithReason(fleet.getMemoryWithoutUpdate(), MemFlags.MEMORY_KEY_LOW_REP_IMPACT, reason, true, -1);
1460 }
1461 public static void makeNoRepImpact(CampaignFleetAPI fleet, String reason) {
1462 setFlagWithReason(fleet.getMemoryWithoutUpdate(), MemFlags.MEMORY_KEY_LOW_REP_IMPACT, reason, true, -1);
1463 setFlagWithReason(fleet.getMemoryWithoutUpdate(), MemFlags.MEMORY_KEY_NO_REP_IMPACT, reason, true, -1);
1464 }
1465
1466 public static void makeHostile(CampaignFleetAPI fleet) {
1467 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_MAKE_HOSTILE, true);
1468 }
1469
1470 public static void makeHostileToPlayerTradeFleets(CampaignFleetAPI fleet) {
1471 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_MAKE_HOSTILE_TO_PLAYER_TRADE_FLEETS, true);
1472 }
1473
1474 public static void makeHostileToAllTradeFleets(CampaignFleetAPI fleet) {
1475 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_MAKE_HOSTILE_TO_ALL_TRADE_FLEETS, true);
1476 }
1477
1478 public static void makeNonHostileToFaction(CampaignFleetAPI fleet, String factionId, float dur) {
1479 makeNonHostileToFaction(fleet, factionId, true, dur);
1480 }
1481 public static void makeNonHostileToFaction(CampaignFleetAPI fleet, String factionId, boolean nonHostile, float dur) {
1482 String flag = MemFlags.MEMORY_KEY_MAKE_NON_HOSTILE + "_" + factionId;
1483 if (!nonHostile) {
1484 fleet.getMemoryWithoutUpdate().unset(flag);
1485 } else {
1486 fleet.getMemoryWithoutUpdate().set(flag, true, dur);
1487 }
1488 }
1489 public static void makeHostileToFaction(CampaignFleetAPI fleet, String factionId, float dur) {
1490 makeHostileToFaction(fleet, factionId, true, dur);
1491 }
1492 public static void makeHostileToFaction(CampaignFleetAPI fleet, String factionId, boolean hostile, float dur) {
1493 String flag = MemFlags.MEMORY_KEY_MAKE_HOSTILE + "_" + factionId;
1494 if (!hostile) {
1495 fleet.getMemoryWithoutUpdate().unset(flag);
1496 } else {
1497 fleet.getMemoryWithoutUpdate().set(flag, true, dur);
1498 }
1499 }
1500
1501 public static boolean isFleetMadeHostileToFaction(CampaignFleetAPI fleet, FactionAPI faction) {
1502 return isFleetMadeHostileToFaction(fleet, faction.getId());
1503 }
1504 public static boolean isFleetMadeHostileToFaction(CampaignFleetAPI fleet, String factionId) {
1505 if (Factions.PLAYER.equals(factionId) &&
1506 fleet.getMemoryWithoutUpdate().contains(MemFlags.MEMORY_KEY_MAKE_HOSTILE)) {
1507 return true;
1508 }
1509 String flag = MemFlags.MEMORY_KEY_MAKE_HOSTILE + "_" + factionId;
1510 return fleet.getMemoryWithoutUpdate().getBoolean(flag);
1511 }
1512
1513 public static void makeNotLowRepImpact(CampaignFleetAPI fleet, String reason) {
1514 setFlagWithReason(fleet.getMemoryWithoutUpdate(), MemFlags.MEMORY_KEY_LOW_REP_IMPACT, reason, false, -1);
1515 setFlagWithReason(fleet.getMemoryWithoutUpdate(), MemFlags.MEMORY_KEY_NO_REP_IMPACT, reason, false, -1);
1516 }
1517
1518
1519 public static String getAgoStringForTimestamp(long timestamp) {
1520 CampaignClockAPI clock = Global.getSector().getClock();
1521 float days = clock.getElapsedDaysSince(timestamp);
1522
1523 if (days <= 1f) {
1524 return "Today";
1525 } else if (days <= 6f) {
1526 return (int)Math.ceil(days) + " days ago";
1527 } else if (days <= 7) {
1528 return "1 week ago";
1529 } else if (days <= 14) {
1530 return "2 weeks ago";
1531 } else if (days <= 21) {
1532 return "3 weeks ago";
1533 } else if (days <= 30 + 14) {
1534 return "1 month ago";
1535 } else if (days < 30 * 2 + 14) {
1536 return "2 months ago";
1537 } else if (days < 30 * 3 + 14) {
1538 return "3 months ago";
1539 } else {
1540 return "Over 3 months ago";
1541 }
1542 }
1543
1544 public static String getDetailedAgoString(long timestamp) {
1545 CampaignClockAPI clock = Global.getSector().getClock();
1546 int days = (int) clock.getElapsedDaysSince(timestamp);
1547
1548 if (days == 0) {
1549 return "0 days ago";
1550 } else if (days == 1) {
1551 return "1 day ago";
1552 } else if (days <= 6) {
1553 return (int)Math.ceil(days) + " days ago";
1554 } else if (days <= 7) {
1555 return "1 week ago";
1556 } else if (days <= 14) {
1557 return "2 weeks ago";
1558 } else if (days <= 21) {
1559 return "3 weeks ago";
1560 } else {
1561 int months = days / 30;
1562 if (months <= 12) {
1563 if (months <= 1) {
1564 return "1 month ago";
1565 } else {
1566 return "" + months + " months ago";
1567 }
1568 } else {
1569 int years = months / 12;
1570 if (years <= 1) {
1571 return "1 cycle ago";
1572 } else {
1573 return "" + years + " cycles ago";
1574 }
1575 }
1576 }
1577 }
1578
1579 public static String getAtLeastStringForDays(int days) {
1580 if (days <= 1f) {
1581 return "at least a day";
1582 } else if (days <= 6f) {
1583 return "at least a few days";
1584 } else if (days <= 7 + 6) {
1585 return "at least a week";
1586 } else if (days <= 14 + 6) {
1587 return "at least two weeks";
1588 } else if (days <= 21 + 8) {
1589 return "at least three weeks";
1590 } else if (days <= 30 + 29) {
1591 return "at least a month";
1592 } else if (days < 30 * 2 + 29) {
1593 return "at least two months";
1594 } else if (days < 30 * 3 + 29) {
1595 return "at least three months";
1596 } else {
1597 return "many months";
1598 }
1599 }
1600
1601 public static String getStringForDays(int days) {
1602 if (days <= 1f) {
1603 return "a day";
1604 } else if (days <= 6f) {
1605 return "a few days";
1606 } else if (days <= 7 + 6) {
1607 return "a week";
1608 } else if (days <= 14 + 6) {
1609 return "two weeks";
1610 } else if (days <= 21 + 8) {
1611 return "three weeks";
1612 } else if (days <= 30 + 29) {
1613 return "a month";
1614 } else if (days < 30 * 2 + 29) {
1615 return "two months";
1616 } else if (days < 30 * 3 + 29) {
1617 return "three months";
1618 } else {
1619 return "many months";
1620 }
1621 }
1622
1623// public static String getTimeStringForDays(int days) {
1624// if (days <= 1f) {
1625// return "1 day";
1626// } else if (days <= 6f) {
1627// return "at least a few days";
1628// } else if (days <= 7) {
1629// return "at least a week";
1630// } else if (days <= 14) {
1631// return "at least 2 weeks";
1632// } else if (days <= 21) {
1633// return "at least 3 weeks";
1634// } else if (days <= 30 + 14) {
1635// return "at least a month";
1636// } else if (days < 30 * 2 + 14) {
1637// return "at least 2 months";
1638// } else if (days < 30 * 3 + 14) {
1639// return "at least 3 months";
1640// } else {
1641// return "many months";
1642// }
1643// }
1644
1645 public static float getBurnLevelForSpeed(float speed) {
1647 if (speed < 0 || speed <= Global.getSettings().getFloat("minTravelSpeed") + 1f) speed = 0;
1648 float currBurn = speed / Global.getSettings().getSpeedPerBurnLevel();
1649 // 1/1/20: changed to not add +0.01f; not sure why it was there but could cause issues w/ isSlowMoving(), maybe?
1650 //return Math.round(currBurn + 0.01f);
1651 return Math.round(currBurn);
1652 }
1653
1654 public static float getFractionalBurnLevelForSpeed(float speed) {
1655// System.out.println("Speed: " + Global.getSector().getPlayerFleet().getVelocity().length());
1656// System.out.println("Max: " + Global.getSector().getPlayerFleet().getTravelSpeed());
1658 if (speed < 0 || speed <= Global.getSettings().getFloat("minTravelSpeed") + 1f) speed = 0;
1659 float currBurn = speed / Global.getSettings().getSpeedPerBurnLevel();
1660 //System.out.println("ADFSDF: " +Math.round(currBurn));
1661 return currBurn;
1662 }
1663
1664 public static float getSpeedForBurnLevel(float burnLevel) {
1665 float speed = Global.getSettings().getBaseTravelSpeed() + burnLevel * Global.getSettings().getSpeedPerBurnLevel();
1666 return speed;
1667 }
1668
1669 public static float getFuelPerDay(CampaignFleetAPI fleet, float burnLevel) {
1670 float speed = Global.getSettings().getBaseTravelSpeed() + Global.getSettings().getSpeedPerBurnLevel() * burnLevel;
1671 return getFuelPerDayAtSpeed(fleet, speed);
1672 }
1673
1674 public static float getFuelPerDayAtSpeed(CampaignFleetAPI fleet, float speed) {
1675 float perLY = fleet.getLogistics().getFuelCostPerLightYear();
1676
1677 // this is potentially evil - currently, the velocity is in units per SECOND, not per day
1678 speed = speed * Global.getSector().getClock().getSecondsPerDay();
1679 // now, speed is in units per day
1680
1681 speed = speed / Global.getSettings().getUnitsPerLightYear();
1682 // ly/day now
1683
1684
1685 return speed * perLY;
1686 }
1687
1688 public static float getLYPerDayAtBurn(CampaignFleetAPI fleet, float burnLevel) {
1689 float speed = Global.getSettings().getBaseTravelSpeed() + Global.getSettings().getSpeedPerBurnLevel() * burnLevel;
1690 return getLYPerDayAtSpeed(fleet, speed);
1691 }
1692 public static float getLYPerDayAtSpeed(CampaignFleetAPI fleet, float speed) {
1693 // this is potentially evil - currently, the velocity is in units per SECOND, not per day
1694 speed = speed * Global.getSector().getClock().getSecondsPerDay();
1695 // now, speed is in units per day
1696 speed = speed / Global.getSettings().getUnitsPerLightYear();
1697 // ly/day now
1698
1699 return speed * 1f; // 1f days
1700 }
1701
1702 private static Vector3f temp4 = new Vector3f();
1703 public static Color zeroColor = new Color(0,0,0,0);
1704 public static float getDistance(Vector3f v1, Vector3f v2)
1705 {
1706 return Vector3f.sub(v1, v2, temp4).length();
1707 }
1708
1709 public static float getAngleDiff(float from, float to) {
1710 float diff = normalizeAngle(from - to);
1711 if (diff > 180) return 360 - diff;
1712 else return diff;
1713 }
1714
1715 public static boolean isInArc(float direction, float arc, Vector2f from, Vector2f to) {
1716 direction = normalizeAngle(direction);
1717 if (arc >= 360) return true;
1718 if (direction < 0) direction = 360 + direction;
1719 Vector2f towardsTo = new Vector2f(to.x - from.x, to.y - from.y);
1720 if (towardsTo.lengthSquared() == 0) return false;
1721 float dir = Misc.getAngleInDegrees(towardsTo);
1722 if (dir < 0) dir = 360 + dir;
1723 float arcFrom = direction - arc/2f;
1724 if (arcFrom < 0) arcFrom = 360 + arcFrom;
1725 if (arcFrom > 360) arcFrom -= 360;
1726 float arcTo = direction + arc/2f;
1727 if (arcTo < 0) arcTo = 360 + arcTo;
1728 if (arcTo > 360) arcTo -= 360;
1729
1730 if (dir >= arcFrom && dir <= arcTo) return true;
1731 if (dir >= arcFrom && arcFrom > arcTo) return true;
1732 if (dir <= arcTo && arcFrom > arcTo) return true;
1733 return false;
1734 }
1735
1736 public static boolean isInArc(float direction, float arc, float test) {
1738
1739 if (arc >= 360) return true;
1740 if (direction < 0) direction = 360 + direction;
1741 float dir = test;
1742 if (dir < 0) dir = 360 + dir;
1743 float arcFrom = direction - arc/2f;
1744 if (arcFrom < 0) arcFrom = 360 + arcFrom;
1745 if (arcFrom > 360) arcFrom -= 360;
1746 float arcTo = direction + arc/2f;
1747 if (arcTo < 0) arcTo = 360 + arcTo;
1748 if (arcTo > 360) arcTo -= 360;
1749
1750 if (dir >= arcFrom && dir <= arcTo) return true;
1751 if (dir >= arcFrom && arcFrom > arcTo) return true;
1752 if (dir <= arcTo && arcFrom > arcTo) return true;
1753 return false;
1754 }
1755
1756
1757 public static SectorEntityToken addNebulaFromPNG(String image, float centerX, float centerY, LocationAPI location,
1758 String category, String key, int tilesWide, int tilesHigh, StarAge age) {
1759 return addNebulaFromPNG(image, centerX, centerY, location, category, key, tilesWide, tilesHigh, Terrain.NEBULA, age);
1760 }
1761
1762
1763 public static SectorEntityToken addNebulaFromPNG(String image, float centerX, float centerY, LocationAPI location,
1764 String category, String key, int tilesWide, int tilesHigh,
1765 String terrainType, StarAge age) {
1766 try {
1767 BufferedImage img = null;
1768 //img = ImageIO.read(new File("../starfarer.res/res/data/campaign/terrain/nebula_test.png"));
1770
1771 int chunkSize = 10000;
1772 int w = img.getWidth();
1773 int h = img.getHeight();
1774 Raster data = img.getData();
1775 for (int i = 0; i < w; i += chunkSize) {
1776 for (int j = 0; j < h; j += chunkSize) {
1777
1778 int chunkWidth = chunkSize;
1779 if (i + chunkSize > w) chunkWidth = w - i;
1780 int chunkHeight = chunkSize;
1781 if (j + chunkSize > h) chunkHeight = h - i;
1782
1783// boolean hasAny = false;
1784// for (int x = i; x < i + chunkWidth; x++) {
1785// for (int y = j; y < j + chunkHeight; y++) {
1786// int [] pixel = data.getPixel(i, h - j - 1, (int []) null);
1787// int total = pixel[0] + pixel[1] + pixel[2];
1788// if (total > 0) {
1789// hasAny = true;
1790// break;
1791// }
1792// }
1793// }
1794// if (!hasAny) continue;
1795
1796 StringBuilder string = new StringBuilder();
1797 for (int y = j + chunkHeight - 1; y >= j; y--) {
1798 for (int x = i; x < i + chunkWidth; x++) {
1799 int [] pixel = data.getPixel(x, h - y - 1, (int []) null);
1800 int total = pixel[0] + pixel[1] + pixel[2];
1801 if (total > 0) {
1802 string.append("x");
1803 } else {
1804 string.append(" ");
1805 }
1806 }
1807 }
1808
1809 float tileSize = NebulaTerrainPlugin.TILE_SIZE;
1810 float x = centerX - tileSize * (float) w / 2f + (float) i * tileSize + chunkWidth / 2f * tileSize;
1811 float y = centerY - tileSize * (float) h / 2f + (float) j * tileSize + chunkHeight / 2f * tileSize;
1812
1813 SectorEntityToken curr = location.addTerrain(terrainType, new TileParams(string.toString(),
1815 category, key, tilesWide, tilesHigh, null));
1816 curr.getLocation().set(x, y);
1817
1818 if (location instanceof StarSystemAPI) {
1819 StarSystemAPI system = (StarSystemAPI) location;
1820
1821 system.setAge(age);
1822 system.setHasSystemwideNebula(true);
1823 }
1824
1825 return curr;
1826 }
1827 }
1828 return null;
1829 } catch (IOException e) {
1830 throw new RuntimeException(e);
1831 }
1832 }
1833
1834
1835 public static void renderQuad(float x, float y, float width, float height, Color color, float alphaMult) {
1836 GL11.glColor4ub((byte)color.getRed(),
1837 (byte)color.getGreen(),
1838 (byte)color.getBlue(),
1839 (byte)((float)color.getAlpha() * alphaMult));
1840
1841 GL11.glBegin(GL11.GL_QUADS);
1842 {
1843 GL11.glVertex2f(x, y);
1844 GL11.glVertex2f(x, y + height);
1845 GL11.glVertex2f(x + width, y + height);
1846 GL11.glVertex2f(x + width, y);
1847 }
1848 GL11.glEnd();
1849 }
1850
1858 public static float distanceFromLineToPoint(Vector2f p1, Vector2f p2, Vector2f p3) {
1859 float u = (p3.x - p1.x) * (p2.x - p1.x) + (p3.y - p1.y) * (p2.y - p1.y);
1860 float denom = Vector2f.sub(p2, p1, new Vector2f()).length();
1861 denom *= denom;
1862 //if (denom == 0) return 0;
1863 u /= denom;
1864 Vector2f i = new Vector2f();
1865 i.x = p1.x + u * (p2.x - p1.x);
1866 i.y = p1.y + u * (p2.y - p1.y);
1867 return Vector2f.sub(i, p3, new Vector2f()).length();
1868 }
1869
1871 float u = (p3.x - p1.x) * (p2.x - p1.x) + (p3.y - p1.y) * (p2.y - p1.y);
1872 float denom = Vector2f.sub(p2, p1, new Vector2f()).length();
1873 denom *= denom;
1874 //if (denom == 0) return 0;
1875 u /= denom;
1876 Vector2f i = new Vector2f();
1877 i.x = p1.x + u * (p2.x - p1.x);
1878 i.y = p1.y + u * (p2.y - p1.y);
1879 return i;
1880 }
1881
1883 float u = (p3.x - p1.x) * (p2.x - p1.x) + (p3.y - p1.y) * (p2.y - p1.y);
1884 float denom = Vector2f.sub(p2, p1, new Vector2f()).length();
1885 denom *= denom;
1886
1887 u /= denom;
1888
1889 // if closest point on line is outside the segment, clamp to on the segment
1890 if (u < 0) u = 0;
1891 if (u > 1) u = 1;
1892
1893 Vector2f i = new Vector2f();
1894 i.x = p1.x + u * (p2.x - p1.x);
1895 i.y = p1.y + u * (p2.y - p1.y);
1896 return i;
1897 }
1898
1899 public static boolean isPointInBounds(Vector2f p1, List<Vector2f> bounds) {
1900 Vector2f p2 = new Vector2f(p1);
1901 p2.x += 10000;
1902 int count = 0;
1903 for (int i = 0; i < 2; i++) {
1904 for (int j = 0; j < bounds.size() - 1; j++) {
1905 Vector2f s1 = bounds.get(j);
1906 Vector2f s2 = bounds.get(j + 1);
1907 Vector2f p = intersectSegments(p1, p2, s1, s2);
1908 if (p != null) {
1909 if (Math.abs(p.x - s1.x) < 0.001f &&
1910 Math.abs(p.y - s1.y) < 0.001f) {
1911 continue; // JUST the first point, (p1, p2]
1912 }
1913 if (areSegmentsCoincident(p1, p2, s1, s2)) {
1914 continue;
1915 }
1916 count++;
1917 }
1918 }
1919 if (i == 0 && count % 2 == 1) {
1920 count = 0;
1921 p2.y += 100;
1922 } else {
1923 break;
1924 }
1925 }
1926 return count % 2 == 1;
1927 }
1928
1930 float denom = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y);
1931 float numUa = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x);
1932 float numUb = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x);
1933
1934 if (denom == 0 && !(numUa == 0 && numUb == 0)) { // parallel, not coincident
1935 return null;
1936 }
1937
1938 if (denom == 0 && numUa == 0 && numUb == 0) { // coincident
1939 float minX, minY, maxX, maxY;
1940 if (a1.x < a2.x) {
1941 minX = a1.x;
1942 maxX = a2.x;
1943 } else {
1944 minX = a2.x;
1945 maxX = a1.x;
1946 }
1947 if (a1.y < a2.y) {
1948 minY = a1.y;
1949 maxY = a2.y;
1950 } else {
1951 minY = a2.y;
1952 maxY = a1.y;
1953 }
1954 // if either one of the endpoints in segment b is between the points in segment a,
1955 // return that endpoint as the intersection. Otherwise, no intersection.
1956 if (b1.x >= minX && b1.x <= maxX && b1.y >= minY && b1.y <= maxY) {
1957 return new Vector2f(b1);
1958 } else if (b2.x >= minX && b2.x <= maxX && b2.y >= minY && b2.y <= maxY) {
1959 return new Vector2f(b2);
1960 } else {
1961 return null;
1962 }
1963 }
1964
1965 float Ua = numUa / denom;
1966 float Ub = numUb / denom;
1967 if (Ua >=0 && Ua <= 1 && Ub >= 0 && Ub <= 1) { // segments intersect
1968 Vector2f result = new Vector2f();
1969// if (Ua <= 0.001f) {
1970// result.x = a1.x;
1971// result.y = a1.y;
1972// } else if (Ua >= 0.999f) {
1973// result.x = a2.x;
1974// result.y = a2.y;
1975// } else {
1976 result.x = a1.x + Ua * (a2.x - a1.x);
1977 result.y = a1.y + Ua * (a2.y - a1.y);
1978// }
1979 return result;
1980 } else { // lines intersect, but segments do not
1981 return null;
1982 }
1983
1984 }
1985
1986
1988 float denom = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y);
1989 float numUa = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x);
1990 float numUb = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x);
1991
1992 if (denom == 0 && !(numUa == 0 && numUb == 0)) { // parallel, not coincident
1993 return null;
1994 }
1995
1996 if (denom == 0 && numUa == 0 && numUb == 0) { // coincident
1997 return new Vector2f(a1);
1998 }
1999
2000 float Ua = numUa / denom;
2001 float Ub = numUb / denom;
2002 Vector2f result = new Vector2f();
2003 result.x = a1.x + Ua * (a2.x - a1.x);
2004 result.y = a1.y + Ua * (a2.y - a1.y);
2005 return result;
2006 }
2007
2008
2009
2010
2019 public static Vector2f intersectSegmentAndCircle(Vector2f p1, Vector2f p2, Vector2f p3, float r) {
2020
2021 float uNom = (p3.x - p1.x) * (p2.x - p1.x) + (p3.y - p1.y) * (p2.y - p1.y);
2022 float uDenom = (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y);
2023
2024 Vector2f closest = new Vector2f();
2025 if (uDenom == 0) { // p1 and p2 are coincident
2026 closest.set(p1);
2027 } else {
2028 float u = uNom / uDenom;
2029 closest.x = p1.x + u * (p2.x - p1.x);
2030 closest.y = p1.y + u * (p2.y - p1.y);
2031 }
2032
2033 float distSq = (closest.x - p3.x) * (closest.x - p3.x) + (closest.y - p3.y) * (closest.y - p3.y);
2034 if (distSq > r * r) { // closest point is farther than radius
2035 //System.out.println("shorted");
2036 return null;
2037 } else if (uDenom == 0) {
2038 return closest; // in the case where p1==p2 and they're inside the circle, return p1.
2039 }
2040
2041 float a = (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y);
2042 float b = 2f * ( (p2.x - p1.x) * (p1.x - p3.x) + (p2.y - p1.y) *
2043 (p1.y - p3.y) );
2044 float c = p3.x * p3.x + p3.y * p3.y + p1.x * p1.x + p1.y * p1.y - 2f
2045 * (p3.x * p1.x + p3.y * p1.y) - r * r;
2046
2047 float bb4ac = b * b - 4f * a * c;
2048
2049 if (bb4ac < 0) return null;
2050
2051 float mu1 = (-b + (float) Math.sqrt(bb4ac)) / (2 * a);
2052 float mu2 = (-b - (float) Math.sqrt(bb4ac)) / (2 * a);
2053
2054 float minMu = mu1;
2055 if ((mu2 < minMu && mu2 >= 0) || minMu < 0) minMu = mu2;
2056
2057 if (minMu < 0 || minMu > 1) {
2058 float p2DistSq = (p2.x - p3.x) * (p2.x - p3.x) + (p2.y - p3.y) * (p2.y - p3.y);
2059 if (p2DistSq <= r * r) return p2;
2060 else return null;
2061 }
2062 //System.out.println("mu1: " + mu1 + ", mu2: " + mu2);
2063
2064 Vector2f result = new Vector2f();
2065 result.x = p1.x + minMu * (p2.x - p1.x);
2066 result.y = p1.y + minMu * (p2.y - p1.y);
2067
2068 return result;
2069 }
2070
2071
2073 float denom = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y);
2074 float numUa = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x);
2075 float numUb = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) *(a1.x - b1.x);
2076
2077 if (denom == 0 && !(numUa == 0 && numUb == 0)) { // parallel, not coincident
2078 return false;
2079 }
2080
2081 if (denom == 0 && numUa == 0 && numUb == 0) { // coincident
2082 return true;
2083 }
2084
2085 return false;
2086 }
2087
2088 public static Vector2f getPerp(Vector2f v) {
2089 Vector2f perp = new Vector2f();
2090 perp.x = v.y;
2091 perp.y = -v.x;
2092 return perp;
2093 }
2094
2095 public static float getClosestTurnDirection(float facing, float desired) {
2097 if (diff < 0) diff += 360;
2098
2099 if (diff == 0 || diff == 360f) {
2100 return 0f;
2101 } else if (diff > 180) {
2102 return -1f;
2103 } else {
2104 return 1f;
2105 }
2106// facing = normalizeAngle(facing);
2107// desired = normalizeAngle(desired);
2108// if (facing == desired) return 0;
2109//
2110// Vector2f desiredVec = getUnitVectorAtDegreeAngle(desired);
2111// //if (desiredVec.lengthSquared() == 0) return 0;
2112// Vector2f more = getUnitVectorAtDegreeAngle(facing + 1);
2113// Vector2f less = getUnitVectorAtDegreeAngle(facing - 1);
2114//
2115// float fromMore = Vector2f.angle(more, desiredVec);
2116// float fromLess = Vector2f.angle(less, desiredVec);
2117// if (fromMore > fromLess) return -1f;
2118// return 1f;
2119 }
2120
2121 public static float getClosestTurnDirection(float facing, Vector2f from, Vector2f to) {
2122 float diff = Misc.normalizeAngle(getAngleInDegrees(from, to)) - Misc.normalizeAngle(facing);
2123 if (diff < 0) diff += 360;
2124
2125 if (diff == 0 || diff == 360f) {
2126 return 0f;
2127 } else if (diff > 180) {
2128 return -1f;
2129 } else {
2130 return 1f;
2131 }
2132// Vector2f desired = getDiff(to, from);
2133// if (desired.lengthSquared() == 0) return 0;
2134// //float angle = getAngleInDegrees(desired);
2135// Vector2f more = getUnitVectorAtDegreeAngle(facing + 1);
2136// Vector2f less = getUnitVectorAtDegreeAngle(facing - 1);
2137//
2138// float fromMore = Vector2f.angle(more, desired);
2139// float fromLess = Vector2f.angle(less, desired);
2140// if (fromMore == fromLess) return 0f;
2141// if (fromMore > fromLess) return -1f;
2142// return 1f;
2143 }
2144
2145 public static float getClosestTurnDirection(Vector2f one, Vector2f two) {
2146 return getClosestTurnDirection(getAngleInDegrees(one), new Vector2f(0, 0), two);
2147 }
2148
2150 {
2151 //Vector2f result = new Vector2f();
2152 return Vector2f.sub(v1, v2, new Vector2f());
2153 }
2154
2155 public static MarketAPI getSourceMarket(CampaignFleetAPI fleet) {
2156 String id = fleet.getMemoryWithoutUpdate().getString(MemFlags.MEMORY_KEY_SOURCE_MARKET);
2157 if (id == null) return null;
2158 MarketAPI market = Global.getSector().getEconomy().getMarket(id);
2159 return market;
2160 }
2161
2162 public static SectorEntityToken getSourceEntity(CampaignFleetAPI fleet) {
2163 String id = fleet.getMemoryWithoutUpdate().getString(MemFlags.MEMORY_KEY_SOURCE_MARKET);
2164 if (id == null) return null;
2165 MarketAPI market = Global.getSector().getEconomy().getMarket(id);
2166 if (market != null && market.getPrimaryEntity() != null) {
2167 return market.getPrimaryEntity();
2168 }
2169 SectorEntityToken entity = Global.getSector().getEntityById(id);
2170 return entity;
2171 }
2172
2173 public static float getSpawnChanceMult(Vector2f locInHyper) {
2174 if (Global.getSector().getPlayerFleet() == null) return 1f;
2175
2176 float min = Global.getSettings().getFloat("minFleetSpawnChanceMult");
2177 float range = Global.getSettings().getFloat("minFleetSpawnChanceRangeLY");
2178
2179 Vector2f playerLoc = Global.getSector().getPlayerFleet().getLocationInHyperspace();
2180 float distLY = getDistanceLY(playerLoc, locInHyper);
2181
2182 float f = (1f - Math.min(1f, distLY/range));
2183 return min + (1f - min) * f * f;
2184 }
2185
2186 public static Vector2f pickHyperLocationNotNearPlayer(Vector2f from, float minDist) {
2187 CampaignFleetAPI player = Global.getSector().getPlayerFleet();
2188 float r = 2000f;
2189 if (player == null || !player.isInHyperspace()) {
2190 return getPointWithinRadius(from, r);
2191 }
2192 float dist = Misc.getDistance(player.getLocation(), from);
2193 if (dist > minDist + r) {
2194 return getPointWithinRadius(from, r);
2195 }
2196 float dir = Misc.getAngleInDegrees(player.getLocation(), from);
2198 v.scale(minDist + 2000 - dist);
2199 Vector2f.add(v, from, v);
2200 return getPointWithinRadius(v, r);
2201 }
2202
2203 public static Vector2f pickLocationNotNearPlayer(LocationAPI where, Vector2f from, float minDist) {
2204 CampaignFleetAPI player = Global.getSector().getPlayerFleet();
2205 float r = 2000f;
2206 if (player == null || player.getContainingLocation() != where) {
2207 return getPointWithinRadius(from, r);
2208 }
2209 float dist = Misc.getDistance(player.getLocation(), from);
2210 if (dist > minDist + r) {
2211 return getPointWithinRadius(from, r);
2212 }
2213 float dir = Misc.getAngleInDegrees(player.getLocation(), from);
2215 v.scale(minDist + 2000 - dist);
2216 Vector2f.add(v, from, v);
2217 return getPointWithinRadius(v, r);
2218 }
2219
2220 public static float getBattleJoinRange() {
2221 return Global.getSettings().getFloat("battleJoinRange");
2222 }
2223
2224 public static void wiggle(Vector2f v, float max) {
2225 v.x += (max * 2f * ((float) Math.random() - 0.5f));
2226 v.y += (max * 2f * ((float) Math.random() - 0.5f));
2227 if (v.length() == 0 || v.lengthSquared() == 0) {
2228 v.x += max * 0.25f;
2229 }
2230 }
2231
2232
2233 public static boolean isPlayerOrCombinedPlayerPrimary(CampaignFleetAPI fleet) {
2234 if (fleet.isPlayerFleet()) return true;
2235
2236 if (fleet.getBattle() != null && fleet.getBattle().isOnPlayerSide(fleet) &&
2237 fleet.getBattle().isPlayerPrimary()) {
2238 return true;
2239 }
2240 return false;
2241 }
2242
2243 public static boolean isPlayerOrCombinedContainingPlayer(CampaignFleetAPI fleet) {
2244 if (fleet.isPlayerFleet()) return true;
2245
2246 if (fleet.getBattle() != null && fleet.getBattle().isOnPlayerSide(fleet)) {
2247 return true;
2248 }
2249 return false;
2250 }
2251
2252 public static final String ASTEROID_SOURCE = "misc_astrdSource";
2253
2254 public static AsteroidSource getAsteroidSource(SectorEntityToken asteroid) {
2255 if (asteroid.getCustomData().containsKey(ASTEROID_SOURCE)) {
2256 return (AsteroidSource) asteroid.getCustomData().get(ASTEROID_SOURCE);
2257 }
2258 return null;
2259 }
2260 public static void setAsteroidSource(SectorEntityToken asteroid, AsteroidSource source) {
2261 asteroid.getCustomData().put(ASTEROID_SOURCE, source);
2262 }
2263 public static void clearAsteroidSource(SectorEntityToken asteroid) {
2264 asteroid.getCustomData().remove(ASTEROID_SOURCE);
2265 }
2266
2267 public static boolean isFastStart() {
2268 return Global.getSector().getMemoryWithoutUpdate().getBoolean("$fastStart");
2269 }
2270 public static boolean isFastStartExplorer() {
2271 return Global.getSector().getMemoryWithoutUpdate().getBoolean("$fastStartExplorer");
2272 }
2273 public static boolean isFastStartMerc() {
2274 return Global.getSector().getMemoryWithoutUpdate().getBoolean("$fastStartMerc");
2275 }
2276
2277 public static boolean isEasy() {
2278 return Difficulties.EASY.equals(Global.getSector().getDifficulty());
2279 }
2280
2281 public static boolean isNormal() {
2282 return Difficulties.NORMAL.equals(Global.getSector().getDifficulty());
2283 }
2284
2285
2286// public static void main(String[] args) {
2287// System.out.println("TEST");
2288// String s = "te\\\"st==$global.one $player.a $>=$sdfdsf\"++++dfdsf0---\"\"quoted \\\"=+!<>param\" one two 1234 1 2342 24 \t\t234234";
2289// //String s = "menuState sdfsdf sdfsdf \"\"= \"main \\\" 1234\"";
2290// //s = "!sdfsdAKJKFHD";
2291// List<Token> result = tokenize(s);
2292// for (Token str : result) {
2293// System.out.println(str);
2294// }
2295 //addNebulaFromPNG();
2296// String s = "ffff0000";
2297// System.out.println(Long.parseLong(s, 16));
2298 //System.out.println(Long.parseLong("aa0F245C", 16));
2299// }
2300
2301 public static CampaignTerrainAPI getHyperspaceTerrain() {
2302 for (CampaignTerrainAPI curr : Global.getSector().getHyperspace().getTerrainCopy()) {
2303 if (curr.getPlugin() instanceof HyperspaceTerrainPlugin) {
2304 return curr;
2305 }
2306 }
2307 return null;
2308 }
2309 public static HyperspaceTerrainPlugin getHyperspaceTerrainPlugin() {
2310 CampaignTerrainAPI hyper = getHyperspaceTerrain();
2311 if (hyper != null) {
2312 return (HyperspaceTerrainPlugin) hyper.getPlugin();
2313 }
2314 return null;
2315 }
2316
2317 public static boolean isInAbyss(Vector2f loc) {
2318 return getAbyssalDepth(loc) > 0;
2319 }
2320 public static boolean isInAbyss(SectorEntityToken entity) {
2321 return getAbyssalDepth(entity) > 0;
2322 }
2323 public static float getAbyssalDepth(Vector2f loc) {
2324 HyperspaceTerrainPlugin plugin = getHyperspaceTerrainPlugin();
2325 if (plugin == null) return 0f;
2326 return plugin.getAbyssalDepth(loc);
2327 }
2328
2330 HyperspaceTerrainPlugin plugin = getHyperspaceTerrainPlugin();
2331 if (plugin == null) return new ArrayList<StarSystemAPI>();
2332 return plugin.getAbyssalSystems();
2333 }
2334
2335 public static float getAbyssalDepthOfPlayer() {
2336 return getAbyssalDepth(Global.getSector().getPlayerFleet());
2337 }
2338 public static float getAbyssalDepth(SectorEntityToken entity) {
2339 if (entity == null || !entity.isInHyperspace()) return 0f;
2340 return getAbyssalDepth(entity.getLocation());
2341 }
2342
2343 public static boolean isInsideBlackHole(CampaignFleetAPI fleet, boolean includeEventHorizon) {
2344 for (PlanetAPI planet : fleet.getContainingLocation().getPlanets()) {
2345 if (planet.isStar() && planet.getSpec() != null && planet.getSpec().isBlackHole()) {
2346 float dist = Misc.getDistance(fleet, planet);
2347 if (dist < planet.getRadius() + fleet.getRadius()) {
2348 return true;
2349 } else if (includeEventHorizon) {
2350 StarCoronaTerrainPlugin corona = getCoronaFor(planet);
2351 if (corona != null && corona.containsEntity(fleet)) {
2352 return true;
2353 }
2354 }
2355 }
2356 }
2357 return false;
2358 }
2359
2360
2361 public static StarCoronaTerrainPlugin getCoronaFor(PlanetAPI star) {
2362 if (star == null) return null;
2363
2364 for (CampaignTerrainAPI curr : star.getContainingLocation().getTerrainCopy()) {
2365 if (curr.getPlugin() instanceof StarCoronaTerrainPlugin) {
2366 StarCoronaTerrainPlugin corona = (StarCoronaTerrainPlugin) curr.getPlugin();
2367 if (corona.getRelatedEntity() == star) return corona;
2368 }
2369 }
2370 return null;
2371 }
2372
2373 public static MagneticFieldTerrainPlugin getMagneticFieldFor(PlanetAPI planet) {
2374 if (planet == null || planet.getContainingLocation() == null) return null;
2375
2376 for (CampaignTerrainAPI curr : planet.getContainingLocation().getTerrainCopy()) {
2377 if (curr.getPlugin() instanceof MagneticFieldTerrainPlugin) {
2378 MagneticFieldTerrainPlugin field = (MagneticFieldTerrainPlugin) curr.getPlugin();
2379 if (field.getRelatedEntity() == planet) return field;
2380 }
2381 }
2382 return null;
2383 }
2384
2385 public static PulsarBeamTerrainPlugin getPulsarFor(PlanetAPI star) {
2386 for (CampaignTerrainAPI curr : star.getContainingLocation().getTerrainCopy()) {
2387 if (curr.getPlugin() instanceof PulsarBeamTerrainPlugin) {
2388 PulsarBeamTerrainPlugin corona = (PulsarBeamTerrainPlugin) curr.getPlugin();
2389 if (corona.getRelatedEntity() == star) return corona;
2390 }
2391 }
2392 return null;
2393 }
2394
2395 public static boolean hasPulsar(StarSystemAPI system) {
2396 return system != null && system.hasPulsar();
2397// if (system.getStar() != null && system.getStar().getSpec().isPulsar()) return true;
2398// if (system.getSecondary() != null && system.getSecondary().getSpec().isPulsar()) return true;
2399// if (system.getTertiary() != null && system.getTertiary().getSpec().isPulsar()) return true;
2400// return false;
2401 }
2402
2404 String str = Global.getSector().getCharacterData().getMemoryWithoutUpdate().getString(MemFlags.FCM_FACTION);
2405 return str;
2406 }
2407
2408 public static FactionAPI getCommissionFaction() {
2410 if (id != null) {
2411 return Global.getSector().getFaction(id);
2412 }
2413 return null;
2414 }
2415
2416 public static FactionCommissionIntel getCommissionIntel() {
2417 Object obj = Global.getSector().getCharacterData().getMemoryWithoutUpdate().get(MemFlags.FCM_EVENT);
2418 if (obj instanceof FactionCommissionIntel) {
2419 return (FactionCommissionIntel) obj;
2420 }
2421 return null;
2422 }
2423
2424
2425 public static boolean caresAboutPlayerTransponder(CampaignFleetAPI fleet) {
2426// if (fleet.isInCurrentLocation()) {
2427// System.out.println("efwefew");
2428// }
2429 if (fleet.getFaction().isPlayerFaction()) return false;
2430
2431 boolean caresAboutTransponder = true;
2432 if (fleet.getFaction().getCustomBoolean(Factions.CUSTOM_ALLOWS_TRANSPONDER_OFF_TRADE)) {
2433 caresAboutTransponder = false;
2434 }
2435 MarketAPI source = Misc.getSourceMarket(fleet);
2436 if (source != null && source.hasCondition(Conditions.FREE_PORT)) {
2437 caresAboutTransponder = false;
2438 }
2439
2440 if (fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_PATROL_ALLOW_TOFF)) {
2441 caresAboutTransponder = false;
2442 }
2443
2444 // prevents "infinitely chase player, re-interact, and don't demand anything or act hostile" scenario
2445 if (fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_MAKE_NON_HOSTILE)) {
2446 caresAboutTransponder = false;
2447 }
2448
2449 if (caresAboutTransponder && source != null && source.getPrimaryEntity() != null) {
2450 final CampaignFleetAPI player = Global.getSector().getPlayerFleet();
2451 if (player == null || player.isInHyperspace()) {
2452 caresAboutTransponder = false;
2453 } else {
2454 caresAboutTransponder = source.getPrimaryEntity().getContainingLocation() == player.getContainingLocation();
2455// boolean alreadyTargetingPlayer = false;
2456// if (fleet.getAI() instanceof ModularFleetAIAPI) {
2457// ModularFleetAIAPI ai = (ModularFleetAIAPI) fleet.getAI();
2458// SectorEntityToken target = ai.getTacticalModule().getTarget();
2459// alreadyTargetingPlayer = target == player;
2460// }
2461// if (!alreadyTargetingPlayer) {
2464// float max = Global.getSettings().getFloat("maxTransponderRequiredRangeAroundMarketSystem");
2465// float dist = getDistanceLY(player.getLocationInHyperspace(), source.getLocationInHyperspace());
2466// if (dist > max) {
2467// caresAboutTransponder = false;
2468// }
2469// }
2470 }
2471 }
2472
2473 return caresAboutTransponder;
2474 }
2475
2476
2477 public static interface FindShipFilter {
2478 public boolean matches(ShipAPI ship);
2479 }
2480
2481 public static ShipAPI findClosestShipEnemyOf(ShipAPI ship, Vector2f locFromForSorting, HullSize smallestToNote, float maxRange, boolean considerShipRadius) {
2483 }
2484 public static ShipAPI findClosestShipEnemyOf(ShipAPI ship, Vector2f locFromForSorting, HullSize smallestToNote, float maxRange, boolean considerShipRadius, FindShipFilter filter) {
2485 CombatEngineAPI engine = Global.getCombatEngine();
2486 List<ShipAPI> ships = engine.getShips();
2487 float minDist = Float.MAX_VALUE;
2488 ShipAPI closest = null;
2489 for (ShipAPI other : ships) {
2490 if (other.getHullSize().ordinal() < smallestToNote.ordinal()) continue;
2491 if (other.isShuttlePod()) continue;
2492 if (other.isHulk()) continue;
2493 if (ship.getOwner() != other.getOwner() && other.getOwner() != 100) {
2494 if (filter != null && !filter.matches(other)) continue;
2495
2496 float dist = getDistance(ship.getLocation(), other.getLocation());
2497 float distSort = getDistance(locFromForSorting, other.getLocation());
2498 float radSum = ship.getCollisionRadius() + other.getCollisionRadius();
2499 if (!considerShipRadius) radSum = 0;
2500 if (dist > maxRange + radSum) continue;
2501 if (distSort < minDist) {
2502 closest = other;
2503 minDist = distSort;
2504 }
2505 }
2506 }
2507 return closest;
2508 }
2509
2510
2515 String val = json.optString(key);
2516 if (val == null || val.equals("")) {
2517 if (defaultOption == null && required) {
2518 throw new RuntimeException("Key [" + key + "] is required");
2519 }
2520 return defaultOption;
2521 }
2522 try {
2523 return (T) Enum.valueOf(enumType, val);
2524 } catch (IllegalArgumentException e) {
2525 throw new RuntimeException("Key [" + key + "] has invalid value [" + val + "] in [" + json.toString() + "]");
2526 }
2527 }
2528
2529 public static Color getColor(JSONObject json, String key) throws JSONException {
2530 if (!json.has(key)) return Color.white;
2531 JSONArray arr = json.getJSONArray(key);
2532 return new Color(arr.getInt(0), arr.getInt(1), arr.getInt(2), arr.getInt(3));
2533 }
2534
2536 if (!json.has(key)) return defaultValue;
2537 JSONArray arr = json.getJSONArray(key);
2538 return new Color(arr.getInt(0), arr.getInt(1), arr.getInt(2), arr.getInt(3));
2539 }
2540
2542 if (!json.has(arrayKey)) return def;
2543 return getVector(json, arrayKey);
2544 }
2546 Vector2f v = new Vector2f();
2547 JSONArray arr = json.getJSONArray(arrayKey);
2548 v.set((float) arr.getDouble(0), (float) arr.getDouble(1));
2549 return v;
2550 }
2551
2553 Vector3f v = new Vector3f();
2554 JSONArray arr = json.getJSONArray(arrayKey);
2555 v.set((float) arr.getDouble(0), (float) arr.getDouble(1), (float) arr.getDouble(1));
2556 return v;
2557 }
2558
2560 Vector2f v = new Vector2f();
2561 JSONArray arr = json.optJSONArray(arrayKey);
2562 if (arr == null) return null;
2563 v.set((float) arr.optDouble(0), (float) arr.optDouble(1));
2564 return v;
2565 }
2566
2568 Vector3f v = new Vector3f();
2569 JSONArray arr = json.optJSONArray(arrayKey);
2570 if (arr == null) return new Vector3f();
2571 v.set((float) arr.getDouble(0), (float) arr.getDouble(1), (float) arr.getDouble(2));
2572 return v;
2573 }
2574
2575 public static Vector2f getVector(JSONObject json, String arrayKey, int index) throws JSONException {
2576 Vector2f v = new Vector2f();
2577 JSONArray arr = json.getJSONArray(arrayKey);
2578 v.set((float) arr.getDouble(index * 2 + 0), (float) arr.getDouble(index * 2 + 1));
2579 return v;
2580 }
2581
2582 public static void normalizeNoise(float[][] noise) {
2583 float minNoise = 1;
2584 float maxNoise = 0;
2585 for (int i = 0; i < noise.length; i++) {
2586 for (int j = 0; j < noise[0].length; j++) {
2587 if (noise[i][j] != -1) {
2588 if (noise[i][j] > maxNoise)
2589 maxNoise = noise[i][j];
2590 if (noise[i][j] < minNoise)
2591 minNoise = noise[i][j];
2592 }
2593 }
2594 }
2595
2596 if (minNoise >= maxNoise) return;
2597
2598 float range = maxNoise - minNoise;
2599
2600 for (int i = 0; i < noise.length; i++) {
2601 for (int j = 0; j < noise[0].length; j++) {
2602 if (noise[i][j] != -1) {
2603 float newNoise = (noise[i][j] - minNoise) / range;
2604 noise[i][j] = newNoise;
2605 } else {
2606 if (i > 0)
2607 noise[i][j] = noise[i - 1][j];
2608 else if (i < noise.length - 1)
2609 noise[i][j] = noise[i + 1][j];
2610 else
2611 noise[i][j] = .5f;
2612 }
2613 }
2614 }
2615 }
2616
2617 public static float [][] initNoise(Random random, int w, int h, float spikes) {
2618 if (random == null) random = Misc.random;
2619 float [][] noise = new float [w][h];
2620 for (int i = 0; i < noise.length; i++) {
2621 for (int j = 0; j < noise[0].length; j++) {
2622 noise[i][j] = -1f;
2623 }
2624 }
2625 noise[0][0] = random.nextFloat() * spikes;
2626 noise[0][noise[0].length - 1] = random.nextFloat() * spikes;
2627 noise[noise.length - 1][0] = random.nextFloat() * spikes;
2628 noise[noise.length - 1][noise[0].length - 1] = random.nextFloat() * spikes;
2629 return noise;
2630 }
2631
2632 public static void genFractalNoise(Random random, float[][] noise, int x1, int y1,
2633 int x2, int y2, int iter, float spikes) {
2634 if (x1 + 1 >= x2 || y1 + 1 >= y2) return; // no more values to fill
2635
2636 int midX = (x1 + x2) / 2;
2637 int midY = (y1 + y2) / 2;
2638
2639 fill(random, noise, midX, y1, x1, y1, x2, y1, iter, spikes);
2640 fill(random, noise, midX, y2, x1, y2, x2, y2, iter, spikes);
2641 fill(random, noise, x1, midY, x1, y1, x1, y2, iter, spikes);
2642 fill(random, noise, x2, midY, x2, y1, x2, y2, iter, spikes);
2643
2644 // averaging 4 neighboring values
2645 fill(random, noise, midX, midY, midX, y1, midX, y2, iter, spikes);
2646 float midValue1 = noise[midX][midY];
2647 fill(random, noise, midX, midY, x1, midY, x2, midY, iter, spikes);
2648 float midValue2 = noise[midX][midY];
2649 noise[midX][midY] = (midValue1 + midValue2)/2f;
2650
2651 genFractalNoise(random, noise, x1, y1, midX, midY, iter + 1, spikes);
2652 genFractalNoise(random, noise, x1, midY, midX, y2, iter + 1, spikes);
2653 genFractalNoise(random, noise, midX, y1, x2, midY, iter + 1, spikes);
2654 genFractalNoise(random, noise, midX, midY, x2, y2, iter + 1, spikes);
2655 }
2656
2657 private static void fill(Random random, float[][] noise, int x, int y, int x1, int y1,
2658 int x2, int y2, int iter, float spikes) {
2659 if (noise[x][y] == -1) {
2660 float avg = (noise[x1][y1] + noise[x2][y2]) / 2f;
2661 noise[x][y] = avg + ((float) Math.pow(spikes, (iter)) * (float) (random.nextFloat() - .5));
2662 }
2663 }
2664
2665
2666 public static float computeAngleSpan(float radius, float range) {
2667 if (range <= 1) return 180f;
2668 return (2f * radius) / (2f * (float) Math.PI * range) * 360f;
2669 }
2670
2671 public static float computeAngleRadius(float angle, float range) {
2672 float rad = (float) Math.toRadians(angle);
2673 return rad * range;
2674 }
2675
2676 public static float approach(float curr, float dest, float minSpeed, float diffSpeedMult, float amount) {
2677 float diff = dest - curr;
2678 float delta = (Math.signum(diff) * minSpeed + (diff * diffSpeedMult)) * amount;
2679
2680 if (Math.abs(delta) > Math.abs(diff)) delta = diff;
2681 return curr + delta;
2682 }
2683
2684 public static void cleanBuffer(Buffer toBeDestroyed) {
2685 try {
2687 Cleaner cleaner = ((DirectBuffer) toBeDestroyed).cleaner();
2688 if (cleaner != null) cleaner.clean();
2689 Global.getLogger(Misc.class).info(String.format("Cleaned buffer (using cast)"));
2690 return;
2691 } else {
2692
2693 }
2694
2695 Method cleanerMethod = toBeDestroyed.getClass().getMethod("cleaner");
2696 cleanerMethod.setAccessible(true);
2698 if (cleaner != null) {
2699 Method cleanMethod = cleaner.getClass().getMethod("clean");
2700 cleanMethod.setAccessible(true);
2701 cleanMethod.invoke(cleaner);
2702 Global.getLogger(Misc.class).info(String.format("Cleaned buffer (using reflection)"));
2703 } else {
2704 Global.getLogger(Misc.class).warn(String.format("Buffer can not be cleaned"));
2705 }
2706 } catch (Exception e) {
2707 Global.getLogger(Misc.class).warn(e.getMessage(), e);
2708 }
2709 }
2710
2711
2712 public static float getFleetwideTotalStat(CampaignFleetAPI fleet, String dynamicMemberStatId) {
2713 float total = 0;
2714 for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) {
2715 if (member.isMothballed()) continue;
2716 total += member.getStats().getDynamic().getValue(dynamicMemberStatId);
2717 }
2718 return total;
2719 }
2720
2721 public static float getFleetwideTotalMod(CampaignFleetAPI fleet, String dynamicMemberStatId, float base) {
2722 return getFleetwideTotalMod(fleet, dynamicMemberStatId, base, null);
2723 }
2724 public static float getFleetwideTotalMod(CampaignFleetAPI fleet, String dynamicMemberStatId, float base, ShipAPI ship) {
2725 float total = 0;
2726 for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) {
2727 if (member.isMothballed()) continue;
2728 if (ship != null && ship.getFleetMember() == member) {
2729 total += ship.getMutableStats().getDynamic().getValue(dynamicMemberStatId, base);
2730 } else {
2731 total += member.getStats().getDynamic().getValue(dynamicMemberStatId, base);
2732 }
2733 }
2734 return total;
2735 }
2736
2737 public static String getStarId(PlanetAPI planet) {
2738 String starId = planet.getContainingLocation().getId();
2739 if (planet.getContainingLocation() instanceof StarSystemAPI) {
2740 StarSystemAPI system = (StarSystemAPI) planet.getContainingLocation();
2741 if (system.getStar() != null) {
2742 starId = system.getStar().getId();
2743 }
2744 }
2745 if (planet.getOrbitFocus() instanceof PlanetAPI) {
2746 PlanetAPI parent = (PlanetAPI) planet.getOrbitFocus();
2747 if (parent.isStar()) {
2748 starId = parent.getId();
2749 } else {
2750 if (parent.getOrbitFocus() instanceof PlanetAPI) {
2751 parent = (PlanetAPI) parent.getOrbitFocus();
2752 if (parent.isStar()) {
2753 starId = parent.getId();
2754 }
2755 }
2756 }
2757 }
2758 return starId;
2759 }
2760
2761
2762// public static enum PlanetDataForSystem {
2763// NONE,
2764// SEEN,
2765// PRELIMINARY,
2766// //PARTIAL,
2767// FULL,
2768// }
2769
2770 public static SurveyLevel getMinSystemSurveyLevel(StarSystemAPI system) {
2771 //boolean some = false, all = true;
2772 SurveyLevel minLevel = SurveyLevel.FULL;
2773 boolean empty = true;
2774 for (PlanetAPI planet : system.getPlanets()) {
2775 if (planet.isStar()) continue;
2776 MarketAPI market = planet.getMarket();
2777 if (market == null) continue;
2778
2779 empty = false;
2780 SurveyLevel level = market.getSurveyLevel();
2781 if (level.ordinal() < minLevel.ordinal()) {
2782 minLevel = level;
2783 }
2784 }
2785
2786 if (!system.isEnteredByPlayer() && empty) minLevel = SurveyLevel.NONE;
2787 if (system.isEnteredByPlayer() && empty) minLevel = SurveyLevel.FULL;
2788
2789 return minLevel;
2790
2791
2792// if (all && system.isEnteredByPlayer()) return PlanetDataForSystem.FULL;
2793// if (some) return PlanetDataForSystem.PARTIAL;
2794// return PlanetDataForSystem.NONE;
2795 }
2796
2797 public static boolean hasAnySurveyDataFor(StarSystemAPI system) {
2798 for (PlanetAPI planet : system.getPlanets()) {
2799 if (planet.isStar()) continue;
2800 MarketAPI market = planet.getMarket();
2801 if (market == null) continue;
2802
2803 SurveyLevel level = market.getSurveyLevel();
2804 if (level != SurveyLevel.NONE) return true;
2805 }
2806 return false;
2807 }
2808
2809
2810
2812 StarSystemAPI system = Global.getSector().getStarSystem(systemName);
2813 if (system != null) {
2814 setAllPlanetsKnown(system);
2815 } else {
2816 throw new RuntimeException("Star system [" + systemName + "] not found");
2817 }
2818 }
2819
2820 public static void setAllPlanetsKnown(StarSystemAPI system) {
2821 for (PlanetAPI planet : system.getPlanets()) {
2822 if (planet.isStar()) continue;
2823
2824 MarketAPI market = planet.getMarket();
2825 if (market == null) continue;
2826 if (!market.isPlanetConditionMarketOnly()) {
2827 market.setSurveyLevel(SurveyLevel.FULL);
2828 } else if (market.getSurveyLevel() == SurveyLevel.NONE) {
2829 market.setSurveyLevel(SurveyLevel.SEEN);
2830 }
2831 }
2832 }
2833
2834 public static void setAllPlanetsSurveyed(StarSystemAPI system, boolean setRuinsExplored) {
2835 for (PlanetAPI planet : system.getPlanets()) {
2836 if (planet.isStar()) continue;
2837
2838 MarketAPI market = planet.getMarket();
2839 if (market == null) continue;
2840
2841 market.setSurveyLevel(SurveyLevel.FULL);
2842 for (MarketConditionAPI mc : market.getConditions()) {
2843 mc.setSurveyed(true);
2844 }
2845
2846 if (setRuinsExplored && Misc.hasRuins(market)) {
2847 market.getMemoryWithoutUpdate().set("$ruinsExplored", true);
2848 }
2849 }
2850 }
2851
2852 public static void generatePlanetConditions(String systemName, StarAge age) {
2853 StarSystemAPI system = Global.getSector().getStarSystem(systemName);
2854 if (system != null) {
2855 generatePlanetConditions(system, age);
2856 } else {
2857 throw new RuntimeException("Star system [" + systemName + "] not found");
2858 }
2859 }
2860
2861 public static void generatePlanetConditions(StarSystemAPI system, StarAge age) {
2862 for (PlanetAPI planet : system.getPlanets()) {
2863 if (planet.isStar()) continue;
2864
2865 if (planet.getMarket() != null && !planet.getMarket().getConditions().isEmpty()) continue;
2866
2867 PlanetConditionGenerator.generateConditionsForPlanet(planet, age);
2868 }
2869 }
2870
2871
2872 public static int getEstimatedOrbitIndex(PlanetAPI planet) {
2873 Vector2f centerLoc = new Vector2f();
2874 float centerRadius = 0;
2875
2876// if (planet.getId().toLowerCase().equals("asharu")) {
2877// System.out.println("sdfwefe");
2878// }
2879
2880 float planetRadius = planet.getRadius();
2881 PlanetAPI parent = null;
2882 PlanetAPI parentParent = null;
2883 if (planet.getOrbitFocus() instanceof PlanetAPI) {
2884 parent = (PlanetAPI) planet.getOrbitFocus();
2885 if (parent.getOrbitFocus() instanceof PlanetAPI) {
2886 parentParent = (PlanetAPI) parent.getOrbitFocus();
2887 }
2888 if (parent.isStar()) {
2889 centerLoc = parent.getLocation();
2890 centerRadius = parent.getRadius();
2891 } else if (parentParent != null && parentParent.isStar()) {
2892 centerLoc = parentParent.getLocation();
2893 centerRadius = parentParent.getRadius();
2894 planetRadius = parent.getRadius();
2895 }
2896 }
2897
2898 float approximateExtraRadiusPerOrbit = 400f;
2899
2900 float dist = Misc.getDistance(centerLoc, planet.getLocation());
2901 int orbitIndex = (int) ((dist - centerRadius - planetRadius -
2902 StarSystemGenerator.STARTING_RADIUS_STAR_BASE - StarSystemGenerator.STARTING_RADIUS_STAR_RANGE * 0.5f) /
2903 (StarSystemGenerator.BASE_INCR * 1.25f + approximateExtraRadiusPerOrbit));
2904 if (orbitIndex == 0) {
2905 orbitIndex = (int) ((dist - centerRadius - planetRadius -
2906 StarSystemGenerator.STARTING_RADIUS_STAR_BASE - StarSystemGenerator.STARTING_RADIUS_STAR_RANGE * 0.5f) /
2907 (StarSystemGenerator.BASE_INCR * 1.25f));
2908 }
2909 if (orbitIndex < 0) orbitIndex = 0;
2910
2911 return orbitIndex;
2912 }
2913
2914
2915 public static Random getRandom(long seed, int level) {
2916 if (seed == 0) return random;
2917
2918 Random r = new Random(seed);
2919 for (int i = 0; i < level; i++) {
2920 r.nextLong();
2921 }
2922 return new Random(r.nextLong());
2923 }
2924
2925
2926 public static void addSurveyDataFor(PlanetAPI planet, TextPanelAPI text) {
2927 SurveyPlugin plugin = (SurveyPlugin) Global.getSettings().getNewPluginInstance("surveyPlugin");
2928 plugin.init(Global.getSector().getPlayerFleet(), planet);
2929
2930 String dataType = plugin.getSurveyDataType(planet);
2931 if (dataType != null) {
2932 Global.getSector().getPlayerFleet().getCargo().addCommodity(dataType, 1);
2933 if (text != null) {
2934 AddRemoveCommodity.addCommodityGainText(dataType, 1, text);
2935 }
2936 }
2937 }
2938
2939 public static void setFullySurveyed(MarketAPI market, TextPanelAPI text, boolean withNotification) {
2940 //if (true) return;
2941
2942 for (MarketConditionAPI mc : market.getConditions()) {
2943 mc.setSurveyed(true);
2944 }
2945 market.setSurveyLevel(SurveyLevel.FULL);
2946
2947 if (withNotification && market.getPrimaryEntity() instanceof PlanetAPI) {
2948 PlanetAPI planet = (PlanetAPI) market.getPrimaryEntity();
2949 String string = "Acquired full survey data for " + planet.getName() + ", " + planet.getTypeNameWithWorld().toLowerCase();
2950 if (text != null) {
2951 text.setFontSmallInsignia();
2952 text.addParagraph(string, planet.getSpec().getIconColor());
2953 text.setFontInsignia();
2954 } else {
2955 //Global.getSector().getCampaignUI().addMessage(string, planet.getSpec().getIconColor());
2956
2957 MessageIntel intel = new MessageIntel("Full survey data: " + planet.getName() + ", " + planet.getTypeNameWithWorld(),
2958 Misc.getBasePlayerColor());//, new String[] {"" + points}, Misc.getHighlightColor());
2959 intel.setIcon(Global.getSettings().getSpriteName("intel", "new_planet_info"));
2960 Global.getSector().getCampaignUI().addMessage(intel, MessageClickAction.INTEL_TAB, planet);
2961
2962// CommMessageAPI message = Global.getFactory().createMessage();
2963// message.setSubject(string);
2964// //message.setSubjectColor(planet.getSpec().getIconColor());
2965// message.setAction(MessageClickAction.INTEL_TAB);
2966// message.setCustomData(planet);
2967// message.setAddToIntelTab(false);
2968// message.setSmallIcon(Global.getSettings().getSpriteName("intel_categories", "star_systems"));
2969// Global.getSector().getCampaignUI().addMessage(message);
2970 }
2971 }
2972 }
2973
2974 public static void setPreliminarySurveyed(MarketAPI market, TextPanelAPI text, boolean withNotification) {
2975 market.setSurveyLevel(SurveyLevel.PRELIMINARY);
2976
2977 if (withNotification && market.getPrimaryEntity() instanceof PlanetAPI) {
2978 PlanetAPI planet = (PlanetAPI) market.getPrimaryEntity();
2979 String string = "Acquired preliminary survey data for " + planet.getName() + ", " + planet.getTypeNameWithWorld().toLowerCase();
2980 if (text != null) {
2981 text.setFontSmallInsignia();
2982 text.addParagraph(string, planet.getSpec().getIconColor());
2983 text.setFontInsignia();
2984 } else {
2985 //Global.getSector().getCampaignUI().addMessage(string, planet.getSpec().getIconColor());
2986
2987 MessageIntel intel = new MessageIntel("Preliminary survey data: " + planet.getName() + ", " + planet.getTypeNameWithWorld(),
2988 Misc.getBasePlayerColor());//, new String[] {"" + points}, Misc.getHighlightColor());
2989 intel.setIcon(Global.getSettings().getSpriteName("intel", "new_planet_info"));
2990 Global.getSector().getCampaignUI().addMessage(intel, MessageClickAction.INTEL_TAB, planet);
2991
2992// CommMessageAPI message = Global.getFactory().createMessage();
2993// message.setSubject(string);
2994// //message.setSubjectColor(planet.getSpec().getIconColor());
2995// message.setAction(MessageClickAction.INTEL_TAB);
2996// message.setCustomData(planet);
2997// message.setAddToIntelTab(false);
2998// message.setSmallIcon(Global.getSettings().getSpriteName("intel_categories", "star_systems"));
2999// Global.getSector().getCampaignUI().addMessage(message);
3000 //Global.getSector().getCampaignUI().addMessage(string, planet.getSpec().getIconColor());
3001 }
3002 }
3003 }
3004
3005 public static void setSeen(MarketAPI market, TextPanelAPI text, boolean withNotification) {
3006 market.setSurveyLevel(SurveyLevel.SEEN);
3007
3008 if (withNotification && market.getPrimaryEntity() instanceof PlanetAPI) {
3009 PlanetAPI planet = (PlanetAPI) market.getPrimaryEntity();
3010 //String string = "Acquired preliminary survey data for " + planet.getName() + ", " + planet.getTypeNameWithWorld().toLowerCase();
3011 String type = planet.getSpec().getName();
3012 if (!planet.isGasGiant()) type += " World";
3013 String string = "New planet data: " + planet.getName() + ", " + type;
3014 if (text != null) {
3015 text.setFontSmallInsignia();
3016 text.addParagraph(string, planet.getSpec().getIconColor());
3017 text.setFontInsignia();
3018 } else {
3019
3020 MessageIntel intel = new MessageIntel(string,
3021 Misc.getBasePlayerColor());//, new String[] {"" + points}, Misc.getHighlightColor());
3022 intel.setIcon(Global.getSettings().getSpriteName("intel", "new_planet_info"));
3023 Global.getSector().getCampaignUI().addMessage(intel, MessageClickAction.INTEL_TAB, planet);
3024
3025// CommMessageAPI message = Global.getFactory().createMessage();
3026// message.setSubject(string);
3027// message.setSubjectColor(planet.getSpec().getIconColor());
3028// message.setAction(MessageClickAction.INTEL_TAB);
3029// message.setCustomData(planet);
3030// message.setAddToIntelTab(false);
3031// message.setSmallIcon(Global.getSettings().getSpriteName("intel_categories", "star_systems"));
3032// Global.getSector().getCampaignUI().addMessage(message);
3033 //Global.getSector().getCampaignUI().addMessage(string, planet.getSpec().getIconColor());
3034 }
3035 }
3036 }
3037
3038
3039
3040 public static String getStringWithTokenReplacement(String format, SectorEntityToken entity, Map<String, MemoryAPI> memoryMap) {
3041 return Global.getSector().getRules().performTokenReplacement(
3042 null, format,
3043 entity, memoryMap);
3044 }
3045
3046
3047 public static void renderQuadAlpha(float x, float y, float width, float height, Color color, float alphaMult) {
3048
3049 GL11.glDisable(GL11.GL_TEXTURE_2D);
3050 GL11.glEnable(GL11.GL_BLEND);
3051 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ZERO);
3052
3053 GL11.glColor4ub((byte)color.getRed(),
3054 (byte)color.getGreen(),
3055 (byte)color.getBlue(),
3056 (byte)(color.getAlpha() * alphaMult));
3057
3058 GL11.glBegin(GL11.GL_QUADS);
3059 {
3060 GL11.glVertex2f(x, y);
3061 GL11.glVertex2f(x, y + height);
3062 GL11.glVertex2f(x + width, y + height);
3063 GL11.glVertex2f(x + width, y);
3064 }
3065 GL11.glEnd();
3066 }
3067
3068
3069 public static void fadeAndExpire(SectorEntityToken entity) {
3070 fadeAndExpire(entity, 1f);
3071 }
3072 public static void fadeAndExpire(final SectorEntityToken entity, final float seconds) {
3073 if (entity.hasTag(Tags.FADING_OUT_AND_EXPIRING)) return;
3074
3075 entity.addTag(Tags.NON_CLICKABLE);
3076 entity.addTag(Tags.FADING_OUT_AND_EXPIRING);
3077 //entity.getContainingLocation().addScript(new EveryFrameScript() {
3078 entity.addScript(new EveryFrameScript() {
3079 float elapsed = 0f;
3080 public boolean runWhilePaused() {
3081 return false;
3082 }
3083 public boolean isDone() {
3084 return entity.isExpired();
3085 }
3086 public void advance(float amount) {
3087 elapsed += amount;
3088 if (elapsed > seconds) {
3089 entity.setExpired(true);
3090 }
3091 float b = 1f - elapsed / seconds;
3092 if (b < 0) b = 0;
3093 if (b > 1) b = 1;
3094 entity.forceSensorFaderBrightness(Math.min(entity.getSensorFaderBrightness(), b));
3095 entity.setAlwaysUseSensorFaderBrightness(true);
3096 }
3097 });
3098 }
3099 public static void fadeInOutAndExpire(final SectorEntityToken entity, final float in, final float dur, final float out) {
3100 entity.addTag(Tags.NON_CLICKABLE);
3101 entity.forceSensorFaderBrightness(0f);
3102 entity.setAlwaysUseSensorFaderBrightness(true);
3103 //entity.getContainingLocation().addScript(new EveryFrameScript() {
3104 entity.addScript(new EveryFrameScript() {
3105 float elapsed = 0f;
3106 public boolean runWhilePaused() {
3107 return false;
3108 }
3109 public boolean isDone() {
3110 return entity.isExpired();
3111 }
3112 public void advance(float amount) {
3113 elapsed += amount;
3114 if (elapsed > in + dur + out) {
3115 entity.setExpired(true);
3116 }
3117 float b = 1f;
3118 if (elapsed < in) {
3119 b = elapsed / in;
3120 } else if (elapsed > in + dur) {
3121 b = 1f - (elapsed - in - dur) / out;
3122 }
3123 if (b < 0) b = 0;
3124 if (b > 1) b = 1;
3125 entity.forceSensorFaderBrightness(Math.min(entity.getSensorFaderBrightness(), b));
3126 entity.setAlwaysUseSensorFaderBrightness(true);
3127 }
3128 });
3129 }
3130
3131 public static void fadeIn(final SectorEntityToken entity, final float in) {
3132 entity.forceSensorFaderBrightness(0f);
3133 entity.setAlwaysUseSensorFaderBrightness(true);
3134 entity.addScript(new EveryFrameScript() {
3135 float elapsed = 0f;
3136 public boolean runWhilePaused() {
3137 return false;
3138 }
3139 public boolean isDone() {
3140 return elapsed > in;
3141 }
3142 public void advance(float amount) {
3143 elapsed += amount;
3144 if (elapsed > in) {
3145 entity.setAlwaysUseSensorFaderBrightness(false);
3146 return;
3147 }
3148 float b = elapsed / in;
3149 if (b < 0) b = 0;
3150 if (b > 1) b = 1;
3151 entity.forceSensorFaderBrightness(Math.min(entity.getSensorFaderBrightness(), b));
3152 entity.setAlwaysUseSensorFaderBrightness(true);
3153 }
3154 });
3155 }
3156// public static void fadeSensorContactAndExpire(final SectorEntityToken entity, final float seconds) {
3157// entity.addTag(Tags.NON_CLICKABLE);
3158// entity.addTag(Tags.FADING_OUT_AND_EXPIRING);
3159// //entity.getContainingLocation().addScript(new EveryFrameScript() {
3160// entity.addScript(new EveryFrameScript() {
3161// float elapsed = 0f;
3162// public boolean runWhilePaused() {
3163// return false;
3164// }
3165// public boolean isDone() {
3166// return entity.isExpired();
3167// }
3168// public void advance(float amount) {
3169// elapsed += amount;
3170// if (elapsed > seconds) {
3171// entity.setExpired(true);
3172// }
3173// float b = 1f - elapsed / seconds;
3174// if (b < 0) b = 0;
3175// if (b > 1) b = 1;
3176// entity.forceSensorContactFaderBrightness(Math.min(entity.getSensorContactFaderBrightness(), b));
3177// }
3178// });
3179// }
3180
3181 public static CustomCampaignEntityAPI addCargoPods(LocationAPI where, Vector2f loc) {
3182 CustomCampaignEntityAPI pods = where.addCustomEntity(null, null, Entities.CARGO_PODS, Factions.NEUTRAL);
3183 pods.getLocation().x = loc.x;
3184 pods.getLocation().y = loc.y;
3185
3186 Vector2f vel = Misc.getUnitVectorAtDegreeAngle((float) Math.random() * 360f);
3187 vel.scale(5f + 10f * (float) Math.random());
3188 pods.getVelocity().set(vel);
3189
3190 pods.setDiscoverable(null);
3191 pods.setDiscoveryXP(null);
3192 pods.setSensorProfile(1f);
3193
3194 return pods;
3195 }
3196
3197
3198 public static SectorEntityToken addDebrisField(LocationAPI loc, DebrisFieldParams params, Random random) {
3199 if (random == null) random = Misc.random;
3200 SectorEntityToken debris = loc.addTerrain(Terrain.DEBRIS_FIELD, params);
3201 debris.setSensorProfile(1f);
3202 debris.setDiscoverable(true);
3203 debris.setName(((CampaignTerrainAPI)debris).getPlugin().getTerrainName());
3204
3205// float range = 300f + params.bandWidthInEngine * 5;
3206// if (range > 2000) range = 2000;
3207// debris.getDetectedRangeMod().modifyFlat("gen", range);
3208
3209 float range = DebrisFieldTerrainPlugin.computeDetectionRange(params.bandWidthInEngine);
3210 debris.getDetectedRangeMod().modifyFlat("gen", range);
3211
3212 debris.getMemoryWithoutUpdate().set(MemFlags.SALVAGE_SEED, random.nextLong());
3213
3214 // add some default salvage
3215 // most uses of this will want to clear that out and add something more specific
3216 DropData data = new DropData();
3217 data.group = Drops.BASIC;
3218 data.value = (int) ((1000 + params.bandWidthInEngine) * 5);
3219 debris.addDropValue(data);
3220
3221 debris.setDiscoveryXP((float)((int)(params.bandWidthInEngine * 0.2f)));
3222 if (params.baseSalvageXP <= 0) {
3223 debris.setSalvageXP((float)((int)(params.bandWidthInEngine * 0.6f)));
3224 }
3225
3226 return debris;
3227 }
3228
3229 public static boolean isUnboardable(FleetMemberAPI member) {
3230 if (member.getVariant() != null && member.getVariant().hasTag(Tags.VARIANT_UNBOARDABLE)) {
3231 return true;
3232 }
3233 return isUnboardable(member.getHullSpec());
3234 }
3235
3236 public static boolean isUnboardable(ShipHullSpecAPI hullSpec) {
3237 if (hullSpec.getHints().contains(ShipTypeHints.UNBOARDABLE)) {
3238 for (String tag : getAllowedRecoveryTags()) {
3239 if (hullSpec.hasTag(tag)) return false;
3240 }
3241 if (hullSpec.isDefaultDHull()) {
3242 ShipHullSpecAPI parent = hullSpec.getDParentHull();
3243 for (String tag : getAllowedRecoveryTags()) {
3244 if (parent.hasTag(tag)) return false;
3245 }
3246 }
3247 return true;
3248 }
3249 return false;
3250 }
3251
3252
3253 public static boolean isShipRecoverable(FleetMemberAPI member, CampaignFleetAPI recoverer, boolean own, boolean useOfficerRecovery, float chanceMult) {
3254 //Random rand = new Random(1000000 * (member.getId().hashCode() + seed + Global.getSector().getClock().getDay()));
3255 //Random rand = new Random(1000000 * (member.getId().hashCode() + Global.getSector().getClock().getDay()));
3256 if (own) {
3257 if (!member.getVariant().getSMods().isEmpty()) {
3258 return true;
3259 }
3260 if (!member.getVariant().getSModdedBuiltIns().isEmpty()) {
3261 return true;
3262 }
3263 if (member.getCaptain() != null && !member.getCaptain().isDefault()) {
3264 return true;
3265 }
3266 }
3267 if (member.getVariant().hasTag(Tags.VARIANT_ALWAYS_RECOVERABLE)) {
3268 return true;
3269 }
3270 Random rand = new Random(1000000 * member.getId().hashCode() + Global.getSector().getPlayerBattleSeed());
3271 //rand = new Random();
3272 float chance = Global.getSettings().getFloat("baseShipRecoveryChance");
3273 if (own) {
3274 chance = Global.getSettings().getFloat("baseOwnShipRecoveryChance");
3275 }
3276 chance = member.getStats().getDynamic().getMod(Stats.INDIVIDUAL_SHIP_RECOVERY_MOD).computeEffective(chance);
3277 if (recoverer != null) {
3278 chance = recoverer.getStats().getDynamic().getMod(Stats.SHIP_RECOVERY_MOD).computeEffective(chance);
3279 if (useOfficerRecovery) {
3280 chance = recoverer.getStats().getDynamic().getMod(Stats.OFFICER_SHIP_RECOVERY_MOD).computeEffective(chance);
3281 }
3282 }
3283 chance *= chanceMult;
3284
3285 if (chance < 0) chance = 0;
3286 if (chance > 1f) chance = 1f;
3287 boolean recoverable = rand.nextFloat() < chance;
3288
3289// System.out.println("Recovery for " + member.getHullSpec().getHullId() +
3290// "(" + member.getId().hashCode() + "): " + chance + " (" + recoverable + ")");
3291 return recoverable;
3292 }
3293
3294// public static float computeDetectionRangeForEntity(float radius) {
3295// float range = 300f + radius * 5f;
3296// if (range > 2000) range = 2000;
3297// return radius;
3298// }
3299
3300
3301
3302 public static JumpPointAPI findNearestJumpPointTo(SectorEntityToken entity) {
3303 return findNearestJumpPointTo(entity, false);
3304 }
3305 public static JumpPointAPI findNearestJumpPointTo(SectorEntityToken entity, boolean allowWormhole) {
3306 float min = Float.MAX_VALUE;
3307 JumpPointAPI result = null;
3308 List<JumpPointAPI> points = entity.getContainingLocation().getEntities(JumpPointAPI.class);
3309
3310 for (JumpPointAPI curr : points) {
3311 if (!allowWormhole && curr.isWormhole()) continue;
3312 if (curr.getMemoryWithoutUpdate().getBoolean(JumpPointInteractionDialogPluginImpl.UNSTABLE_KEY)) {
3313 continue;
3314 }
3315 float dist = Misc.getDistance(entity.getLocation(), curr.getLocation());
3316 if (dist < min) {
3317 min = dist;
3318 result = curr;
3319 }
3320 }
3321 return result;
3322 }
3323
3324 public static JumpPointAPI findNearestJumpPointThatCouldBeExitedFrom(SectorEntityToken entity) {
3325 float min = Float.MAX_VALUE;
3326 JumpPointAPI result = null;
3327 List<JumpPointAPI> points = entity.getContainingLocation().getEntities(JumpPointAPI.class);
3328
3329 for (JumpPointAPI curr : points) {
3330 if (curr.isGasGiantAnchor() || curr.isStarAnchor()) continue;
3331 float dist = Misc.getDistance(entity.getLocation(), curr.getLocation());
3332 if (dist < min) {
3333 min = dist;
3334 result = curr;
3335 }
3336 }
3337 return result;
3338 }
3339
3340 public static SectorEntityToken findNearestPlanetTo(SectorEntityToken entity, boolean requireGasGiant, boolean allowStars) {
3341 float min = Float.MAX_VALUE;
3342 SectorEntityToken result = null;
3343 List<PlanetAPI> planets = entity.getContainingLocation().getPlanets();
3344
3345 for (PlanetAPI curr : planets) {
3346 if (requireGasGiant && !curr.isGasGiant()) continue;
3347 if (!allowStars && curr.isStar()) continue;
3348 float dist = Misc.getDistance(entity.getLocation(), curr.getLocation());
3349 if (dist < min) {
3350 min = dist;
3351 result = curr;
3352 }
3353 }
3354 return result;
3355 }
3356
3357
3358
3359 public static final boolean shouldConvertFromStub(LocationAPI containingLocation, Vector2f location) {
3360 //if (true) return false;
3361 if (Global.getSector().getPlayerFleet() == null) return false;
3362
3363// if (containingLocation == null ||
3364// containingLocation != Global.getSector().getPlayerFleet().getContainingLocation()) return false;
3365
3366 Vector2f stubLocInHyper = null;
3367 if (containingLocation == null || containingLocation.isHyperspace()) {
3368 stubLocInHyper = location;
3369 } else {
3370 stubLocInHyper = containingLocation.getLocation();
3371 }
3372
3373 Vector2f playerLoc = Global.getSector().getPlayerFleet().getLocationInHyperspace();
3374
3375 boolean sameLoc = containingLocation != null &&
3376 Global.getSector().getPlayerFleet().getContainingLocation() == containingLocation;
3377
3378 float maxDist = 6000;
3379 if (!sameLoc) maxDist = 3000;
3380
3382 return dist < maxDist;
3383 }
3384
3385// public static final boolean shouldConvertFromStub(FleetStubAPI stub) {
3386// if (Global.getSector().getPlayerFleet() == null) return false;
3387//
3388// return shouldConvertFromStub(stub.getContainingLocation(), stub.getLocation());
3389// }
3390//
3391//
3392// public static final boolean shouldConvertToStub(CampaignFleetAPI fleet) {
3393// if (fleet.getStub() == null || !fleet.isConvertToStub()) return false;
3394//
3395// if (Global.getSector().getPlayerFleet() == null) return true;
3396//
3397// Vector2f fleetLocInHyper = fleet.getLocationInHyperspace();
3398// Vector2f playerLoc = Global.getSector().getPlayerFleet().getLocationInHyperspace();
3399//
3400// boolean sameLoc = fleet.getContainingLocation() != null &&
3401// Global.getSector().getPlayerFleet().getContainingLocation() == fleet.getContainingLocation();
3402//
3403// float maxDist = 8000;
3404// if (!sameLoc) maxDist = 4000;
3405//
3406// float dist = Misc.getDistance(playerLoc, fleetLocInHyper);
3407// return dist > maxDist;
3408// }
3409
3410
3411 private static final AtomicLong seedUniquifier = new AtomicLong(8682522807148012L);
3412
3417 public static long genRandomSeed() {
3418 return seedUniquifier() ^ System.nanoTime();
3419 }
3420 public static long seedUniquifier() {
3421 // L'Ecuyer, "Tables of Linear Congruential Generators of
3422 // Different Sizes and Good Lattice Structure", 1999
3423 for (;;) {
3424 long current = seedUniquifier.get();
3425 long next = current * 181783497276652981L;
3426 //long next = current * 1181783497276652981L; // actual correct number?
3427 if (seedUniquifier.compareAndSet(current, next)) {
3428 return next;
3429 }
3430 }
3431 }
3432
3433
3434 public static String genUID() {
3435 if (Global.getSettings() != null && Global.getSettings().isInGame() &&
3437 return Global.getSector().genUID();
3438 }
3439 return UUID.randomUUID().toString();
3440 }
3441
3442
3443 public static String colorsToString(List<Color> colors) {
3444 String result = "";
3445 for (Color c : colors) {
3446 result += Integer.toHexString(c.getRGB()) + "|";
3447 }
3448 if (result.length() > 0) {
3449 result = result.substring(0, result.length() - 1);
3450 }
3451 return result;
3452 }
3453
3455 List<Color> result = new ArrayList<Color>();
3456 for (String p : in.split("\\|")) {
3457 //result.add(new Color(Integer.parseInt(p, 16)));
3458 result.add(new Color((int)Long.parseLong(p, 16)));
3459 }
3460 return result;
3461 }
3462
3463 public static JumpPointAPI getJumpPointTo(PlanetAPI star) {
3464 for (Object entity : Global.getSector().getHyperspace().getEntities(JumpPointAPI.class)) {
3465 JumpPointAPI jp = (JumpPointAPI) entity;
3466 if (jp.getDestinationVisualEntity() == star) return jp;
3467 }
3468 return null;
3469 }
3470
3471 @SuppressWarnings("unchecked")
3472 public static JumpPointAPI findNearestJumpPoint(SectorEntityToken from) {
3473 float min = Float.MAX_VALUE;
3474 JumpPointAPI result = null;
3475 LocationAPI location = from.getContainingLocation();
3476 List<JumpPointAPI> points = location.getEntities(JumpPointAPI.class);
3477 for (JumpPointAPI curr : points) {
3478 float dist = Misc.getDistance(from.getLocation(), curr.getLocation());
3479 if (dist < min) {
3480 min = dist;
3481 result = curr;
3482 }
3483 }
3484 return result;
3485 }
3486
3487
3488 public static final String D_HULL_SUFFIX = "_default_D";
3489 public static String getDHullId(ShipHullSpecAPI spec) {
3490 String base = spec.getHullId();
3491 if (base.endsWith(D_HULL_SUFFIX)) return base;
3492 return base + D_HULL_SUFFIX;
3493 }
3494
3495
3496 public static HullModSpecAPI getMod(String id) {
3497 return Global.getSettings().getHullModSpec(id);
3498 }
3499
3500 public static float getDistanceFromArc(float direction, float arc, float angle) {
3501 direction = normalizeAngle(direction);
3502 angle = normalizeAngle(angle);
3503
3504 float dist1 = Math.abs(angle - direction) - arc/2f;
3505 float dist2 = Math.abs(360 - Math.abs(angle - direction)) - arc/2f;
3506
3507 if (dist1 <= 0 || dist2 <= 0) return 0;
3508
3509 return dist1 > dist2 ? dist2 : dist1;
3510 }
3511
3512 public static void initConditionMarket(PlanetAPI planet) {
3513 if (planet.getMarket() != null) {
3514 Global.getSector().getEconomy().removeMarket(planet.getMarket());
3515 }
3516
3517 MarketAPI market = Global.getFactory().createMarket("market_" + planet.getId(), planet.getName(), 1);
3518 market.setPlanetConditionMarketOnly(true);
3519 market.setPrimaryEntity(planet);
3520 market.setFactionId(Factions.NEUTRAL);
3521 planet.setMarket(market);
3522
3523 long seed = StarSystemGenerator.random.nextLong();
3524 planet.getMemoryWithoutUpdate().set(MemFlags.SALVAGE_SEED, seed);
3525 }
3526
3527 public static void initEconomyMarket(PlanetAPI planet) {
3528 if (planet.getMarket() != null) {
3529 Global.getSector().getEconomy().removeMarket(planet.getMarket());
3530 }
3531
3532 MarketAPI market = Global.getFactory().createMarket("market_" + planet.getId(), planet.getName(), 1);
3533 //market.setPlanetConditionMarketOnly(true);
3534 market.setPrimaryEntity(planet);
3535 market.setFactionId(Factions.NEUTRAL);
3536 planet.setMarket(market);
3537 Global.getSector().getEconomy().addMarket(market, true);
3538 }
3539
3540 public static String getSurveyLevelString(SurveyLevel level, boolean withBrackets) {
3541 String str = " ";
3542 if (level == SurveyLevel.NONE) str = UNKNOWN;
3543 else if (level == SurveyLevel.SEEN) str = UNSURVEYED;
3544 else if (level == SurveyLevel.PRELIMINARY) str = PRELIMINARY;
3545 else if (level == SurveyLevel.FULL) str = FULL;
3546
3547 if (withBrackets) {
3548 str = "[" + str + "]";
3549 }
3550 return str;
3551 }
3552
3553
3554 public static void setDefenderOverride(SectorEntityToken entity, DefenderDataOverride override) {
3555 entity.getMemoryWithoutUpdate().set(MemFlags.SALVAGE_DEFENDER_OVERRIDE, override);
3556 }
3557
3558 public static void setSalvageSpecial(SectorEntityToken entity, Object data) {
3559 entity.getMemoryWithoutUpdate().set(MemFlags.SALVAGE_SPECIAL_DATA, data);
3560// if (data instanceof ShipRecoverySpecialData) {
3561// BaseSalvageSpecial.clearExtraSalvage(entity);
3562// }
3563 }
3564
3565 public static void setPrevSalvageSpecial(SectorEntityToken entity, Object data) {
3566 entity.getMemoryWithoutUpdate().set(MemFlags.PREV_SALVAGE_SPECIAL_DATA, data);
3567 }
3568
3569 public static Object getSalvageSpecial(SectorEntityToken entity) {
3570 return entity.getMemoryWithoutUpdate().get(MemFlags.SALVAGE_SPECIAL_DATA);
3571 }
3572 public static Object getPrevSalvageSpecial(SectorEntityToken entity) {
3573 return entity.getMemoryWithoutUpdate().get(MemFlags.PREV_SALVAGE_SPECIAL_DATA);
3574 }
3575
3576
3577
3578
3579 public static List<StarSystemAPI> getSystemsInRange(SectorEntityToken from, Set<StarSystemAPI> exclude, boolean nonEmpty, float maxRange) {
3581
3582 for (StarSystemAPI system : Global.getSector().getStarSystems()) {
3583 if (exclude != null && exclude.contains(system)) continue;
3584
3585 float dist = Misc.getDistance(from.getLocationInHyperspace(), system.getLocation());
3586 if (dist > maxRange) continue;
3587 if (nonEmpty && !systemHasPlanets(system)) continue;
3588
3589 systems.add(system);
3590 }
3591
3592 return systems;
3593 }
3594
3595// public static boolean systemHasPulsar(StarSystemAPI system) {
3596// return hasPulsar(system);
3601// }
3602 public static PlanetAPI getPulsarInSystem(StarSystemAPI system) {
3603 if (system.getStar() != null && system.getStar().getSpec().isPulsar()) {
3604 return system.getStar();
3605 }
3606 if (system.getSecondary() != null && system.getSecondary().getSpec().isPulsar()) {
3607 return system.getSecondary();
3608 }
3609 if (system.getTertiary() != null && system.getTertiary().getSpec().isPulsar()) {
3610 return system.getTertiary();
3611 }
3612 return null;
3613 }
3614 public static boolean systemHasPlanets(StarSystemAPI system) {
3615 for (PlanetAPI p : system.getPlanets()) {
3616 if (!p.isStar()) return true;
3617 }
3618 return false;
3619 }
3620
3621 public static float getCampaignShipScaleMult(HullSize size) {
3622 switch (size) {
3623 case CAPITAL_SHIP:
3624 return 0.07f;
3625 case CRUISER:
3626 return 0.08f;
3627 case DESTROYER:
3628 return 0.09f;
3629 case FRIGATE:
3630 return 0.11f;
3631 case FIGHTER:
3632 return 0.15f;
3633 case DEFAULT:
3634 return 0.1f;
3635 }
3636 return 0.1f;
3637 }
3638
3640 return createStringPicker(StarSystemGenerator.random, params);
3641 }
3642
3645 for (int i = 0; i < params.length; i += 2) {
3646 String item = (String) params[i];
3647 float weight = 0f;
3648 if (params[i+1] instanceof Float) {
3649 weight = (Float) params[i+1];
3650 } else if (params[i+1] instanceof Integer) {
3651 weight = (Integer) params[i+1];
3652 }
3653 picker.add(item, weight);
3654 }
3655 return picker;
3656 }
3657
3658 public static void setWarningBeaconGlowColor(SectorEntityToken beacon, Color color) {
3659 beacon.getMemoryWithoutUpdate().set(WarningBeaconEntityPlugin.GLOW_COLOR_KEY, color);
3660 }
3661
3662 public static void setWarningBeaconPingColor(SectorEntityToken beacon, Color color) {
3663 beacon.getMemoryWithoutUpdate().set(WarningBeaconEntityPlugin.PING_COLOR_KEY, color);
3664 }
3665
3666 public static void setWarningBeaconColors(SectorEntityToken beacon, Color glow, Color ping) {
3667 if (glow != null) setWarningBeaconGlowColor(beacon, glow);
3668 if (ping != null) setWarningBeaconPingColor(beacon, ping);
3669 }
3670
3671
3672 public static List<CampaignFleetAPI> getNearbyFleets(SectorEntityToken from, float maxDist) {
3674 for (CampaignFleetAPI other : from.getContainingLocation().getFleets()) {
3675 if (from == other) continue;
3676 float dist = getDistance(from.getLocation(), other.getLocation());
3677 if (dist <= maxDist) {
3678 result.add(other);
3679 }
3680 }
3681 return result;
3682 }
3683
3684 public static List<CampaignFleetAPI> getVisibleFleets(SectorEntityToken from, boolean includeSensorContacts) {
3686 for (CampaignFleetAPI other : from.getContainingLocation().getFleets()) {
3687 if (from == other) continue;
3688 VisibilityLevel level = other.getVisibilityLevelTo(from);
3689 if (level == VisibilityLevel.COMPOSITION_AND_FACTION_DETAILS || level == VisibilityLevel.COMPOSITION_DETAILS) {
3690 result.add(other);
3691 } else if (level == VisibilityLevel.SENSOR_CONTACT && includeSensorContacts) {
3692 result.add(other);
3693 }
3694 }
3695 return result;
3696 }
3697
3698 public static boolean isSameCargo(CargoAPI baseOne, CargoAPI baseTwo) {
3699 CargoAPI one = Global.getFactory().createCargo(true);
3700 one.addAll(baseOne);
3701 one.sort();
3702
3703 CargoAPI two = Global.getFactory().createCargo(true);
3704 two.addAll(baseTwo);
3705 two.sort();
3706
3707
3708 if (one.getStacksCopy().size() != two.getStacksCopy().size()) return false;
3709
3710 List<CargoStackAPI> stacks1 = one.getStacksCopy();
3711 List<CargoStackAPI> stacks2 = two.getStacksCopy();
3712 for (int i = 0; i < stacks1.size(); i++) {
3713 CargoStackAPI s1 = stacks1.get(i);
3714 CargoStackAPI s2 = stacks2.get(i);
3715
3716 if ((s1 == null || s2 == null) && s1 != s2) return false;
3717 if (s1.getSize() != s2.getSize()) return false;
3718 if (s1.getType() != s2.getType()) return false;
3719 if ((s1.getData() == null || s2.getData() == null) && s1.getData() != s2.getData()) return false;
3720 if (!s1.getData().equals(s2.getData())) return false;
3721 }
3722
3723
3724 return true;
3725 }
3726
3727
3728 public static JumpPointAPI getDistressJumpPoint(StarSystemAPI system) {
3729 SectorEntityToken jumpPoint = null;
3730 float minDist = Float.MAX_VALUE;
3731 for (SectorEntityToken curr : system.getJumpPoints()) {
3732 float dist = Misc.getDistance(system.getCenter().getLocation(), curr.getLocation());
3733 if (dist < minDist) {
3734 jumpPoint = curr;
3735 minDist = dist;
3736 }
3737 }
3738 if (jumpPoint instanceof JumpPointAPI) {
3739 return (JumpPointAPI) jumpPoint;
3740 }
3741 return null;
3742 }
3743
3744
3745 public static void clearTarget(CampaignFleetAPI fleet, boolean forgetTransponder) {
3746 fleet.setInteractionTarget(null);
3747 if (fleet.getAI() instanceof ModularFleetAIAPI) {
3748 ModularFleetAIAPI ai = (ModularFleetAIAPI) fleet.getAI();
3749 ai.getTacticalModule().setTarget(null);
3750 ai.getTacticalModule().setPriorityTarget(null, 0f, false);
3751 }
3752 if (forgetTransponder) {
3754 }
3755 }
3756
3757 public static void giveStandardReturnToSourceAssignments(CampaignFleetAPI fleet) {
3759 }
3760
3761 public static String FLEET_RETURNING_TO_DESPAWN = "$core_fleetReturningToDespawn";
3762
3763 public static boolean isFleetReturningToDespawn(CampaignFleetAPI fleet) {
3764 return fleet.getMemoryWithoutUpdate().getBoolean(FLEET_RETURNING_TO_DESPAWN);
3765 }
3766
3767 public static void giveStandardReturnToSourceAssignments(CampaignFleetAPI fleet, boolean withClear) {
3768 if (withClear) {
3769 fleet.clearAssignments();
3770 }
3771 fleet.getMemoryWithoutUpdate().set(FLEET_RETURNING_TO_DESPAWN, true);
3772 MarketAPI source = Misc.getSourceMarket(fleet);
3773 if (source != null) {
3774 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION, source.getPrimaryEntity(), 1000f, "returning to " + source.getName());
3775 fleet.addAssignment(FleetAssignment.ORBIT_PASSIVE, source.getPrimaryEntity(), 1f + 1f * (float) Math.random());
3776 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION_AND_DESPAWN, source.getPrimaryEntity(), 1000f);
3777 } else {
3778 SectorEntityToken entity = getSourceEntity(fleet);
3779 if (entity != null) {
3780 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION, entity, 1000f, "returning to " + entity.getName());
3781 fleet.addAssignment(FleetAssignment.ORBIT_PASSIVE, entity, 1f + 1f * (float) Math.random());
3782 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION_AND_DESPAWN, entity, 1000f);
3783 } else {
3784 SectorEntityToken token = Global.getSector().getHyperspace().createToken(0, 0);
3785 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION_AND_DESPAWN, token, 1000f);
3786 }
3787 }
3788 }
3789
3790 public static void giveStandardReturnAssignments(CampaignFleetAPI fleet, SectorEntityToken where, String text, boolean withClear) {
3791 if (withClear) {
3792 fleet.clearAssignments();
3793 }
3794 fleet.getMemoryWithoutUpdate().set(FLEET_RETURNING_TO_DESPAWN, true);
3795 if (text == null) {
3796 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION, where, 1000f, "returning to " + where.getName());
3797 } else {
3798 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION, where, 1000f, text + " " + where.getName());
3799 }
3800 fleet.addAssignment(FleetAssignment.ORBIT_PASSIVE, where, 5f + 5f * (float) Math.random());
3801 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION_AND_DESPAWN, where, 1000f);
3802 }
3803
3804
3805 public static void adjustRep(float repChangeFaction, RepLevel limit, String factionId,
3806 float repChangePerson, RepLevel personLimit, PersonAPI person,
3807 TextPanelAPI text) {
3808 if (repChangeFaction != 0) {
3809 CustomRepImpact impact = new CustomRepImpact();
3810 impact.delta = repChangeFaction;
3811 impact.limit = limit;
3812 Global.getSector().adjustPlayerReputation(
3813 new RepActionEnvelope(RepActions.CUSTOM, impact,
3814 null, text, true),
3815 factionId);
3816
3817 if (person != null) {
3818 impact.delta = repChangePerson;
3819 impact.limit = personLimit;
3820 Global.getSector().adjustPlayerReputation(
3821 new RepActionEnvelope(RepActions.CUSTOM, impact,
3822 null, text, true), person);
3823 }
3824 }
3825 }
3826
3827
3828 public static void interruptAbilitiesWithTag(CampaignFleetAPI fleet, String tag) {
3829 for (AbilityPlugin curr : fleet.getAbilities().values()) {
3830 if (curr.isActive()) {
3831 for (String t : curr.getSpec().getTags()) {
3832 if (t.equals(tag)) {
3833 curr.deactivate();
3834 break;
3835 }
3836 }
3837 }
3838 }
3839 }
3840
3841
3842 public static Vector2f getInterceptPoint(CampaignFleetAPI from, SectorEntityToken to) {
3843
3844 //if (true) return new Vector2f(to.getLocation());
3845 //Vector2f v1 = new Vector2f(from.getVelocity());
3846 //Vector2f v2 = new Vector2f(to.getVelocity());
3847 Vector2f v2 = Vector2f.sub(to.getVelocity(), from.getVelocity(), new Vector2f());
3848
3849 float s1 = from.getTravelSpeed();
3850 float s2 = v2.length();
3851
3852 if (s1 < 10) s1 = 10;
3853 if (s2 < 10) s2 = 10;
3854
3855 Vector2f p1 = new Vector2f(from.getLocation());
3856 Vector2f p2 = new Vector2f(to.getLocation());
3857
3858 float dist = getDistance(p1, p2);
3859 float time = dist / s1;
3860 float maxTime = dist / s2 * 0.75f;
3861 if (time > maxTime) time = maxTime; // to ensure intercept point is never behind the from fleet
3862
3864
3865 p3.scale(time * s2);
3866 Vector2f.add(p2, p3, p3);
3867
3869 overshoot.scale(3000f);
3870 Vector2f.add(p3, overshoot, p3);
3871
3872 return p3;
3873 }
3874
3875 public static Vector2f getInterceptPoint(SectorEntityToken from, SectorEntityToken to, float maxSpeedFrom) {
3876
3877 //if (true) return new Vector2f(to.getLocation());
3878 //Vector2f v1 = new Vector2f(from.getVelocity());
3879 //Vector2f v2 = new Vector2f(to.getVelocity());
3880 Vector2f v2 = Vector2f.sub(to.getVelocity(), from.getVelocity(), new Vector2f());
3881
3882 float s1 = maxSpeedFrom;
3883 float s2 = v2.length();
3884
3885 if (s1 < 10) s1 = 10;
3886 if (s2 < 10) s2 = 10;
3887
3888 Vector2f p1 = new Vector2f(from.getLocation());
3889 Vector2f p2 = new Vector2f(to.getLocation());
3890
3891 float dist = getDistance(p1, p2);
3892 float time = dist / s1;
3893 float maxTime = dist / s2 * 0.75f;
3894 if (time > maxTime) time = maxTime; // to ensure intercept point is never behind the from fleet
3895
3897
3898 p3.scale(time * s2);
3899 Vector2f.add(p2, p3, p3);
3900
3902 overshoot.scale(3000f);
3903 Vector2f.add(p3, overshoot, p3);
3904
3905 return p3;
3906 }
3907
3908 public static void stopPlayerFleet() {
3909 CampaignFleetAPI player = Global.getSector().getPlayerFleet();
3910 if (player != null) {
3911 player.setVelocity(0, 0);
3912 }
3913 }
3914
3916 List<String> list = new ArrayList<String>();
3917 for (String con : res.keySet()) {
3918 CommoditySpecAPI spec = Global.getSettings().getCommoditySpec(con);
3919 int qty = res.get(con);
3920 list.add("" + qty + " " + spec.getName().toLowerCase());
3921 quantities.add("" + qty);
3922 }
3923 return Misc.getAndJoined(list);
3924 }
3925
3926
3927 public static void setColor(Color color) {
3928 GL11.glColor4ub((byte)color.getRed(),
3929 (byte)color.getGreen(),
3930 (byte)color.getBlue(),
3931 (byte)color.getAlpha());
3932 }
3933
3934 public static void setColor(Color color, float alphaMult) {
3935 GL11.glColor4ub((byte)color.getRed(),
3936 (byte)color.getGreen(),
3937 (byte)color.getBlue(),
3938 (byte)((float)color.getAlpha() * alphaMult));
3939 }
3940
3941
3942 public static void setColor(Color color, int alpha) {
3943 GL11.glColor4ub((byte)color.getRed(),
3944 (byte)color.getGreen(),
3945 (byte)color.getBlue(),
3946 (byte)alpha);
3947 }
3948
3949
3950 public static boolean doesMarketHaveMissionImportantPeopleOrIsMarketMissionImportant(SectorEntityToken entity) {
3951 MarketAPI market = entity.getMarket();
3952 if (market == null) return false;
3953 if (market.getPrimaryEntity() != entity) return false;
3954
3955 if (market.getMemoryWithoutUpdate().getBoolean(MemFlags.ENTITY_MISSION_IMPORTANT)) return true;
3956
3957 if (market != null && market.getCommDirectory() != null) {
3958 for (CommDirectoryEntryAPI entry : market.getCommDirectory().getEntriesCopy()) {
3959 if (entry.getType() == EntryType.PERSON && entry.getEntryData() instanceof PersonAPI) {
3960 PersonAPI person = (PersonAPI) entry.getEntryData();
3961 if (person.getMemoryWithoutUpdate().getBoolean(MemFlags.ENTITY_MISSION_IMPORTANT)) {
3962 return true;
3963 }
3964 }
3965 }
3966 }
3967 return false;
3968 }
3969
3970
3971
3972 public static void makeImportant(SectorEntityToken entity, String reason) {
3973 makeImportant(entity.getMemoryWithoutUpdate(), reason, -1);
3974 }
3975 public static void makeImportant(SectorEntityToken entity, String reason, float dur) {
3976 makeImportant(entity.getMemoryWithoutUpdate(), reason, dur);
3977 }
3978 public static void makeImportant(PersonAPI person, String reason) {
3979 makeImportant(person.getMemoryWithoutUpdate(), reason, -1);
3980 }
3981 public static void makeImportant(PersonAPI person, String reason, float dur) {
3982 makeImportant(person.getMemoryWithoutUpdate(), reason, dur);
3983 }
3984 public static void makeImportant(MemoryAPI memory, String reason) {
3985 Misc.setFlagWithReason(memory, MemFlags.ENTITY_MISSION_IMPORTANT,
3986 reason, true, -1);
3987 }
3988 public static void makeImportant(MemoryAPI memory, String reason, float dur) {
3989 Misc.setFlagWithReason(memory, MemFlags.ENTITY_MISSION_IMPORTANT,
3990 reason, true, dur);
3991 }
3992
3993 public static boolean isImportantForReason(MemoryAPI memory, String reason) {
3994 String flagKey = MemFlags.ENTITY_MISSION_IMPORTANT;
3995 return flagHasReason(memory, flagKey, reason);
3996 }
3997
3998 public static void makeUnimportant(SectorEntityToken entity, String reason) {
3999 makeUnimportant(entity.getMemoryWithoutUpdate(), reason);
4000 }
4001 public static void makeUnimportant(PersonAPI person, String reason) {
4002 makeUnimportant(person.getMemoryWithoutUpdate(), reason);
4003 }
4004 public static void makeUnimportant(MemoryAPI memory, String reason) {
4005 Misc.setFlagWithReason(memory, MemFlags.ENTITY_MISSION_IMPORTANT,
4006 reason, false, 0);
4007 }
4008
4009 public static void cleanUpMissionMemory(MemoryAPI memory, String prefix) {
4010 List<String> unset = new ArrayList<String>();
4011 for (String key : memory.getKeys()) {
4012 if (key.startsWith("$" + prefix)) {
4013 unset.add(key);
4014 }
4015 }
4016 for (String key : unset) {
4017 memory.unset(key);
4018 }
4019
4020 if (prefix.endsWith("_")) {
4021 prefix = prefix.substring(0, prefix.length() - 1);
4022 }
4023
4024 Misc.setFlagWithReason(memory, MemFlags.ENTITY_MISSION_IMPORTANT,
4025 prefix, false, 0f);
4026 }
4027
4028
4029 public static void clearAreaAroundPlayer(float minDist) {
4030 CampaignFleetAPI player = Global.getSector().getPlayerFleet();
4031 if (player == null) return;
4032
4033 for (CampaignFleetAPI other : player.getContainingLocation().getFleets()) {
4034 if (player == other) continue;
4035 if (other.getBattle() != null) continue;
4036 if (other.getOrbit() != null) continue;
4037 if (!other.isHostileTo(player)) continue;
4038
4039 float dist = Misc.getDistance(player.getLocation(), other.getLocation());
4040 if (dist < minDist) {
4041 float angle = Misc.getAngleInDegrees(player.getLocation(), other.getLocation());
4043 v.scale(minDist);
4044 Vector2f.add(v, other.getLocation(), v);
4045 other.setLocation(v.x, v.y);
4046 }
4047 }
4048 }
4049
4050 public static long getSalvageSeed(SectorEntityToken entity) {
4051 return getSalvageSeed(entity, false);
4052 }
4053 public static long getSalvageSeed(SectorEntityToken entity, boolean nonRandom) {
4054 long seed = entity.getMemoryWithoutUpdate().getLong(MemFlags.SALVAGE_SEED);
4055 if (seed == 0) {
4056 //seed = new Random().nextLong();
4057 String id = entity.getId();
4058 if (id == null) id = genUID();
4059 if (nonRandom) {
4060 seed = (entity.getId().hashCode() * 17000) * 1181783497276652981L;
4061 } else {
4062 seed = seedUniquifier() ^ (entity.getId().hashCode() * 17000);
4063 }
4064 Random r = new Random(seed);
4065 for (int i = 0; i < 5; i++) {
4066 r.nextLong();
4067 }
4068 long result = r.nextLong();
4069 entity.getMemoryWithoutUpdate().set(MemFlags.SALVAGE_SEED, result);
4070 return result;
4071 }
4072 return seed;
4073 }
4074
4075 public static long getNameBasedSeed(SectorEntityToken entity) {
4076 String id = entity.getName();
4077 if (id == null) id = genUID();
4078
4079 long seed = (entity.getId().hashCode() * 17000);
4080 Random r = new Random(seed);
4081 for (int i = 0; i < 53; i++) {
4082 r.nextLong();
4083 }
4084 long result = r.nextLong();
4085 return result;
4086 }
4087
4088 public static void forgetAboutTransponder(CampaignFleetAPI fleet) {
4089 MemoryAPI mem = fleet.getMemoryWithoutUpdate();
4090 if (mem.getBoolean(MemFlags.MEMORY_KEY_MAKE_HOSTILE_WHILE_TOFF)) {
4091 mem.removeAllRequired(MemFlags.MEMORY_KEY_MAKE_HOSTILE_WHILE_TOFF);
4092 }
4093 mem.unset(MemFlags.MEMORY_KEY_SAW_PLAYER_WITH_TRANSPONDER_OFF);
4094 mem.unset(MemFlags.MEMORY_KEY_SAW_PLAYER_WITH_TRANSPONDER_ON);
4095 }
4096
4097 public static void setAbandonedStationMarket(String marketId, SectorEntityToken station) {
4098 station.getMemoryWithoutUpdate().set("$abandonedStation", true);
4099 MarketAPI market = Global.getFactory().createMarket(marketId, station.getName(), 0);
4100 market.setSurveyLevel(SurveyLevel.FULL);
4101 market.setPrimaryEntity(station);
4102 market.setFactionId(station.getFaction().getId());
4103 market.addCondition(Conditions.ABANDONED_STATION);
4104 market.addSubmarket(Submarkets.SUBMARKET_STORAGE);
4105 market.setPlanetConditionMarketOnly(false);
4106 ((StoragePlugin)market.getSubmarket(Submarkets.SUBMARKET_STORAGE).getPlugin()).setPlayerPaidToUnlock(true);
4107 station.setMarket(market);
4108 station.getMemoryWithoutUpdate().unset("$tradeMode");
4109 }
4110
4111 public static float getDesiredMoveDir(CampaignFleetAPI fleet) {
4112 if (fleet.getMoveDestination() == null) return 0f;
4113
4114 if (fleet.wasSlowMoving()) {
4115 Vector2f vel = fleet.getVelocity();
4116 Vector2f neg = new Vector2f(vel);
4117 neg.negate();
4118 return getAngleInDegrees(neg);
4119 }
4120
4121 return getAngleInDegrees(fleet.getLocation(), fleet.getMoveDestination());
4122 }
4123
4124 public static boolean isPermaKnowsWhoPlayerIs(CampaignFleetAPI fleet) {
4125 MemoryAPI mem = fleet.getMemoryWithoutUpdate();
4126 if (mem.contains(MemFlags.MEMORY_KEY_SAW_PLAYER_WITH_TRANSPONDER_ON) &&
4127 mem.getExpire(MemFlags.MEMORY_KEY_SAW_PLAYER_WITH_TRANSPONDER_ON) < 0) {
4128 return true;
4129 }
4130 return false;
4131 }
4132
4133
4134 public static ImmigrationPlugin getImmigrationPlugin(MarketAPI market) {
4135 ImmigrationPlugin plugin = Global.getSector().getPluginPicker().pickImmigrationPlugin(market);
4136 if (plugin == null) {
4137 plugin = new CoreImmigrationPluginImpl(market);
4138 }
4139 return plugin;
4140 }
4141
4142 public static AICoreAdminPlugin getAICoreAdminPlugin(String commodityId) {
4143 AICoreAdminPlugin plugin = Global.getSector().getPluginPicker().pickAICoreAdminPlugin(commodityId);
4144 return plugin;
4145 }
4146
4147 public static AICoreOfficerPlugin getAICoreOfficerPlugin(String commodityId) {
4148 AICoreOfficerPlugin plugin = Global.getSector().getPluginPicker().pickAICoreOfficerPlugin(commodityId);
4149 return plugin;
4150 }
4151
4152 public static AbandonMarketPlugin getAbandonMarketPlugin(MarketAPI market) {
4153 AbandonMarketPlugin plugin = Global.getSector().getGenericPlugins().pickPlugin(AbandonMarketPlugin.class, market);
4154 return plugin;
4155 }
4156
4157 public static StabilizeMarketPlugin getStabilizeMarketPlugin(MarketAPI market) {
4158 StabilizeMarketPlugin plugin = Global.getSector().getGenericPlugins().pickPlugin(StabilizeMarketPlugin.class, market);
4159 return plugin;
4160 }
4161
4162
4163 public static FleetInflater getInflater(CampaignFleetAPI fleet, Object params) {
4164 FleetInflater plugin = Global.getSector().getPluginPicker().pickFleetInflater(fleet, params);
4165 return plugin;
4166 }
4167
4168// public static float getIncomingRate(MarketAPI market, float weight) {
4169// ImmigrationPlugin plugin = getImmigrationPlugin(market);
4170// float diff = plugin.getWeightForMarketSize(market.getSize() + 1) -
4171// plugin.getWeightForMarketSize(market.getSize());
4172// if (diff <= 0) return 0f;
4173//
4174// //PopulationComposition incoming = market.getIncoming();
4175// return weight / diff;
4176//
4177// }
4178
4179 public static boolean playerHasStorageAccess(MarketAPI market) {
4180 SubmarketAPI storage = market.getSubmarket(Submarkets.SUBMARKET_STORAGE);
4181 if (storage != null && storage.getPlugin().getOnClickAction(null) == OnClickAction.OPEN_SUBMARKET) {
4182 return true;
4183 }
4184 return false;
4185 }
4186
4187 public static float getMarketSizeProgress(MarketAPI market) {
4188 ImmigrationPlugin plugin = getImmigrationPlugin(market);
4189 float min = plugin.getWeightForMarketSize(market.getSize());
4190 float max = plugin.getWeightForMarketSize(market.getSize() + 1);
4191
4192 float curr = market.getPopulation().getWeightValue();
4193
4194 if (max <= min) return 0f;
4195
4196 float f = (curr - min) / (max - min);
4197 if (f < 0) f = 0;
4198 if (f > 1) f = 1;
4199 return f;
4200 }
4201
4202
4203 public static float getStorageFeeFraction() {
4204 float storageFreeFraction = Global.getSettings().getFloat("storageFreeFraction");
4205 return storageFreeFraction;
4206 }
4207
4208 public static int getStorageCostPerMonth(MarketAPI market) {
4209 return (int) (getStorageTotalValue(market) * getStorageFeeFraction());
4210 }
4211
4212 public static SubmarketPlugin getStorage(MarketAPI market) {
4213 if (market == null) return null;
4214 SubmarketAPI submarket = market.getSubmarket(Submarkets.SUBMARKET_STORAGE);
4215 if (submarket == null) return null;
4216 return (StoragePlugin) submarket.getPlugin();
4217 }
4218
4219 public static SubmarketPlugin getLocalResources(MarketAPI market) {
4220 SubmarketAPI submarket = market.getSubmarket(Submarkets.LOCAL_RESOURCES);
4221 if (submarket == null) return null;
4222 return submarket.getPlugin();
4223 }
4224 public static CargoAPI getStorageCargo(MarketAPI market) {
4225 if (market == null) return null;
4226 SubmarketAPI submarket = market.getSubmarket(Submarkets.SUBMARKET_STORAGE);
4227 if (submarket == null) return null;
4228 return submarket.getCargo();
4229 }
4230
4231 public static CargoAPI getLocalResourcesCargo(MarketAPI market) {
4232 SubmarketAPI submarket = market.getSubmarket(Submarkets.LOCAL_RESOURCES);
4233 if (submarket == null) return null;
4234 return submarket.getCargo();
4235 }
4236
4237 public static float getStorageTotalValue(MarketAPI market) {
4238 return getStorageCargoValue(market) + getStorageShipValue(market);
4239 }
4240 public static float getStorageCargoValue(MarketAPI market) {
4241 SubmarketPlugin plugin = getStorage(market);
4242 if (plugin == null) return 0f;
4243 float value = 0f;
4244 for (CargoStackAPI stack : plugin.getCargo().getStacksCopy()) {
4245 value += stack.getSize() * stack.getBaseValuePerUnit();
4246 }
4247 return value;
4248 }
4249
4250 public static float getStorageShipValue(MarketAPI market) {
4251 SubmarketPlugin plugin = getStorage(market);
4252 if (plugin == null) return 0f;
4253 float value = 0f;
4254
4255 for (FleetMemberAPI member : plugin.getCargo().getMothballedShips().getMembersListCopy()) {
4256 value += member.getBaseValue();
4257 }
4258 return value;
4259 }
4260
4261
4266 public static boolean addStorageInfo(TooltipMakerAPI tooltip, Color color, Color dark, MarketAPI market,
4267 //boolean showFees,
4268 boolean includeLocalResources, boolean addSectionIfEmpty) {
4269 SubmarketPlugin storage = Misc.getStorage(market);
4270 SubmarketPlugin local = Misc.getLocalResources(market);
4271
4272 CargoAPI cargo = Global.getFactory().createCargo(true);
4274 if (storage != null) {
4275 cargo.addAll(storage.getCargo());
4276 ships.addAll(storage.getCargo().getMothballedShips().getMembersListCopy());
4277 }
4278 if (local != null && includeLocalResources) {
4279 cargo.addAll(local.getCargo());
4280 ships.addAll(local.getCargo().getMothballedShips().getMembersListCopy());
4281 }
4282
4283 float opad = 15f;
4284 if (!cargo.isEmpty() || addSectionIfEmpty) {
4285 String title = "Cargo in storage";
4286 if (includeLocalResources && local != null) {
4287 title = "Cargo in storage and resource stockpiles";
4288 }
4289 tooltip.addSectionHeading(title, color, dark, Alignment.MID, opad);
4290 opad = 10f;
4291 tooltip.showCargo(cargo, 10, true, opad);
4292 }
4293
4294 if (!ships.isEmpty() || addSectionIfEmpty) {
4295 String title = "Ships in storage";
4296 if (includeLocalResources && local != null) {
4297 title = "Ships in storage";
4298 }
4299 tooltip.addSectionHeading(title, color, dark, Alignment.MID, opad);
4300 opad = 10f;
4301 tooltip.showShips(ships, 10, true, opad);
4302 }
4303
4304 if (!market.isPlayerOwned()) {
4305 int cost = getStorageCostPerMonth(market);
4306 if (cost > 0) {
4307 tooltip.addPara("Monthly storage fee: %s", opad, getHighlightColor(), getDGSCredits(cost));
4308 }
4309 }
4310
4311 if (addSectionIfEmpty) return true;
4312
4313 return !cargo.isEmpty() || !ships.isEmpty();
4314 }
4315
4316 public static String getTokenReplaced(String in, SectorEntityToken entity) {
4317 in = Global.getSector().getRules().performTokenReplacement(null, in, entity, null);
4318 return in;
4319 }
4320
4321 public static float getOutpostPenalty() {
4322 return Global.getSettings().getFloat("colonyOverMaxPenalty");
4323 }
4324
4325
4326 public static float getAdminSalary(PersonAPI admin) {
4327 int tier = (int) admin.getMemoryWithoutUpdate().getFloat("$ome_adminTier");
4328 String salaryKey = "adminSalaryTier" + tier;
4329 float s = Global.getSettings().getInt(salaryKey);
4330 return s;
4331 }
4332
4333 public static float getOfficerSalary(PersonAPI officer) {
4334 return getOfficerSalary(officer, Misc.isMercenary(officer));
4335 }
4336 public static float getOfficerSalary(PersonAPI officer, boolean mercenary) {
4337 int officerBase = Global.getSettings().getInt("officerSalaryBase");
4338 int officerPerLevel = Global.getSettings().getInt("officerSalaryPerLevel");
4339
4340 float payMult = 1f;
4341 if (mercenary) {
4342 payMult = Global.getSettings().getFloat("officerMercPayMult");
4343 }
4344
4345 float salary = (officerBase + officer.getStats().getLevel() * officerPerLevel) * payMult;
4346 return salary;
4347 }
4348
4349// public static int getAccessibilityPercent(float a) {
4350// int result = (int) Math.round(a * 100f);
4351// if (a < 0 && result == 0) result = -1; // shipping penalty at "below zero"
4352// return result;
4353// }
4354
4356 //public static Map<String, Boolean> variantToIsBaseCache = new HashMap<String, Boolean>();
4358 //public static Map<String, String> hullIdToHasTag = new HashMap<String, String>();
4359 public static String getHullIdForVariantId(String variantId) {
4360 String hull = variantToHullCache.get(variantId);
4361 if (hull != null) return hull;
4362
4363 ShipVariantAPI variant = Global.getSettings().getVariant(variantId);
4364 hull = variant.getHullSpec().getHullId();
4365 variantToHullCache.put(variantId, hull);
4366
4367 return hull;
4368 }
4369
4370// public static boolean getIsBaseForVariantId(String variantId) {
4371// Boolean isBase = variantToIsBaseCache.get(variantId);
4372// if (isBase != null) return isBase;
4377// ShipVariantAPI variant = Global.getSettings().getVariant(variantId);
4378// isBase = variant.getHullSpec().hasTag(Items.TAG_BASE_BP);
4379// variantToIsBaseCache.put(variantId, isBase);
4380//
4381// return isBase;
4382// }
4383
4384 public static int getFPForVariantId(String variantId) {
4385 Integer fp = variantToFPCache.get(variantId);
4386 if (fp != null) return fp;
4387
4388 ShipVariantAPI variant = Global.getSettings().getVariant(variantId);
4389 fp = variant.getHullSpec().getFleetPoints();
4390 variantToFPCache.put(variantId, fp);
4391
4392 return fp;
4393 }
4394
4395 public static FactionPersonalityPickerPlugin getFactionPersonalityPicker() {
4396 return (FactionPersonalityPickerPlugin) Global.getSettings().getPlugin("factionPersonalityPicker");
4397 }
4398
4399
4400 public static float getAdjustedStrength(float fp, MarketAPI market) {
4401 fp *= Math.max(0.25f, 0.5f + Math.min(1f, Misc.getShipQuality(market)));
4402
4403 if (market != null) {
4404 float numShipsMult = market.getStats().getDynamic().getMod(Stats.COMBAT_FLEET_SIZE_MULT).computeEffective(0f);
4405 fp *= numShipsMult;
4406
4407 // float pts = market.getFaction().getDoctrine().getNumShips() + market.getFaction().getDoctrine().getOfficerQuality();
4408 // fp *= 1f + (pts - 2f) / 4f;
4409 float pts = market.getFaction().getDoctrine().getOfficerQuality();
4410 fp *= 1f + (pts - 1f) / 4f;
4411 }
4412 return fp;
4413 }
4414 public static float getAdjustedFP(float fp, MarketAPI market) {
4415 if (market != null) {
4416 float numShipsMult = market.getStats().getDynamic().getMod(Stats.COMBAT_FLEET_SIZE_MULT).computeEffective(0f);
4417 fp *= numShipsMult;
4418 }
4419 return fp;
4420 }
4421
4422 public static float getShipQuality(MarketAPI market) {
4423 return getShipQuality(market, null);
4424 }
4425 public static float getShipQuality(MarketAPI market, String factionId) {
4426 return ShipQuality.getShipQuality(market, factionId);
4427// float quality = 0f;
4428//
4429// if (market != null) {
4430// CommodityOnMarketAPI com = market.getCommodityData(Commodities.SHIPS);
4431//
4432// SupplierData sd = com.getSupplier();
4433// if (sd != null && sd.getMarket() != null) {
4434// quality = sd.getMarket().getStats().getDynamic().getMod(Stats.PRODUCTION_QUALITY_MOD).computeEffective(0f);
4435// if (factionId == null && sd.getMarket().getFaction() != market.getFaction()) {
4436// quality -= FleetFactoryV3.IMPORTED_QUALITY_PENALTY;
4437// } else if (factionId != null && !factionId.equals(sd.getMarket().getFactionId())) {
4438// quality -= FleetFactoryV3.IMPORTED_QUALITY_PENALTY;
4439// }
4440// }
4441//
4442// quality += market.getStats().getDynamic().getMod(Stats.FLEET_QUALITY_MOD).computeEffective(0f);
4443// }
4444//
4445//
4446// if (factionId == null) {
4447// //quality += market.getFaction().getDoctrine().getShipQualityContribution();
4448// } else {
4449// if (market != null) {
4450// quality -= market.getFaction().getDoctrine().getShipQualityContribution();
4451// }
4452// quality += Global.getSector().getFaction(factionId).getDoctrine().getShipQualityContribution();
4453// }
4454//
4455// return quality;
4456 }
4457
4458
4459 public static ShipPickMode getShipPickMode(MarketAPI market) {
4460 return getShipPickMode(market, null);
4461 }
4462 public static ShipPickMode getShipPickMode(MarketAPI market, String factionId) {
4463 QualityData d = ShipQuality.getInstance().getQualityData(market);
4464 if (d.market != null) {
4465 if (factionId == null && d.market.getFaction() != market.getFaction()) {
4466 return ShipPickMode.IMPORTED;
4467 } else if (factionId != null && !factionId.equals(d.market.getFactionId())) {
4468 return ShipPickMode.IMPORTED;
4469 }
4470 return ShipPickMode.PRIORITY_THEN_ALL;
4471 }
4472 return ShipPickMode.IMPORTED;
4473 }
4474
4475 public static boolean isBusy(CampaignFleetAPI fleet) {
4476 return fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.FLEET_BUSY);
4477 }
4478
4479 public static SectorEntityToken getStationEntity(MarketAPI market, CampaignFleetAPI fleet) {
4480 for (SectorEntityToken entity : market.getConnectedEntities()) {
4481 if (entity.hasTag(Tags.STATION)) {
4482 CampaignFleetAPI curr = getStationFleet(entity);
4483 if (curr != null && curr == fleet) return entity;
4484 }
4485 }
4486 return null;
4487 }
4488 public static CampaignFleetAPI getStationFleet(MarketAPI market) {
4489 for (SectorEntityToken entity : market.getConnectedEntities()) {
4490 if (entity.hasTag(Tags.STATION)) {
4491 CampaignFleetAPI fleet = getStationFleet(entity);
4492 if (fleet != null) return fleet;
4493 }
4494 }
4495 return null;
4496 }
4497 public static CampaignFleetAPI getStationFleet(SectorEntityToken station) {
4498 if (station.hasTag(Tags.STATION)) {// && station instanceof CustomCampaignEntityAPI) {
4499 Object test = station.getMemoryWithoutUpdate().get(MemFlags.STATION_FLEET);
4500 if (test instanceof CampaignFleetAPI) {
4501 return (CampaignFleetAPI) test;
4502 }
4503 }
4504 return null;
4505 }
4506
4507 public static CampaignFleetAPI getStationBaseFleet(MarketAPI market) {
4508 for (SectorEntityToken entity : market.getConnectedEntities()) {
4509 if (entity.hasTag(Tags.STATION)) {
4510 CampaignFleetAPI fleet = getStationBaseFleet(entity);
4511 if (fleet != null) return fleet;
4512 }
4513 }
4514 return null;
4515 }
4516 public static CampaignFleetAPI getStationBaseFleet(SectorEntityToken station) {
4517 if (station.hasTag(Tags.STATION)) {// && station instanceof CustomCampaignEntityAPI) {
4518 Object test = station.getMemoryWithoutUpdate().get(MemFlags.STATION_BASE_FLEET);
4519 if (test instanceof CampaignFleetAPI) {
4520 return (CampaignFleetAPI) test;
4521 }
4522 }
4523 return null;
4524 }
4525
4526 public static MarketAPI getStationMarket(CampaignFleetAPI station) {
4527 Object test = station.getMemoryWithoutUpdate().get(MemFlags.STATION_MARKET);
4528 if (test instanceof MarketAPI) {
4529 return (MarketAPI) test;
4530 }
4531 return null;
4532 }
4533
4534 public static Industry getStationIndustry(MarketAPI market) {
4535 for (Industry ind : market.getIndustries()) {
4536 if (ind.getSpec().hasTag(Industries.TAG_STATION)) {
4537 return ind;
4538 }
4539 }
4540 return null;
4541 }
4542
4543 public static boolean isActiveModule(ShipVariantAPI variant) {
4544 boolean notActiveModule = variant.getHullSpec().getOrdnancePoints(null) <= 0 &&
4545 variant.getWeaponGroups().isEmpty() &&
4546 variant.getHullSpec().getFighterBays() <= 0;
4547 return !notActiveModule;
4548 }
4549 public static boolean isActiveModule(ShipAPI ship) {
4550 boolean notActiveModule = ship.getVariant().getHullSpec().getOrdnancePoints(null) <= 0 &&
4551 ship.getVariant().getWeaponGroups().isEmpty() &&
4552 ship.getMutableStats().getNumFighterBays().getModifiedValue() <= 0;
4553 return !notActiveModule;
4554 }
4555
4556 public static void addCreditsMessage(String format, int credits) {
4557 Global.getSector().getCampaignUI().getMessageDisplay().addMessage(
4559 }
4560
4561
4563 for (JumpDestination d : jp.getDestinations()) {
4564 if (d.getDestination() != null && d.getDestination().getContainingLocation() != null &&
4565 d.getDestination().getContainingLocation().isHyperspace()) {
4566 return d.getDestination().getLocation();
4567 }
4568 }
4569 return jp.getLocationInHyperspace();
4570 }
4571
4572
4573 public static boolean isNear(SectorEntityToken entity, Vector2f hyperLoc) {
4574 float maxRange = Global.getSettings().getFloat("commRelayRangeAroundSystem");
4575 float dist = Misc.getDistanceLY(entity.getLocationInHyperspace(), hyperLoc);
4576 if (dist > maxRange) return false;
4577 return true;
4578 }
4579
4580 public static float getDays(float amount) {
4581 return Global.getSector().getClock().convertToDays(amount);
4582 }
4583
4584 public static float getProbabilityMult(float desired, float current, float deviationMult) {
4586 float exponent = (desired - current) / deviation;
4587 if (exponent > 4) exponent = 4;
4588 float probMult = (float) Math.pow(10f, exponent);
4589 return probMult;
4590 }
4591
4592 public static boolean isHyperspaceAnchor(SectorEntityToken entity) {
4593 return entity != null && entity.hasTag(Tags.SYSTEM_ANCHOR);
4594 }
4595
4596 public static StarSystemAPI getStarSystemForAnchor(SectorEntityToken anchor) {
4597 return (StarSystemAPI) anchor.getMemoryWithoutUpdate().get(MemFlags.STAR_SYSTEM_IN_ANCHOR_MEMORY);
4598 }
4599
4600 public static void showCost(TextPanelAPI text, Color color, Color dark, String [] res, int [] quantities) {
4601 showCost(text, "Resources: consumed (available)", true, color, dark, res, quantities);
4602 }
4603 public static void showCost(TextPanelAPI text, String title, boolean withAvailable, Color color, Color dark, String [] res, int [] quantities) {
4604 showCost(text, title, withAvailable, -1f, color, dark, res, quantities, null);
4605 }
4606 public static void showCost(TextPanelAPI text, String title, boolean withAvailable, float widthOverride, Color color, Color dark, String [] res, int [] quantities, boolean [] consumed) {
4607 if (color == null) color = getBasePlayerColor();
4608 if (dark == null) dark = getDarkPlayerColor();
4609
4612
4613 CargoAPI cargo = Global.getSector().getPlayerFleet().getCargo();
4614
4615 for (int i = 0; i < res.length; i++) {
4616 String commodityId = res[i];
4617 int quantity = quantities[i];
4618 if (quantity > cargo.getQuantity(CargoItemType.RESOURCES, commodityId)) {
4619 unmet.add(commodityId);
4620 }
4621 all.add(commodityId);
4622 }
4623
4624 float costHeight = 67;
4625 ResourceCostPanelAPI cost = text.addCostPanel(title, costHeight,
4626 color, dark);
4627 cost.setNumberOnlyMode(true);
4628 cost.setWithBorder(false);
4629 cost.setAlignment(Alignment.LMID);
4630
4631 if (widthOverride > 0) {
4632 cost.setComWidthOverride(widthOverride);
4633 }
4634
4635 boolean dgs = true;
4636 for (int i = 0; i < res.length; i++) {
4637 String commodityId = res[i];
4638 int required = quantities[i];
4639 int available = (int) cargo.getCommodityQuantity(commodityId);
4640 Color curr = color;
4641 if (withAvailable && required > cargo.getQuantity(CargoItemType.RESOURCES, commodityId)) {
4643 }
4644 if (dgs) {
4645 if (withAvailable) {
4646 cost.addCost(commodityId, Misc.getWithDGS(required) + " (" + Misc.getWithDGS(available) + ")", curr);
4647 } else {
4648 cost.addCost(commodityId, Misc.getWithDGS(required), curr);
4649 }
4650 if (consumed != null && consumed[i]) {
4651 cost.setLastCostConsumed(true);
4652 }
4653 } else {
4654 if (withAvailable) {
4655 cost.addCost(commodityId, "" + required + " (" + available + ")", curr);
4656 } else {
4657 cost.addCost(commodityId, "" + required, curr);
4658 }
4659 if (consumed != null && consumed[i]) {
4660 cost.setLastCostConsumed(true);
4661 }
4662 }
4663 }
4664 cost.update();
4665 }
4666
4667 public static boolean isPlayerFactionSetUp() {
4668 String key = "$shownFactionConfigDialog";
4669 if (Global.getSector().getMemoryWithoutUpdate().contains(key)) {
4670 return true;
4671 }
4672 return false;
4673 }
4674
4675 public static boolean isPatrol(CampaignFleetAPI fleet) {
4676 return fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_PATROL_FLEET);
4677 }
4678 public static boolean isSmuggler(CampaignFleetAPI fleet) {
4679 return fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_SMUGGLER);
4680 }
4681 public static boolean isTrader(CampaignFleetAPI fleet) {
4682 return fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_TRADE_FLEET);
4683 }
4684 public static boolean isPirate(CampaignFleetAPI fleet) {
4685 return fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_PIRATE);
4686 }
4687 public static boolean isScavenger(CampaignFleetAPI fleet) {
4688 return fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_SCAVENGER);
4689 }
4690 public static boolean isRaider(CampaignFleetAPI fleet) {
4691 return fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_RAIDER);
4692 }
4693 public static boolean isWarFleet(CampaignFleetAPI fleet) {
4694 return fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_WAR_FLEET);
4695 }
4696
4697
4704 SectorEntityToken closestEntity = null;
4705 CampaignFleetAPI closest = null;
4706 float minDist = Float.MAX_VALUE;
4707 for (SectorEntityToken station : from.getContainingLocation().getCustomEntitiesWithTag(Tags.STATION)) {
4708 CampaignFleetAPI fleet = Misc.getStationFleet(station);
4709 if (fleet == null || fleet.isEmpty()) continue;
4710
4711 if (!isStationInSupportRange(from, fleet)) continue;
4712 float dist = Misc.getDistance(from.getLocation(), station.getLocation());
4713
4714 if (dist < minDist) {
4715 closest = fleet;
4716 closestEntity = station;
4717 minDist = dist;
4718 }
4719 }
4720
4721 // remnant stations and other fleets that are in station mode, w/o a related market
4722 for (CampaignFleetAPI fleet : from.getContainingLocation().getFleets()) {
4723 if (!fleet.isStationMode()) continue;
4724 if (fleet.isHidden()) continue;
4725
4726 if (!isStationInSupportRange(from, fleet)) continue;
4727 float dist = Misc.getDistance(from.getLocation(), fleet.getLocation());
4728
4729 if (dist < minDist) {
4730 closest = fleet;
4731 closestEntity = null;
4732 minDist = dist;
4733 }
4734 }
4735
4736 if (closest == null) return null;
4737
4739 }
4740
4741 public static boolean isStationInSupportRange(CampaignFleetAPI fleet, CampaignFleetAPI station) {
4742 float check = Misc.getBattleJoinRange();
4743 float distPrimary = 10000f;
4744 MarketAPI market = getStationMarket(station);
4745 if (market != null) {
4746 distPrimary = Misc.getDistance(fleet.getLocation(), market.getPrimaryEntity().getLocation());
4747 }
4748 float distStation = Misc.getDistance(fleet.getLocation(), station.getLocation());
4749
4750 if (distPrimary > check && distStation > check) {
4751 return false;
4752 }
4753 return true;
4754
4755 }
4756
4757
4758 public static float getMemberStrength(FleetMemberAPI member) {
4759 return getMemberStrength(member, true, true, true);
4760 }
4761
4762 public static float getMemberStrength(FleetMemberAPI member, boolean withHull, boolean withQuality, boolean withCaptain) {
4763 float str = member.getMemberStrength();
4764 float min = 0.25f;
4765 if (str < min) str = min;
4766
4767 float quality = 0.5f;
4768 float sMods = 0f;
4769 if (member.getFleetData() != null && member.getFleetData().getFleet() != null) {
4770 CampaignFleetAPI fleet = member.getFleetData().getFleet();
4771 if (fleet.getInflater() != null && !fleet.isInflated()) {
4772 quality = fleet.getInflater().getQuality();
4773 sMods = fleet.getInflater().getAverageNumSMods();
4774 } else {
4775 BattleAPI battle = fleet.getBattle();
4776 CampaignFleetAPI source = battle == null ? null : battle.getSourceFleet(member);
4777 if (source != null && source.getInflater() != null &&
4778 !source.isInflated()) {
4779 quality = source.getInflater().getQuality();
4780 sMods = source.getInflater().getAverageNumSMods();
4781 } else {
4782 float dmods = DModManager.getNumDMods(member.getVariant());
4783 quality = 1f - Global.getSettings().getFloat("qualityPerDMod") * dmods;
4784 if (quality < 0) quality = 0f;
4785
4786 sMods = member.getVariant().getSMods().size();
4787 }
4788 }
4789 }
4790
4791 if (member.isStation()) {
4792 quality = 1f;
4793 }
4794
4795 if (sMods > 0) {
4796 quality += sMods * Global.getSettings().getFloat("qualityPerSMod");
4797 }
4798
4799 float captainMult = 1f;
4800 if (member.getCaptain() != null) {
4801 float captainLevel = (member.getCaptain().getStats().getLevel() - 1f);
4802 if (member.isStation()) {
4804 } else {
4806 }
4807 }
4808
4809 if (withQuality) {
4810 //str *= Math.max(0.25f, 0.5f + quality);
4811 str *= Math.max(0.25f, 0.8f + quality * 0.4f);
4812 }
4813 if (withHull) {
4814 str *= 0.5f + 0.5f * member.getStatus().getHullFraction();
4815 }
4816 if (withCaptain) {
4817 str *= captainMult;
4818 }
4819 //System.out.println("Member: " + member + ", str: " + str);
4820
4821 return str;
4822 }
4823
4824
4825 public static void increaseMarketHostileTimeout(MarketAPI market, float days) {
4826 MemoryAPI mem = market.getMemoryWithoutUpdate();
4827 float expire = days;
4828 if (mem.contains(MemFlags.MEMORY_KEY_PLAYER_HOSTILE_ACTIVITY_NEAR_MARKET)) {
4829 expire += mem.getExpire(MemFlags.MEMORY_KEY_PLAYER_HOSTILE_ACTIVITY_NEAR_MARKET);
4830 }
4831 if (expire > 180) expire = 180;
4832 if (expire > 0) {
4833 mem.set(MemFlags.MEMORY_KEY_PLAYER_HOSTILE_ACTIVITY_NEAR_MARKET, true, expire);
4834 }
4835 }
4836
4837 public static void removeRadioChatter(MarketAPI market) {
4838 if (market.getContainingLocation() == null) return;
4839 for (CampaignTerrainAPI terrain : market.getContainingLocation().getTerrainCopy()) {
4840 if (Terrain.RADIO_CHATTER.equals(terrain.getType())) {
4841 float dist = Misc.getDistance(terrain, market.getPrimaryEntity());
4842 if (dist < 200) {
4843 market.getContainingLocation().removeEntity(terrain);
4844 }
4845 }
4846 }
4847 }
4848
4849
4853
4858
4859
4860 public static LabelAPI addDesignTypePara(TooltipMakerAPI tooltip, String design, float pad) {
4861 if (design != null && !design.isEmpty()) {
4862 return tooltip.addPara("Design type: %s", pad, Misc.getGrayColor(), Global.getSettings().getDesignTypeColor(design), design);
4863 }
4864 return null;
4865 }
4866
4867 public static float getFleetRadiusTerrainEffectMult(CampaignFleetAPI fleet) {
4870 float radius = fleet.getRadius();
4871
4872 //radius = 1000;
4873
4874 float mult = (radius - min) / (max - min);
4875 if (mult > 1) mult = 1;
4876 //if (mult < 0) mult = 0;
4878 //mult = MIN_BURN_PENALTY + mult * BURN_PENALTY_RANGE;
4879
4880 float skillMod = fleet.getCommanderStats().getDynamic().getValue(Stats.NAVIGATION_PENALTY_MULT);
4881 mult *= skillMod;
4882
4883 mult = Math.round(mult * 100f) / 100f;
4884
4885 return mult;
4886 }
4887
4888 public static float MIN_TERRAIN_EFFECT_MULT = Global.getSettings().getFloat("minTerrainEffectMult");
4889 public static float BURN_PENALTY_MULT = Global.getSettings().getFloat("standardBurnPenaltyMult");
4890 public static float getBurnMultForTerrain(CampaignFleetAPI fleet) {
4891 float mult = getFleetRadiusTerrainEffectMult(fleet);
4892 mult = (1f - BURN_PENALTY_MULT * mult);
4893 mult = Math.round(mult * 100f) / 100f;
4894 if (mult < 0.1f) mult = 0.1f;
4895// if (mult > 1) mult = 1;
4896 return mult;
4897 }
4898
4899
4900 public static void addHitGlow(LocationAPI location, Vector2f loc, Vector2f vel, float size, Color color) {
4901 float dur = 1f + (float) Math.random();
4902 addHitGlow(location, loc, vel, size, dur, color);
4903 }
4904 public static void addHitGlow(LocationAPI location, Vector2f loc, Vector2f vel, float size, float dur, Color color) {
4905 location.addHitParticle(loc, vel,
4906 size, 0.4f, dur, color);
4907 location.addHitParticle(loc, vel,
4908 size * 0.25f, 0.4f, dur, color);
4909 location.addHitParticle(loc, vel,
4910 size * 0.15f, 1f, dur, Color.white);
4911 }
4912
4913 public static ParticleControllerAPI [] addGlowyParticle(LocationAPI location, Vector2f loc, Vector2f vel, float size, float rampUp, float dur, Color color) {
4914 //rampUp = 0f;
4915 //dur = 3f;
4916
4917 ParticleControllerAPI [] result = new ParticleControllerAPI[3];
4918
4919 result[0] = location.addParticle(loc, vel,
4920 size, 0.4f, rampUp, dur, color);
4921 result[1] = location.addParticle(loc, vel,
4922 size * 0.25f, 0.4f, rampUp, dur, color);
4923 result[2] = location.addParticle(loc, vel,
4924 size * 0.15f, 1f, rampUp, dur, Color.white);
4925
4926 return result;
4927 }
4928
4929
4930 public static float SAME_FACTION_BONUS = Global.getSettings().getFloat("accessibilitySameFactionBonus");
4931 public static float PER_UNIT_SHIPPING = Global.getSettings().getFloat("accessibilityPerUnitShipping");
4932
4933 public static int getShippingCapacity(MarketAPI market, boolean inFaction) {
4934 float a = Math.round(market.getAccessibilityMod().computeEffective(0f) * 100f) / 100f;
4935 if (inFaction) {
4937 }
4938 return (int) Math.max(0, a / PER_UNIT_SHIPPING);
4939 }
4940
4941 public static String getStrengthDesc(float strAdjustedFP) {
4943 if (strAdjustedFP < 50) {
4944 strDesc = "very weak";
4945 } else if (strAdjustedFP < 150) {
4946 strDesc = "somewhat weak";
4947 } else if (strAdjustedFP < 300) {
4948 strDesc = "fairly capable";
4949 } else if (strAdjustedFP < 750) {
4950 strDesc = "fairly strong";
4951 } else if (strAdjustedFP < 1250) {
4952 strDesc = "strong";
4953 } else {
4954 strDesc = "very strong";
4955 }
4956 return strDesc;
4957 }
4958
4959 public static boolean isMilitary(MarketAPI market) {
4960 return market != null && market.getMemoryWithoutUpdate().getBoolean(MemFlags.MARKET_MILITARY);
4961 }
4962
4963 public static boolean hasHeavyIndustry(MarketAPI market) {
4964 boolean heavyIndustry = false;
4965 for (Industry curr : market.getIndustries()) {
4966 if (curr.getSpec().hasTag(Industries.TAG_HEAVYINDUSTRY)) {
4967 heavyIndustry = true;
4968 }
4969 }
4970 return heavyIndustry;
4971 }
4972
4973 public static boolean hasOrbitalStation(MarketAPI market) {
4974 for (Industry curr : market.getIndustries()) {
4975 if (curr.getSpec().hasTag(Industries.TAG_STATION)) {
4976 return true;
4977 }
4978 }
4979 return false;
4980 }
4981
4982 public static FactionAPI getClaimingFaction(SectorEntityToken planet) {
4983 if (planet.getStarSystem() != null) {
4984 String claimedBy = planet.getStarSystem().getMemoryWithoutUpdate().getString(MemFlags.CLAIMING_FACTION);
4985 if (claimedBy != null) {
4986 return Global.getSector().getFaction(claimedBy);
4987 }
4988 }
4989
4990 int max = 0;
4991 MarketAPI result = null;
4992 List<MarketAPI> markets = Global.getSector().getEconomy().getMarkets(planet.getContainingLocation());
4993 for (MarketAPI curr : markets) {
4994 if (curr.isHidden()) continue;
4995 if (curr.getFaction().isPlayerFaction()) continue;
4996
4997 int score = curr.getSize();
4998 for (MarketAPI other : markets) {
4999 if (other != curr && other.getFaction() == curr.getFaction()) score++;
5000 }
5001 if (isMilitary(curr)) score += 10;
5002 if (score > max) {
5003 JSONObject json = curr.getFaction().getCustom().optJSONObject(Factions.CUSTOM_PUNITIVE_EXPEDITION_DATA);
5004 if (json == null) continue;
5005 boolean territorial = json.optBoolean("territorial");
5006 if (!territorial) continue;
5007
5008 max = score;
5009 result = curr;
5010 }
5011 }
5012 if (result == null) return null;
5013
5014 return result.getFaction();
5015 }
5016
5017
5018 public static int computeTotalShutdownRefund(MarketAPI market) {
5019 int total = 0;
5020 for (Industry industry : market.getIndustries()) {
5021 total += computeShutdownRefund(market, industry);
5022 }
5023
5024 // since incentives no longer work this way...
5025// float refundFraction = Global.getSettings().getFloat("industryRefundFraction");
5026// float incentives = market.getIncentiveCredits() * refundFraction;
5027// total += incentives;
5028
5029 return total;
5030 }
5031
5032 public static int computeShutdownRefund(MarketAPI market, Industry industry) {
5033 float refund = 0;
5034
5035 Industry upInd = null;
5036 if (industry.isUpgrading()) {
5037 String up = industry.getSpec().getUpgrade();
5038 if (up != null) {
5039 upInd = market.instantiateIndustry(up);
5040 }
5041 }
5042 if (industry.isUpgrading() && upInd != null) {
5043 refund += upInd.getBuildCost();
5044 }
5045
5046 float refundFraction = Global.getSettings().getFloat("industryRefundFraction");
5047 Industry curr = industry;
5048 while (curr != null) {
5049 if (curr.isBuilding() && !curr.isUpgrading()) {
5050 refund += curr.getBuildCost();
5051 } else {
5052 refund += curr.getBuildCost() * refundFraction;
5053 }
5054 String down = curr.getSpec().getDowngrade();
5055 if (down != null) {
5056 curr = market.instantiateIndustry(down);
5057 } else {
5058 curr = null;
5059 }
5060 }
5061
5062 return (int) refund;
5063 }
5064
5065
5066 public static SectorEntityToken addWarningBeacon(SectorEntityToken center, OrbitGap gap, String beaconTag) {
5067 CustomCampaignEntityAPI beacon = center.getContainingLocation().addCustomEntity(null, null, Entities.WARNING_BEACON, Factions.NEUTRAL);
5068 beacon.addTag(beaconTag);
5069
5070 float radius = (gap.start + gap.end) / 2f;
5071 float orbitDays = radius / (10f + StarSystemGenerator.random.nextFloat() * 5f);
5072 beacon.setCircularOrbitPointingDown(center, StarSystemGenerator.random.nextFloat() * 360f, radius, orbitDays);
5073
5074 Color glowColor = new Color(255,200,0,255);
5075 Color pingColor = new Color(255,200,0,255);
5076 if (beaconTag.equals(Tags.BEACON_MEDIUM)) {
5077 glowColor = new Color(250,155,0,255);
5078 pingColor = new Color(250,155,0,255);
5079 } else if (beaconTag.equals(Tags.BEACON_HIGH)) {
5080 glowColor = new Color(250,55,0,255);
5081 pingColor = new Color(250,125,0,255);
5082 }
5083 Misc.setWarningBeaconColors(beacon, glowColor, pingColor);
5084 return beacon;
5085 }
5086
5087
5088 public static CoreUITradeMode getTradeMode(MemoryAPI memory) {
5089 CoreUITradeMode mode = CoreUITradeMode.OPEN;
5090 String val = memory.getString("$tradeMode");
5091 if (val != null && !val.isEmpty()) {
5092 mode = CoreUITradeMode.valueOf(val);
5093 }
5094 return mode;
5095 }
5096
5097 public static boolean isSpacerStart() {
5098 return Global.getSector().getMemoryWithoutUpdate().getBoolean("$spacerStart");
5099 }
5100
5101 public static Industry getSpaceport(MarketAPI market) {
5102 for (Industry ind : market.getIndustries()) {
5103 if (ind.getSpec().hasTag(Industries.TAG_SPACEPORT)) {
5104 return ind;
5105 }
5106 }
5107 return null;
5108 }
5109
5110 public static Color setBrightness(Color color, int brightness) {
5111 float max = color.getRed();
5112 if (color.getGreen() > max) max = color.getGreen();
5113 if (color.getBlue() > max) max = color.getBlue();
5114 float f = brightness / max;
5115 color = scaleColorSaturate(color, f);
5116 return color;
5117 }
5118
5119 public static Color scaleColorSaturate(Color color, float factor) {
5120 int red = (int) (color.getRed() * factor);
5121 int green = (int) (color.getGreen() * factor);
5122 int blue = (int) (color.getBlue() * factor);
5123 int alpha = (int) (color.getAlpha() * factor);
5124
5125 if (red > 255) red = 255;
5126 if (green > 255) green = 255;
5127 if (blue > 255) blue = 255;
5128 if (alpha > 255) alpha = 255;
5129
5130 return new Color(red, green, blue, alpha);
5131 }
5132
5133 public static int getMaxOfficers(CampaignFleetAPI fleet) {
5134 int max = (int) fleet.getCommander().getStats().getOfficerNumber().getModifiedValue();
5135 return max;
5136 }
5137 public static int getNumNonMercOfficers(CampaignFleetAPI fleet) {
5138 int count = 0;
5139 for (OfficerDataAPI od : fleet.getFleetData().getOfficersCopy()) {
5140 if (!isMercenary(od.getPerson())) {
5141 count++;
5142 }
5143 }
5144 return count;
5145 }
5146
5147 public static List<OfficerDataAPI> getMercs(CampaignFleetAPI fleet) {
5149 for (OfficerDataAPI od : fleet.getFleetData().getOfficersCopy()) {
5150 if (isMercenary(od.getPerson())) {
5151 mercs.add(od);
5152 }
5153 }
5154 return mercs;
5155 }
5156
5157
5158 public static int getMaxIndustries(MarketAPI market) {
5159 return (int)Math.round(market.getStats().getDynamic().getMod(Stats.MAX_INDUSTRIES).computeEffective(0));
5160 }
5161
5162 public static int getNumIndustries(MarketAPI market) {
5163 int count = 0;
5164 for (Industry curr : market.getIndustries()) {
5165 if (curr.isIndustry()) {
5166 count++;
5167 } else if (curr.isUpgrading()) {
5168 String up = curr.getSpec().getUpgrade();
5169 if (up != null) {
5170 Industry upInd = market.instantiateIndustry(up);
5171 if (upInd.isIndustry()) count++;
5172 }
5173 }
5174 }
5175 for (ConstructionQueueItem item : market.getConstructionQueue().getItems()) {
5176 IndustrySpecAPI spec = Global.getSettings().getIndustrySpec(item.id);
5177 if (spec.hasTag(Industries.TAG_INDUSTRY)) count++;
5178 }
5179 return count;
5180 }
5181
5182 public static int getNumImprovedIndustries(MarketAPI market) {
5183 int count = 0;
5184 for (Industry curr : market.getIndustries()) {
5185 if (curr.isImproved()) {
5186 count++;
5187 }
5188 }
5189 return count;
5190 }
5191
5192 public static int getNumStableLocations(StarSystemAPI system) {
5193 int count = system.getEntitiesWithTag(Tags.STABLE_LOCATION).size();
5194 count += system.getEntitiesWithTag(Tags.OBJECTIVE).size();
5195 for (SectorEntityToken e : system.getJumpPoints()) {
5196 if (e instanceof JumpPointAPI) {
5197 JumpPointAPI jp = (JumpPointAPI) e;
5198 if (jp.isWormhole()) count++;
5199 }
5200 }
5201 return count;
5202 }
5203
5204 public static Industry getCurrentlyBeingConstructed(MarketAPI market) {
5205 for (Industry curr : market.getIndustries()) {
5206 if (curr.getSpec().hasTag(Industries.TAG_POPULATION)) continue;
5207
5208 if (curr.isBuilding() && !curr.isUpgrading()) {
5209 return curr;
5210 }
5211 }
5212 return null;
5213 }
5214
5215 public static Color getRelColor(float rel) {
5216 Color relColor = new Color(125,125,125,255);
5217 if (rel > 1) rel = 1;
5218 if (rel < -1) rel = -1;
5219
5220 if (rel > 0) {
5222 } else if (rel < 0) {
5224 }
5225 return relColor;
5226 }
5227
5228 public static MusicPlayerPlugin musicPlugin = null;
5230 if (musicPlugin == null) {
5232 }
5233 return musicPlugin;
5234 }
5235
5236
5237
5238 public static String DANGER_LEVEL_OVERRIDE = "$dangerLevelOverride";
5239 public static int getDangerLevel(CampaignFleetAPI fleet) {
5240 if (fleet.getMemoryWithoutUpdate().contains(DANGER_LEVEL_OVERRIDE)) {
5241 return (int) fleet.getMemoryWithoutUpdate().getFloat(DANGER_LEVEL_OVERRIDE);
5242 }
5243
5244 CampaignFleetAPI pf = Global.getSector().getPlayerFleet();
5245
5246 float playerStr = 0f;
5247 float fleetStr = 0f;
5248 for (FleetMemberAPI member : pf.getFleetData().getMembersListCopy()) {
5249 float strength = Misc.getMemberStrength(member, true, true, true);
5250 playerStr += strength;
5251 }
5252
5253 for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) {
5254 float strength = Misc.getMemberStrength(member, true, true, true);
5255 fleetStr += strength;
5256 }
5257
5258 if (playerStr > fleetStr * 3f) return 1;
5259 if (playerStr > fleetStr * 1.5f) return 2;
5260 if (playerStr > fleetStr * 0.75f) return 3;
5261 if (playerStr > fleetStr * 0.33f) return 4;
5262 return 5;
5263 }
5264
5265
5266 public static float getHitGlowSize(float baseSize, float baseDamage, ApplyDamageResultAPI result) {
5267 if (result == null || baseDamage <= 0) return baseSize;
5268
5269 float sd = result.getDamageToShields() + result.getOverMaxDamageToShields();
5270 float ad = result.getTotalDamageToArmor();
5271 float hd = result.getDamageToHull();
5272 float ed = result.getEmpDamage();
5273 DamageType type = result.getType();
5274 return getHitGlowSize(baseSize, baseDamage, type, sd, ad, hd, ed);
5275 }
5276
5277
5278 public static float getHitGlowSize(float baseSize, float baseDamage, DamageType type, float sd, float ad, float hd, float ed) {
5279
5280 float minBonus = 0f;
5281 if (type == DamageType.KINETIC) {
5282 sd *= 0.5f;
5283 //if (sd > 0) minBonus = 0.1f;
5284 } else if (type == DamageType.HIGH_EXPLOSIVE) {
5285 ad *= 0.5f;
5286 if (ad > 0) minBonus = 0.1f;
5287 } else if (type == DamageType.FRAGMENTATION) {
5288 if (hd > 0) {
5289 minBonus = 0.2f * (hd / (hd + ad));
5290 }
5291 sd *= 2f;
5292 ad *= 2f;
5293 hd *= 2f;
5294 }
5295
5296 float totalDamage = sd + ad + hd;
5297 if (totalDamage <= 0) return baseSize;
5298
5299 // emp damage makes the hitglow normal-sized, but not bigger
5300 if (totalDamage < baseDamage) {
5301 totalDamage += ed;
5302 if (totalDamage > baseDamage) {
5304 }
5305 }
5306
5307 float minSize = 15f;
5308 float minMult = minSize / baseSize;
5309 minMult = Math.max(minMult, 0.67f + minBonus);
5310 if (minMult > 1) minMult = 1;
5311
5312 float mult = totalDamage / baseDamage;
5313 if (mult < minMult) mult = minMult;
5314
5315 float maxMult = 1.5f;
5316 if (mult > maxMult) mult = maxMult;
5317 //mult = maxMult;
5318 //mult = 1f;
5319 //System.out.println("Mult: " + mult);
5320 return baseSize * mult;
5321 }
5322
5323 public static int getNumEliteSkills(PersonAPI person) {
5324 int count = 0;
5325 for (SkillLevelAPI sl : person.getStats().getSkillsCopy()) {
5326 if (sl.getLevel() >= 2) count++;
5327 }
5328 return count;
5329 }
5330
5331
5332// public static void spawnExtraHitGlow(Object param, Vector2f loc, Vector2f vel, float intensity) {
5333// if (param instanceof DamagingProjectileAPI) {
5334// DamagingProjectileAPI proj = (DamagingProjectileAPI) param;
5335// ProjectileSpecAPI spec = proj.getProjectileSpec();
5336// if (spec != null) {
5337// CombatEngineAPI engine = Global.getCombatEngine();
5338// float base = spec.getHitGlowRadius();
5339// if (base == 0) base = spec.getLength() * 1.0f;
5340// float size = base * (1f + 1f * intensity) * 0.5f;
5341// if (size < 20) return;
5342//
5343// Color color = Misc.interpolateColor(spec.getFringeColor(), spec.getCoreColor(), 0.25f);
5344// engine.addHitParticle(loc, vel, size, 0.75f * intensity, color);
5345// }
5346// } else if (param instanceof BeamAPI) {
5347// BeamAPI beam = (BeamAPI) param;
5348// CombatEngineAPI engine = Global.getCombatEngine();
5349// float size = beam.getHitGlowRadius() * (1f + intensity) * 0.5f;
5350// if (size < 20) return;
5351//
5352// Color color = Misc.interpolateColor(beam.getFringeColor(), beam.getCoreColor(), 0.25f);
5353// engine.addHitParticle(loc, vel, size, 0.75f * intensity, color);
5354// }
5355// }
5356
5357 public static String MENTORED = "$mentored";
5358 public static boolean isMentored(PersonAPI person) {
5359 return person.getMemoryWithoutUpdate().is(MENTORED, true);
5360 }
5361
5362 public static void setMentored(PersonAPI person, boolean mentored) {
5363 person.getMemoryWithoutUpdate().set(MENTORED, mentored);
5364 }
5365
5366 public static final String IS_MERCENARY = "$isMercenary";
5367 public static boolean isMercenary(PersonAPI person) {
5368 return person != null && person.getMemoryWithoutUpdate().is(IS_MERCENARY, true);
5369 }
5370
5371 public static final String MERCENARY_HIRE_TIMESTAMP = "$mercHireTS";
5372 public static void setMercHiredNow(PersonAPI person) {
5373 person.getMemoryWithoutUpdate().set(MERCENARY_HIRE_TIMESTAMP, Global.getSector().getClock().getTimestamp());
5374 }
5375
5376 public static float getMercDaysSinceHired(PersonAPI person) {
5377 long ts = person.getMemoryWithoutUpdate().getLong(MERCENARY_HIRE_TIMESTAMP);
5378 return Global.getSector().getClock().getElapsedDaysSince(ts);
5379 }
5380
5381 public static void setMercenary(PersonAPI person, boolean mercenary) {
5382 person.getMemoryWithoutUpdate().set(IS_MERCENARY, mercenary);
5383 }
5384
5385 public static final String CAPTAIN_UNREMOVABLE = "$captain_unremovable";
5386 public static boolean isUnremovable(PersonAPI person) {
5387 //if (true) return true;
5388 return person != null && person.getMemoryWithoutUpdate().is(CAPTAIN_UNREMOVABLE, true);
5389 }
5390
5391 public static void setUnremovable(PersonAPI person, boolean unremovable) {
5392 person.getMemoryWithoutUpdate().set(CAPTAIN_UNREMOVABLE, unremovable);
5393 }
5394
5395 public static boolean isAutomated(MutableShipStatsAPI stats) {
5396 if (stats == null) return false;
5397 return isAutomated(stats.getFleetMember());
5398
5399 }
5400 public static boolean isAutomated(FleetMemberAPI member) {
5401 return member != null && member.getVariant() != null && isAutomated(member.getVariant());
5402 }
5403 public static boolean isAutomated(ShipVariantAPI variant) {
5404 return variant != null && variant.hasHullMod(HullMods.AUTOMATED);
5405 }
5406 public static boolean isAutomated(ShipAPI ship) {
5407 if (ship == null) return false;
5408 return isAutomated(ship.getVariant());
5409 }
5410
5411
5412 public static String RECOVERY_TAGS_KEY = "$core_recoveryTags";
5413 @SuppressWarnings("unchecked")
5415 Set<String> tags = (Set<String>) Global.getSector().getMemoryWithoutUpdate().get(RECOVERY_TAGS_KEY);
5416 if (tags == null) {
5417 tags = new HashSet<String>();
5418 Global.getSector().getMemoryWithoutUpdate().set(RECOVERY_TAGS_KEY, tags);
5419 }
5420 return tags;
5421 }
5422
5423 public static int MAX_PERMA_MODS = Global.getSettings().getInt("maxPermanentHullmods");
5424
5425 public static int getMaxPermanentMods(ShipAPI ship) {
5426 if (ship == null) return 0;
5427 return (int) Math.round(ship.getMutableStats().getDynamic().getMod(Stats.MAX_PERMANENT_HULLMODS_MOD).computeEffective(MAX_PERMA_MODS));
5428 }
5429
5430 public static int getMaxPermanentMods(FleetMemberAPI member, MutableCharacterStatsAPI stats) {
5431 if (member == null) return 0;
5432 PersonAPI prev = member.getFleetCommanderForStats();
5433 PersonAPI fake = Global.getFactory().createPerson();
5434 fake.setStats(stats);
5435 member.setFleetCommanderForStats(fake, null);
5436 int num = (int) Math.round(member.getStats().getDynamic().getMod(Stats.MAX_PERMANENT_HULLMODS_MOD).computeEffective(MAX_PERMA_MODS));
5437 member.setFleetCommanderForStats(prev, null);
5438 return num;
5439 }
5440
5441
5442 public static float getBuildInBonusXP(HullModSpecAPI mod, HullSize size) {
5443 //float threshold = Global.getSettings().getBonusXP("permModNoBonusXPOPThreshold");
5444
5445 float fraction = 0f;
5446 //float cost = 0f;
5447 switch (size) {
5448 case CAPITAL_SHIP:
5449 fraction = Global.getSettings().getBonusXP("permModCapital");
5450 //cost = mod.getCapitalCost();
5451 break;
5452 case CRUISER:
5453 fraction = Global.getSettings().getBonusXP("permModCruiser");
5454 //cost = mod.getCruiserCost();
5455 break;
5456 case DESTROYER:
5457 fraction = Global.getSettings().getBonusXP("permModDestroyer");
5458 //cost = mod.getDestroyerCost();
5459 break;
5460 case FRIGATE:
5461 fraction = Global.getSettings().getBonusXP("permModFrigate");
5462 //cost = mod.getFrigateCost();
5463 break;
5464 }
5465
5466 //float max = Global.getSettings().getBonusXP("permModMaxBonusXP");
5467
5468// float fraction = 0f;
5469// if (threshold > 0) {
5470// fraction = max * (1f - cost / threshold);
5471// if (fraction < 0f) fraction = 0f;
5472// if (fraction > 1f) fraction = 1f;
5473// }
5474
5475// MutableCharacterStatsAPI stats = Global.getSector().getPlayerStats();
5476// fraction += stats.getDynamic().getMod(Stats.BUILD_IN_BONUS_XP_MOD).computeEffective(0);
5477 if (fraction < 0f) fraction = 0f;
5478 if (fraction > 1f) fraction = 1f;
5479 return fraction;
5480 }
5481
5482 public static int getOPCost(HullModSpecAPI mod, HullSize size) {
5483 switch (size) {
5484 case CAPITAL_SHIP:
5485 return mod.getCapitalCost();
5486 case CRUISER:
5487 return mod.getCruiserCost();
5488 case DESTROYER:
5489 return mod.getDestroyerCost();
5490 case FRIGATE:
5491 return mod.getFrigateCost();
5492 }
5493 return mod.getFrigateCost();
5494 }
5495
5496 public static boolean isSpecialMod(ShipVariantAPI variant, HullModSpecAPI spec) {
5497// if (spec.getId().equals(HullMods.ANDRADA_MODS)) {
5498// return true;fwewefwefe
5499// }
5500 if (spec.isHidden()) return false;
5501 if (spec.isHiddenEverywhere()) return false;
5502 if (spec.hasTag(Tags.HULLMOD_DMOD)) return false;
5503 if (!variant.getPermaMods().contains(spec.getId())) return false;
5504 if (variant.getHullSpec().getBuiltInMods().contains(spec.getId())) return false;
5505 if (!variant.getSMods().contains(spec.getId())) return false;
5506
5507 return true;
5508 }
5509
5510 public static boolean hasSModdableBuiltIns(ShipVariantAPI variant) {
5511 if (!CAN_SMOD_BUILT_IN || variant == null) return false;
5512 int num = 0;
5513 for (String id : variant.getHullMods()) {
5514 HullModSpecAPI spec = Global.getSettings().getHullModSpec(id);
5515 if (spec.isHidden()) continue;
5516 if (spec.isHiddenEverywhere()) continue;
5517 if (spec.hasTag(Tags.HULLMOD_DMOD)) continue;
5518 if (variant.getHullSpec().isBuiltInMod(id) &&
5519 spec.getEffect().hasSModEffect() && !spec.getEffect().isSModEffectAPenalty() &&
5520 !variant.getSModdedBuiltIns().contains(id)) {
5521 num++;
5522 }
5523 }
5524 return num > 0;
5525 }
5526 public static int getCurrSpecialMods(ShipVariantAPI variant) {
5527 if (variant == null) return 0;
5528 int num = 0;
5529 for (String id : variant.getHullMods()) {
5530 HullModSpecAPI spec = Global.getSettings().getHullModSpec(id);
5531 if (!isSpecialMod(variant, spec)) continue;
5532// if (spec.isHidden()) continue;
5533// if (spec.isHiddenEverywhere()) continue;
5534// if (spec.hasTag(Tags.HULLMOD_DMOD)) continue;
5535// if (!variant.getPermaMods().contains(spec.getId())) continue;
5536 num++;
5537 }
5538 return num;
5539 }
5540
5541 public static List<HullModSpecAPI> getCurrSpecialModsList(ShipVariantAPI variant) {
5543 if (variant == null) return result;
5544 int num = 0;
5545 for (String id : variant.getHullMods()) {
5546 HullModSpecAPI spec = Global.getSettings().getHullModSpec(id);
5547 if (!isSpecialMod(variant, spec)) continue;
5548 result.add(spec);
5549 }
5550 return result;
5551 }
5552
5553 public static boolean isSlowMoving(CampaignFleetAPI fleet) {
5554 return fleet.getCurrBurnLevel() <= getGoSlowBurnLevel(fleet);
5555 }
5556
5557
5558
5559 //public static float MAX_SNEAK_BURN_LEVEL = Global.getSettings().getFloat("maxSneakBurnLevel");
5560 public static float SNEAK_BURN_MULT = Global.getSettings().getFloat("sneakBurnMult");
5561
5562 public static int getGoSlowBurnLevel(CampaignFleetAPI fleet) {
5563// if (fleet.isPlayerFleet()) {
5564// System.out.println("fewfewfe");
5565// }
5566 float bonus = fleet.getStats().getDynamic().getMod(Stats.MOVE_SLOW_SPEED_BONUS_MOD).computeEffective(0);
5567 //int burn = (int)Math.round(MAX_SNEAK_BURN_LEVEL + bonus);
5568 //int burn = (int)Math.round(fleet.getFleetData().getMinBurnLevelUnmodified() * SNEAK_BURN_MULT);
5569 int burn = (int)Math.round(fleet.getFleetData().getMinBurnLevel() * SNEAK_BURN_MULT);
5570 burn += bonus;
5571 //burn = (int) Math.min(burn, fleet.getFleetData().getBurnLevel() - 1);
5572 return burn;
5573 }
5574
5575
5576 public static enum FleetMemberDamageLevel {
5577 LOW,
5578 MEDIUM,
5579 HIGH,
5580 }
5581
5582 public static void applyDamage(FleetMemberAPI member, Random random, FleetMemberDamageLevel level,
5584 boolean withMessage, TextPanelAPI textPanel,
5586 float damageMult = 1f;
5587 switch (level) {
5588 case LOW:
5589 damageMult = 3f;
5590 break;
5591 case MEDIUM:
5592 damageMult = 10f;
5593 break;
5594 case HIGH:
5595 damageMult = 20f;
5596 break;
5597 }
5599 withMessage, textPanel, messageText);
5600 }
5601
5602 public static void applyDamage(FleetMemberAPI member, Random random, float damageMult,
5604 boolean withMessage, TextPanelAPI textPanel,
5606 if (random == null) random = Misc.random;
5607 damageMult *= 0.75f + random.nextFloat() * 0.5f;
5608
5609// float hitStrength = 0f;
5610// hitStrength += member.getHullSpec().getArmorRating() * 0.1f;
5611// hitStrength *= damageMult;
5612
5613 // hull damage going to be overridden by hullDamageFraction, anyway
5614 // so just want enough hitStrength to visibly damage the armor
5615 float hitStrength = member.getHullSpec().getArmorRating() * 2f;
5616
5617 float hullDamageFraction = 0.025f * damageMult;
5618 float max = 0.5f + random.nextFloat() * 0.1f;
5619 float min = 0.01f + random.nextFloat() * 0.04f;
5620 if (hullDamageFraction > max) hullDamageFraction = max;
5621 if (hullDamageFraction < min) hullDamageFraction = min;
5622
5623 if (hitStrength > 0) {
5624 float numHits = 3f;
5625 for (int i = 0; i < numHits; i++) {
5626 member.getStatus().applyDamage(hitStrength / numHits, hullDamageFraction / numHits);
5627 }
5628 if (member.getStatus().getHullFraction() < 0.01f) {
5629 member.getStatus().setHullFraction(0.01f);
5630 }
5631
5632 boolean isPF = member != null && member.getFleetData() != null &&
5633 member.getFleetData().getFleet() != null && member.getFleetData().getFleet().isPlayerFleet();
5634
5635 if (withCRDamage) {
5636 float crPerDep = member.getDeployCost();
5637 float currCR = member.getRepairTracker().getBaseCR();
5638 float crDamage = Math.min(currCR, crPerDep * 0.1f * damageMult);
5639 if (crDamage > 0) {
5640 if (isPF) {
5641 member.getRepairTracker().applyCREvent(-crDamage, crDamageId, crDamageReason);
5642 } else {
5643 member.getRepairTracker().applyCREvent(-crDamage, null, null);
5644 }
5645 }
5646 }
5647
5648 if (withMessage && isPF) {
5649 MessageIntel intel = new MessageIntel(messageText,
5651 intel.setIcon(Global.getSettings().getSpriteName("intel", "damage_report"));
5652
5653 if (textPanel != null) {
5654 Global.getSector().getIntelManager().addIntelToTextPanel(intel, textPanel);
5655 } else {
5656 Global.getSector().getCampaignUI().addMessage(intel, MessageClickAction.REFIT_TAB, member);
5657 }
5658 }
5659 }
5660 }
5661
5662 public static float getBonusXPForRecovering(FleetMemberAPI member) {
5663 float ownedShip = Global.getSettings().getBonusXP("recoverOwnedShip");
5664 float threshold = Global.getSettings().getBonusXP("recoverNoBonusXPDeploymentPoints");
5665
5666 if (member.getOwner() == 0) {
5667 return ownedShip;
5668 }
5669
5670 float f = 1f - member.getDeploymentPointsCost() / threshold;
5671 if (f < 0) f = 0;
5672 if (f > 1) f = 1;
5673
5674 return f;
5675 }
5676
5677 public static float [] getBonusXPForScuttling(FleetMemberAPI member) {
5678 float points = 0f;
5679 float xp = 0f;
5680 for (SModRecord record : PlaythroughLog.getInstance().getSModsInstalled()) {
5681 //if (member.getId() != null && member.getId().equals(record.getMemberId())) {
5682 if (member == record.getMember() && record.getMember() != null) {
5683 points += record.getSPSpent();
5684 xp += record.getBonusXPFractionGained() * record.getSPSpent();
5685 }
5686 }
5687 if (points > 0) {
5688 return new float[] {points, 1f - xp/points};
5689 }
5690 return new float[] {0f, 0f};
5691 }
5692
5693 public static float getSpawnFPMult(CampaignFleetAPI fleet) {
5694 float mult = fleet.getMemoryWithoutUpdate().getFloat(FleetFactoryV3.KEY_SPAWN_FP_MULT);
5695 if (mult == 0) mult = 1f;
5696 return mult;
5697 }
5698
5699 public static void setSpawnFPMult(CampaignFleetAPI fleet, float mult) {
5700 fleet.getMemoryWithoutUpdate().set(FleetFactoryV3.KEY_SPAWN_FP_MULT, mult);
5701 }
5702
5703 public static boolean isDecentralized(FactionAPI faction) {
5704 return faction != null && faction.getCustomBoolean(Factions.CUSTOM_DECENTRALIZED);
5705 }
5706
5707 public static String getPersonalityName(PersonAPI person) {
5708 String personalityName = person.getPersonalityAPI().getDisplayName();
5709 if (person.isAICore()) {
5710 if (Personalities.RECKLESS.equals(person.getPersonalityAPI().getId())) {
5711 personalityName = "Fearless";
5712 }
5713 }
5714 return personalityName;
5715 }
5716
5717 public static String LAST_RAIDED_AT = "$lastRaidedAt";
5718 public static void setRaidedTimestamp(MarketAPI market) {
5719 market.getMemoryWithoutUpdate().set(LAST_RAIDED_AT, Global.getSector().getClock().getTimestamp());
5720 }
5721
5722 public static float getDaysSinceLastRaided(MarketAPI market) {
5723 Long ts = market.getMemoryWithoutUpdate().getLong(LAST_RAIDED_AT);
5724 if (ts == null) return Float.MAX_VALUE;
5725 return Global.getSector().getClock().getElapsedDaysSince(ts);
5726 }
5727
5728 public static int computeEconUnitChangeFromTradeModChange(CommodityOnMarketAPI com, int quantity) {
5729 float currQty = com.getCombinedTradeModQuantity();
5730 int currMod = (int) com.getModValueForQuantity(currQty);
5731
5732 float quantityWithTX = com.getTradeMod().getModifiedValue() + quantity +
5733 Math.max(com.getTradeModPlus().getModifiedValue(), 0) +
5734 Math.min(com.getTradeModMinus().getModifiedValue(), 0);
5735
5736 int newMod = (int) com.getModValueForQuantity(quantityWithTX);
5737
5738 int diff = newMod - currMod;
5739
5740 return diff;
5741 }
5742
5743 public static void affectAvailabilityWithinReason(CommodityOnMarketAPI com, int quantity) {
5744 int units = computeEconUnitChangeFromTradeModChange(com, quantity);
5745 int maxUnits = Math.min(3, Math.max(com.getMaxDemand(), com.getMaxSupply()));
5746 if (Math.abs(units) > maxUnits) {
5747 int sign = (int) Math.signum(quantity);
5748 quantity = (int) Math.round(com.getQuantityForModValue(maxUnits));
5749 quantity *= sign;
5750 }
5751 com.addTradeMod("mod_" + Misc.genUID(), quantity, BaseSubmarketPlugin.TRADE_IMPACT_DAYS);
5752 }
5753
5754
5755 public static boolean isOpenlyPopulated(StarSystemAPI system) {
5756 for (MarketAPI market : Misc.getMarketsInLocation(system)) {
5757 if (!market.isHidden()) return true;
5758 }
5759 return false;
5760 }
5761
5762
5763 public static boolean hasAtLeastOneOfTags(Collection<String> tags, String ... other) {
5764 for (String tag : other) {
5765 if (tags.contains(tag)) return true;
5766 }
5767 return false;
5768 }
5769
5770
5771
5772// public static boolean isUnpopulatedPlanet(PlanetAPI planet) {
5773// if (planet.isStar() ||
5774// planet.getMarket() == null ||
5775// !planet.getMarket().isPlanetConditionMarketOnly()) {
5776// return false;
5777// }
5778// return true;
5779// }
5780
5781 public static boolean hasUnexploredRuins(MarketAPI market) {
5782 return market != null && market.isPlanetConditionMarketOnly() &&
5783 hasRuins(market) && !market.getMemoryWithoutUpdate().getBoolean("$ruinsExplored");
5784 }
5785 public static boolean hasRuins(MarketAPI market) {
5786 return market != null &&
5787 (market.hasCondition(Conditions.RUINS_SCATTERED) ||
5788 market.hasCondition(Conditions.RUINS_WIDESPREAD) ||
5789 market.hasCondition(Conditions.RUINS_EXTENSIVE) ||
5790 market.hasCondition(Conditions.RUINS_VAST));
5791 }
5792
5793 public static boolean hasFarmland(MarketAPI market) {
5794 return market != null &&
5795 (market.hasCondition(Conditions.FARMLAND_POOR) ||
5796 market.hasCondition(Conditions.FARMLAND_ADEQUATE) ||
5797 market.hasCondition(Conditions.FARMLAND_RICH) ||
5798 market.hasCondition(Conditions.FARMLAND_BOUNTIFUL));
5799 }
5800
5801
5802 public static String DEFEAT_TRIGGERS = "$defeatTriggers";
5803 public static void addDefeatTrigger(CampaignFleetAPI fleet, String trigger) {
5804 List<String> triggers = getDefeatTriggers(fleet, true);
5805 triggers.add(trigger);
5806 }
5807
5808 public static void removeDefeatTrigger(CampaignFleetAPI fleet, String trigger) {
5809 List<String> triggers = getDefeatTriggers(fleet, false);
5810 if (triggers != null) {
5811 triggers.remove(trigger);
5813 }
5814 }
5815
5816 @SuppressWarnings("unchecked")
5817 public static List<String> getDefeatTriggers(CampaignFleetAPI fleet, boolean createIfNecessary) {
5818 MemoryAPI mem = fleet.getMemoryWithoutUpdate();
5819 List<String> triggers = null;
5821 if (!createIfNecessary) return null;
5822 triggers = new ArrayList<String>();
5823 mem.set(DEFEAT_TRIGGERS, triggers);
5824 } else {
5825 triggers = (List<String>) mem.get(DEFEAT_TRIGGERS);
5826 }
5827 return triggers;
5828 }
5829
5830 public static void clearDefeatTriggersIfNeeded(CampaignFleetAPI fleet) {
5831 List<String> triggers = getDefeatTriggers(fleet, false);
5832 if (triggers != null && triggers.isEmpty()) {
5833 MemoryAPI mem = fleet.getMemoryWithoutUpdate();
5834 mem.unset(DEFEAT_TRIGGERS);
5835 }
5836 }
5837
5838 public static boolean shouldShowDamageFloaty(ShipAPI source, ShipAPI target) {
5839 CombatEngineAPI engine = Global.getCombatEngine();
5840 ShipAPI playerShip = engine.getPlayerShip();
5841
5842 boolean sourceIsPlayerShipWing = false;
5843 sourceIsPlayerShipWing = source != null && source.getWing() != null &&
5844 source.getWing().getSourceShip() == playerShip;
5845
5846 CombatEntityAPI followedEntity = engine.getCombatUI().getEntityToFollowV2();
5847 boolean showFloaty = target == playerShip || // this is the player's ship
5848 target == followedEntity || // getting video feed from this ship
5849 source == playerShip || // the damage came from the player's ship
5851 target == playerShip.getShipTarget() || // the ship is the player ship's target
5852 engine.hasAttachedFloaty(target); // the ship already has a floaty on it, meaning the player is likely looking at it
5853 showFloaty = showFloaty && !target.isFighter(); // no floaties on fighters
5854 showFloaty = showFloaty && Global.getSettings().isShowDamageFloaties();
5855 return showFloaty;
5856 }
5857
5858//
5859// public static Vector2f cubeBezier(Vector2f p0, Vector2f p1, Vector2f p2, Vector2f p3, float t)
5860// {
5861// float r = 1f - t;
5862// float f0 = r * r * r;
5863// float f1 = r * r * t * 3;
5864// float f2 = r * t * t * 3;
5865// float f3 = t * t * t;
5866// return f0*p0 + f1*p1 + f2*p2 + f3*p3;
5867// }
5868
5869
5870// long memorySize = ((com.sun.management.OperatingSystemMXBean) ManagementFactory
5871// .getOperatingSystemMXBean()).getTotalPhysicalMemorySize();
5872 protected static Boolean canCheckVramNVIDIA = null;
5873 public static boolean canCheckVram() {
5874 if (canCheckVramNVIDIA == null) {
5875 String str = GL11.glGetString(GL11.GL_EXTENSIONS);
5876 if (str != null) {
5877 List<String> extensions = Arrays.asList(str.split(" "));
5878 canCheckVramNVIDIA = extensions.contains("GL_NVX_gpu_memory_info");
5879 //canCheckVramATI = extensions.contains("GL_ATI_meminfo");
5880 } else {
5881 canCheckVramNVIDIA = false;
5882 }
5883 }
5884 return true;
5885 }
5890 public static int getVramFreeKB() {
5891 if (canCheckVramNVIDIA) {
5892 return GL11.glGetInteger(NVXGpuMemoryInfo.GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX);
5893 } else {
5894 return GL11.glGetInteger(ATIMeminfo.GL_TEXTURE_FREE_MEMORY_ATI);
5895 }
5896 }
5897
5898 public static int getVramMaximumKB() {
5899 return GL11.glGetInteger(NVXGpuMemoryInfo.GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX);
5900 }
5901 public static int getVramDedicatedKB() {
5902 return GL11.glGetInteger(NVXGpuMemoryInfo.GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX);
5903 }
5904 public static int getVramUsedKB() {
5905 return getVramMaximumKB() - getVramFreeKB();
5906 }
5907
5908// public static void printExtensions() {
5909// String str = GL11.glGetString(GL11.GL_EXTENSIONS);
5910// System.out.println(str);
5911// }
5912
5913
5914 public static float IMPACT_VOLUME_MULT = Global.getSettings().getFloat("impactSoundVolumeMult");
5915
5916 public static void playSound(ApplyDamageResultAPI result, Vector2f loc, Vector2f vel,
5919 ) {
5920 float shieldDam = result.getDamageToShields();
5921 float armorDam = result.getTotalDamageToArmor();
5922 float hullDam = result.getDamageToHull();
5923 float fluxDam = result.getEmpDamage();
5924
5925
5926 float totalDam = shieldDam + armorDam + hullDam;
5927 // if no damage, don't play sounds
5928 if (totalDam + fluxDam <= 0) return;
5929
5930 float vol = 1f;
5931
5933
5934 // if shields were damaged, then ONLY shields were damaged
5935 if (shieldDam > 0) {
5936 String soundId = null;
5937 if (shieldDam < 70) {
5938 vol = shieldDam / 20f;
5939 if (vol > 1) vol = 1;
5940 soundId = lightShields;
5941 } else if (shieldDam < 200) {
5942 soundId = solidShields;
5943 } else {
5944 soundId = heavyShields;
5945 }
5946 if (soundId != null) {
5947 Global.getSoundPlayer().playSound(soundId, 1f, vol * volMult, loc, vel);
5948 }
5949 return;
5950 }
5951
5952 String soundId = null;
5953
5954 float physicalDam = armorDam + hullDam + fluxDam;
5955 //System.out.println(physicalDam);
5956 if (physicalDam < 5) {
5957 vol = physicalDam / 5f;
5958 if (vol > 1) vol = 1;
5959 soundId = lightHull;
5960 } else if (physicalDam < 40) {
5961 soundId = lightHull;
5962 } else if (physicalDam < 150) {
5963 soundId = solidHull;
5964 } else {
5965 soundId = heavyHull;
5966 }
5967
5968 if (soundId != null) {
5969 Global.getSoundPlayer().playSound(soundId, 1f, vol * volMult, loc, vel);
5970 }
5971 return;
5972 }
5973
5974
5975 public static float getShipWeight(ShipAPI ship) {
5976 return getShipWeight(ship, true);
5977 }
5978
5979 public static float getShipWeight(ShipAPI ship, boolean adjustForNonCombat) {
5980 if (ship.isDrone()) return 0.1f;
5981 boolean nonCombat = ship.isNonCombat(false);
5982 float weight = 0;
5983 switch (ship.getHullSize()) {
5984 case CAPITAL_SHIP: weight += 8; break;
5985 case CRUISER: weight += 4; break;
5986 case DESTROYER: weight += 2; break;
5987 case FRIGATE: weight += 1; break;
5988 case FIGHTER: weight += 1; break;
5989 }
5990 if (nonCombat && adjustForNonCombat) weight *= 0.25f;
5991 if (ship.isDrone()) weight *= 0.1f;
5992 return weight;
5993 }
5994
5995 public static float getIncapacitatedTime(ShipAPI ship) {
5996 float incapTime = 0f;
5997 if (ship.getFluxTracker().isVenting()){
5998 incapTime = ship.getFluxTracker().getTimeToVent();
5999 } else if (ship.getFluxTracker().isOverloaded()) {
6000 incapTime = ship.getFluxTracker().getOverloadTimeRemaining();
6001 }
6002 return incapTime;
6003 }
6004
6005 public static boolean isAvoidingPlayerHalfheartedly(CampaignFleetAPI fleet) {
6006 if (fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_NEVER_AVOID_PLAYER_SLOWLY)) {
6007 return false;
6008 }
6009 CampaignFleetAPI player = Global.getSector().getPlayerFleet();
6010 boolean avoidingPlayer = fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_AVOID_PLAYER_SLOWLY);
6011 if (avoidingPlayer && !fleet.isHostileTo(player)) return true;
6012
6013 CampaignFleetAPI fleeingFrom = fleet.getMemoryWithoutUpdate().getFleet(FleetAIFlags.NEAREST_FLEEING_FROM);
6014 if (fleeingFrom != null && fleeingFrom.isPlayerFleet()) {
6015 if (Misc.shouldNotWantRunFromPlayerEvenIfWeaker(fleet) && fleet.isHostileTo(player)) {
6016 return true;
6017 }
6018 }
6019 return false;
6020 }
6021
6027 public static boolean isPirateFaction(FactionAPI faction) {
6028 return faction != null &&
6029 faction.getCustomBoolean(Factions.CUSTOM_PIRATE_BEHAVIOR);// &&
6030 //faction.getCustomBoolean(Factions.CUSTOM_MAKES_PIRATE_BASES);
6031 }
6032
6038 word = word.toLowerCase();
6039 for (String other : new String[] {"euler", "heir", "honest", "hono"}) {
6040 if (word.startsWith(other)) {
6041 return "an";
6042 }
6043 }
6044
6045 if (word.startsWith("hour") && !word.startsWith("houri")) {
6046 return "an";
6047 }
6048
6049 Pattern p;
6050 Matcher m;
6051
6052 for (String regex : new String[] { "^e[uw]", "^onc?e\b", "^uni([^nmd]|mo)", "^u[bcfhjkqrst][aeiou]"}) {
6053 p = Pattern.compile("(?is)" + regex + ".*");
6054 m = p.matcher(word);
6055 if (m.matches()) {
6056 return "a";
6057 }
6058 }
6059
6060 p = Pattern.compile("(?is)" + "^U[NK][AIEO]");
6061 m = p.matcher(word);
6062 if (m.matches()) {
6063 return "a";
6064 }
6065
6066 for (String letter : new String[] { "a", "e", "i", "o", "u" }) {
6067 if (word.startsWith(letter)) {
6068 return "an";
6069 }
6070 }
6071
6072 p = Pattern.compile("(?is)" + "^y(b[lor]|cl[ea]|fere|gg|p[ios]|rou|tt)" + ".*");
6073 m = p.matcher(word);
6074 if (m.matches()) {
6075 return "an";
6076 }
6077
6078 return "a";
6079 }
6080
6081
6082 public static void moveToMarket(PersonAPI person, MarketAPI destination, boolean alwaysAddToCommDirectory) {
6083 ContactIntel intel = ContactIntel.getContactIntel(person);
6084 if (intel != null) {
6085 intel.relocateToMarket(destination, false);
6086 } else {
6088 boolean hidden = false;
6089 if (person.getMarket() != null) {
6090 MarketAPI market = person.getMarket();
6091 CommDirectoryEntryAPI entry = market.getCommDirectory().getEntryForPerson(person);
6092 if (entry != null) {
6093 addToComms = true;
6094 hidden = entry.isHidden();
6095 }
6096 market.removePerson(person);
6097 market.getCommDirectory().removePerson(person);
6098 }
6099
6100 if (!destination.getPeopleCopy().contains(person)) {
6101 destination.addPerson(person);
6102 }
6103 person.setMarket(destination);
6104
6105 if (addToComms) {
6106 if (destination.getCommDirectory() != null &&
6107 destination.getCommDirectory().getEntryForPerson(person) == null) {
6108 destination.getCommDirectory().addPerson(person);
6109 if (hidden) {
6110 CommDirectoryEntryAPI entry = destination.getCommDirectory().getEntryForPerson(person);
6111 if (entry != null) {
6112 entry.setHidden(true);
6113 }
6114 }
6115 }
6116 }
6117 }
6118 }
6119
6120 public static void makeStoryCritical(String marketId, String reason) {
6121 makeStoryCritical(Global.getSector().getEconomy().getMarket(marketId), reason);
6122 }
6123 public static void makeStoryCritical(MarketAPI market, String reason) {
6124 makeStoryCritical(market.getMemoryWithoutUpdate(), reason);
6125 }
6126 public static void makeStoryCritical(MemoryAPI memory, String reason) {
6127 setFlagWithReason(memory, MemFlags.STORY_CRITICAL, reason, true, -1f);
6128 }
6129 public static void makeNonStoryCritical(MarketAPI market, String reason) {
6130 makeNonStoryCritical(market.getMemoryWithoutUpdate(), reason);
6131 }
6132 public static void makeNonStoryCritical(MemoryAPI memory, String reason) {
6133 setFlagWithReason(memory, MemFlags.STORY_CRITICAL, reason, false, -1f);
6134 }
6135 public static boolean isStoryCritical(MarketAPI market) {
6136 return isStoryCritical(market.getMemoryWithoutUpdate());
6137 }
6138 public static boolean isStoryCritical(MemoryAPI memory) {
6139 return memory.getBoolean(MemFlags.STORY_CRITICAL);
6140 }
6141
6142
6149 public static boolean isInsignificant(CampaignFleetAPI fleet) {
6150 boolean recentlyBeaten = fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_RECENTLY_DEFEATED_BY_PLAYER);
6151 if (recentlyBeaten) return true;
6152
6153 CampaignFleetAPI pf = Global.getSector().getPlayerFleet();
6154 if (pf == null) return true; // ??
6155 if (fleet.getAI() != null) {
6156 EncounterOption opt = fleet.getAI().pickEncounterOption(null, pf);
6157 if (opt == EncounterOption.DISENGAGE || opt == EncounterOption.HOLD_VS_STRONGER) {
6158 return true;
6159 }
6160 if (opt == EncounterOption.ENGAGE) {
6161 return false;
6162 }
6163 }
6164 int pfCount = pf.getFleetSizeCount();
6165 int otherCount = fleet.getFleetSizeCount();
6166
6167 return otherCount <= pfCount / 4;
6168 }
6169
6176 public static boolean shouldNotWantRunFromPlayerEvenIfWeaker(CampaignFleetAPI fleet) {
6177 boolean recentlyBeaten = fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_RECENTLY_DEFEATED_BY_PLAYER);
6178 if (recentlyBeaten) return true;
6179 if (fleet.getFleetData() == null) return false;
6180
6181 float count = 0;
6182 for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) {
6183 if (!member.isCivilian() && member.getHullSpec() != null) {
6184 switch (member.getHullSpec().getHullSize()) {
6185 case CAPITAL_SHIP: count += 4; break;
6186 case CRUISER: count += 3; break;
6187 case DESTROYER: count += 2; break;
6188 case FRIGATE: count += 1; break;
6189 }
6190 }
6191 }
6192
6193 CampaignFleetAPI pf = Global.getSector().getPlayerFleet();
6194 float pfCount = 0;
6195 for (FleetMemberAPI member : pf.getFleetData().getMembersListCopy()) {
6196 if (!member.isCivilian() && member.getHullSpec() != null) {
6197 switch (member.getHullSpec().getHullSize()) {
6198 case CAPITAL_SHIP: pfCount += 4; break;
6199 case CRUISER: pfCount += 3; break;
6200 case DESTROYER: pfCount += 2; break;
6201 case FRIGATE: pfCount += 1; break;
6202 }
6203 }
6204 }
6205
6206 if (count > pfCount * 0.67f) {
6207 return true;
6208 }
6209
6210 if (isInsignificant(fleet) && count <= 6) return true;
6211
6212 return false;
6213 }
6214
6215 public static float findKth(float[] arr, int k) {
6216 if (arr == null || arr.length <= k || k < 0) {
6217 return -1;
6218 }
6219
6220 int from = 0;
6221 int to = arr.length - 1;
6222
6223 while (from < to) {
6224 int r = from;
6225 int w = to;
6226 float mid = arr[(r + w) / 2];
6227
6228 while (r < w) {
6229 if (arr[r] >= mid) {
6230 float tmp = arr[w];
6231 arr[w] = arr[r];
6232 arr[r] = tmp;
6233 w--;
6234 } else {
6235 r++;
6236 }
6237 }
6238
6239 if (arr[r] > mid) r--;
6240
6241 if (k <= r) {
6242 to = r;
6243 } else {
6244 from = r + 1;
6245 }
6246 }
6247
6248 return arr[k];
6249 }
6250
6251 public static float getAdjustedBaseRange(float base, ShipAPI ship, WeaponAPI weapon) {
6252 if (ship == null || weapon == null) return base;
6253 float flat = CombatListenerUtil.getWeaponBaseRangeFlatMod(ship, weapon);
6254 float percent = CombatListenerUtil.getWeaponBaseRangePercentMod(ship, weapon);
6255 float mult = CombatListenerUtil.getWeaponBaseRangeMultMod(ship, weapon);
6256 return (base * (1f + percent/100f) + flat) * mult;
6257 }
6258
6259
6260 public static Vector2f bezier(Vector2f p0, Vector2f p1, Vector2f p2, float t) {
6261 if (t < 0) t = 0;
6262 if (t > 1) t = 1;
6263 Vector2f r = new Vector2f();
6264 r.x = (1f - t) * (1f - t) * p0.x + 2f * (1f - t) * t * p1.x + t * t * p2.x;
6265 r.y = (1f - t) * (1f - t) * p0.y + 2f * (1f - t) * t * p1.y + t * t * p2.y;
6266 return r;
6267 }
6268
6269 public static Vector2f bezierCubic(Vector2f p0, Vector2f p1, Vector2f p2, Vector2f p3, float t) {
6270 if (t < 0) t = 0;
6271 if (t > 1) t = 1;
6272 Vector2f r = new Vector2f();
6273
6274 r.x = (1f - t) * (1f - t) * (1f -t) * p0.x +
6275 3f * (1f - t) * (1f - t) * t * p1.x +
6276 3f * (1f - t) * t * t * p2.x +
6277 t * t * t * p3.x;
6278 r.y = (1f - t) * (1f - t) * (1f -t) * p0.y +
6279 3f * (1f - t) * (1f - t) * t * p1.y +
6280 3f * (1f - t) * t * t * p2.y +
6281 t * t * t * p3.y;
6282 return r;
6283 }
6284
6285 public static boolean isInsideSlipstream(Vector2f loc, float radius) {
6286 return isInsideSlipstream(loc, radius, Global.getSector().getHyperspace());
6287 }
6288 public static boolean isInsideSlipstream(Vector2f loc, float radius, LocationAPI location) {
6289 if (location == null) return false;
6290 for (CampaignTerrainAPI ter : location.getTerrainCopy()) {
6291 if (ter.getPlugin() instanceof SlipstreamTerrainPlugin2) {
6292 SlipstreamTerrainPlugin2 plugin = (SlipstreamTerrainPlugin2) ter.getPlugin();
6293 if (plugin.containsPoint(loc, radius)) {
6294 return true;
6295 }
6296 }
6297 }
6298 return false;
6299 }
6300 public static boolean isInsideSlipstream(SectorEntityToken entity) {
6301 if (entity == null || entity.getContainingLocation() == null) return false;
6302 for (CampaignTerrainAPI ter : entity.getContainingLocation().getTerrainCopy()) {
6303 if (ter.getPlugin() instanceof SlipstreamTerrainPlugin2) {
6304 SlipstreamTerrainPlugin2 plugin = (SlipstreamTerrainPlugin2) ter.getPlugin();
6305 if (plugin.containsEntity(entity)) {
6306 return true;
6307 }
6308 }
6309 }
6310 return false;
6311 }
6312
6313 public static boolean isOutsideSector(Vector2f loc) {
6314 float sw = Global.getSettings().getFloat("sectorWidth");
6315 float sh = Global.getSettings().getFloat("sectorHeight");
6316 return loc.x < -sw/2f || loc.x > sw/2f || loc.y < -sh/2f || loc.y > sh/2f;
6317 }
6318
6319 public static boolean crossesAnySlipstream(LocationAPI location, Vector2f from, Vector2f to) {
6320 for (CampaignTerrainAPI ter : location.getTerrainCopy()) {
6321 if (ter.getPlugin() instanceof SlipstreamTerrainPlugin2) {
6322 SlipstreamTerrainPlugin2 plugin = (SlipstreamTerrainPlugin2) ter.getPlugin();
6323 List<SlipstreamSegment> segments = plugin.getSegments();
6324 int skip = Math.max(20, segments.size() / 10);
6325 for (int i = 0; i < segments.size(); i += skip) {
6326 int i2 = i + skip;
6327 if (i2 > segments.size() - skip/2) i2 = segments.size() - 1;
6328 if (i2 >= segments.size()) i2 = segments.size() - 1;
6329
6330 if (i2 <= i) break;
6331
6332 Vector2f p = intersectSegments(segments.get(i).loc, segments.get(i2).loc, from, to);
6333 if (p != null) return true;
6334 }
6335 }
6336 }
6337 return false;
6338 }
6339
6340 public static void computeCoreWorldsExtent() {
6341 Vector2f min = new Vector2f();
6342 Vector2f max = new Vector2f();
6343 for (StarSystemAPI curr : Global.getSector().getStarSystems()) {
6344 if (curr.hasTag(Tags.THEME_CORE)) {
6345 Vector2f loc = curr.getLocation();
6346 min.x = Math.min(min.x, loc.x);
6347 min.y = Math.min(min.y, loc.y);
6348 max.x = Math.max(max.x, loc.x);
6349 max.y = Math.max(max.y, loc.y);
6350 }
6351 }
6352
6353 Vector2f core = Vector2f.add(min, max, new Vector2f());
6354 core.scale(0.5f);
6355
6356 Global.getSector().getMemoryWithoutUpdate().set("$coreWorldsMin", min);
6357 Global.getSector().getMemoryWithoutUpdate().set("$coreWorldsMax", max);
6358 Global.getSector().getMemoryWithoutUpdate().set("$coreWorldsCenter", core);
6359 }
6360
6361 public static Vector2f getCoreMin() {
6362 Vector2f v = (Vector2f) Global.getSector().getMemoryWithoutUpdate().get("$coreWorldsMin");
6363 if (v == null) {
6365 v = (Vector2f) Global.getSector().getMemoryWithoutUpdate().get("$coreWorldsMin");
6366 }
6367 return v;
6368 }
6369 public static Vector2f getCoreMax() {
6370 Vector2f v = (Vector2f) Global.getSector().getMemoryWithoutUpdate().get("$coreWorldsMax");
6371 if (v == null) {
6373 v = (Vector2f) Global.getSector().getMemoryWithoutUpdate().get("$coreWorldsMax");
6374 }
6375 return v;
6376 }
6377 public static Vector2f getCoreCenter() {
6378 Vector2f v = (Vector2f) Global.getSector().getMemoryWithoutUpdate().get("$coreWorldsCenter");
6379 if (v == null) {
6381 v = (Vector2f) Global.getSector().getMemoryWithoutUpdate().get("$coreWorldsCenter");
6382 }
6383 return v;
6384 }
6385
6386
6387// public static void createColonyStatic(MarketAPI market)
6388// {
6389// String factionId = Factions.PLAYER;
6390//
6391// market.setSize(3);
6392// market.addCondition("population_3");
6393// market.setFactionId(factionId);
6394// market.setPlanetConditionMarketOnly(false);
6395//
6396// if (market.hasCondition(Conditions.DECIVILIZED))
6397// {
6398// market.removeCondition(Conditions.DECIVILIZED);
6399// market.addCondition(Conditions.DECIVILIZED_SUBPOP);
6400// }
6401// market.addIndustry(Industries.POPULATION);
6402//
6403// market.addSubmarket(Submarkets.LOCAL_RESOURCES);
6404// market.addSubmarket(Submarkets.SUBMARKET_STORAGE);
6405//
6406// market.setSurveyLevel(MarketAPI.SurveyLevel.FULL);
6407// for (MarketConditionAPI cond : market.getConditions())
6408// {
6409// cond.setSurveyed(true);
6410// }
6411//
6412// Global.getSector().getEconomy().addMarket(market, true);
6413// market.getPrimaryEntity().setFaction(factionId);
6414//
6415// market.setPlayerOwned(true);
6416// market.addIndustry(Industries.SPACEPORT);
6417// SubmarketAPI storage = market.getSubmarket(Submarkets.SUBMARKET_STORAGE);
6418// if (storage != null)
6419// ((StoragePlugin)storage.getPlugin()).setPlayerPaidToUnlock(true);
6420// }
6421
6422
6423 public static boolean turnTowardsPointV2(MissileAPI missile, Vector2f point, float angVel) {
6424 float desiredFacing = getAngleInDegrees(missile.getLocation(), point);
6425 return turnTowardsFacingV2(missile, desiredFacing, angVel);
6426 }
6427
6428 public static boolean turnTowardsFacingV2(MissileAPI missile, float desiredFacing, float relativeAngVel) {
6429
6430 float turnVel = missile.getAngularVelocity() - relativeAngVel;
6431 float absTurnVel = Math.abs(turnVel);
6432
6433 float turnDecel = missile.getEngineController().getTurnDeceleration();
6434 // v t - 0.5 a t t = dist
6435 // dv = a t; t = v / a
6436 float decelTime = absTurnVel / turnDecel;
6438
6439 float facingAfterNaturalDecel = missile.getFacing() + Math.signum(turnVel) * decelDistance;
6441 float diffWithCurrFacing = getAngleDiff(missile.getFacing(), desiredFacing);
6442
6443 if (diffWithEventualFacing > 1f) {
6444 float turnDir = getClosestTurnDirection(missile.getFacing(), desiredFacing);
6445 if (Math.signum(turnVel) == Math.signum(turnDir)) {
6447 turnDir = -turnDir;
6448 }
6449 }
6450 if (turnDir < 0) {
6451 missile.giveCommand(ShipCommand.TURN_RIGHT);
6452 } else if (turnDir >= 0) {
6453 missile.giveCommand(ShipCommand.TURN_LEFT);
6454 } else {
6455 return false;
6456 }
6457 }
6458 return false;
6459 }
6460
6461 public static int getUntrustwortyCount() {
6462 int count = Global.getSector().getPlayerMemoryWithoutUpdate().getInt(MemFlags.PLAYER_UNTRUSTWORTHY);
6463 return count;
6464 }
6465
6466 public static void incrUntrustwortyCount() {
6467 int count = getUntrustwortyCount();
6468 Global.getSector().getPlayerMemoryWithoutUpdate().set(MemFlags.PLAYER_UNTRUSTWORTHY, count + 1);
6469 }
6470
6471 public static ReputationAdjustmentResult adjustRep(PersonAPI person, float delta, TextPanelAPI text) {
6472 return adjustRep(person, delta, null, text);
6473 }
6474 public static ReputationAdjustmentResult adjustRep(PersonAPI person, float delta, RepLevel limit, TextPanelAPI text) {
6475 return adjustRep(person, delta, limit, text, true, true);
6476 }
6477 public static ReputationAdjustmentResult adjustRep(PersonAPI person, float delta, RepLevel limit, TextPanelAPI text,
6478 boolean addMessageOnNoChange, boolean withMessage) {
6479 CustomRepImpact impact = new CustomRepImpact();
6480 impact.delta = delta;
6481 if (limit != null) {
6482 impact.limit = limit;
6483 }
6484 return Global.getSector().adjustPlayerReputation(
6485 new RepActionEnvelope(RepActions.CUSTOM,
6486 impact, null, text, addMessageOnNoChange, withMessage),
6487 person);
6488 }
6489
6490 public static ReputationAdjustmentResult adjustRep(String factionId, float delta, TextPanelAPI text) {
6491 return adjustRep(factionId, delta, null, text);
6492 }
6493 public static ReputationAdjustmentResult adjustRep(String factionId, float delta, RepLevel limit, TextPanelAPI text) {
6494 return adjustRep(factionId, delta, limit, text, true, true);
6495 }
6496 public static ReputationAdjustmentResult adjustRep(String factionId, float delta, RepLevel limit, TextPanelAPI text,
6497 boolean addMessageOnNoChange, boolean withMessage) {
6498 CustomRepImpact impact = new CustomRepImpact();
6499 impact.delta = delta;
6500 if (limit != null) {
6501 impact.limit = limit;
6502 }
6503 return Global.getSector().adjustPlayerReputation(
6504 new RepActionEnvelope(RepActions.CUSTOM,
6505 impact, null, text, addMessageOnNoChange, withMessage),
6506 factionId);
6507 }
6508
6509 public static String getHullSizeStr(HullSize size) {
6510 switch (size) {
6511 case CAPITAL_SHIP: return "Capital";
6512 case CRUISER: return "Cruiser";
6513 case DESTROYER: return "Destroyer";
6514 case FIGHTER: return "Fighter";
6515 case FRIGATE: return "Frigate";
6516 }
6517 return "Unknown";
6518 }
6519
6520 public static float getColorDist(Color one, Color two) {
6521 float r = Math.abs(one.getRed() - two.getRed());
6522 float g = Math.abs(one.getGreen() - two.getGreen());
6523 float b = Math.abs(one.getBlue() - two.getBlue());
6524 float a = Math.abs(one.getAlpha() - two.getAlpha());
6525
6526 return (float) Math.sqrt(r * r + g * g + b * b + a * a);
6527 }
6528
6529
6530 public static float FRINGE_THRESHOLD = 0.7f;
6531
6532 public static boolean isFringe(SectorEntityToken entity) {
6533 return isFringe(entity.getLocationInHyperspace());
6534 }
6535 public static boolean isFringe(StarSystemAPI system) {
6536 return isFringe(system.getLocation());
6537 }
6538 public static boolean isFringe(Vector2f loc) {
6539 return getFringeFactor(loc) > FRINGE_THRESHOLD;
6540 }
6541 public static float getFringeFactor(Vector2f loc) {
6542 float sw = Global.getSettings().getFloat("sectorWidth");
6543 float sh = Global.getSettings().getFloat("sectorHeight");
6544 float mult = 0.8f;
6545 //float mult = 1f;
6546 float a = sw * 0.5f * mult;
6547 float b = sh * 0.5f * mult;
6548 float x = loc.x;
6549 float y = loc.y;
6550
6551 float f = (x * x) / (a * a) + (y * y)/ (b * b);
6552 if (f < 0) f = 0;
6553 if (f > 1) f = 1;
6554 return f;
6555 }
6556
6557 public static boolean isHiddenBase(MarketAPI market) {
6558 return market.getMemoryWithoutUpdate().getBoolean(MemFlags.HIDDEN_BASE_MEM_FLAG);
6559 }
6560
6561
6562 public static boolean isReversePolarity(SectorEntityToken entity) {
6563 return entity.getMemoryWithoutUpdate().getBoolean(ReversePolarityToggle.REVERSED_POLARITY);
6564 }
6565
6566
6567
6568 public static enum CatalogEntryType {
6569 PLANET("P"),
6570 GIANT("G"),
6571 STAR("S"),
6572 BLACK_HOLE("B");
6573
6574 public String suffix;
6575 private CatalogEntryType(String suffix) {
6576 this.suffix = suffix;
6577 }
6578
6579 }
6580 public static String genEntityCatalogId(CatalogEntryType type) {
6581 return genEntityCatalogId(-1, -1, -1, type);
6582 }
6583 public static String genEntityCatalogId(int cycleOverride, int monthOverride, int dayOverride, CatalogEntryType type) {
6585 }
6586 public static String genEntityCatalogId(String firstChar, int cycleOverride, int monthOverride, int dayOverride, CatalogEntryType type) {
6587
6588 String base = "Perseus";
6589
6590 int cycle = Global.getSector().getClock().getCycle();
6591 cycle += 3000;
6592 if (cycleOverride > 0) cycle = cycleOverride;
6593
6594 int month = Global.getSector().getClock().getMonth();
6596 int day = Global.getSector().getClock().getDay();
6597 if (dayOverride > 0) day = dayOverride;
6598
6599 String s1 = Integer.toHexString(cycle).toUpperCase();
6600
6601 Random r = StarSystemGenerator.random;
6602
6603 String s0 = Integer.toHexString(r.nextInt(16)).toUpperCase();
6604 if (firstChar != null) s0 = firstChar;
6605
6606 String s2 = Integer.toHexString(month).toUpperCase();
6607 String s3 = Integer.toHexString(day).toUpperCase();
6608
6609// s1 = "" + cycle;
6610// s0 = "";
6611
6612 while (s1.length() < 3) s1 = "0" + s1;
6613 while (s3.length() < 2) s3 = "0" + s3;
6614
6615 return base + " " + s0 + s1 + "-" + s2 + s3 + type.suffix;
6616 }
6617}
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
static SettingsAPI getSettings()
Definition Global.java:51
static SoundPlayerAPI getSoundPlayer()
Definition Global.java:43
static FactoryAPI getFactory()
Definition Global.java:35
static Logger getLogger(Class c)
Definition Global.java:26
static CombatEngineAPI getCombatEngine()
Definition Global.java:63
static SectorAPI getSector()
Definition Global.java:59
static float getFleetwideTotalStat(CampaignFleetAPI fleet, String dynamicMemberStatId)
Definition Misc.java:2712
static void setDefenderOverride(SectorEntityToken entity, DefenderDataOverride override)
Definition Misc.java:3554
static void setWarningBeaconColors(SectorEntityToken beacon, Color glow, Color ping)
Definition Misc.java:3666
static long getNameBasedSeed(SectorEntityToken entity)
Definition Misc.java:4075
static boolean isStoryCritical(MarketAPI market)
Definition Misc.java:6135
static String getJoined(String joiner, String ... strings)
Definition Misc.java:875
static Color getStoryOptionColor()
Definition Misc.java:775
static float getBonusXPForRecovering(FleetMemberAPI member)
Definition Misc.java:5662
static float getBurnMultForTerrain(CampaignFleetAPI fleet)
Definition Misc.java:4890
static void setUnremovable(PersonAPI person, boolean unremovable)
Definition Misc.java:5391
static float getDistanceSq(Vector2f v1, Vector2f v2)
Definition Misc.java:606
static Color getRelColor(float rel)
Definition Misc.java:5215
static Color getTextColor()
Definition Misc.java:832
static float getGenericRollingAverageFactor()
Definition Misc.java:855
static ShipAPI findClosestShipEnemyOf(ShipAPI ship, Vector2f locFromForSorting, HullSize smallestToNote, float maxRange, boolean considerShipRadius)
Definition Misc.java:2481
static float getBuildInBonusXP(HullModSpecAPI mod, HullSize size)
Definition Misc.java:5442
static SectorEntityToken addWarningBeacon(SectorEntityToken center, OrbitGap gap, String beaconTag)
Definition Misc.java:5066
static String getStringWithTokenReplacement(String format, SectorEntityToken entity, Map< String, MemoryAPI > memoryMap)
Definition Misc.java:3040
static List< StarSystemAPI > getSystemsInRange(SectorEntityToken from, Set< StarSystemAPI > exclude, boolean nonEmpty, float maxRange)
Definition Misc.java:3579
static boolean isHiddenBase(MarketAPI market)
Definition Misc.java:6557
static int getMaxOfficers(CampaignFleetAPI fleet)
Definition Misc.java:5133
static String getDGSCredits(float num)
Definition Misc.java:1383
static int getNumStableLocations(StarSystemAPI system)
Definition Misc.java:5192
static String genEntityCatalogId(int cycleOverride, int monthOverride, int dayOverride, CatalogEntryType type)
Definition Misc.java:6583
static void applyDamage(FleetMemberAPI member, Random random, float damageMult, boolean withCRDamage, String crDamageId, String crDamageReason, boolean withMessage, TextPanelAPI textPanel, String messageText)
Definition Misc.java:5602
static void cleanBuffer(Buffer toBeDestroyed)
Definition Misc.java:2684
static MarketAPI getSourceMarket(CampaignFleetAPI fleet)
Definition Misc.java:2155
static String getWithDGS(float num)
Definition Misc.java:1374
static SectorEntityToken addNebulaFromPNG(String image, float centerX, float centerY, LocationAPI location, String category, String key, int tilesWide, int tilesHigh, String terrainType, StarAge age)
Definition Misc.java:1763
static DecimalFormat format
Definition Misc.java:1358
static boolean isPatrol(CampaignFleetAPI fleet)
Definition Misc.java:4675
static int getShippingCapacity(MarketAPI market, boolean inFaction)
Definition Misc.java:4933
static boolean turnTowardsPointV2(MissileAPI missile, Vector2f point, float angVel)
Definition Misc.java:6423
static JumpPointAPI findNearestJumpPointThatCouldBeExitedFrom(SectorEntityToken entity)
Definition Misc.java:3324
static Color getButtonTextColor()
Definition Misc.java:835
static Color genColor(Color min, Color max, Random random)
Definition Misc.java:1266
static float getSpawnChanceMult(Vector2f locInHyper)
Definition Misc.java:2173
static int getNumImprovedIndustries(MarketAPI market)
Definition Misc.java:5182
static boolean hasHeavyIndustry(MarketAPI market)
Definition Misc.java:4963
static void makeNonHostileToFaction(CampaignFleetAPI fleet, String factionId, float dur)
Definition Misc.java:1478
static void playSound(ApplyDamageResultAPI result, Vector2f loc, Vector2f vel, String lightShields, String solidShields, String heavyShields, String lightHull, String solidHull, String heavyHull)
Definition Misc.java:5916
static void renderQuad(float x, float y, float width, float height, Color color, float alphaMult)
Definition Misc.java:1835
static void removeDefeatTrigger(CampaignFleetAPI fleet, String trigger)
Definition Misc.java:5808
static void makeImportant(MemoryAPI memory, String reason, float dur)
Definition Misc.java:3988
static List< StarSystemAPI > getSystemsWithPlayerColonies(boolean includeNonPlayerFaction)
Definition Misc.java:989
static float getDistanceLY(SectorEntityToken from, SectorEntityToken to)
Definition Misc.java:595
static float getShipWeight(ShipAPI ship)
Definition Misc.java:5975
static PlanetAPI getPulsarInSystem(StarSystemAPI system)
Definition Misc.java:3602
static float GATE_FUEL_COST_MULT
Definition Misc.java:213
static float getMercDaysSinceHired(PersonAPI person)
Definition Misc.java:5376
static Vector2f getPointAtRadius(Vector2f from, float r, Random random)
Definition Misc.java:697
static FleetInflater getInflater(CampaignFleetAPI fleet, Object params)
Definition Misc.java:4163
static int getDangerLevel(CampaignFleetAPI fleet)
Definition Misc.java:5239
static SectorEntityToken addNebulaFromPNG(String image, float centerX, float centerY, LocationAPI location, String category, String key, int tilesWide, int tilesHigh, StarAge age)
Definition Misc.java:1757
static CampaignEventPlugin startEvent(CampaignEventTarget eventTarget, String eventId, Object params)
Definition Misc.java:754
static float getDistanceFromArc(float direction, float arc, float angle)
Definition Misc.java:3500
static Map< String, Integer > variantToFPCache
Definition Misc.java:4355
static AICoreOfficerPlugin getAICoreOfficerPlugin(String commodityId)
Definition Misc.java:4147
static List< MarketAPI > getFactionMarkets(String factionId)
Definition Misc.java:1001
static float getStorageShipValue(MarketAPI market)
Definition Misc.java:4250
static int getNumEliteSkills(PersonAPI person)
Definition Misc.java:5323
static Vector2f getInterceptPoint(SectorEntityToken from, SectorEntityToken to, float maxSpeedFrom)
Definition Misc.java:3875
static Vector2f closestPointOnSegmentToPoint(Vector2f p1, Vector2f p2, Vector2f p3)
Definition Misc.java:1882
static Vector2f getUnitVectorAtDegreeAngle(float degrees)
Definition Misc.java:1189
static String lcFirst(String str)
Definition Misc.java:558
static void setMentored(PersonAPI person, boolean mentored)
Definition Misc.java:5362
static long getSalvageSeed(SectorEntityToken entity, boolean nonRandom)
Definition Misc.java:4053
static Color getStoryDarkColor()
Definition Misc.java:766
static float getStorageFeeFraction()
Definition Misc.java:4203
static float getColorDist(Color one, Color two)
Definition Misc.java:6520
static List< CampaignFleetAPI > getNearbyFleets(SectorEntityToken from, float maxDist)
Definition Misc.java:3672
static boolean isInAbyss(Vector2f loc)
Definition Misc.java:2317
static WeightedRandomPicker< String > createStringPicker(Random random, Object ... params)
Definition Misc.java:3643
static float getFleetwideTotalMod(CampaignFleetAPI fleet, String dynamicMemberStatId, float base, ShipAPI ship)
Definition Misc.java:2724
static List< String > getDefeatTriggers(CampaignFleetAPI fleet, boolean createIfNecessary)
Definition Misc.java:5817
static int computeTotalShutdownRefund(MarketAPI market)
Definition Misc.java:5018
static boolean isWarFleet(CampaignFleetAPI fleet)
Definition Misc.java:4693
static boolean isRaider(CampaignFleetAPI fleet)
Definition Misc.java:4690
static ReputationAdjustmentResult adjustRep(String factionId, float delta, RepLevel limit, TextPanelAPI text)
Definition Misc.java:6493
static void unsetAll(String prefix, String memKey, MemoryAPI memory)
Definition Misc.java:1334
static List< StarSystemAPI > getAbyssalSystems()
Definition Misc.java:2329
static boolean isInsideSlipstream(Vector2f loc, float radius)
Definition Misc.java:6285
static void setAsteroidSource(SectorEntityToken asteroid, AsteroidSource source)
Definition Misc.java:2260
static SectorEntityToken addDebrisField(LocationAPI loc, DebrisFieldParams params, Random random)
Definition Misc.java:3198
static float FP_TO_GROUND_RAID_STR_APPROX_MULT
Definition Misc.java:220
static boolean isSameCargo(CargoAPI baseOne, CargoAPI baseTwo)
Definition Misc.java:3698
static float getEconomyInterval()
Definition Misc.java:851
static List< FleetMemberAPI > getSnapshotMembersLost(CampaignFleetAPI fleet)
Definition Misc.java:741
static List< MarketAPI > getMarketsInLocation(LocationAPI location, String factionId)
Definition Misc.java:929
static float approach(float curr, float dest, float minSpeed, float diffSpeedMult, float amount)
Definition Misc.java:2676
static float getClosestTurnDirection(Vector2f one, Vector2f two)
Definition Misc.java:2145
static Color getMissileMountColor()
Definition Misc.java:805
static String ucFirst(String str)
Definition Misc.java:552
static float getMemberStrength(FleetMemberAPI member)
Definition Misc.java:4758
static boolean isMercenary(PersonAPI person)
Definition Misc.java:5367
static boolean isFastStartExplorer()
Definition Misc.java:2270
static float getDesiredMoveDir(CampaignFleetAPI fleet)
Definition Misc.java:4111
static Color getNegativeHighlightColor()
Definition Misc.java:795
static Object getSalvageSpecial(SectorEntityToken entity)
Definition Misc.java:3569
static float getSizeNum(HullSize size)
Definition Misc.java:1315
static Map< String, String > variantToHullCache
Definition Misc.java:4357
static Vector2f bezier(Vector2f p0, Vector2f p1, Vector2f p2, float t)
Definition Misc.java:6260
static void addHitGlow(LocationAPI location, Vector2f loc, Vector2f vel, float size, float dur, Color color)
Definition Misc.java:4904
static CargoAPI getStorageCargo(MarketAPI market)
Definition Misc.java:4224
static float getAngleInDegreesStrict(Vector2f from, Vector2f to)
Definition Misc.java:1113
static String getHullSizeStr(HullSize size)
Definition Misc.java:6509
static void moveToMarket(PersonAPI person, MarketAPI destination, boolean alwaysAddToCommDirectory)
Definition Misc.java:6082
static float getStorageCargoValue(MarketAPI market)
Definition Misc.java:4240
static void setColor(Color color, float alphaMult)
Definition Misc.java:3934
static void makeImportant(PersonAPI person, String reason)
Definition Misc.java:3978
static float getIncapacitatedTime(ShipAPI ship)
Definition Misc.java:5995
static String getHullIdForVariantId(String variantId)
Definition Misc.java:4359
static boolean shouldShowDamageFloaty(ShipAPI source, ShipAPI target)
Definition Misc.java:5838
static float getRoundedValueFloat(float value)
Definition Misc.java:654
static int computeShutdownRefund(MarketAPI market, Industry industry)
Definition Misc.java:5032
static void setColor(Color color)
Definition Misc.java:3927
static void setAbandonedStationMarket(String marketId, SectorEntityToken station)
Definition Misc.java:4097
static String getStringForDays(int days)
Definition Misc.java:1601
static Vector2f getSystemJumpPointHyperExitLocation(JumpPointAPI jp)
Definition Misc.java:4562
static float getDistance(Vector3f v1, Vector3f v2)
Definition Misc.java:1704
static boolean doesMarketHaveMissionImportantPeopleOrIsMarketMissionImportant(SectorEntityToken entity)
Definition Misc.java:3950
static boolean areSegmentsCoincident(Vector2f a1, Vector2f a2, Vector2f b1, Vector2f b2)
Definition Misc.java:2072
static float getHitGlowSize(float baseSize, float baseDamage, DamageType type, float sd, float ad, float hd, float ed)
Definition Misc.java:5278
static boolean hasOrbitalStation(MarketAPI market)
Definition Misc.java:4973
static void makeHostileToFaction(CampaignFleetAPI fleet, String factionId, float dur)
Definition Misc.java:1489
static SurveyLevel getMinSystemSurveyLevel(StarSystemAPI system)
Definition Misc.java:2770
static void genFractalNoise(Random random, float[][] noise, int x1, int y1, int x2, int y2, int iter, float spikes)
Definition Misc.java:2632
static List< MarketAPI > getFactionMarkets(FactionAPI faction, String econGroup)
Definition Misc.java:964
static Random getRandom(long seed, int level)
Definition Misc.java:2915
static Color setAlpha(Color color, int alpha)
Definition Misc.java:1309
static String getJoined(String joiner, List< String > strings)
Definition Misc.java:872
static void giveStandardReturnToSourceAssignments(CampaignFleetAPI fleet, boolean withClear)
Definition Misc.java:3767
static void removeRadioChatter(MarketAPI market)
Definition Misc.java:4837
static void setPrevSalvageSpecial(SectorEntityToken entity, Object data)
Definition Misc.java:3565
static String DEFEAT_TRIGGERS
Definition Misc.java:5802
static Color FLOATY_ARMOR_DAMAGE_COLOR
Definition Misc.java:207
static boolean isAutomated(MutableShipStatsAPI stats)
Definition Misc.java:5395
static Vector2f pickLocationNotNearPlayer(LocationAPI where, Vector2f from, float minDist)
Definition Misc.java:2203
static void makeStoryCritical(MemoryAPI memory, String reason)
Definition Misc.java:6126
static String getTokenReplaced(String in, SectorEntityToken entity)
Definition Misc.java:4316
static List< HullModSpecAPI > getCurrSpecialModsList(ShipVariantAPI variant)
Definition Misc.java:5541
static float getDistance(float x1, float y1, float x2, float y2)
Definition Misc.java:611
static void makeImportant(SectorEntityToken entity, String reason)
Definition Misc.java:3972
static void fadeInOutAndExpire(final SectorEntityToken entity, final float in, final float dur, final float out)
Definition Misc.java:3099
static CampaignFleetAPI getStationBaseFleet(SectorEntityToken station)
Definition Misc.java:4516
static Pair< SectorEntityToken, CampaignFleetAPI > getNearestStationInSupportRange(CampaignFleetAPI from)
Definition Misc.java:4703
static Vector2f rotateAroundOrigin(Vector2f v, float angle)
Definition Misc.java:1198
static CustomCampaignEntityAPI addCargoPods(LocationAPI where, Vector2f loc)
Definition Misc.java:3181
static Vector2f closestPointOnLineToPoint(Vector2f p1, Vector2f p2, Vector2f p3)
Definition Misc.java:1870
static String genEntityCatalogId(String firstChar, int cycleOverride, int monthOverride, int dayOverride, CatalogEntryType type)
Definition Misc.java:6586
static void increaseMarketHostileTimeout(MarketAPI market, float days)
Definition Misc.java:4825
static boolean isAutomated(ShipAPI ship)
Definition Misc.java:5406
static float MAX_OFFICER_LEVEL
Definition Misc.java:232
static String getStarId(PlanetAPI planet)
Definition Misc.java:2737
static boolean turnTowardsFacingV2(MissileAPI missile, float desiredFacing, float relativeAngVel)
Definition Misc.java:6428
static void setAllPlanetsSurveyed(StarSystemAPI system, boolean setRuinsExplored)
Definition Misc.java:2834
static float[] getBonusXPForScuttling(FleetMemberAPI member)
Definition Misc.java:5677
static Color getStoryBrightColor()
Definition Misc.java:769
static int getGoSlowBurnLevel(CampaignFleetAPI fleet)
Definition Misc.java:5562
static PulsarBeamTerrainPlugin getPulsarFor(PlanetAPI star)
Definition Misc.java:2385
static void addSurveyDataFor(PlanetAPI planet, TextPanelAPI text)
Definition Misc.java:2926
static Object getPrevSalvageSpecial(SectorEntityToken entity)
Definition Misc.java:3572
static float getShipWeight(ShipAPI ship, boolean adjustForNonCombat)
Definition Misc.java:5979
static boolean isActiveModule(ShipAPI ship)
Definition Misc.java:4549
static float getCampaignShipScaleMult(HullSize size)
Definition Misc.java:3621
static final Vector2f ZERO
Definition Misc.java:242
static final String D_HULL_SUFFIX
Definition Misc.java:3488
static StabilizeMarketPlugin getStabilizeMarketPlugin(MarketAPI market)
Definition Misc.java:4157
static float getFleetwideTotalMod(CampaignFleetAPI fleet, String dynamicMemberStatId, float base)
Definition Misc.java:2721
static HullModSpecAPI getMod(String id)
Definition Misc.java:3496
static ReputationAdjustmentResult adjustRep(PersonAPI person, float delta, TextPanelAPI text)
Definition Misc.java:6471
static CampaignFleetAPI getStationBaseFleet(MarketAPI market)
Definition Misc.java:4507
static final boolean shouldConvertFromStub(LocationAPI containingLocation, Vector2f location)
Definition Misc.java:3359
static boolean isStoryCritical(MemoryAPI memory)
Definition Misc.java:6138
static String getAgoStringForTimestamp(long timestamp)
Definition Misc.java:1519
static float getMarketSizeProgress(MarketAPI market)
Definition Misc.java:4187
static String getAtLeastStringForDays(int days)
Definition Misc.java:1579
static boolean isFastStartMerc()
Definition Misc.java:2273
static float DISSIPATION_PER_VENT
Definition Misc.java:190
static List< StarSystemAPI > getPlayerSystems(boolean includeNonPlayerFaction)
Definition Misc.java:986
static boolean isAutomated(ShipVariantAPI variant)
Definition Misc.java:5403
static boolean isInsideBlackHole(CampaignFleetAPI fleet, boolean includeEventHorizon)
Definition Misc.java:2343
static void incrUntrustwortyCount()
Definition Misc.java:6466
static Industry getSpaceport(MarketAPI market)
Definition Misc.java:5101
static float computeAngleSpan(float radius, float range)
Definition Misc.java:2666
static boolean isFringe(SectorEntityToken entity)
Definition Misc.java:6532
static JumpPointAPI findNearestJumpPoint(SectorEntityToken from)
Definition Misc.java:3472
static Vector2f getVector(JSONObject json, String arrayKey, int index)
Definition Misc.java:2575
static float computeAngleRadius(float angle, float range)
Definition Misc.java:2671
static JumpPointAPI getDistressJumpPoint(StarSystemAPI system)
Definition Misc.java:3728
static List< StarSystemAPI > getNearbyStarSystems(SectorEntityToken token, float maxRangeLY)
Definition Misc.java:1038
static void giveStandardReturnToSourceAssignments(CampaignFleetAPI fleet)
Definition Misc.java:3757
static Vector2f pickHyperLocationNotNearPlayer(Vector2f from, float minDist)
Definition Misc.java:2186
static boolean playerHasStorageAccess(MarketAPI market)
Definition Misc.java:4179
static CargoAPI getLocalResourcesCargo(MarketAPI market)
Definition Misc.java:4231
static boolean isBusy(CampaignFleetAPI fleet)
Definition Misc.java:4475
static void makeNonStoryCritical(MemoryAPI memory, String reason)
Definition Misc.java:6132
static SectorEntityToken findNearestPlanetTo(SectorEntityToken entity, boolean requireGasGiant, boolean allowStars)
Definition Misc.java:3340
static void makeNotLowRepImpact(CampaignFleetAPI fleet, String reason)
Definition Misc.java:1513
static void addCreditsMessage(String format, int credits)
Definition Misc.java:4556
static List< CampaignFleetAPI > getFleetsInOrNearSystem(StarSystemAPI system)
Definition Misc.java:919
static final int OWNER_PLAYER
Definition Misc.java:204
static void wiggle(Vector2f v, float max)
Definition Misc.java:2224
static Color getBasePlayerColor()
Definition Misc.java:826
static FactionCommissionIntel getCommissionIntel()
Definition Misc.java:2416
static float getHitGlowSize(float baseSize, float baseDamage, ApplyDamageResultAPI result)
Definition Misc.java:5266
static void normalizeNoise(float[][] noise)
Definition Misc.java:2582
static boolean isDecentralized(FactionAPI faction)
Definition Misc.java:5703
static boolean isShipRecoverable(FleetMemberAPI member, CampaignFleetAPI recoverer, boolean own, boolean useOfficerRecovery, float chanceMult)
Definition Misc.java:3253
static List< CampaignFleetAPI > getVisibleFleets(SectorEntityToken from, boolean includeSensorContacts)
Definition Misc.java:3684
static Color getGrayColor()
Definition Misc.java:819
static String DANGER_LEVEL_OVERRIDE
Definition Misc.java:5238
static void initConditionMarket(PlanetAPI planet)
Definition Misc.java:3512
static String colorsToString(List< Color > colors)
Definition Misc.java:3443
static void cleanUpMissionMemory(MemoryAPI memory, String prefix)
Definition Misc.java:4009
static DecimalFormat getFormat()
Definition Misc.java:1359
static boolean hasRuins(MarketAPI market)
Definition Misc.java:5785
static void fadeAndExpire(SectorEntityToken entity)
Definition Misc.java:3069
static Vector2f getVector(JSONObject json, String arrayKey)
Definition Misc.java:2545
static String getAOrAnFor(String word)
Definition Misc.java:6037
static void addDefeatTrigger(CampaignFleetAPI fleet, String trigger)
Definition Misc.java:5803
static String getAndJoined(String ... strings)
Definition Misc.java:868
static AsteroidSource getAsteroidSource(SectorEntityToken asteroid)
Definition Misc.java:2254
static int getNumIndustries(MarketAPI market)
Definition Misc.java:5162
static List< OfficerDataAPI > getMercs(CampaignFleetAPI fleet)
Definition Misc.java:5147
static void setSeen(MarketAPI market, TextPanelAPI text, boolean withNotification)
Definition Misc.java:3005
static float getShieldedCargoFraction(CampaignFleetAPI fleet)
Definition Misc.java:1240
static void adjustRep(float repChangeFaction, RepLevel limit, String factionId, float repChangePerson, RepLevel personLimit, PersonAPI person, TextPanelAPI text)
Definition Misc.java:3805
static void addHitGlow(LocationAPI location, Vector2f loc, Vector2f vel, float size, Color color)
Definition Misc.java:4900
static List< MarketAPI > findNearbyLocalMarkets(SectorEntityToken token, float maxDist, MarketFilter filter)
Definition Misc.java:1158
static float getFuelPerDay(CampaignFleetAPI fleet, float burnLevel)
Definition Misc.java:1669
static int getVramDedicatedKB()
Definition Misc.java:5901
static boolean isBetween(float one, float two, float check)
Definition Misc.java:1225
static StarSystemAPI getNearestStarSystem(SectorEntityToken token)
Definition Misc.java:1068
static void makeStoryCritical(String marketId, String reason)
Definition Misc.java:6120
static String getStrengthDesc(float strAdjustedFP)
Definition Misc.java:4941
static boolean CAN_SMOD_BUILT_IN
Definition Misc.java:182
static MarketAPI findNearestLocalMarketWithSameFaction(final SectorEntityToken token, float maxDist)
Definition Misc.java:1176
static boolean isSmuggler(CampaignFleetAPI fleet)
Definition Misc.java:4678
static float getDistance(Vector2f v1, Vector2f v2)
Definition Misc.java:601
static void clearDefeatTriggersIfNeeded(CampaignFleetAPI fleet)
Definition Misc.java:5830
static void computeCoreWorldsExtent()
Definition Misc.java:6340
static float findKth(float[] arr, int k)
Definition Misc.java:6215
static Color getDesignTypeColorDim(String designType)
Definition Misc.java:4854
static Vector2f intersectLines(Vector2f a1, Vector2f a2, Vector2f b1, Vector2f b2)
Definition Misc.java:1987
static void renderQuadAlpha(float x, float y, float width, float height, Color color, float alphaMult)
Definition Misc.java:3047
static boolean isFleetMadeHostileToFaction(CampaignFleetAPI fleet, FactionAPI faction)
Definition Misc.java:1501
static String getDHullId(ShipHullSpecAPI spec)
Definition Misc.java:3489
static Color getEnergyMountColor()
Definition Misc.java:808
static WeightedRandomPicker< String > createStringPicker(Object ... params)
Definition Misc.java:3639
static void makeHostileToAllTradeFleets(CampaignFleetAPI fleet)
Definition Misc.java:1474
static Vector2f bezierCubic(Vector2f p0, Vector2f p1, Vector2f p2, Vector2f p3, float t)
Definition Misc.java:6269
static float getAdminSalary(PersonAPI admin)
Definition Misc.java:4326
static Vector2f getCoreMin()
Definition Misc.java:6361
static float getAngleDiff(float from, float to)
Definition Misc.java:1709
static boolean isOpenlyPopulated(StarSystemAPI system)
Definition Misc.java:5755
static StarSystemAPI getNearbyStarSystem(SectorEntityToken token)
Definition Misc.java:1085
static List< Color > colorsFromString(String in)
Definition Misc.java:3454
static Color setBrightness(Color color, int brightness)
Definition Misc.java:5110
static Color getBrightPlayerColor()
Definition Misc.java:823
static float getDistance(SectorEntityToken from, SectorEntityToken to)
Definition Misc.java:592
static float getClosestTurnDirection(float facing, Vector2f from, Vector2f to)
Definition Misc.java:2121
static void applyDamage(FleetMemberAPI member, Random random, FleetMemberDamageLevel level, boolean withCRDamage, String crDamageId, String crDamageReason, boolean withMessage, TextPanelAPI textPanel, String messageText)
Definition Misc.java:5582
static void setAllPlanetsKnown(StarSystemAPI system)
Definition Misc.java:2820
static float getProfitMarginFlat()
Definition Misc.java:843
static boolean hasPulsar(StarSystemAPI system)
Definition Misc.java:2395
static StarSystemAPI getNearbyStarSystem(SectorEntityToken token, float maxRangeLY)
Definition Misc.java:1049
static float getShipQuality(MarketAPI market, String factionId)
Definition Misc.java:4425
static boolean isFringe(Vector2f loc)
Definition Misc.java:6538
static float getDays(float amount)
Definition Misc.java:4580
static Vector2f getPointWithinRadius(Vector2f from, float r, Random random)
Definition Misc.java:707
static long getSalvageSeed(SectorEntityToken entity)
Definition Misc.java:4050
static boolean isReversePolarity(SectorEntityToken entity)
Definition Misc.java:6562
static boolean isMentored(PersonAPI person)
Definition Misc.java:5358
static boolean isNear(SectorEntityToken entity, Vector2f hyperLoc)
Definition Misc.java:4573
static Vector2f getUnitVector(Vector2f from, Vector2f to)
Definition Misc.java:1184
static float getFleetRadiusTerrainEffectMult(CampaignFleetAPI fleet)
Definition Misc.java:4867
static void fadeAndExpire(final SectorEntityToken entity, final float seconds)
Definition Misc.java:3072
static float getFringeFactor(Vector2f loc)
Definition Misc.java:6541
static float getStorageTotalValue(MarketAPI market)
Definition Misc.java:4237
static boolean isHyperspaceAnchor(SectorEntityToken entity)
Definition Misc.java:4592
static MusicPlayerPlugin musicPlugin
Definition Misc.java:5228
static List< Token > tokenize(String string)
Definition Misc.java:418
static Color scaleAlpha(Color color, float factor)
Definition Misc.java:1302
static String getSurveyLevelString(SurveyLevel level, boolean withBrackets)
Definition Misc.java:3540
static void setFullySurveyed(MarketAPI market, TextPanelAPI text, boolean withNotification)
Definition Misc.java:2939
static boolean isOutsideSector(Vector2f loc)
Definition Misc.java:6313
static float getUnitsPerLightYear()
Definition Misc.java:839
static boolean flagHasReason(MemoryAPI memory, String flagKey, String reason)
Definition Misc.java:1446
static AICoreAdminPlugin getAICoreAdminPlugin(String commodityId)
Definition Misc.java:4142
static float getOfficerSalary(PersonAPI officer, boolean mercenary)
Definition Misc.java:4336
static boolean hasSModdableBuiltIns(ShipVariantAPI variant)
Definition Misc.java:5510
static Vector2f intersectSegmentAndCircle(Vector2f p1, Vector2f p2, Vector2f p3, float r)
Definition Misc.java:2019
static List< MarketAPI > getNearbyMarkets(Vector2f locInHyper, float distLY)
Definition Misc.java:1015
static boolean hasUnexploredRuins(MarketAPI market)
Definition Misc.java:5781
static SubmarketPlugin getLocalResources(MarketAPI market)
Definition Misc.java:4219
static float getClosestTurnDirection(float facing, float desired)
Definition Misc.java:2095
static Color getHighlightedOptionColor()
Definition Misc.java:781
static MusicPlayerPlugin getMusicPlayerPlugin()
Definition Misc.java:5229
static void setSalvageSpecial(SectorEntityToken entity, Object data)
Definition Misc.java:3558
static boolean hasAtLeastOneOfTags(Collection< String > tags, String ... other)
Definition Misc.java:5763
static FactionPersonalityPickerPlugin getFactionPersonalityPicker()
Definition Misc.java:4395
static int getMaxPermanentMods(FleetMemberAPI member, MutableCharacterStatsAPI stats)
Definition Misc.java:5430
static void makeNonStoryCritical(MarketAPI market, String reason)
Definition Misc.java:6129
static MarketAPI getStationMarket(CampaignFleetAPI station)
Definition Misc.java:4526
static void showCost(TextPanelAPI text, String title, boolean withAvailable, float widthOverride, Color color, Color dark, String[] res, int[] quantities, boolean[] consumed)
Definition Misc.java:4606
static boolean isInsideSlipstream(Vector2f loc, float radius, LocationAPI location)
Definition Misc.java:6288
static boolean isInAbyss(SectorEntityToken entity)
Definition Misc.java:2320
static float getDistanceToPlayerLY(Vector2f locInHyper)
Definition Misc.java:619
static void affectAvailabilityWithinReason(CommodityOnMarketAPI com, int quantity)
Definition Misc.java:5743
static Vector2f getInterceptPoint(CampaignFleetAPI from, SectorEntityToken to)
Definition Misc.java:3842
static Vector2f intersectSegments(Vector2f a1, Vector2f a2, Vector2f b1, Vector2f b2)
Definition Misc.java:1929
static boolean isSpecialMod(ShipVariantAPI variant, HullModSpecAPI spec)
Definition Misc.java:5496
static boolean isTrader(CampaignFleetAPI fleet)
Definition Misc.java:4681
static CampaignTerrainAPI getHyperspaceTerrain()
Definition Misc.java:2301
static void makeImportant(SectorEntityToken entity, String reason, float dur)
Definition Misc.java:3975
static void forgetAboutTransponder(CampaignFleetAPI fleet)
Definition Misc.java:4088
static float distanceFromLineToPoint(Vector2f p1, Vector2f p2, Vector2f p3)
Definition Misc.java:1858
static void clearAreaAroundPlayer(float minDist)
Definition Misc.java:4029
static boolean isFleetMadeHostileToFaction(CampaignFleetAPI fleet, String factionId)
Definition Misc.java:1504
static void makeImportant(PersonAPI person, String reason, float dur)
Definition Misc.java:3981
static void makeUnimportant(SectorEntityToken entity, String reason)
Definition Misc.java:3998
static int getMaxPermanentMods(ShipAPI ship)
Definition Misc.java:5425
static Color FLOATY_HULL_DAMAGE_COLOR
Definition Misc.java:209
static boolean isSpacerStart()
Definition Misc.java:5097
static Color getHighlightColor()
Definition Misc.java:785
static boolean isInsignificant(CampaignFleetAPI fleet)
Definition Misc.java:6149
static String RECOVERY_TAGS_KEY
Definition Misc.java:5412
static Color getDesignTypeColor(String designType)
Definition Misc.java:4850
static Color optColor(JSONObject json, String key, Color defaultValue)
Definition Misc.java:2535
static int getEstimatedOrbitIndex(PlanetAPI planet)
Definition Misc.java:2872
static Color FLOATY_EMP_DAMAGE_COLOR
Definition Misc.java:206
static boolean isPlayerOrCombinedContainingPlayer(CampaignFleetAPI fleet)
Definition Misc.java:2243
static float getShipQuality(MarketAPI market)
Definition Misc.java:4422
static Vector2f optVector(JSONObject json, String arrayKey)
Definition Misc.java:2559
static LabelAPI addDesignTypePara(TooltipMakerAPI tooltip, String design, float pad)
Definition Misc.java:4860
static void clearAsteroidSource(SectorEntityToken asteroid)
Definition Misc.java:2263
static boolean hasAnySurveyDataFor(StarSystemAPI system)
Definition Misc.java:2797
static AbandonMarketPlugin getAbandonMarketPlugin(MarketAPI market)
Definition Misc.java:4152
static void setColor(Color color, int alpha)
Definition Misc.java:3942
static< T extends Enum< T > T mapToEnum(JSONObject json, String key, Class< T > enumType, T defaultOption, boolean required)
Definition Misc.java:2514
static String getDetailedAgoString(long timestamp)
Definition Misc.java:1544
static String getAndJoined(List< String > strings)
Definition Misc.java:864
static void makeImportant(MemoryAPI memory, String reason)
Definition Misc.java:3984
static Color FLOATY_SHIELD_DAMAGE_COLOR
Definition Misc.java:208
static Color getTooltipTitleAndLightHighlightColor()
Definition Misc.java:792
static int getMaxIndustries(MarketAPI market)
Definition Misc.java:5158
static boolean addStorageInfo(TooltipMakerAPI tooltip, Color color, Color dark, MarketAPI market, boolean includeLocalResources, boolean addSectionIfEmpty)
Definition Misc.java:4266
static float getAdjustedFP(float fp, MarketAPI market)
Definition Misc.java:4414
static boolean isFastStart()
Definition Misc.java:2267
static CampaignFleetAPI getStationFleet(SectorEntityToken station)
Definition Misc.java:4497
static void setMercHiredNow(PersonAPI person)
Definition Misc.java:5372
static float getRounded(float in)
Definition Misc.java:632
static boolean isInArc(float direction, float arc, float test)
Definition Misc.java:1736
static boolean isPermaKnowsWhoPlayerIs(CampaignFleetAPI fleet)
Definition Misc.java:4124
static List< MarketAPI > getFactionMarkets(FactionAPI faction)
Definition Misc.java:1004
static ImmigrationPlugin getImmigrationPlugin(MarketAPI market)
Definition Misc.java:4134
static HyperspaceTerrainPlugin getHyperspaceTerrainPlugin()
Definition Misc.java:2309
static SubmarketPlugin getStorage(MarketAPI market)
Definition Misc.java:4212
static boolean setFlagWithReason(MemoryAPI memory, String flagKey, String reason, boolean value, float expire)
Definition Misc.java:1432
static boolean isNormal()
Definition Misc.java:2281
static void initEconomyMarket(PlanetAPI planet)
Definition Misc.java:3527
static float getClosingSpeed(Vector2f p1, Vector2f p2, Vector2f v1, Vector2f v2)
Definition Misc.java:1347
static void interruptAbilitiesWithTag(CampaignFleetAPI fleet, String tag)
Definition Misc.java:3828
static ShipAPI findClosestShipEnemyOf(ShipAPI ship, Vector2f locFromForSorting, HullSize smallestToNote, float maxRange, boolean considerShipRadius, FindShipFilter filter)
Definition Misc.java:2484
static String getPersonalityName(PersonAPI person)
Definition Misc.java:5707
static float interpolate(float from, float to, float progress)
Definition Misc.java:1284
static CoreUITradeMode getTradeMode(MemoryAPI memory)
Definition Misc.java:5088
static int getFPForVariantId(String variantId)
Definition Misc.java:4384
static Color scaleColorSaturate(Color color, float factor)
Definition Misc.java:5119
static float getMemberStrength(FleetMemberAPI member, boolean withHull, boolean withQuality, boolean withCaptain)
Definition Misc.java:4762
static CampaignFleetAPI getStationFleet(MarketAPI market)
Definition Misc.java:4488
static void showCost(TextPanelAPI text, Color color, Color dark, String[] res, int[] quantities)
Definition Misc.java:4600
static boolean isPirateFaction(FactionAPI faction)
Definition Misc.java:6027
static float getSpawnFPMult(CampaignFleetAPI fleet)
Definition Misc.java:5693
static String getListOfResources(Map< String, Integer > res, List< String > quantities)
Definition Misc.java:3915
static Vector2f getPointWithinRadiusUniform(Vector2f from, float minR, float maxR, Random random)
Definition Misc.java:723
static boolean isAvoidingPlayerHalfheartedly(CampaignFleetAPI fleet)
Definition Misc.java:6005
static float getSnapshotFPLost(CampaignFleetAPI fleet)
Definition Misc.java:731
static void makeHostileToPlayerTradeFleets(CampaignFleetAPI fleet)
Definition Misc.java:1470
static final String ASTEROID_SOURCE
Definition Misc.java:2252
static Color scaleColorOnly(Color color, float factor)
Definition Misc.java:1295
static boolean isImportantForReason(MemoryAPI memory, String reason)
Definition Misc.java:3993
static int getCurrSpecialMods(ShipVariantAPI variant)
Definition Misc.java:5526
static boolean shouldNotWantRunFromPlayerEvenIfWeaker(CampaignFleetAPI fleet)
Definition Misc.java:6176
static Vector2f getPerp(Vector2f v)
Definition Misc.java:2088
static int OVER_MAX_INDUSTRIES_PENALTY
Definition Misc.java:216
static SectorEntityToken getSourceEntity(CampaignFleetAPI fleet)
Definition Misc.java:2162
static Vector2f getInterceptPointBasic(SectorEntityToken from, SectorEntityToken to)
Definition Misc.java:1389
static float getFuelPerDayAtSpeed(CampaignFleetAPI fleet, float speed)
Definition Misc.java:1674
static boolean hasFarmland(MarketAPI market)
Definition Misc.java:5793
static Boolean canCheckVramNVIDIA
Definition Misc.java:5872
static float getBurnLevelForSpeed(float speed)
Definition Misc.java:1645
static boolean isUnremovable(PersonAPI person)
Definition Misc.java:5386
static final int OWNER_NEUTRAL
Definition Misc.java:203
static float getAdjustedBaseRange(float base, ShipAPI ship, WeaponAPI weapon)
Definition Misc.java:6251
static float[][] initNoise(Random random, int w, int h, float spikes)
Definition Misc.java:2617
static float normalizeAngle(float angleDeg)
Definition Misc.java:1135
static Vector2f getPointAtRadius(Vector2f from, float r)
Definition Misc.java:690
static ShipPickMode getShipPickMode(MarketAPI market, String factionId)
Definition Misc.java:4462
static void setPreliminarySurveyed(MarketAPI market, TextPanelAPI text, boolean withNotification)
Definition Misc.java:2974
static Industry getStationIndustry(MarketAPI market)
Definition Misc.java:4534
static float logOfBase(float base, float num)
Definition Misc.java:686
static JumpPointAPI getJumpPointTo(PlanetAPI star)
Definition Misc.java:3463
static boolean isInsideSlipstream(SectorEntityToken entity)
Definition Misc.java:6300
static ReputationAdjustmentResult adjustRep(PersonAPI person, float delta, RepLevel limit, TextPanelAPI text)
Definition Misc.java:6474
static boolean isPlayerFactionSetUp()
Definition Misc.java:4667
static Vector2f getDiff(Vector2f v1, Vector2f v2)
Definition Misc.java:2149
static Industry getCurrentlyBeingConstructed(MarketAPI market)
Definition Misc.java:5204
static boolean isPirate(CampaignFleetAPI fleet)
Definition Misc.java:4684
static void makeHostileToFaction(CampaignFleetAPI fleet, String factionId, boolean hostile, float dur)
Definition Misc.java:1492
static Vector2f rotateAroundOrigin(Vector2f v, float angle, Vector2f origin)
Definition Misc.java:1207
static boolean isPointInBounds(Vector2f p1, List< Vector2f > bounds)
Definition Misc.java:1899
static String replaceTokensFromMemory(String text, Map< String, MemoryAPI > memoryMap)
Definition Misc.java:565
static Vector2f interpolateVector(Vector2f from, Vector2f to, float progress)
Definition Misc.java:1275
static void setMercenary(PersonAPI person, boolean mercenary)
Definition Misc.java:5381
static JumpPointAPI findNearestJumpPointTo(SectorEntityToken entity, boolean allowWormhole)
Definition Misc.java:3305
static int getNumNonMercOfficers(CampaignFleetAPI fleet)
Definition Misc.java:5137
static Vector2f getVector(JSONObject json, String arrayKey, Vector2f def)
Definition Misc.java:2541
static void setWarningBeaconGlowColor(SectorEntityToken beacon, Color color)
Definition Misc.java:3658
static int getNumHostileMarkets(FactionAPI faction, SectorEntityToken from, float maxDist)
Definition Misc.java:1025
static boolean systemHasPlanets(StarSystemAPI system)
Definition Misc.java:3614
static void makeStoryCritical(MarketAPI market, String reason)
Definition Misc.java:6123
static boolean isFleetReturningToDespawn(CampaignFleetAPI fleet)
Definition Misc.java:3763
static float getAbyssalDepth(Vector2f loc)
Definition Misc.java:2323
static final String MERCENARY_HIRE_TIMESTAMP
Definition Misc.java:5371
static List< MarketAPI > getPlayerMarkets(boolean includeNonPlayerFaction)
Definition Misc.java:973
static float getOfficerSalary(PersonAPI officer)
Definition Misc.java:4333
static void setWarningBeaconPingColor(SectorEntityToken beacon, Color color)
Definition Misc.java:3662
static float getDistanceLY(Vector2f v1, Vector2f v2)
Definition Misc.java:628
static MarketAPI findNearestLocalMarket(SectorEntityToken token, float maxDist, MarketFilter filter)
Definition Misc.java:1139
static float getTargetingRadius(Vector2f from, CombatEntityAPI target, boolean considerShield)
Definition Misc.java:1342
static Color interpolateColor(Color from, Color to, float progress)
Definition Misc.java:1254
static boolean canCheckVram()
Definition Misc.java:5873
static float getSpeedForBurnLevel(float burnLevel)
Definition Misc.java:1664
static boolean isFringe(StarSystemAPI system)
Definition Misc.java:6535
static Color getDarkHighlightColor()
Definition Misc.java:788
static String genEntityCatalogId(CatalogEntryType type)
Definition Misc.java:6580
static IntervalUtil createEconIntervalTracker()
Definition Misc.java:859
static float MIN_TERRAIN_EFFECT_MULT
Definition Misc.java:4888
static boolean isAutomated(FleetMemberAPI member)
Definition Misc.java:5400
static Vector2f getCoreMax()
Definition Misc.java:6369
static void makeHostile(CampaignFleetAPI fleet)
Definition Misc.java:1466
static int getStorageCostPerMonth(MarketAPI market)
Definition Misc.java:4208
static boolean caresAboutPlayerTransponder(CampaignFleetAPI fleet)
Definition Misc.java:2425
static Vector2f getPointWithinRadius(Vector2f from, float r)
Definition Misc.java:704
static FactionAPI getCommissionFaction()
Definition Misc.java:2408
static void clearTarget(CampaignFleetAPI fleet, boolean forgetTransponder)
Definition Misc.java:3745
static void giveStandardReturnAssignments(CampaignFleetAPI fleet, SectorEntityToken where, String text, boolean withClear)
Definition Misc.java:3790
static float getProfitMarginMult()
Definition Misc.java:847
static final String CAPTAIN_UNREMOVABLE
Definition Misc.java:5385
static float FLUX_PER_CAPACITOR
Definition Misc.java:189
static boolean isPlayerOrCombinedPlayerPrimary(CampaignFleetAPI fleet)
Definition Misc.java:2233
static float getBattleJoinRange()
Definition Misc.java:2220
static String FLEET_RETURNING_TO_DESPAWN
Definition Misc.java:3761
static int computeEconUnitChangeFromTradeModChange(CommodityOnMarketAPI com, int quantity)
Definition Misc.java:5728
static void setAllPlanetsKnown(String systemName)
Definition Misc.java:2811
static float getLYPerDayAtSpeed(CampaignFleetAPI fleet, float speed)
Definition Misc.java:1692
static MarketAPI getBiggestMarketInLocation(LocationAPI location)
Definition Misc.java:939
static ParticleControllerAPI[] addGlowyParticle(LocationAPI location, Vector2f loc, Vector2f vel, float size, float rampUp, float dur, Color color)
Definition Misc.java:4913
static final String IS_MERCENARY
Definition Misc.java:5366
static StarSystemAPI getStarSystemForAnchor(SectorEntityToken anchor)
Definition Misc.java:4596
static boolean isSlowMoving(CampaignFleetAPI fleet)
Definition Misc.java:5553
static Color getDarkPlayerColor()
Definition Misc.java:829
static float getLYPerDayAtBurn(CampaignFleetAPI fleet, float burnLevel)
Definition Misc.java:1688
static float getProbabilityMult(float desired, float current, float deviationMult)
Definition Misc.java:4584
static void showCost(TextPanelAPI text, String title, boolean withAvailable, Color color, Color dark, String[] res, int[] quantities)
Definition Misc.java:4603
static Color getColor(JSONObject json, String key)
Definition Misc.java:2529
static Color getStoryDarkBrighterColor()
Definition Misc.java:763
static void makeUnimportant(PersonAPI person, String reason)
Definition Misc.java:4001
static void stopPlayerFleet()
Definition Misc.java:3908
static void generatePlanetConditions(String systemName, StarAge age)
Definition Misc.java:2852
static int getUntrustwortyCount()
Definition Misc.java:6461
static float FP_TO_BOMBARD_COST_APPROX_MULT
Definition Misc.java:219
static void makeNoRepImpact(CampaignFleetAPI fleet, String reason)
Definition Misc.java:1461
static Set< String > getAllowedRecoveryTags()
Definition Misc.java:5414
static float getOutpostPenalty()
Definition Misc.java:4321
static float IMPACT_VOLUME_MULT
Definition Misc.java:5914
static void clearFlag(MemoryAPI memory, String flagKey)
Definition Misc.java:1452
static boolean crossesAnySlipstream(LocationAPI location, Vector2f from, Vector2f to)
Definition Misc.java:6319
static float getAngleInDegreesStrict(Vector2f v)
Definition Misc.java:1108
static void setRaidedTimestamp(MarketAPI market)
Definition Misc.java:5718
static float SAME_FACTION_BONUS
Definition Misc.java:4930
static boolean isActiveModule(ShipVariantAPI variant)
Definition Misc.java:4543
static JumpPointAPI findNearestJumpPointTo(SectorEntityToken entity)
Definition Misc.java:3302
static void setSpawnFPMult(CampaignFleetAPI fleet, float mult)
Definition Misc.java:5699
static float getDistanceToPlayerLY(SectorEntityToken other)
Definition Misc.java:623
static void fadeIn(final SectorEntityToken entity, final float in)
Definition Misc.java:3131
static ShipPickMode getShipPickMode(MarketAPI market)
Definition Misc.java:4459
static Color getPositiveHighlightColor()
Definition Misc.java:815
static MagneticFieldTerrainPlugin getMagneticFieldFor(PlanetAPI planet)
Definition Misc.java:2373
static float getDaysSinceLastRaided(MarketAPI market)
Definition Misc.java:5722
static String getRoundedValueMaxOneAfterDecimal(float value)
Definition Misc.java:666
static float getAdjustedStrength(float fp, MarketAPI market)
Definition Misc.java:4400
static ReputationAdjustmentResult adjustRep(String factionId, float delta, TextPanelAPI text)
Definition Misc.java:6490
static List< MarketAPI > getMarketsInLocation(LocationAPI location)
Definition Misc.java:953
static int getOPCost(HullModSpecAPI mod, HullSize size)
Definition Misc.java:5482
static void makeUnimportant(MemoryAPI memory, String reason)
Definition Misc.java:4004
static boolean showRuleDialog(SectorEntityToken entity, String initialTrigger)
Definition Misc.java:1096
static FactionAPI getClaimingFaction(SectorEntityToken planet)
Definition Misc.java:4982
static ReputationAdjustmentResult adjustRep(String factionId, float delta, RepLevel limit, TextPanelAPI text, boolean addMessageOnNoChange, boolean withMessage)
Definition Misc.java:6496
static Vector2f getCoreCenter()
Definition Misc.java:6377
static SectorEntityToken getStationEntity(MarketAPI market, CampaignFleetAPI fleet)
Definition Misc.java:4479
static boolean isMilitary(MarketAPI market)
Definition Misc.java:4959
static boolean isUnboardable(FleetMemberAPI member)
Definition Misc.java:3229
static float getAngleInDegrees(Vector2f from, Vector2f to)
Definition Misc.java:1123
static boolean isInArc(float direction, float arc, Vector2f from, Vector2f to)
Definition Misc.java:1715
static boolean isStationInSupportRange(CampaignFleetAPI fleet, CampaignFleetAPI station)
Definition Misc.java:4741
static List< CampaignFleetAPI > findNearbyFleets(SectorEntityToken from, float maxRange, FleetFilter filter)
Definition Misc.java:905
static Vector2f getPointWithinRadiusUniform(Vector2f from, float r, Random random)
Definition Misc.java:715
static float getFractionalBurnLevelForSpeed(float speed)
Definition Misc.java:1654
static String getRoundedValueOneAfterDecimalIfNotWhole(float value)
Definition Misc.java:676
static StarCoronaTerrainPlugin getCoronaFor(PlanetAPI star)
Definition Misc.java:2361
static< T extends Enum< T > T mapToEnum(JSONObject json, String key, Class< T > enumType, T defaultOption)
Definition Misc.java:2511
static boolean isScavenger(CampaignFleetAPI fleet)
Definition Misc.java:4687
static void makeNonHostileToFaction(CampaignFleetAPI fleet, String factionId, boolean nonHostile, float dur)
Definition Misc.java:1481
static String getCommissionFactionId()
Definition Misc.java:2403
static float getAngleInDegrees(Vector2f v)
Definition Misc.java:1119
static ReputationAdjustmentResult adjustRep(PersonAPI person, float delta, RepLevel limit, TextPanelAPI text, boolean addMessageOnNoChange, boolean withMessage)
Definition Misc.java:6477
static void generatePlanetConditions(StarSystemAPI system, StarAge age)
Definition Misc.java:2861
static Vector2f normalise(Vector2f v)
Definition Misc.java:1127
static Vector3f optVector3f(JSONObject json, String arrayKey)
Definition Misc.java:2567
static Vector3f getVector3f(JSONObject json, String arrayKey)
Definition Misc.java:2552
static Color scaleColor(Color color, float factor)
Definition Misc.java:1289
static void makeLowRepImpact(CampaignFleetAPI fleet, String reason)
Definition Misc.java:1458
static boolean isEasy()
Definition Misc.java:2277
static float getAbyssalDepthOfPlayer()
Definition Misc.java:2335
static String getRoundedValue(float value)
Definition Misc.java:640
static boolean isUnboardable(ShipHullSpecAPI hullSpec)
Definition Misc.java:3236
static float getAbyssalDepth(SectorEntityToken entity)
Definition Misc.java:2338
static Color getBallisticMountColor()
Definition Misc.java:802
CargoAPI createCargo(boolean unlimitedStacks)
MarketAPI createMarket(String id, String name, int size)
float getTargetingRadius(Vector2f from, CombatEntityAPI target, boolean considerShield)
String getSpriteName(String category, String id)
ShipVariantAPI getVariant(String variantId)
HullModSpecAPI getHullModSpec(String modId)
IndustrySpecAPI getIndustrySpec(String industryId)
InputStream openStream(String filename)
Object getNewPluginInstance(String id)
boolean getBoolean(String key)
CommoditySpecAPI getCommoditySpec(String commodityId)
float getAngleInDegreesFast(Vector2f v)
Color getDesignTypeColor(String designType)
SoundAPI playSound(String id, float pitch, float volume, Vector2f loc, Vector2f vel)