Starsector API
Loading...
Searching...
No Matches
PatrolAssignmentAIV4.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.fleets;
2
3import java.util.List;
4import java.util.Random;
5
6import com.fs.starfarer.api.Script;
7import com.fs.starfarer.api.campaign.CampaignFleetAPI;
8import com.fs.starfarer.api.campaign.CustomCampaignEntityAPI;
9import com.fs.starfarer.api.campaign.FleetActionTextProvider;
10import com.fs.starfarer.api.campaign.FleetAssignment;
11import com.fs.starfarer.api.campaign.LocationAPI;
12import com.fs.starfarer.api.campaign.SectorEntityToken;
13import com.fs.starfarer.api.campaign.StarSystemAPI;
14import com.fs.starfarer.api.campaign.ai.FleetAssignmentDataAPI;
15import com.fs.starfarer.api.campaign.econ.MarketAPI;
16import com.fs.starfarer.api.impl.campaign.econ.impl.MilitaryBase.PatrolFleetData;
17import com.fs.starfarer.api.impl.campaign.fleets.FleetFactory.PatrolType;
18import com.fs.starfarer.api.impl.campaign.fleets.RouteLocationCalculator.TaskInterval;
19import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
20import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment;
21import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
22import com.fs.starfarer.api.impl.campaign.ids.Tags;
23import com.fs.starfarer.api.impl.campaign.procgen.themes.RouteFleetAssignmentAI;
24import com.fs.starfarer.api.util.CountingMap;
25import com.fs.starfarer.api.util.Misc;
26import com.fs.starfarer.api.util.WeightedRandomPicker;
27
28public class PatrolAssignmentAIV4 extends RouteFleetAssignmentAI implements FleetActionTextProvider {
29
30 public static final String PREP_STAGE = "a";
31 public static final String TRAVEL_TO_STAGE = "b";
32 public static final String PATROL_STAGE = "c";
33 public static final String RETURN_STAGE = "d";
34 public static final String STAND_DOWN_STAGE = "e";
35
36
37 public PatrolAssignmentAIV4(CampaignFleetAPI fleet, RouteData route) {
38 super(fleet, route);
39 }
40
41
42 @Override
43 protected void giveInitialAssignments() {
44 //super.giveInitialAssignments();
45
46
47 SectorEntityToken target = pickEntityToGuard();
48 if (target == null) return;
49
50 RouteSegment current = route.getCurrent();
51 SectorEntityToken source = route.getMarket().getPrimaryEntity();
52
53 TaskInterval [] intervals = new TaskInterval[] {
54 TaskInterval.days(3f + (float) Math.random() * 3f),
55 TaskInterval.travel(),
56 TaskInterval.remaining(1f),
57 TaskInterval.travel(),
58 TaskInterval.days(3f + (float) Math.random() * 3f),
59 };
60
61 RouteLocationCalculator.computeIntervalsAndSetLocation(fleet, current.elapsed, current.daysMax,
62 false, intervals,
63 source, source, target, target, source, source);
64
65 fleet.clearAssignments();
66
67 // time to spend traveling to location and patrolling it
68 float combinedTravelAndPatrolTime = intervals[1].value + intervals[2].value;
69
70 if (intervals[0].value > 0) {
71 fleet.addAssignment(FleetAssignment.ORBIT_PASSIVE, source, intervals[0].value, PREP_STAGE);
72 }
73 if (intervals[1].value > 0) {
74 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION, target, combinedTravelAndPatrolTime, TRAVEL_TO_STAGE,
75 true, null, null);
76 combinedTravelAndPatrolTime = 0f;
77 }
78 if (intervals[2].value > 0) {
79 fleet.addAssignment(FleetAssignment.PATROL_SYSTEM, target, combinedTravelAndPatrolTime, PATROL_STAGE,
80 false,
81 target.isSystemCenter() ? new Script() {
82 public void run() {
83 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_ALLOW_LONG_PURSUIT, true);
84 }} : null,
85 target.isSystemCenter() ? new Script() {
86 public void run() {
87 fleet.getMemoryWithoutUpdate().unset(MemFlags.MEMORY_KEY_ALLOW_LONG_PURSUIT);
88 }} : null
89 );
90 }
91
92
93 if (intervals[3].value > 0) { // return for as long as it takes, not just the interval value
94 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION, source, 1000f, RETURN_STAGE);
95 }
96
97 // if there was no return stage, that means we spawned right in orbit, since
98 // here always justSpawned == true
99 fleet.addAssignment(FleetAssignment.ORBIT_PASSIVE, source, intervals[4].value, STAND_DOWN_STAGE);
100 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION_AND_DESPAWN, source, 1000f,
101 STAND_DOWN_STAGE, goNextScript(current));
102
103 fleet.getAI().setActionTextProvider(this);
104
105 }
106
107 public String getActionText(CampaignFleetAPI fleet) {
108// if (Misc.getDistance(Global.getSector().getPlayerFleet(), fleet) < fleet.getRadius()) {
109// System.out.println("ewfwefwe");
110// }
111 FleetAssignmentDataAPI curr = fleet.getCurrentAssignment();
112 if (curr == null) return null;
113
114 String stage = curr.getActionText();
115 SectorEntityToken target = curr.getTarget();
116
117 String name = "";
118 if (target != null) {
119 name = target.getName();
120 if (target instanceof CustomCampaignEntityAPI) {
121 CustomCampaignEntityAPI cce = (CustomCampaignEntityAPI) target;
122 if (name.equals(cce.getCustomEntitySpec().getDefaultName())) {
123 //name = name.toLowerCase();
124 name = cce.getCustomEntitySpec().getNameInText();
125 }
126 }
127 }
128
129 boolean pirate = fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_PIRATE);
130
131 if (pirate) {
132 if (PREP_STAGE.equals(stage)) {
133 return "preparing for patrol duty";
134 } else if (TRAVEL_TO_STAGE.equals(stage) && target != null && !target.isSystemCenter() && !target.isInHyperspace()) {
135 return "traveling to " + name;
136 } else if (TRAVEL_TO_STAGE.equals(stage)) {
137 return "traveling";
138 } else if (PATROL_STAGE.equals(stage) && target != null) {
139 if (target.hasTag(Tags.OBJECTIVE)) {
140 return "guarding " + name;
141 } else if (target.hasTag(Tags.JUMP_POINT)) {
142 return "guarding " + name;
143 } else if (target.getMarket() != null) {
144 return "defending " + name;
145 } else {
146 return "patrolling";
147 }
148 } else if (RETURN_STAGE.equals(stage) && target != null && !target.isSystemCenter()) {
149 return "returning to " + name;
150 } else if (STAND_DOWN_STAGE.equals(stage)) {
151 return "standing down";
152 }
153 } else {
154 if (PREP_STAGE.equals(stage)) {
155 return "preparing for patrol duty";
156 } else if (TRAVEL_TO_STAGE.equals(stage) && target != null && !target.isSystemCenter() && !target.isInHyperspace()) {
157 return "traveling to " + name;
158 } else if (TRAVEL_TO_STAGE.equals(stage)) {
159 return "traveling";
160 } else if (PATROL_STAGE.equals(stage) && target != null) {
161 if (target.hasTag(Tags.OBJECTIVE)) {
162 return "guarding " + name;
163 } else if (target.hasTag(Tags.JUMP_POINT)) {
164 return "guarding " + name;
165 } else if (target.getMarket() != null) {
166 return "patrolling around " + name;
167 } else {
168 return "patrolling";
169 }
170 } else if (RETURN_STAGE.equals(stage) && target != null && !target.isSystemCenter()) {
171 return "returning to " + name;
172 } else if (STAND_DOWN_STAGE.equals(stage)) {
173 return "standing down from patrol duty";
174 }
175 }
176
177 //"traveling to " + target.getName()
178 //return "patrolling";
179 return null;
180 }
181
182 @Override
183 public void advance(float amount) {
184// if (fleet.isInCurrentLocation() &&
185// Misc.getDistance(Global.getSector().getPlayerFleet(), fleet) < fleet.getRadius()) {
186// System.out.println("ewfwefwe");
187// }
188 super.advance(amount);
189
190 checkCapture(amount);
191 checkBuild(amount);
192 }
193
194
195 public SectorEntityToken pickEntityToGuard() {
196 Random random = route.getRandom(1);
197
198 PatrolFleetData custom = (PatrolFleetData) route.getCustom();
199 PatrolType type = custom.type;
200
201 LocationAPI loc = fleet.getContainingLocation();
202 if (loc == null) return null;
203
204 WeightedRandomPicker<SectorEntityToken> picker = new WeightedRandomPicker<SectorEntityToken>(random);
205
206 CountingMap<SectorEntityToken> existing = new CountingMap<SectorEntityToken>();
207 for (RouteData data : RouteManager.getInstance().getRoutesForSource(route.getSource())) {
208 CampaignFleetAPI other = data.getActiveFleet();
209 if (other == null) continue;
210 FleetAssignmentDataAPI curr = other.getCurrentAssignment();
211 if (curr == null || curr.getTarget() == null ||
212 curr.getAssignment() != FleetAssignment.PATROL_SYSTEM) {
213 continue;
214 }
215 existing.add(curr.getTarget());
216 }
217
218 List<MarketAPI> markets = Misc.getMarketsInLocation(fleet.getContainingLocation());
219 int hostileMax = 0;
220 int ourMax = 0;
221 for (MarketAPI market : markets) {
222 if (market.getFaction().isHostileTo(fleet.getFaction())) {
223 hostileMax = Math.max(hostileMax, market.getSize());
224 } else if (market.getFaction() == fleet.getFaction()) {
225 ourMax = Math.max(ourMax, market.getSize());
226 }
227 }
228 boolean inControl = ourMax > hostileMax;
229
230 for (SectorEntityToken entity : loc.getEntitiesWithTag(Tags.OBJECTIVE)) {
231 if (entity.getFaction() != fleet.getFaction()) continue;
232
233 float w = 2f;
234 for (int i = 0; i < existing.getCount(entity); i++) w *= 0.1f;
235
236 if (type == PatrolType.HEAVY) w *= 0.1f;
237
238 picker.add(entity, w);
239 }
240
241 // patrol stable locations, will build there
242 for (SectorEntityToken entity : loc.getEntitiesWithTag(Tags.STABLE_LOCATION)) {
243 float w = 2f;
244 for (int i = 0; i < existing.getCount(entity); i++) w *= 0.1f;
245
246 if (type == PatrolType.HEAVY) w *= 0.1f;
247
248 picker.add(entity, w);
249 }
250
251 if (inControl) {
252 for (SectorEntityToken entity : loc.getJumpPoints()) {
253 float w = 2f;
254 for (int i = 0; i < existing.getCount(entity); i++) w *= 0.1f;
255
256 if (type == PatrolType.HEAVY) w *= 0.1f;
257
258 picker.add(entity, w);
259 }
260
261 if (loc instanceof StarSystemAPI && custom.type == PatrolType.HEAVY) {
262 StarSystemAPI system = (StarSystemAPI) loc;
263 if (system.getHyperspaceAnchor() != null) {
264 float w = 3f;
265 for (int i = 0; i < existing.getCount(system.getHyperspaceAnchor()); i++) w *= 0.1f;
266 picker.add(system.getHyperspaceAnchor(), w);
267 }
268 }
269 }
270
271 for (MarketAPI market : markets) {
272 if (market.getFaction().isHostileTo(fleet.getFaction())) continue;
273
274 float w = 0f;
275 if (market == route.getMarket()) {
276 w = 5f;
277 } else {
278 // defend on-hostile non-military markets; prefer own faction
279 //if (!market.hasSubmarket(Submarkets.GENERIC_MILITARY)) {
280 if (market.getMemoryWithoutUpdate().getBoolean(MemFlags.MARKET_PATROL)) {
281 if (market.getFaction() != fleet.getFaction()) {
282 w = 0f; // don't patrol near patrolHQ/military markets of another faction
283 } else {
284 w = 4f;
285 }
286 }
287 }
288
289 for (int i = 0; i < existing.getCount(market.getPrimaryEntity()); i++) w *= 0.1f;
290 picker.add(market.getPrimaryEntity(), w);
291 }
292
293 if (fleet.getContainingLocation() instanceof StarSystemAPI && type != PatrolType.HEAVY) {
294 StarSystemAPI system = (StarSystemAPI) fleet.getContainingLocation();
295 float w = 1f;
296 for (int i = 0; i < existing.getCount(system.getCenter()); i++) w *= 0.1f;
297 picker.add(system.getCenter(), w);
298 }
299
300 SectorEntityToken target = picker.pick();
301 if (target == null) {
302 target = route.market.getPrimaryEntity();
303 }
304
305 return target;
306 }
307
308
309
310}
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
static void computeIntervalsAndSetLocation(CampaignFleetAPI fleet, float daysElapsed, float maxDays, boolean onlyComputeIntervals, TaskInterval[] intervals, SectorEntityToken ... sequence)