Starsector API
Loading...
Searching...
No Matches
AssembleStage.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.intel.raid;
2
3import java.awt.Color;
4import java.util.ArrayList;
5import java.util.List;
6
7import com.fs.starfarer.api.campaign.SectorEntityToken;
8import com.fs.starfarer.api.campaign.FactionAPI.ShipPickMode;
9import com.fs.starfarer.api.campaign.econ.MarketAPI;
10import com.fs.starfarer.api.impl.campaign.DebugFlags;
11import com.fs.starfarer.api.impl.campaign.fleets.RouteLocationCalculator;
12import com.fs.starfarer.api.impl.campaign.fleets.RouteManager;
13import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.OptionalFleetData;
14import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
15import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment;
16import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
17import com.fs.starfarer.api.impl.campaign.ids.Stats;
18import com.fs.starfarer.api.impl.campaign.intel.inspection.HIAssembleStage;
19import com.fs.starfarer.api.impl.campaign.intel.punitive.PEAssembleStage;
20import com.fs.starfarer.api.impl.campaign.intel.raid.RaidIntel.RaidStageStatus;
21import com.fs.starfarer.api.ui.TooltipMakerAPI;
22import com.fs.starfarer.api.util.IntervalUtil;
23import com.fs.starfarer.api.util.Misc;
24import com.fs.starfarer.api.util.WeightedRandomPicker;
25
26public class AssembleStage extends BaseRaidStage {
27
28 public static final String PREP_STAGE = "prep_stage";
29 public static final String WAIT_STAGE = "wait_stage";
30
31 protected List<MarketAPI> sources = new ArrayList<MarketAPI>();
32 protected IntervalUtil interval = new IntervalUtil(0.1f, 0.2f);
33
34 protected SectorEntityToken gatheringPoint;
35 protected float spawnFP = 0;
36 protected float origSpawnFP = 0;
37
38 protected float minDays = 3f;
39
40 public AssembleStage(RaidIntel raid, SectorEntityToken gatheringPoint) {
41 super(raid);
42 this.gatheringPoint = gatheringPoint;
43 interval.forceIntervalElapsed();
44 }
45
46 public boolean isSourceKnown() {
47 return true;
48 }
49
50 public void setSpawnFP(float spawnFP) {
51 this.spawnFP = spawnFP;
52 this.origSpawnFP = spawnFP;
53 }
54
55 public float getOrigSpawnFP() {
56 return origSpawnFP;
57 }
58
59 public float getSpawnFP() {
60 return spawnFP;
61 }
62
63 public void addSource(MarketAPI source) {
64 sources.add(source);
65 }
66 public List<MarketAPI> getSources() {
67 return sources;
68 }
69
70 public void advance(float amount) {
71 addRoutesAsNeeded(amount);
72 minDays -= Misc.getDays(amount);
73 super.advance(amount);
74 }
75
76 protected void updateStatus() {
77 if (spawnFP > 0) return;
78 if (minDays > 0) return;
79
82 }
83
84 protected int currSource = 0;
85 protected String prevType = null;
86
87 public static float FP_SMALL = 20;
88 public static float FP_MEDIUM = 45;
89 public static float FP_LARGE = 85;
90
91 protected float getFPSmall() {
92 return FP_SMALL;
93 }
94 protected float getFPMedium() {
95 return FP_MEDIUM;
96 }
97 protected float getFPLarge() {
98 return FP_LARGE;
99 }
100
101 //public static float LARGE_SIZE = Global.getSettings().getFloat("approximateMaxFP");
102 protected float getLargeSize(boolean limitToSpawnFP) {
103 //if (true) return getFPLarge();
104 //float base = LARGE_SIZE;
105 float mult = 1f;
106 if (!getSources().isEmpty()) {
107 MarketAPI source = getSources().get(0);
108 ShipPickMode mode = Misc.getShipPickMode(source);
109 float base = source.getFaction().getApproximateMaxFPPerFleet(mode);
110
111 float numShipsMult = source.getStats().getDynamic().getMod(Stats.COMBAT_FLEET_SIZE_MULT).computeEffective(0f);
112 if (numShipsMult < 1f) numShipsMult = 1f;
113 mult = 1f / numShipsMult;
114 if (limitToSpawnFP) {
115 return Math.min(spawnFP, base * mult);
116 }
117 return base * mult;
118 } else {
119 return 250f;
120 }
121
122 }
123
124
125 protected String pickNextType() {
126 if (spawnFP >= getLargeSize(true) + getFPMedium()) {
127 return FleetTypes.PATROL_LARGE;
128 }
129
130 WeightedRandomPicker<String> picker = new WeightedRandomPicker<String>();
131 if (!FleetTypes.PATROL_SMALL.equals(prevType)) {
132 picker.add(FleetTypes.PATROL_SMALL);
133 }
134 if (!FleetTypes.PATROL_MEDIUM.equals(prevType) && spawnFP >= FP_MEDIUM) {
135 picker.add(FleetTypes.PATROL_MEDIUM);
136 }
137 if (!FleetTypes.PATROL_LARGE.equals(prevType) && spawnFP >= FP_LARGE) {
138 picker.add(FleetTypes.PATROL_LARGE);
139 }
140 prevType = picker.pick();
141 if (prevType == null) prevType = FleetTypes.PATROL_SMALL;
142 return prevType;
143 }
144
145 protected float getFP(String type) {
146 if (spawnFP >= getLargeSize(true) + getFPMedium()) {
147 float fp = getLargeSize(true);
148 spawnFP -= fp;
149 return fp;
150 }
151
152 float base = getFPSmall();
153 if (FleetTypes.PATROL_SMALL.equals(type)) {
154 base = getFPSmall();
155 } else if (FleetTypes.PATROL_MEDIUM.equals(type)) {
156 base = getFPMedium();
157 } else if (FleetTypes.PATROL_LARGE.equals(type)) {
158 base = getFPLarge();
159 }
160 base *= (1f + ((float) Math.random() - 0.5f) * 0.5f);
161 if (base > spawnFP) base = spawnFP;
162 spawnFP -= base;
163 if (spawnFP < getFPSmall() * 0.5f) {
164 base += spawnFP;
165 spawnFP = 0f;
166 }
167
168 return base;
169 }
170
171 protected void addRoutesAsNeeded(float amount) {
172 if (spawnFP <= 0) return;
173
174 float days = Misc.getDays(amount);
175
176 interval.advance(days);
177 if (!interval.intervalElapsed()) return;
178
179 if (sources.isEmpty()) {
180 status = RaidStageStatus.FAILURE;
181 return;
182 }
183
184 MarketAPI market = sources.get(currSource);
185 if (!market.isInEconomy() || !market.getPrimaryEntity().isAlive()) {
186 sources.remove(market);
187 return;
188 }
189
190 currSource ++;
191 currSource %= sources.size();
192
193
194 OptionalFleetData extra = new OptionalFleetData(market);
195
196 String sid = intel.getRouteSourceId();
197 RouteData route = RouteManager.getInstance().addRoute(sid, market, Misc.genRandomSeed(), extra, intel, null);
198
199 extra.fleetType = pickNextType();
200 float fp = getFP(extra.fleetType);
201
202 //extra.fp = Misc.getAdjustedFP(fp, market);
203 extra.fp = fp;
204 extra.strength = Misc.getAdjustedStrength(fp, market);
205
206
207 float prepDays = 3f + 3f * (float) Math.random();
208 float travelDays = RouteLocationCalculator.getTravelDays(market.getPrimaryEntity(), gatheringPoint);
209
211 (this instanceof PEAssembleStage && DebugFlags.PUNITIVE_EXPEDITION_DEBUG) ||
212 (this instanceof HIAssembleStage && DebugFlags.HEGEMONY_INSPECTION_DEBUG)) {
213 prepDays *= 0.1f;
214 travelDays *= 0.1f;
215 }
216
217 route.addSegment(new RouteSegment(prepDays, market.getPrimaryEntity(), PREP_STAGE));
218 route.addSegment(new RouteSegment(travelDays, market.getPrimaryEntity(), gatheringPoint));
219 route.addSegment(new RouteSegment(1000f, gatheringPoint, WAIT_STAGE));
220
221 maxDays = Math.max(maxDays, prepDays + travelDays);
222 //maxDays = 6f;
223
224 }
225
226 public void showStageInfo(TooltipMakerAPI info) {
227 int curr = intel.getCurrentStage();
228 int index = intel.getStageIndex(this);
229
230 Color h = Misc.getHighlightColor();
231 Color g = Misc.getGrayColor();
232 Color tc = Misc.getTextColor();
233 float pad = 3f;
234 float opad = 10f;
235
236 if (status == RaidStageStatus.FAILURE) {
237 info.addPara("The raiding forces have failed to successfully assemble at the rendezvous point. The raid is now over.", opad);
238 } else if (curr == index) {
239 if (isSourceKnown()) {
240 info.addPara("The raid is currently assembling in the " + gatheringPoint.getContainingLocation().getNameWithLowercaseType() + ".", opad);
241 } else {
242 info.addPara("The raid is currently assembling at an unknown location.", opad);
243 }
244 }
245 }
246
247}
248
249
250
AssembleStage(RaidIntel raid, SectorEntityToken gatheringPoint)
void updateStatusBasedOnReaching(SectorEntityToken dest, boolean giveReturnOrders)