Starsector API
Loading...
Searching...
No Matches
SmugglingScanScript.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign;
2
3import java.util.List;
4
5import com.fs.starfarer.api.EveryFrameScript;
6import com.fs.starfarer.api.Global;
7import com.fs.starfarer.api.campaign.CampaignFleetAPI;
8import com.fs.starfarer.api.campaign.FleetAssignment;
9import com.fs.starfarer.api.campaign.SectorEntityToken.VisibilityLevel;
10import com.fs.starfarer.api.campaign.ai.FleetAssignmentDataAPI;
11import com.fs.starfarer.api.campaign.ai.ModularFleetAIAPI;
12import com.fs.starfarer.api.campaign.econ.MarketAPI;
13import com.fs.starfarer.api.campaign.rules.MemoryAPI;
14import com.fs.starfarer.api.impl.campaign.events.BaseEventPlugin.MarketFilter;
15import com.fs.starfarer.api.impl.campaign.ids.Conditions;
16import com.fs.starfarer.api.impl.campaign.ids.Factions;
17import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
18import com.fs.starfarer.api.util.IntervalUtil;
19import com.fs.starfarer.api.util.Misc;
20import com.fs.starfarer.api.util.Misc.FleetFilter;
21
22public class SmugglingScanScript implements EveryFrameScript {
23
24 public static final String SCAN_COMPLETE_KEY = "$smugglingScanComplete";
25 public static final String MARKET_TIMEOUT_KEY = "$smugglingScanTimeout";
26
27 private IntervalUtil interval = new IntervalUtil(0.1f, 0.3f);
28
29 private float currDuration = 0f;
30 private float currElapsed = 0f;
31 private CampaignFleetAPI curr = null;
32
33 public void advance(float amount) {
34 float days = Global.getSector().getClock().convertToDays(amount);
35
36 if (curr != null) {
38 return;
39 }
40
41 interval.advance(days);
42 if (!interval.intervalElapsed()) return;
43
44 final float MAX_RANGE_FROM_MARKET = 5000;
45 final float MAX_RANGE_FROM_PLAYER = 2000;
46
47 final CampaignFleetAPI player = Global.getSector().getPlayerFleet();
48 if (player == null || player.isInHyperspace()) return;
49 final MarketAPI market = Misc.findNearestLocalMarket(player, MAX_RANGE_FROM_MARKET, new MarketFilter() {
50 public boolean acceptMarket(MarketAPI market) {
51 if (market.hasCondition(Conditions.FREE_PORT)) return false;
52
53 MemoryAPI mem = market.getMemoryWithoutUpdate();
54 //mem.unset(MARKET_TIMEOUT_KEY);
55 if (mem.contains(MARKET_TIMEOUT_KEY)) return false;
56 return true;
57 }
58 });
59 if (market == null) return;
60 if (!market.getFaction().getCustomBoolean(Factions.CUSTOM_ALLOWS_TRANSPONDER_OFF_TRADE) && !player.isTransponderOn()) {
61 return;
62 }
63
64 if (market.getFaction().isHostileTo(player.getFaction())) return;
65
66 List<CampaignFleetAPI> patrols = Misc.findNearbyFleets(player, MAX_RANGE_FROM_PLAYER, new FleetFilter() {
67 public boolean accept(CampaignFleetAPI curr) {
68 if (curr.getFaction() != market.getFaction()) return false;
69 if (curr.getFaction().isPlayerFaction()) return false;
70 if (curr.isHostileTo(player)) return false;
71 if (curr.isStationMode()) return false;
72 if (Misc.getSourceMarket(curr) != market) return false;
73 if (!curr.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_PATROL_FLEET)) return false;
74 if (curr.getAI() instanceof ModularFleetAIAPI) {
75 ModularFleetAIAPI ai = (ModularFleetAIAPI) curr.getAI();
76 if (ai.isFleeing()) return false;
77 if (curr.getInteractionTarget() instanceof CampaignFleetAPI) return false;
78 }
79 VisibilityLevel vis = player.getVisibilityLevelTo(curr);
80 if (vis == VisibilityLevel.NONE) return false;
81 return true;
82 }
83 });
84
85 if (patrols.isEmpty()) return;
86
87 float minDist = Float.MAX_VALUE;
88 CampaignFleetAPI closestPatrol = null;
89 float closestSuspicion = 0f;
90 for (CampaignFleetAPI curr : patrols) {
91 float dist = Misc.getDistance(player.getLocation(), curr.getLocation());
92 float extra = curr.getMemoryWithoutUpdate().getFloat(MemFlags.PATROL_EXTRA_SUSPICION);
93 if (dist < minDist || extra > closestSuspicion) {
94 minDist = dist;
95 closestSuspicion = extra;
96 closestPatrol = curr;
97 }
98 }
99
100 if (closestPatrol == null) return;
101
102 curr = closestPatrol;
103
104 float threshold = 0.05f;
105 MemoryAPI marketMemory = market.getMemory();
106 float suspicionLevel = marketMemory.getFloat(MemFlags.MEMORY_MARKET_SMUGGLING_SUSPICION_LEVEL);
107 suspicionLevel += closestSuspicion;
108 //suspicionLevel = 1f;
109 boolean doScan = (float) Math.random() < suspicionLevel * 5f && suspicionLevel >= threshold;
110 //doScan = true;
111
112 if (doScan) {
113 currDuration = 10f + (float) Math.random() * 5f;
114 currElapsed = 0f;
115 MemoryAPI mem = curr.getMemoryWithoutUpdate();
116 Misc.setFlagWithReason(mem, MemFlags.MEMORY_KEY_PURSUE_PLAYER, "smugglingScan", true, 1f);
117 Misc.setFlagWithReason(mem, MemFlags.MEMORY_KEY_STICK_WITH_PLAYER_IF_ALREADY_TARGET, "smugglingScan", true, currDuration);
118 } else {
119 curr = null;
120 }
121
122
123 if (suspicionLevel >= threshold) {
124 float timeoutDuration = 20f + (float) Math.random() * 10f;
125 marketMemory.set(MARKET_TIMEOUT_KEY, true, timeoutDuration);
126 }
127 }
128
129 public void maintainOngoingScan(float days) {
130 if (!curr.isAlive()) {
131 cleanUpCurr();
132 return;
133 }
134 if (curr.isHostileTo(Global.getSector().getPlayerFleet())) {
135 cleanUpCurr();
136 return;
137 }
138
139 currElapsed += days;
140 if (currElapsed > currDuration) {
141 cleanUpCurr();
142 return;
143 }
144
145
146 // if visible, keep extending "pursue player" duration by a day
147 // so, player has to lose the patrol for a day to be able to sneak into market
148 CampaignFleetAPI player = Global.getSector().getPlayerFleet();
149 if (player.isInHyperspace() || player.isInHyperspaceTransition()) {
150 cleanUpCurr();
151 return;
152 }
153
154 VisibilityLevel vis = player.getVisibilityLevelTo(curr);
155
156 if (vis != VisibilityLevel.NONE) {
157 MemoryAPI mem = curr.getMemoryWithoutUpdate();
158 if (mem.getBoolean(SCAN_COMPLETE_KEY)) { // this happens when fleet interacts w/ player
159 cleanUpCurr();
160 return;
161 }
162 //curr.getMemoryWithoutUpdate().contains("$pursuePlayer_smugglingScan");
163 Misc.setFlagWithReason(mem, MemFlags.MEMORY_KEY_PURSUE_PLAYER, "smugglingScan", true, 1f);
164 }
165 }
166
167
168 protected void cleanUpCurr() {
169 if (curr != null) {
170 CampaignFleetAPI pf = Global.getSector().getPlayerFleet();
171 FleetAssignmentDataAPI a = curr.getCurrentAssignment();
172 if (a != null && a.getAssignment() == FleetAssignment.INTERCEPT &&
173 a.getTarget() == pf) {
174 curr.removeFirstAssignmentIfItIs(a.getAssignment());
175 }
176 curr.setInteractionTarget(null);
177 if (curr.getAI() instanceof ModularFleetAIAPI) {
178 ModularFleetAIAPI ai = (ModularFleetAIAPI) curr.getAI();
179 if (ai.getTacticalModule().getTarget() == pf) {
180 ai.getTacticalModule().setTarget(null);
181 }
182 }
183
184 MemoryAPI mem = curr.getMemoryWithoutUpdate();
185 Misc.setFlagWithReason(mem, MemFlags.MEMORY_KEY_PURSUE_PLAYER, "smugglingScan", false, 0f);
186 Misc.setFlagWithReason(mem, MemFlags.MEMORY_KEY_STICK_WITH_PLAYER_IF_ALREADY_TARGET, "smugglingScan", false, 0f);
187 mem.unset(SCAN_COMPLETE_KEY);
188 curr = null;
189 currDuration = currElapsed = 0f;
190 }
191 }
192
193
194 public boolean isDone() {
195 return false;
196 }
197
198 public boolean runWhilePaused() {
199 return false;
200 }
201}
202
203
204
205
206
207
208
209
210
211
212
213
214
static SectorAPI getSector()
Definition Global.java:59