Starsector API
Loading...
Searching...
No Matches
HasslePlayerScript.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign;
2
3import java.util.List;
4
5import org.lwjgl.util.vector.Vector2f;
6
7import com.fs.starfarer.api.EveryFrameScript;
8import com.fs.starfarer.api.Global;
9import com.fs.starfarer.api.campaign.CampaignFleetAPI;
10import com.fs.starfarer.api.campaign.FleetAssignment;
11import com.fs.starfarer.api.campaign.SectorEntityToken.VisibilityLevel;
12import com.fs.starfarer.api.campaign.ai.FleetAssignmentDataAPI;
13import com.fs.starfarer.api.campaign.ai.ModularFleetAIAPI;
14import com.fs.starfarer.api.campaign.rules.MemoryAPI;
15import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
16import com.fs.starfarer.api.util.IntervalUtil;
17import com.fs.starfarer.api.util.Misc;
18import com.fs.starfarer.api.util.Misc.FleetFilter;
19
20public class HasslePlayerScript implements EveryFrameScript {
21
22 public static final String HASSLE_COMPLETE_KEY = "$hassleComplete";
23 public static final String HASSLE_TIMEOUT_KEY = "$hassleTimeout";
24
25 private IntervalUtil interval = new IntervalUtil(0.1f, 0.3f);
26
27 private float currDuration = 0f;
28 private float currElapsed = 0f;
29 private CampaignFleetAPI curr = null;
30 private Vector2f startHyperLoc;
31 private float leashRange = 0f;
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_PLAYER = 2000;
45
46 final MemoryAPI global = Global.getSector().getMemoryWithoutUpdate();
47 //if (global.contains(HASSLE_TIMEOUT_KEY)) return;
48
49 final CampaignFleetAPI player = Global.getSector().getPlayerFleet();
50 if (player == null || player.isInHyperspace()) return;
51
52
53 List<CampaignFleetAPI> fleets = Misc.findNearbyFleets(player, MAX_RANGE_FROM_PLAYER, new FleetFilter() {
54 public boolean accept(CampaignFleetAPI curr) {
55 if (curr.getFaction().isPlayerFaction()) return false;
56 if (curr.isHostileTo(player)) return false;
57 if (curr.isStationMode()) return false;
58 if (!curr.getMemoryWithoutUpdate().getBoolean(MemFlags.WILL_HASSLE_PLAYER)) return false;
59 if (curr.getMemoryWithoutUpdate().getBoolean(MemFlags.FLEET_SPECIAL_ACTION)) return false;
60
61 String type = curr.getMemoryWithoutUpdate().getString(MemFlags.HASSLE_TYPE);
62 if (type == null || type.isEmpty()) return false;
63 String timeoutKey = HASSLE_TIMEOUT_KEY + "_" + type;
64 if (global.contains(timeoutKey)) return false;
65
66 if (curr.getAI() instanceof ModularFleetAIAPI) {
67 ModularFleetAIAPI ai = (ModularFleetAIAPI) curr.getAI();
68 if (ai.isFleeing()) return false;
69 if (curr.getInteractionTarget() instanceof CampaignFleetAPI) return false;
70 }
71
72 VisibilityLevel vis = player.getVisibilityLevelTo(curr);
73 if (vis == VisibilityLevel.NONE) return false;
74 return true;
75 }
76 });
77
78 if (fleets.isEmpty()) return;
79
80 float minDist = Float.MAX_VALUE;
81 CampaignFleetAPI closestHassler = null;
82 for (CampaignFleetAPI curr : fleets) {
83 float dist = Misc.getDistance(player.getLocation(), curr.getLocation());
84 if (dist < minDist) {
85 minDist = dist;
86 closestHassler = curr;
87 }
88 }
89
90 if (closestHassler == null) return;
91
92 curr = closestHassler;
93
94 boolean hassle = (float) Math.random() < 0.25f;
95
96 if (hassle) {
97 currDuration = 10f + (float) Math.random() * 5f;
98 currElapsed = 0f;
99 MemoryAPI mem = curr.getMemoryWithoutUpdate();
100 Misc.setFlagWithReason(mem, MemFlags.MEMORY_KEY_PURSUE_PLAYER, "hassle", true, 1f);
101 mem.set(MemFlags.FLEET_SPECIAL_ACTION, true, 1f);
102 Misc.setFlagWithReason(mem, MemFlags.MEMORY_KEY_STICK_WITH_PLAYER_IF_ALREADY_TARGET, "hassle", true, currDuration);
103
104 startHyperLoc = curr.getLocationInHyperspace();
105 leashRange = Global.getSettings().getFloat("commRelayRangeAroundSystem");
106 if (curr.isInHyperspace()) {
107 leashRange *= 2f;
108 }
109
110 float timeoutDuration = 20f + (float) Math.random() * 10f;
111
112 String type = curr.getMemoryWithoutUpdate().getString(MemFlags.HASSLE_TYPE);
113 if (type != null && !type.isEmpty()) {
114 String timeoutKey = HASSLE_TIMEOUT_KEY + "_" + type;
115 global.set(timeoutKey, true, timeoutDuration);
116 }
117 //global.set(HASSLE_TIMEOUT_KEY, true, timeoutDuration);
118 } else {
119 curr = null;
120 }
121 }
122
123 public void maintainOngoingHassle(float days) {
124 if (!curr.isAlive()) {
125 cleanUpCurr();
126 return;
127 }
128 if (curr.isHostileTo(Global.getSector().getPlayerFleet())) {
129 cleanUpCurr();
130 return;
131 }
132
133 currElapsed += days;
134 if (currElapsed > currDuration) {
135 cleanUpCurr();
136 return;
137 }
138
139
140
141 CampaignFleetAPI player = Global.getSector().getPlayerFleet();
142 if (startHyperLoc != null) {
143 float dist = Misc.getDistanceLY(player.getLocationInHyperspace(), startHyperLoc);
144 if (dist > leashRange) {
145 cleanUpCurr();
146 return;
147 }
148 }
149// if (player.isInHyperspace() || player.isInHyperspaceTransition()) {
150// cleanUpCurr();
151// return;
152// }
153
154 MemoryAPI mem = curr.getMemoryWithoutUpdate();
155 if (mem.getBoolean(HASSLE_COMPLETE_KEY)) { // this happens when fleet interacts w/ player
156 cleanUpCurr();
157 return;
158 }
159 Misc.setFlagWithReason(mem, MemFlags.FLEET_BUSY, "hassle", true, 1f);
160 mem.set(MemFlags.FLEET_SPECIAL_ACTION, true, 1f);
161 // if visible, keep extending "pursue player" duration by a day
162 // so, player has to lose the hassling fleet for a day to get away
163 VisibilityLevel vis = player.getVisibilityLevelTo(curr);
164 if (vis != VisibilityLevel.NONE) {
165 Misc.setFlagWithReason(mem, MemFlags.MEMORY_KEY_PURSUE_PLAYER, "hassle", true, 1f);
166 }
167
168
169 }
170
171
172 protected void cleanUpCurr() {
173 if (curr != null) {
174 CampaignFleetAPI pf = Global.getSector().getPlayerFleet();
175 FleetAssignmentDataAPI a = curr.getCurrentAssignment();
176 if (a != null && a.getAssignment() == FleetAssignment.INTERCEPT &&
177 a.getTarget() == pf) {
178 curr.removeFirstAssignmentIfItIs(a.getAssignment());
179 }
180 curr.setInteractionTarget(null);
181 if (curr.getAI() instanceof ModularFleetAIAPI) {
182 ModularFleetAIAPI ai = (ModularFleetAIAPI) curr.getAI();
183 if (ai.getTacticalModule().getTarget() == pf) {
184 ai.getTacticalModule().setTarget(null);
185 }
186 }
187
188 MemoryAPI mem = curr.getMemoryWithoutUpdate();
189 Misc.setFlagWithReason(mem, MemFlags.FLEET_BUSY, "hassle", false, 0f);
190 mem.unset(MemFlags.FLEET_SPECIAL_ACTION);
191 Misc.setFlagWithReason(mem, MemFlags.MEMORY_KEY_PURSUE_PLAYER, "hassle", false, 0f);
192 Misc.setFlagWithReason(mem, MemFlags.MEMORY_KEY_STICK_WITH_PLAYER_IF_ALREADY_TARGET, "hassle", false, 0f);
193 mem.unset(HASSLE_COMPLETE_KEY);
194 curr = null;
195 currDuration = currElapsed = 0f;
196 startHyperLoc = null;
197 leashRange = 0f;
198 }
199 }
200
201
202 public boolean isDone() {
203 return false;
204 }
205
206 public boolean runWhilePaused() {
207 return false;
208 }
209}
210
211
212
213
214
215
216
217
218
219
220
221
222
static SettingsAPI getSettings()
Definition Global.java:51
static SectorAPI getSector()
Definition Global.java:59