1package com.fs.starfarer.api.impl.campaign;
3import java.util.HashSet;
5import java.util.Random;
8import com.fs.starfarer.api.Global;
9import com.fs.starfarer.api.campaign.CampaignEngineLayers;
10import com.fs.starfarer.api.campaign.CargoAPI;
11import com.fs.starfarer.api.campaign.CustomCampaignEntityAPI;
12import com.fs.starfarer.api.campaign.FactionAPI;
13import com.fs.starfarer.api.campaign.SectorEntityToken;
14import com.fs.starfarer.api.campaign.SectorEntityToken.VisibilityLevel;
15import com.fs.starfarer.api.combat.ShipAPI.HullSize;
16import com.fs.starfarer.api.combat.ViewportAPI;
17import com.fs.starfarer.api.fleet.FleetMemberAPI;
18import com.fs.starfarer.api.fleet.FleetMemberType;
19import com.fs.starfarer.api.graphics.SpriteAPI;
20import com.fs.starfarer.api.impl.campaign.ids.Drops;
21import com.fs.starfarer.api.impl.campaign.ids.ShipRoles;
22import com.fs.starfarer.api.impl.campaign.procgen.DropGroupRow;
23import com.fs.starfarer.api.impl.campaign.procgen.SalvageEntityGenDataSpec.DropData;
24import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.BaseSalvageSpecial;
25import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.ShipRecoverySpecial.PerShipData;
26import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.ShipRecoverySpecial.ShipCondition;
27import com.fs.starfarer.api.ui.TooltipMakerAPI;
28import com.fs.starfarer.api.util.Misc;
29import com.fs.starfarer.api.util.WeightedRandomPicker;
35 public static enum DerelictType {
46 public static DerelictShipData
createHull(String hullId, Random random,
float sModProb) {
48 WeightedRandomPicker<String> picker =
new WeightedRandomPicker<String>(random);
50 String variantId = picker.pick();
51 if (variantId ==
null) {
56 public static DerelictShipData
createVariant(String variantId, Random random,
float sModProb) {
58 PerShipData ship =
new PerShipData(variantId, condition, sModProb);
59 return new DerelictShipData(ship,
true);
62 public static DerelictShipData
createRandom(String factionId, DerelictType type, Random random) {
65 public static DerelictShipData
createRandom(String factionId, DerelictType type, Random random,
float sModProb) {
66 if (random ==
null) random =
new Random();
68 String variantId =
null;
76 if (variantId ==
null)
return null;
80 PerShipData ship =
new PerShipData(variantId, condition, sModProb);
82 return new DerelictShipData(ship,
true);
86 if (random ==
null) random =
new Random();
87 WeightedRandomPicker<DerelictType> picker =
new WeightedRandomPicker<DerelictType>(random);
89 picker.add(DerelictType.CIVILIAN, 10f);
90 picker.add(DerelictType.LARGE, 5f);
91 picker.add(DerelictType.MEDIUM, 10f);
92 picker.add(DerelictType.SMALL, 20f);
97 if (random ==
null) random =
new Random();
98 WeightedRandomPicker<ShipCondition> picker =
new WeightedRandomPicker<ShipCondition>(random);
100 picker.add(ShipCondition.WRECKED, 10f);
101 picker.add(ShipCondition.BATTERED, 10f);
102 picker.add(ShipCondition.AVERAGE, 7f);
103 picker.add(ShipCondition.GOOD, 5f);
104 picker.add(ShipCondition.PRISTINE, 1f);
106 return picker.pick();
110 if (random ==
null) random =
new Random();
111 WeightedRandomPicker<ShipCondition> picker =
new WeightedRandomPicker<ShipCondition>(random);
113 picker.add(ShipCondition.WRECKED, 10f);
114 picker.add(ShipCondition.BATTERED, 10f);
115 picker.add(ShipCondition.AVERAGE, 3f);
117 return picker.pick();
123 ShipRoles.CIV_RANDOM, 7f,
124 ShipRoles.FREIGHTER_SMALL, 10f,
125 ShipRoles.FREIGHTER_MEDIUM, 3f,
126 ShipRoles.FREIGHTER_LARGE, 1f,
127 ShipRoles.LINER_SMALL, 10f,
128 ShipRoles.LINER_MEDIUM, 3f,
129 ShipRoles.LINER_LARGE, 1f,
130 ShipRoles.TANKER_SMALL, 10f,
131 ShipRoles.TANKER_MEDIUM, 3f,
132 ShipRoles.TANKER_LARGE, 1f,
133 ShipRoles.PERSONNEL_SMALL, 10f,
134 ShipRoles.PERSONNEL_MEDIUM, 3f,
135 ShipRoles.PERSONNEL_LARGE, 1f
141 ShipRoles.COMBAT_SMALL, 10f,
142 ShipRoles.COMBAT_FREIGHTER_SMALL, 3f,
143 ShipRoles.FREIGHTER_SMALL, 1f,
144 ShipRoles.TANKER_SMALL, 1f,
145 ShipRoles.LINER_SMALL, 1f,
146 ShipRoles.PERSONNEL_SMALL, 1f
153 ShipRoles.COMBAT_MEDIUM, 10f,
154 ShipRoles.COMBAT_FREIGHTER_MEDIUM, 3f,
155 ShipRoles.CARRIER_SMALL, 1f,
156 ShipRoles.FREIGHTER_MEDIUM, 1f,
157 ShipRoles.TANKER_MEDIUM, 1f,
158 ShipRoles.LINER_MEDIUM, 1f,
159 ShipRoles.PERSONNEL_MEDIUM, 1f
166 ShipRoles.COMBAT_LARGE, 10f,
167 ShipRoles.COMBAT_CAPITAL, 3f,
168 ShipRoles.COMBAT_FREIGHTER_LARGE, 1f,
169 ShipRoles.CARRIER_MEDIUM, 1f,
170 ShipRoles.FREIGHTER_LARGE, 1f,
171 ShipRoles.CARRIER_LARGE, 1f,
172 ShipRoles.TANKER_LARGE, 1f,
173 ShipRoles.LINER_LARGE, 1f,
174 ShipRoles.TANKER_MEDIUM, 1f,
175 ShipRoles.PERSONNEL_LARGE, 1f
182 public static String
pickVariant(String factionId, Random random, Object ... shipRoles) {
183 if (random ==
null) random =
new Random();
187 WeightedRandomPicker<String> picker =
new WeightedRandomPicker<String>(random);
188 for (
int i = 0; i < shipRoles.length; i += 2) {
189 String role = (String) shipRoles[i];
190 Float weight = (Float) shipRoles[i + 1];
191 picker.add(role, weight);
194 Set<String> variantsForRole =
new HashSet<String>();
195 while (variantsForRole.isEmpty() && !picker.isEmpty()) {
196 String role = picker.pickAndRemove();
197 if (role ==
null)
return null;
199 variantsForRole = faction.getVariantsForRole(role);
203 picker.addAll(variantsForRole);
204 String variantId = picker.pick();
211 public static class DerelictShipData {
212 public PerShipData ship;
213 public float durationDays = 10000000f;
214 public boolean canHaveExtraCargo =
false;
215 public DerelictShipData(PerShipData ship,
boolean canHaveExtraCargo) {
217 this.canHaveExtraCargo = canHaveExtraCargo;
229 private DerelictShipData data;
231 private transient GenericCampaignEntitySprite sprite;
232 private transient FleetMemberAPI member;
233 private transient float scale;
235 private float angVel = 0f;
238 super.init(
entity, params);
240 data = (DerelictShipData) params;
242 angVel = 5f + (float) Math.random() * 10f;
243 angVel *= Math.signum((
float) Math.random() - 0.5f);
247 entity.setSensorProfile(1f);
248 entity.setDiscoverable(
false);
254 entity.getDetectedRangeMod().modifyFlat(
"gen", range);
256 ((CustomCampaignEntityAPI)
entity).setRadius(
getRadius(member.getHullSpec().getHullSize()));
260 DropData data =
new DropData();
261 data.group = Drops.BASIC;
263 entity.addDropValue(data);
270 if (this.data.canHaveExtraCargo) {
273 long seed = Misc.getSalvageSeed(
entity);
274 Random r = Misc.getRandom(seed, 2);
275 float extraProb = 0.5f;
276 if (r.nextFloat() < extraProb) {
277 if (member.getVariant().isFreighter()) {
278 WeightedRandomPicker<DropGroupRow> picker = DropGroupRow.getPicker(Drops.FREIGHTER_CARGO);
279 picker.setRandom(
new Random(seed));
281 for (
int i = 0; i < 3; i++) {
282 DropGroupRow pick = picker.pick();
283 if (pick.isCommodity()) {
284 extraSalvage.addCommodity(pick.getCommodity(),
285 (int)Math.ceil(member.getCargoCapacity() * (0.15f + 0.15f * r.nextFloat())));
288 BaseSalvageSpecial.addExtraSalvage(extraSalvage,
entity.getMemoryWithoutUpdate(), -1);
289 }
else if (member.getVariant().isTanker()) {
291 extraSalvage.addFuel((
int)Math.ceil(member.getFuelCapacity() * (0.25f + 0.25f * r.nextFloat())));
292 BaseSalvageSpecial.addExtraSalvage(extraSalvage,
entity.getMemoryWithoutUpdate(), -1);
302 entity.setDiscoveryXP((
float) data.value * 0.05f);
304 entity.setSalvageXP((
float) data.value * 0.15f);
312 case CAPITAL_SHIP:
return 40f;
313 case CRUISER:
return 35f;
314 case DESTROYER:
return 30f;
315 case FRIGATE:
return 25f;
322 case CAPITAL_SHIP:
return 50f;
323 case CRUISER:
return 40f;
324 case DESTROYER:
return 30f;
325 case FRIGATE:
return 25f;
332 case CAPITAL_SHIP:
return 1700f;
333 case CRUISER:
return 1300f;
334 case DESTROYER:
return 1000f;
335 case FRIGATE:
return 800f;
341 float value = member.getDeploymentCostSupplies() * 200f;
345 Object readResolve() {
347 if (data.ship.variantId !=
null) {
353 scale = Misc.getCampaignShipScaleMult(member.getHullSpec().getHullSize());
357 sprite =
new GenericCampaignEntitySprite(
entity, member.getHullSpec().getSpriteName(), scale);
361 float w = base.getWidth();
362 float h = base.getHeight();
363 float size = Math.max(w, h) * 3f * scale;
364 overlay.setSize(size, size);
365 sprite.setOverlay(overlay);
377 if (
entity.isInCurrentLocation()) {
378 float turn = amount * angVel;
379 entity.setFacing(Misc.normalizeAngle(
entity.getFacing() + turn));
390 VisibilityLevel vis =
entity.getVisibilityLevelToPlayerFleet();
391 boolean playerCanSee =
entity.isInCurrentLocation() &&
392 (vis == VisibilityLevel.COMPOSITION_AND_FACTION_DETAILS ||
393 vis == VisibilityLevel.COMPOSITION_DETAILS);
395 Misc.fadeAndExpire(
entity, 1f);
402 return entity.getRadius() + 100f;
405 public void render(CampaignEngineLayers layer, ViewportAPI viewport) {
406 float alphaMult = viewport.getAlphaMult();
407 alphaMult *=
entity.getSensorFaderBrightness();
408 alphaMult *=
entity.getSensorContactFaderBrightness();
409 if (alphaMult <= 0)
return;
411 sprite.render(0, 0,
entity.getFacing(), alphaMult);
static SettingsAPI getSettings()
static FactoryAPI getFactory()
static SectorAPI getSector()
static ShipCondition pickBadCondition(Random random)
static String pickVariant(String factionId, Random random, Object ... shipRoles)
static DerelictShipData createRandom(String factionId, DerelictType type, Random random, float sModProb)
static String pickCivilianVariantId(String factionId, Random random)
static String pickSmallVariantId(String factionId, Random random)
void advance(float amount)
void init(SectorEntityToken entity, Object params)
static float getDefaultSModProb()
static String pickLargeVariantId(String factionId, Random random)
static float getRadius(HullSize size)
static float DEFAULT_SMOD_PROB
static DerelictShipData createRandom(String factionId, DerelictType type, Random random)
static String pickMediumVariantId(String factionId, Random random)
void appendToCampaignTooltip(TooltipMakerAPI tooltip, VisibilityLevel level)
static DerelictType pickDerelictType(Random random)
void render(CampaignEngineLayers layer, ViewportAPI viewport)
static DerelictShipData createVariant(String variantId, Random random, float sModProb)
static float getDetectedAtRange(HullSize size)
static ShipCondition pickDerelictCondition(Random random)
static float getBasicDropValue(FleetMemberAPI member)
static DerelictShipData createHull(String hullId, Random random, float sModProb)
DerelictShipData getData()
static float getBaseDuration(HullSize size)
CargoAPI createCargo(boolean unlimitedStacks)
FleetMemberAPI createFleetMember(FleetMemberType type, String variantOrWingId)
ListMap< String > getHullIdToVariantListMap()
SpriteAPI getSprite(String filename)