Starsector API
Loading...
Searching...
No Matches
SalvageSpecialAssigner.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.procgen.themes;
2
3import java.util.ArrayList;
4import java.util.Arrays;
5import java.util.List;
6import java.util.Random;
7
8import org.lwjgl.util.vector.Vector2f;
9
10import com.fs.starfarer.api.Global;
11import com.fs.starfarer.api.campaign.CampaignTerrainAPI;
12import com.fs.starfarer.api.campaign.FactionAPI;
13import com.fs.starfarer.api.campaign.PlanetAPI;
14import com.fs.starfarer.api.campaign.SectorEntityToken;
15import com.fs.starfarer.api.campaign.StarSystemAPI;
16import com.fs.starfarer.api.campaign.econ.MarketAPI;
17import com.fs.starfarer.api.characters.PersonAPI;
18import com.fs.starfarer.api.combat.ShipAPI.HullSize;
19import com.fs.starfarer.api.combat.ShipHullSpecAPI.ShipTypeHints;
20import com.fs.starfarer.api.combat.ShipVariantAPI;
21import com.fs.starfarer.api.impl.campaign.DerelictShipEntityPlugin;
22import com.fs.starfarer.api.impl.campaign.DerelictShipEntityPlugin.DerelictShipData;
23import com.fs.starfarer.api.impl.campaign.DerelictShipEntityPlugin.DerelictType;
24import com.fs.starfarer.api.impl.campaign.econ.impl.TechMining;
25import com.fs.starfarer.api.impl.campaign.events.OfficerManagerEvent;
26import com.fs.starfarer.api.impl.campaign.events.OfficerManagerEvent.SkillPickPreference;
27import com.fs.starfarer.api.impl.campaign.fleets.FleetParamsV3;
28import com.fs.starfarer.api.impl.campaign.ids.Commodities;
29import com.fs.starfarer.api.impl.campaign.ids.Entities;
30import com.fs.starfarer.api.impl.campaign.ids.Factions;
31import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
32import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
33import com.fs.starfarer.api.impl.campaign.ids.Tags;
34import com.fs.starfarer.api.impl.campaign.intel.events.ht.HTPoints;
35import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator;
36import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.AddedEntity;
37import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.StarSystemData;
38import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.BlueprintSpecial.BlueprintSpecialData;
39import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.BreadcrumbSpecial.BreadcrumbSpecialData;
40import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.CargoManifestSpecial.CargoManifestSpecialData;
41import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.CryopodOfficerGen;
42import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.CryopodOfficerGen.CryopodOfficerTemplate;
43import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.ShipRecoverySpecial.PerShipData;
44import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.ShipRecoverySpecial.ShipCondition;
45import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.ShipRecoverySpecial.ShipRecoverySpecialData;
46import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.SleeperPodsSpecial.SleeperPodsSpecialData;
47import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.SleeperPodsSpecial.SleeperSpecialType;
48import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.SurveyDataSpecial.SurveyDataSpecialData;
49import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.SurveyDataSpecial.SurveyDataSpecialType;
50import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.TopographicDataSpecial.TopographicDataSpecialData;
51import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.TransmitterTrapSpecial.TransmitterTrapSpecialData;
52import com.fs.starfarer.api.impl.campaign.terrain.DebrisFieldTerrainPlugin;
53import com.fs.starfarer.api.util.Misc;
54import com.fs.starfarer.api.util.WeightedRandomPicker;
55
57
58 public static int STANDARD_PODS_OFFICER_LEVEL = Global.getSettings().getInt("standardSleeperPodsOfficerLevel");
59 public static int EXCEPTIONAL_PODS_OFFICER_LEVEL = Global.getSettings().getInt("exceptionalSleeperPodsOfficerLevel");
60 public static int EXCEPTIONAL_PODS_OFFICER_ELITE_SKILLS = Global.getSettings().getInt("exceptionalSleeperPodsOfficerEliteSkills");
61 public static int MAX_EXCEPTIONAL_PODS_OFFICERS = Global.getSettings().getInt("maxExceptionalSleeperPodsOfficers");
62 public static float PROB_EXCEPTIONAL_PODS_OFFICER = Global.getSettings().getFloat("probSleeperPodsOfficerIsExceptional");
63 public static float PROB_UNEXCEPTIONAL_USE_TEMPLATE = Global.getSettings().getFloat("probSleeperPodsUnexceptionalOfficerUseTemplate");
64
65 public static int MAX_NORMAL_OFFICER_LEVEL = Global.getSettings().getInt("officerMaxLevel");
66
67 public static class SpecialCreationContext {
68 public String themeId;
69 public boolean onNewGame = true;
70 public List<SectorEntityToken> all = new ArrayList<SectorEntityToken>();
71 public SpecialCreationContext() {
72 }
73
74 }
75
76 public static interface SpecialCreator {
77 Object createSpecial(SectorEntityToken entity, SpecialCreationContext context);
78 }
79
80 public static void assignSpecialForBattleWreck(SectorEntityToken entity) {
81 Random random = StarSystemGenerator.random;
82 WeightedRandomPicker<SpecialCreator> picker = new WeightedRandomPicker<SpecialCreator>(random);
83
84 picker.add(new NothingSpecialCreator(), 10f);
85 picker.add(new ShipRecoverySpecialCreator(random, 0, 0, false, null, null), 10f);
86 SpecialCreator pick = picker.pick();
87
88 SpecialCreationContext context = new SpecialCreationContext();
89
90 Object specialData = pick.createSpecial(entity, context);
91 if (specialData != null) {
92 Misc.setSalvageSpecial(entity, specialData);
93 }
94 }
95
96 public static void assignSpecialForDistressDerelict(SectorEntityToken entity) {
97 Random random = new Random();
98
99 WeightedRandomPicker<SpecialCreator> picker = new WeightedRandomPicker<SpecialCreator>(random);
100
101 DerelictShipEntityPlugin plugin = (DerelictShipEntityPlugin) entity.getCustomPlugin();
102 PerShipData shipData = plugin.getData().ship;
103 ShipVariantAPI variant = shipData.variant;
104 if (variant == null && shipData.variantId != null) {
105 variant = Global.getSettings().getVariant(shipData.variantId);
106 }
107 float p = variant.getHullSpec().getMaxCrew();
108 float c = variant.getHullSpec().getCargo();
109
110 WeightedRandomPicker<String> recoverableShipFactions = getNearbyFactions(random, entity);
111 if (entity.getContainingLocation().hasTag(Tags.THEME_REMNANT)) {
112 recoverableShipFactions = Misc.createStringPicker(random,
113 Factions.TRITACHYON, 10f, Factions.HEGEMONY, 7f, Factions.INDEPENDENT, 3f);
114 }
115 WeightedRandomPicker<String> officerFactions = recoverableShipFactions;
116 WeightedRandomPicker<String> valuableCargo = getValuableCargo(random);
117
118 picker.add(new NothingSpecialCreator(), 10f);
119 picker.add(new ShipRecoverySpecialCreator(random, 0, 0, false, null, null), 30f);
120 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.MARINES, p * 0.125f, p * 0.25f, null), 2f);
121 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.CREW, p * 0.25f, p * 0.5f, null), 20f);
122 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.OFFICER, STANDARD_PODS_OFFICER_LEVEL, EXCEPTIONAL_PODS_OFFICER_LEVEL, officerFactions), 15f);
123 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ADMIN, 1, 1, officerFactions), 2f);
124 picker.add(new CargoManifestSpecialCreator(random, valuableCargo, c * 0.25f, c * 0.5f), 10f);
125 picker.add(new SurveyDataSpecialCreator(random, SurveyDataSpecialType.AUTO_PICK_NOT_SYSTEM), 5f);
126 picker.add(new BlueprintSpecialCreator(random), 1f);
127 picker.add(new TopographicDataSpecialCreator(random, HTPoints.LOW_MIN, HTPoints.LOW_MAX), 1f);
128
129 SpecialCreator pick = picker.pick();
130 SpecialCreationContext context = new SpecialCreationContext();
131
132 Object specialData = pick.createSpecial(entity, context);
133 if (specialData != null) {
134 Misc.setSalvageSpecial(entity, specialData);
135 }
136 }
137
138 public static void assignSpecialForDebrisField(SectorEntityToken entity) {
139 Random random = StarSystemGenerator.random;
140 WeightedRandomPicker<SpecialCreator> picker = new WeightedRandomPicker<SpecialCreator>(random);
141
142 WeightedRandomPicker<String> recoverableShipFactions = getNearbyFactions(random, entity);
143 WeightedRandomPicker<String> trapFactions = Misc.createStringPicker(random, Factions.PIRATES, 10f);
144 WeightedRandomPicker<String> valuableCargo = getValuableCargo(random);
145
146 picker.add(new NothingSpecialCreator(), 60f);
147 picker.add(new ShipRecoverySpecialCreator(random, 1, 3, true, null, recoverableShipFactions), 10f);
148 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.MARINES, 10, 20, null), 2f);
149 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.CREW, 20, 40, null), 6f);
150 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ORGANS, 1, 5, null), 3f);
151 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.OFFICER, STANDARD_PODS_OFFICER_LEVEL, EXCEPTIONAL_PODS_OFFICER_LEVEL, recoverableShipFactions), 1f);
152 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ADMIN, 1, 1, recoverableShipFactions), 0.2f);
153 picker.add(new CargoManifestSpecialCreator(random, valuableCargo, 10, 50), 10f);
154 picker.add(new SurveyDataSpecialCreator(random, SurveyDataSpecialType.AUTO_PICK_NOT_SYSTEM), 10f);
155 picker.add(new BreadcrumbSpecialCreator(random, null), 10f);
156 picker.add(new TransmitterTrapSpecialCreator(random, 0.5f, FleetTypes.PATROL_SMALL, trapFactions, 4, 25), 10f);
157 picker.add(new TopographicDataSpecialCreator(random, HTPoints.LOW_MIN, HTPoints.LOW_MAX), 5f);
158
159 SpecialCreator pick = picker.pick();
160
161 SpecialCreationContext context = new SpecialCreationContext();
162
163 Object specialData = pick.createSpecial(entity, context);
164 if (specialData != null) {
165 Misc.setSalvageSpecial(entity, specialData);
166 }
167 }
168
169 public static WeightedRandomPicker<String> getValuableCargo(Random random) {
170 WeightedRandomPicker<String> valuableCargo = Misc.createStringPicker(random,
171 Commodities.VOLATILES, 10f, Commodities.RARE_METALS, 10f, Commodities.RARE_ORE, 10f,
172 Commodities.HEAVY_MACHINERY, 10f,
173 Commodities.HAND_WEAPONS, 10f, Commodities.ORGANS, 10f, Commodities.DRUGS, 10f,
174 Commodities.LUXURY_GOODS, 10f, Commodities.LOBSTER, 10f);
175 return valuableCargo;
176 }
177
178 public static WeightedRandomPicker<String> getIndustryCargo(Random random) {
179 WeightedRandomPicker<String> industryCargo = Misc.createStringPicker(random,
180 Commodities.VOLATILES, 10f, Commodities.RARE_METALS, 10f, Commodities.RARE_ORE, 10f,
181 Commodities.HEAVY_MACHINERY, 10f, Commodities.ORE, 10f);
182 return industryCargo;
183 }
184
185 public static WeightedRandomPicker<String> getHabCargo(Random random) {
186 WeightedRandomPicker<String> habCargo = Misc.createStringPicker(random,
187 Commodities.HAND_WEAPONS, 10f, Commodities.ORGANS, 10f, Commodities.DRUGS, 10f,
188 Commodities.LUXURY_GOODS, 10f, Commodities.LOBSTER, 10f);
189 return habCargo;
190 }
191
192 public static WeightedRandomPicker<String> getNearbyFactions(Random random, SectorEntityToken entity) {
193 WeightedRandomPicker<String> picker = Misc.createStringPicker(random, Factions.INDEPENDENT, 10f);
194 for (MarketAPI market : Misc.getNearbyMarkets(entity.getLocationInHyperspace(), 10f)) {
195 picker.add(market.getFactionId(), market.getSize());
196 }
197 return picker;
198 }
199
200 public static WeightedRandomPicker<String> getNearbyFactions(Random random, SectorEntityToken entity,
201 float rangeLY,
202 float indWeight, float pirateWeight) {
203 if (random == null) random = new Random();
204 return getNearbyFactions(random, entity.getLocationInHyperspace(), rangeLY, indWeight, pirateWeight);
205 }
206 public static WeightedRandomPicker<String> getNearbyFactions(Random random, Vector2f locationInHyper,
207 float rangeLY,
208 float indWeight, float pirateWeight) {
209 if (random == null) random = new Random();
210 WeightedRandomPicker<String> picker = new WeightedRandomPicker<String>(random);
211 if (indWeight > 0) {
212 picker.add(Factions.INDEPENDENT, indWeight);
213 picker.add(Factions.MERCENARY, indWeight * 0.1f);
214 }
215 if (pirateWeight > 0) picker.add(Factions.PIRATES, pirateWeight);
216 for (MarketAPI market : Misc.getNearbyMarkets(locationInHyper, rangeLY)) {
217 picker.add(market.getFactionId(), market.getSize());
218 }
219 return picker;
220 }
221
222 public static SpecialCreator pickSpecialFor(SectorEntityToken entity, SpecialCreationContext context) {
223
224 Random random = StarSystemGenerator.random;
225 if (randomOverride != null) {
226 random = randomOverride;
227 }
228
229 WeightedRandomPicker<SpecialCreator> picker = new WeightedRandomPicker<SpecialCreator>(random);
230
231 //System.out.println("Random: " + random.nextLong());
232
233 String type = entity.getCustomEntityType();
234
235 WeightedRandomPicker<String> recoverableShipFactions = getNearbyFactions(random, entity);
236
237 if (entity.getContainingLocation().hasTag(Tags.THEME_REMNANT)) {
238 recoverableShipFactions = Misc.createStringPicker(random,
239 Factions.TRITACHYON, 10f, Factions.HEGEMONY, 7f, Factions.INDEPENDENT, 3f);
240 }
241
242 int maxPodsOfficerLevel = EXCEPTIONAL_PODS_OFFICER_LEVEL;
243 // limited to MAX_EXCEPTIONAL_PODS_OFFICERS anyway, so it's fine to generate after new game sectorgen if possible
244// if (context != null && !context.onNewGame) {
245// maxPodsOfficerLevel = MAX_NORMAL_OFFICER_LEVEL;
246// }
247
248 WeightedRandomPicker<String> remnantsFaction = Misc.createStringPicker(random, Factions.REMNANTS, 10f);
249 WeightedRandomPicker<String> piratesFaction = Misc.createStringPicker(random, Factions.PIRATES, 10f);
250
251
252 WeightedRandomPicker<String> trapFactions = piratesFaction;
253 if (entity.getContainingLocation().hasTag(Tags.THEME_REMNANT_SUPPRESSED) ||
254 entity.getContainingLocation().hasTag(Tags.THEME_REMNANT_RESURGENT)) {
255 trapFactions = remnantsFaction;
256 }
257
258
259// WeightedRandomPicker<String> officerFactions = Misc.createStringPicker(random,
260// Factions.PIRATES, 10f, Factions.HEGEMONY, 5f, Factions.INDEPENDENT, 10f,
261// Factions.TRITACHYON, 5f, Factions.LUDDIC_CHURCH, 5f, Factions.PERSEAN, 10f,
262// Factions.DIKTAT, 5f);
263//
264// if (entity.getContainingLocation().hasTag(Tags.THEME_REMNANT)) {
265// officerFactions.add(Factions.TRITACHYON, 10f);
266// officerFactions.add(Factions.HEGEMONY, 5f);
267// }
268
269 WeightedRandomPicker<String> officerFactions = recoverableShipFactions;
270
271
272
273 WeightedRandomPicker<String> valuableCargo = getValuableCargo(random);
274 WeightedRandomPicker<String> industryCargo = getIndustryCargo(random);
275
276 WeightedRandomPicker<String> habCargo = getHabCargo(random);
277
278
279 // ruins on a planet
280 if (entity instanceof PlanetAPI) {
281
282 float sizeMult = TechMining.getTechMiningRuinSizeModifier(entity.getMarket());
283
284 picker.add(new NothingSpecialCreator(), 30f);
285 picker.add(new ShipRecoverySpecialCreator(random, 1, 2, false, DerelictType.CIVILIAN, recoverableShipFactions), 5f);
286 picker.add(new ShipRecoverySpecialCreator(random, 1, 3, false, DerelictType.SMALL, recoverableShipFactions), 10f);
287 picker.add(new ShipRecoverySpecialCreator(random, 1, 1, false, DerelictType.MEDIUM, recoverableShipFactions), 3f);
288 picker.add(new ShipRecoverySpecialCreator(random, 1, 1, false, DerelictType.LARGE, recoverableShipFactions), 1f);
289 if (sizeMult > 0) {
290 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.MARINES, 100 * sizeMult, 200 * sizeMult, null), 2f);
291 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.CREW, 500 * sizeMult, 1000 * sizeMult, null), 6f);
292 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ORGANS, 50 * sizeMult, 500 * sizeMult, null), 3f);
293 }
294 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.OFFICER, STANDARD_PODS_OFFICER_LEVEL, maxPodsOfficerLevel, officerFactions), 1f);
295 // min/max doesn't matter for ADMIN
296 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ADMIN, 1, 1, officerFactions), 5f);
297
298 picker.add(new CargoManifestSpecialCreator(random, industryCargo, 500 * sizeMult, 2500 * sizeMult), 15f);
299 picker.add(new CargoManifestSpecialCreator(random, valuableCargo, 500 * sizeMult, 2500 * sizeMult), 15f);
300
301 picker.add(new TransmitterTrapSpecialCreator(random, 0.5f, FleetTypes.PATROL_LARGE, trapFactions,
302 (int)(10 + 30 * sizeMult), (int)(10 + 30 * sizeMult)), 10f);
303 picker.add(new TopographicDataSpecialCreator(random, HTPoints.LOW_MIN, HTPoints.HIGH_MAX), 3f);
304
305 // text for these is not set up to handle the "planet" case
306 //picker.add(new SurveyDataSpecialCreator(random, SurveyDataSpecialType.AUTO_PICK), 20f);
307 //picker.add(new BreadcrumbSpecialCreator(random, context.all), 10f);
308 }
309
310
311 // derelict ship
312 if (entity.getCustomPlugin() instanceof DerelictShipEntityPlugin || Entities.WRECK.equals(type)) {
313 DerelictShipEntityPlugin plugin = (DerelictShipEntityPlugin) entity.getCustomPlugin();
314
315 PerShipData shipData = plugin.getData().ship;
316 ShipVariantAPI variant = shipData.variant;
317 if (variant == null && shipData.variantId != null) {
318 variant = Global.getSettings().getVariant(shipData.variantId);
319 }
320 float p = variant.getHullSpec().getMaxCrew();
321 float c = variant.getHullSpec().getCargo();
322
323 picker.add(new NothingSpecialCreator(), 40f);
324 picker.add(new ShipRecoverySpecialCreator(random, 0, 0, false, null, null), 30f);
325 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.MARINES, p * 0.125f, p * 0.25f, null), 2f);
326 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.CREW, p * 0.25f, p * 0.5f, null), 7f);
327 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ORGANS, p * 0.1f, p * 0.2f, null), 3f);
328 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.OFFICER, STANDARD_PODS_OFFICER_LEVEL, maxPodsOfficerLevel, officerFactions), 10f);
329 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ADMIN, 1, 1, officerFactions), 0.2f);
330 picker.add(new CargoManifestSpecialCreator(random, valuableCargo, c * 0.25f, c * 0.5f), 10f);
331 picker.add(new SurveyDataSpecialCreator(random, SurveyDataSpecialType.AUTO_PICK_NOT_SYSTEM), 10f);
332 picker.add(new BreadcrumbSpecialCreator(random, context.all), 10f);
333 picker.add(new TopographicDataSpecialCreator(random, HTPoints.LOW_MIN, HTPoints.LOW_MAX), 5f);
334
335 if (entity.getOrbit() != null) {
336 picker.add(new TransmitterTrapSpecialCreator(random, 0.5f, FleetTypes.PATROL_SMALL, trapFactions, 4, 25), 10f);
337 }
338
339 if (!entity.hasTag(Tags.EXPIRES)) {
340 picker.add(new BlueprintSpecialCreator(random), 1f);
341 }
342 }
343
344 // debris field
345 boolean debris = entity instanceof CampaignTerrainAPI &&
346 ((CampaignTerrainAPI)entity).getPlugin() instanceof DebrisFieldTerrainPlugin;
347 if (debris) {
348 picker.add(new NothingSpecialCreator(), 60f);
349 picker.add(new ShipRecoverySpecialCreator(random, 1, 3, true, null, recoverableShipFactions), 10f);
350 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.MARINES, 10, 30, null), 2f);
351 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.CREW, 10, 50, null), 6f);
352 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ORGANS, 1, 5, null), 3f);
353 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.OFFICER, STANDARD_PODS_OFFICER_LEVEL, maxPodsOfficerLevel, officerFactions), 1f);
354 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ADMIN, 1, 5, officerFactions), 0.2f);
355 picker.add(new CargoManifestSpecialCreator(random, valuableCargo, 10, 50), 10f);
356 picker.add(new SurveyDataSpecialCreator(random, SurveyDataSpecialType.AUTO_PICK_NOT_SYSTEM), 10f);
357 picker.add(new BreadcrumbSpecialCreator(random, context.all), 10f);
358 picker.add(new TransmitterTrapSpecialCreator(random, 0.5f, FleetTypes.PATROL_SMALL, trapFactions, 4, 25), 10f);
359 picker.add(new TopographicDataSpecialCreator(random, HTPoints.LOW_MIN, HTPoints.LOW_MAX), 1f);
360 }
361
362 if (Entities.STATION_MINING_REMNANT.equals(type) || Entities.STATION_MINING.equals(type)) {
363 picker.add(new NothingSpecialCreator(), 30f);
364 picker.add(new ShipRecoverySpecialCreator(random, 1, 3, false, DerelictType.CIVILIAN, recoverableShipFactions), 10f);
365 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.MARINES, 10, 20, null), 1f);
366 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.CREW, 100, 200, null), 6f);
367 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ORGANS, 5, 50, null), 3f);
368 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.OFFICER, STANDARD_PODS_OFFICER_LEVEL, maxPodsOfficerLevel, officerFactions), 1f);
369 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ADMIN, 1, 5, officerFactions), 3f);
370 picker.add(new CargoManifestSpecialCreator(random, industryCargo, 50, 250), 30f);
371 picker.add(new SurveyDataSpecialCreator(random, SurveyDataSpecialType.AUTO_PICK), 20f);
372 picker.add(new BreadcrumbSpecialCreator(random, context.all), 10f);
373 picker.add(new TransmitterTrapSpecialCreator(random, 0.5f, FleetTypes.PATROL_MEDIUM, trapFactions, 10, 16), 10f);
374 picker.add(new TopographicDataSpecialCreator(random, HTPoints.MEDIUM_MIN, HTPoints.MEDIUM_MAX), 1f);
375 }
376
377 if (Entities.STATION_RESEARCH_REMNANT.equals(type) || Entities.STATION_RESEARCH.equals(type)) {
378 picker.add(new NothingSpecialCreator(), 30f);
379 picker.add(new ShipRecoverySpecialCreator(random, 1, 3, false, DerelictType.CIVILIAN, recoverableShipFactions), 10f);
380 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.MARINES, 50, 100, null), 2f);
381 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.CREW, 100, 200, null), 6f);
382 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ORGANS, 5, 50, null), 3f);
383 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.OFFICER, STANDARD_PODS_OFFICER_LEVEL, maxPodsOfficerLevel, officerFactions), 1f);
384 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ADMIN, 1, 5, officerFactions), 3f);
385 picker.add(new CargoManifestSpecialCreator(random, valuableCargo, 10, 30), 10f);
386 picker.add(new SurveyDataSpecialCreator(random, SurveyDataSpecialType.AUTO_PICK), 10f);
387 picker.add(new BreadcrumbSpecialCreator(random, context.all), 10f);
388 picker.add(new TransmitterTrapSpecialCreator(random, 0.5f, FleetTypes.PATROL_MEDIUM, trapFactions, 10, 16), 20f);
389 picker.add(new TopographicDataSpecialCreator(random, HTPoints.HIGH_MIN, HTPoints.HIGH_MAX), 10f);
390 }
391
392 if (Entities.ORBITAL_HABITAT_REMNANT.equals(type) || Entities.ORBITAL_HABITAT.equals(type)) {
393 picker.add(new NothingSpecialCreator(), 40f);
394 picker.add(new ShipRecoverySpecialCreator(random, 1, 3, false, DerelictType.CIVILIAN, recoverableShipFactions), 20f);
395 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.MARINES, 50, 100, null), 6f);
396 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.CREW, 100, 200, null), 20f);
397 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ORGANS, 5, 50, null), 5f);
398 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.OFFICER, STANDARD_PODS_OFFICER_LEVEL, maxPodsOfficerLevel, officerFactions), 10f);
399 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ADMIN, 1, 5, officerFactions), 5f);
400 picker.add(new CargoManifestSpecialCreator(random, habCargo, 10, 30), 10f);
401 picker.add(new SurveyDataSpecialCreator(random, SurveyDataSpecialType.AUTO_PICK), 5f);
402 picker.add(new BreadcrumbSpecialCreator(random, context.all), 10f);
403 picker.add(new TransmitterTrapSpecialCreator(random, 0.5f, FleetTypes.PATROL_MEDIUM, trapFactions, 10, 16), 10f);
404 picker.add(new TopographicDataSpecialCreator(random, HTPoints.MEDIUM_MIN, HTPoints.MEDIUM_MAX), 2f);
405 }
406
407
408 List<String> weapons = Arrays.asList(Entities.WEAPONS_CACHE, Entities.WEAPONS_CACHE_HIGH, Entities.WEAPONS_CACHE_LOW, Entities.WEAPONS_CACHE_REMNANT);
409 if (weapons.contains(type)) {
410 picker.add(new NothingSpecialCreator(), 30f);
411 picker.add(new ShipRecoverySpecialCreator(random, 1, 1, false, DerelictType.SMALL, recoverableShipFactions), 10f);
412 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.MARINES, 50, 100, null), 1f);
413 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.OFFICER, STANDARD_PODS_OFFICER_LEVEL, maxPodsOfficerLevel, officerFactions), 2f);
414 picker.add(new CargoManifestSpecialCreator(random, valuableCargo, 10, 30), 10f);
415 picker.add(new TransmitterTrapSpecialCreator(random, 0.5f, FleetTypes.PATROL_SMALL, trapFactions, 4, 8), 10f);
416 }
417
418 List<String> weaponsSmall = Arrays.asList(Entities.WEAPONS_CACHE_SMALL, Entities.WEAPONS_CACHE_SMALL_HIGH,
419 Entities.WEAPONS_CACHE_SMALL_LOW, Entities.WEAPONS_CACHE_SMALL_REMNANT);
420 if (weaponsSmall.contains(type)) {
421 picker.add(new NothingSpecialCreator(), 30f);
422 picker.add(new ShipRecoverySpecialCreator(random, 1, 1, false, DerelictType.SMALL, recoverableShipFactions), 10f);
423 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.OFFICER, STANDARD_PODS_OFFICER_LEVEL, maxPodsOfficerLevel, officerFactions), 1f);
424 picker.add(new CargoManifestSpecialCreator(random, valuableCargo, 10, 30), 10f);
425 picker.add(new TransmitterTrapSpecialCreator(random, 0.5f, FleetTypes.PATROL_SMALL, trapFactions, 4, 8), 10f);
426 }
427
428
429 List<String> supplies = Arrays.asList(Entities.SUPPLY_CACHE);
430 if (supplies.contains(type)) {
431 picker.add(new NothingSpecialCreator(), 30f);
432 picker.add(new ShipRecoverySpecialCreator(random, 1, 1, false, DerelictType.SMALL, recoverableShipFactions), 10f);
433 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.OFFICER, STANDARD_PODS_OFFICER_LEVEL, maxPodsOfficerLevel, officerFactions), 1f);
434 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ADMIN, 1, 5, officerFactions), 0.2f);
435 picker.add(new CargoManifestSpecialCreator(random, valuableCargo, 10, 30), 10f);
436 picker.add(new TransmitterTrapSpecialCreator(random, 0.5f, FleetTypes.PATROL_SMALL, trapFactions, 4, 8), 10f);
437 }
438
439 List<String> suppliesSmall = Arrays.asList(Entities.SUPPLY_CACHE_SMALL);
440 if (suppliesSmall.contains(type)) {
441 picker.add(new NothingSpecialCreator(), 30f);
442 picker.add(new ShipRecoverySpecialCreator(random, 1, 1, false, DerelictType.SMALL, recoverableShipFactions), 10f);
443 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.OFFICER, STANDARD_PODS_OFFICER_LEVEL, maxPodsOfficerLevel, officerFactions), 1f);
444 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ADMIN, 1, 5, officerFactions), 0.2f);
445 picker.add(new CargoManifestSpecialCreator(random, valuableCargo, 10, 30), 10f);
446 picker.add(new TransmitterTrapSpecialCreator(random, 0.5f, FleetTypes.PATROL_SMALL, trapFactions, 4, 8), 10f);
447 }
448
449
450 List<String> equipment = Arrays.asList(Entities.EQUIPMENT_CACHE);
451 if (equipment.contains(type)) {
452 picker.add(new NothingSpecialCreator(), 30f);
453 picker.add(new ShipRecoverySpecialCreator(random, 1, 1, false, DerelictType.SMALL, recoverableShipFactions), 10f);
454 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.OFFICER, STANDARD_PODS_OFFICER_LEVEL, maxPodsOfficerLevel, officerFactions), 1f);
455 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ADMIN, 1, 5, officerFactions), 0.2f);
456 picker.add(new CargoManifestSpecialCreator(random, industryCargo, 10, 30), 10f);
457 picker.add(new TransmitterTrapSpecialCreator(random, 0.5f, FleetTypes.PATROL_SMALL, trapFactions, 4, 8), 10f);
458 picker.add(new TopographicDataSpecialCreator(random, HTPoints.LOW_MIN, HTPoints.LOW_MAX), 1f);
459 }
460
461 List<String> equipmentSmall = Arrays.asList(Entities.EQUIPMENT_CACHE_SMALL);
462 if (equipmentSmall.contains(type)) {
463 picker.add(new NothingSpecialCreator(), 30f);
464 picker.add(new ShipRecoverySpecialCreator(random, 1, 1, false, DerelictType.SMALL, recoverableShipFactions), 10f);
465 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.OFFICER, STANDARD_PODS_OFFICER_LEVEL, maxPodsOfficerLevel, officerFactions), 1f);
466 picker.add(new SleeperPodsSpecialCreator(random, SleeperSpecialType.ADMIN, 1, 5, officerFactions), 0.2f);
467 picker.add(new CargoManifestSpecialCreator(random, industryCargo, 10, 30), 10f);
468 picker.add(new TransmitterTrapSpecialCreator(random, 0.5f, FleetTypes.PATROL_SMALL, trapFactions, 4, 8), 10f);
469 }
470
471
472 return picker.pick();
473 }
474
475
476 public static void assignSpecials(SectorEntityToken entity) {
477 assignSpecials(entity, true);
478 }
479
480 protected static Random randomOverride = null;
481 public static void assignSpecials(SectorEntityToken entity, boolean onNewGame, Random random) {
482 randomOverride = random;
483 assignSpecials(entity, onNewGame);
484 randomOverride = null;
485 }
486 public static void assignSpecials(SectorEntityToken entity, boolean onNewGame) {
487 SpecialCreationContext context = new SpecialCreationContext();
488 context.onNewGame = onNewGame;
489
490 SpecialCreator creator = pickSpecialFor(entity, context);
491 if (creator == null) return;
492
493 Object specialData = creator.createSpecial(entity, context);
494 if (specialData != null) {
495 Misc.setSalvageSpecial(entity, specialData);
496
498 String id = entity.getCustomEntityType();
499 if (id == null) id = entity.getClass().getSimpleName();
500 System.out.println("Assigned " + specialData.getClass().getSimpleName() + " to " + id);
501 }
502 }
503 }
504
505
506 public static void assignSpecials(List<StarSystemData> systemData, SpecialCreationContext context) {
507
508 context.all.clear();
509 for (StarSystemData data : systemData) {
510 for (AddedEntity added : data.generated) {
511 context.all.add(added.entity);
512 }
513 for (PlanetAPI planet : data.system.getPlanets()) {
514 if (planet.getMarket() != null &&
515 planet.getMarket().isPlanetConditionMarketOnly() &&
516 Misc.hasRuins(planet.getMarket())) {
517 context.all.add(planet);
518 }
519 }
520 }
521
523 System.out.println("\n\n\nAssigning salvage specials");
524 }
525
526 for (SectorEntityToken entity : context.all) {
527 SpecialCreator creator = pickSpecialFor(entity, context);
528 if (creator == null) continue;
529
530 Object specialData = creator.createSpecial(entity, context);
531 if (specialData != null) {
532 Misc.setSalvageSpecial(entity, specialData);
533
535 String id = entity.getCustomEntityType();
536 if (id == null) id = entity.getClass().getSimpleName();
537 System.out.println("Assigned " + specialData.getClass().getSimpleName() + " to " + id);
538 }
539 }
540
541 //System.out.println("" + StarSystemGenerator.random.nextLong());
542 }
543
545 System.out.println("Finished assigning salvage specials\n\n\n\n");
546 }
547
548 }
549
550
551
552
553
554 public static class NothingSpecialCreator implements SpecialCreator {
555 public Object createSpecial(SectorEntityToken entity, SpecialCreationContext context) {
556 return null;
557 }
558 }
559
560 public static class ShipRecoverySpecialCreator implements SpecialCreator {
561 private int min, max;
562 private WeightedRandomPicker<String> factionPicker;
563 private Random random;
564 private boolean badCondition;
565 private DerelictType type;
566 public ShipRecoverySpecialCreator(Random random, int min, int max, boolean badCondition,
567 DerelictType type,
568 WeightedRandomPicker<String> factionPicker) {
569 this.badCondition = badCondition;
570 this.type = type;
571 if (random == null) random = new Random();
572 this.random = random;
573 this.min = min;
574 this.max = max;
575 this.factionPicker = factionPicker;
576 }
577
578 public Object createSpecial(SectorEntityToken entity, SpecialCreationContext context) {
579
580 if (entity.getCustomPlugin() instanceof DerelictShipEntityPlugin) {
581 DerelictShipEntityPlugin plugin = (DerelictShipEntityPlugin) entity.getCustomPlugin();
582
583 ShipRecoverySpecialData data = new ShipRecoverySpecialData(null);
584 data.addShip(plugin.getData().ship.clone());
585 return data;
586 }
587
588// boolean debris = entity instanceof CampaignTerrainAPI &&
589// ((CampaignTerrainAPI)entity).getPlugin() instanceof DebrisFieldTerrainPlugin;
590 String desc = null;
591 if (entity instanceof PlanetAPI) {
592 desc = "found in a sealed hangar bay";
593 }
594
595 ShipRecoverySpecialData data = new ShipRecoverySpecialData(desc);
596 int num = min + random.nextInt(max - min + 1);
597 for (int i = 0; i < num; i++) {
598 String factionId = factionPicker.pick();
599 ShipCondition condition = DerelictShipEntityPlugin.pickDerelictCondition(random);
600 if (badCondition) {
601 condition = DerelictShipEntityPlugin.pickBadCondition(random);
602 }
603 DerelictShipData dsd = DerelictShipEntityPlugin.createRandom(factionId, type, random, 0f);
604 if (dsd == null || dsd.ship == null) continue;
605
606 dsd.ship.condition = condition;
607 data.addShip(dsd.ship);
608 }
609
610 if (data.ships == null || data.ships.isEmpty()) return null;
611
612 return data;
613 }
614
615 }
616
617
618 public static class SleeperPodsSpecialCreator implements SpecialCreator {
619 private SleeperSpecialType type;
620 private int min, max;
621 private WeightedRandomPicker<String> officerFactions;
622 private Random random;
623
624 public SleeperPodsSpecialCreator(Random random, SleeperSpecialType type, float min, float max,
625 WeightedRandomPicker<String> officerFactions) {
626 if (min < 1) min = 1;
627 if (max < 1) max = 1;
628 if (min > max) min = max;
629 this.random = random;
630 this.type = type;
631 this.min = (int) min;
632 this.max = (int) max;
633 this.officerFactions = officerFactions;
634
635// if (type == SleeperSpecialType.OFFICER && max == 15) {
636// System.out.println("ewfwefwe");
637// }
638 }
639
640
641 public Object createSpecial(SectorEntityToken entity, SpecialCreationContext context) {
642 SleeperPodsSpecialData data = new SleeperPodsSpecialData(type, null);
643
644 if (type == SleeperSpecialType.OFFICER) {
645// if (entity.getContainingLocation().getName().startsWith("Dalar's")) {
646// System.out.println("wefwefwe");
647// }
648 String factionId = officerFactions.pick();
649 FactionAPI faction = Global.getSector().getFaction(factionId);
650 //int level = min + random.nextInt(max - min + 1);
651
652 String key = "$SleeperPodsSpecialCreator_exceptionalCount";
653 int numAlreadyCreated = Global.getSector().getMemoryWithoutUpdate().getInt(key);
654
655 int level = min;
656 if (numAlreadyCreated < MAX_EXCEPTIONAL_PODS_OFFICERS &&
657 random.nextFloat() < PROB_EXCEPTIONAL_PODS_OFFICER) {
659 numAlreadyCreated++;
660 Global.getSector().getMemoryWithoutUpdate().set(key, numAlreadyCreated);
661 }
662
663// SkillPickPreference pref = SkillPickPreference.GENERIC;
664// float f = random.nextFloat();
665// if (f < 0.05f) {
666// pref = SkillPickPreference.ANY;
667// } else if (f < 0.1f) {
668// pref = SkillPickPreference.PHASE;
669// } else if (f < 0.25f) {
670// pref = SkillPickPreference.CARRIER;
671// }
672 SkillPickPreference pref = SkillPickPreference.ANY;
673
674 //pref = SkillPickPreference.CARRIER;
675
676
677// WeightedRandomPicker<Integer> numElite = new WeightedRandomPicker<Integer>(random);
678// numElite.add(0, 20f);
679// numElite.add(1, 10f);
680// numElite.add(2, level);
681// if (level >= EXCEPTIONAL_PODS_OFFICER_LEVEL - 1) {
682// numElite.add(3, level);
683// }
684// if (level >= EXCEPTIONAL_PODS_OFFICER_LEVEL) {
685// numElite.add(4, level);
686// }
687// int eliteSkillNumOverride = numElite.pick();
688 int eliteSkillNumOverride = 1;
689 if (level == EXCEPTIONAL_PODS_OFFICER_LEVEL) {
690 eliteSkillNumOverride = EXCEPTIONAL_PODS_OFFICER_ELITE_SKILLS;
691 }
692
693 PersonAPI officer = OfficerManagerEvent.createOfficer(faction, level, pref, true, null, true,
694 true, eliteSkillNumOverride, random);
695 if (level == EXCEPTIONAL_PODS_OFFICER_LEVEL) {
696 CryopodOfficerTemplate template = CryopodOfficerGen.TEMPLATES_EXCEPTIONAL.pick(random);
697 if (template != null) {
698 officer = template.create(faction, random);
699 }
700 } else if (random.nextFloat() < PROB_UNEXCEPTIONAL_USE_TEMPLATE) {
701 CryopodOfficerTemplate template = CryopodOfficerGen.TEMPLATES_NORMAL.pick(random);
702 if (template != null) {
703 officer = template.create(faction, random);
704 }
705 }
706
707 if (level == EXCEPTIONAL_PODS_OFFICER_LEVEL) {
708 officer.getMemoryWithoutUpdate().set(MemFlags.EXCEPTIONAL_SLEEPER_POD_OFFICER, true);
709 }
710 data.officer = officer;
711 data.min = 1;
712 data.max = 1;
713 } else if (type == SleeperSpecialType.ADMIN) {
714 //System.out.println("ADMIN: " + entity.getContainingLocation().getName() + ", " + entity.getName());
715 String factionId = officerFactions.pick();
716 FactionAPI faction = Global.getSector().getFaction(factionId);
717
718 WeightedRandomPicker<Integer> tierPicker = new WeightedRandomPicker<Integer>(random);
719 //tierPicker.add(0, 0);
720 tierPicker.add(1, 50);
721 tierPicker.add(2, 50);
722
723 int tier = tierPicker.pick();
724
725 PersonAPI officer = OfficerManagerEvent.createAdmin(faction, tier, random);
726 data.officer = officer;
727 data.min = 1;
728 data.max = 1;
729 } else {
730 data.min = min;
731 data.max = max;
732 }
733
734 return data;
735 }
736
737 }
738
739
740 public static class SurveyDataSpecialCreator implements SpecialCreator {
741 private Random random;
742 private SurveyDataSpecialType type;
743
744 public SurveyDataSpecialCreator(Random random, SurveyDataSpecialType type) {
745 this.random = random;
746 this.type = type;
747 }
748
749
750 public Object createSpecial(SectorEntityToken entity, SpecialCreationContext context) {
751 SurveyDataSpecialData data = new SurveyDataSpecialData(type);
752 return data;
753 }
754
755 }
756
757 public static class BlueprintSpecialCreator implements SpecialCreator {
758 private Random random;
759
760 public BlueprintSpecialCreator(Random random) {
761 this.random = random;
762 }
763
764 public Object createSpecial(SectorEntityToken entity, SpecialCreationContext context) {
765 return new BlueprintSpecialData();
766 }
767 }
768
769
770 public static class TopographicDataSpecialCreator implements SpecialCreator {
771 private Random random;
772 private int min;
773 private int max;
774
775 public TopographicDataSpecialCreator(Random random, int min, int max) {
776 if (min < 1) min = 1;
777 if (max < 1) max = 1;
778 this.random = random;
779 this.min = (int) min;
780 this.max = (int) max;
781 }
782
783 public Object createSpecial(SectorEntityToken entity, SpecialCreationContext context) {
784 int points = min + random.nextInt(max - min + 1);
785 TopographicDataSpecialData data = new TopographicDataSpecialData(points);
786 return data;
787 }
788 }
789 public static class CargoManifestSpecialCreator implements SpecialCreator {
790 private Random random;
791 private SurveyDataSpecialType type;
792 private WeightedRandomPicker<String> cargoPicker;
793 private int min;
794 private int max;
795
796 public CargoManifestSpecialCreator(Random random, WeightedRandomPicker<String> cargoPicker, float min, float max) {
797 if (min < 1) min = 1;
798 if (max < 1) max = 1;
799 this.random = random;
800 this.cargoPicker = cargoPicker;
801 this.min = (int) min;
802 this.max = (int) max;
803 }
804
805 public Object createSpecial(SectorEntityToken entity, SpecialCreationContext context) {
806 CargoManifestSpecialData data = new CargoManifestSpecialData(cargoPicker.pick(), min, max);
807 return data;
808 }
809 }
810
811 public static class TransmitterTrapSpecialCreator implements SpecialCreator {
812 private Random random;
813 private WeightedRandomPicker<String> factionPicker;
814 private int minPts;
815 private int maxPts;
816 private final float chance;
817 private final String fleetType;
818
819 public TransmitterTrapSpecialCreator(Random random, float chance, String fleetType,
820 WeightedRandomPicker<String> factionPicker, int min, int max) {
821 this.random = random;
822 this.chance = chance;
823 this.fleetType = fleetType;
824 this.factionPicker = factionPicker;
825 this.minPts = min;
826 this.maxPts = max;
827 }
828
829 public Object createSpecial(SectorEntityToken entity, SpecialCreationContext context) {
830
831
832 TransmitterTrapSpecialData data = new TransmitterTrapSpecialData();
833 data.prob = chance;
834 String factionId = factionPicker.pick();
835
836 data.nearbyFleetFaction = factionId;
837 data.useAllFleetsInRange = true;
838
839 if (fleetType != null) {
840 int combatPoints = minPts + random.nextInt(maxPts - minPts + 1);
841 combatPoints *= 5;
842
843 FleetParamsV3 params = new FleetParamsV3(
844 null,
845 entity.getLocationInHyperspace(),
846 factionId,
847 null,
848 fleetType,
849 combatPoints, // combatPts
850 0f, // freighterPts
851 0f, // tankerPts
852 0f, // transportPts
853 0f, // linerPts
854 0f, // utilityPts
855 0f // qualityMod
856 );
857 data.params = params;
858 }
859
860 return data;
861 }
862 }
863
864
865 public static class BreadcrumbSpecialCreator implements SpecialCreator {
866 private Random random;
867 private List<SectorEntityToken> all;
868
869 public BreadcrumbSpecialCreator(Random random, List<SectorEntityToken> all) {
870 this.random = random;
871 this.all = all;
872 }
873
874 public Object createSpecial(SectorEntityToken entity, SpecialCreationContext context) {
875 WeightedRandomPicker<SectorEntityToken> picker = new WeightedRandomPicker<SectorEntityToken>(random);
876
877// boolean debris = entity instanceof CampaignTerrainAPI &&
878// ((CampaignTerrainAPI)entity).getPlugin() instanceof DebrisFieldTerrainPlugin;
879
880 if (all != null) {
881 for (SectorEntityToken other : all) {
882 if (other == entity) continue;
883 // only breadcrumb to larger ships
884 if (!isLargeShipOrNonShip(other)) continue;
885 picker.add(other);
886 }
887 }
888
889 List<StarSystemAPI> systems = Misc.getNearbyStarSystems(entity, 10f);
890 for (StarSystemAPI system : systems) {
891 for (SectorEntityToken other : system.getEntitiesWithTag(Tags.SALVAGEABLE)) {
892 if (!other.hasSensorProfile() && !other.isDiscoverable()) continue;
893 if (other == entity) continue;
894 // only breadcrumb to larger ships
895 if (!isLargeShipOrNonShip(other)) continue;
896 if (other.hasTag(Tags.EXPIRES)) continue;
897 if (other.hasTag(Tags.NOT_RANDOM_MISSION_TARGET)) continue;
898 if (other.getContainingLocation() != null && other.getContainingLocation().hasTag(Tags.THEME_HIDDEN)) continue;
899
900 if (other.getMemoryWithoutUpdate() != null && other.getMemoryWithoutUpdate().getBoolean("$ttWeaponsCache")) continue;
901 picker.add(other);
902 }
903 }
904
905
906 SectorEntityToken target = picker.pick();
907 if (target == null) return null;
908
909 BreadcrumbSpecialData data = new BreadcrumbSpecialData(target.getId());
910 return data;
911 }
912
913 public static boolean isLargeShipOrNonShip(SectorEntityToken other) {
914 if (other.getCustomPlugin() instanceof DerelictShipEntityPlugin) {
915 DerelictShipEntityPlugin dsep = (DerelictShipEntityPlugin) other.getCustomPlugin();
916 ShipVariantAPI variant = dsep.getData().ship.variant;
917 if (variant == null && dsep.getData().ship.variantId != null) {
918 variant = Global.getSettings().getVariant(dsep.getData().ship.variantId);
919 }
920 if (variant != null) {
921 if (variant.getHullSize() == HullSize.FRIGATE) return false;
922 if (variant.getHullSize() == HullSize.DESTROYER) return false;
923 if (variant.getHullSize() == HullSize.CRUISER &&
924 variant.getHullSpec().getHints().contains(ShipTypeHints.CIVILIAN)) return false;
925 }
926 }
927 return true;
928 }
929 }
930
931}
932
933
934
935
936
static SettingsAPI getSettings()
Definition Global.java:51
static WeightedRandomPicker< String > getValuableCargo(Random random)
static WeightedRandomPicker< String > getNearbyFactions(Random random, SectorEntityToken entity)
static WeightedRandomPicker< String > getIndustryCargo(Random random)
static WeightedRandomPicker< String > getNearbyFactions(Random random, SectorEntityToken entity, float rangeLY, float indWeight, float pirateWeight)
static void assignSpecials(List< StarSystemData > systemData, SpecialCreationContext context)
static void assignSpecials(SectorEntityToken entity, boolean onNewGame)
static SpecialCreator pickSpecialFor(SectorEntityToken entity, SpecialCreationContext context)
static void assignSpecials(SectorEntityToken entity, boolean onNewGame, Random random)
static WeightedRandomPicker< String > getNearbyFactions(Random random, Vector2f locationInHyper, float rangeLY, float indWeight, float pirateWeight)
ShipVariantAPI getVariant(String variantId)