Starsector API
Loading...
Searching...
No Matches
CampaignTutorialScript.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.tutorial;
2
3import org.lwjgl.util.vector.Vector2f;
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.CampaignTerrainAPI;
9import com.fs.starfarer.api.campaign.CoreUITabId;
10import com.fs.starfarer.api.campaign.PlanetAPI;
11import com.fs.starfarer.api.campaign.SectorEntityToken;
12import com.fs.starfarer.api.campaign.StarSystemAPI;
13import com.fs.starfarer.api.characters.AbilityPlugin;
14import com.fs.starfarer.api.fleet.FleetMemberAPI;
15import com.fs.starfarer.api.fleet.FleetMemberType;
16import com.fs.starfarer.api.impl.campaign.DModManager;
17import com.fs.starfarer.api.impl.campaign.fleets.FleetFactoryV3;
18import com.fs.starfarer.api.impl.campaign.ids.Abilities;
19import com.fs.starfarer.api.impl.campaign.ids.Factions;
20import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
21import com.fs.starfarer.api.impl.campaign.ids.HullMods;
22import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
23import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.TransmitterTrapSpecial;
24import com.fs.starfarer.api.ui.HintPanelAPI;
25import com.fs.starfarer.api.util.Misc;
26
28
29 public static final String USE_TUTORIAL_RESPAWN = "$tutorialRespawn";
30
31 public static enum CampaignTutorialStage {
32 SHOW_WELCOME_DIALOG,
33 SHOW_DEBRIS_HINT,
34 HEADING_TO_DEBRIS,
35 REACHED_DEBRIS,
36 SAVE_NAG_1,
37 SHOW_PIRATE_DIALOG,
38 SHOW_PIRATE_HINT,
39 PIRATE_APPROACHES,
40 SAVE_NAG_2,
41 SHOW_LEVELUP_DIALOG,
42 SHOW_LEVELUP_HINT,
43 WAIT_CHAR_TAB,
44 SHOW_LAY_IN_COURSE_DIALOG,
45 SHOW_LAY_IN_COURSE_HINT,
46 WAITING_TO_LAY_IN_COURSE,
47 SHOW_GO_SLOW_DIALOG,
48 SHOW_GO_SLOW_HINT,
49 WAITING_TO_GO_SLOW,
50 SHOW_SUSTAINED_BURN_DIALOG,
51 SHOW_SUSTAINED_BURN_HINT,
52 WAIT_SUSTAINED_BURN_USE,
53 SHOW_TRANSPONDER_DIALOG,
54 SHOW_TRANSPONDER_HINT,
55 WAIT_TRANSPONDER_USE,
56 DONE,
57
58 WAITING_TO_QUICKSAVE,
59 }
60
61
62 protected boolean askedPlayerToSave = false;
63 protected boolean playerSaved = false;
64 protected float elapsed = 0f;
65 protected float lastCheckDistToAncyra = -1f;
66
67 protected StarSystemAPI system;
68 protected PlanetAPI ancyra;
69 protected SectorEntityToken derinkuyu;
70 protected CampaignTutorialStage stage = CampaignTutorialStage.SHOW_WELCOME_DIALOG;
71
72 protected boolean orbitalResetDone = false;
73
74 protected CampaignTerrainAPI debrisField;
75 protected CampaignFleetAPI pirateFleet;
76 protected CampaignFleetAPI detachment;
78
79 public CampaignTutorialScript(StarSystemAPI system) {
80 this.system = system;
81 debrisField = (CampaignTerrainAPI) system.getEntityById("debris_tutorial");
82 ancyra = (PlanetAPI) system.getEntityById("ancyra");
83 derinkuyu = system.getEntityById("derinkuyu_station");
84
85 Global.getSector().getMemoryWithoutUpdate().set(USE_TUTORIAL_RESPAWN, true);
86 }
87
88 protected Object readResolve() {
89 return this;
90 }
91
92 protected Object writeReplace() {
94 playerSaved = true;
95 HintPanelAPI hints = Global.getSector().getCampaignUI().getHintPanel();
96 if (hints != null) {
97 hints.clearHints(false);
98 }
99 }
100 return this;
101 }
102
103 protected CampaignTutorialStage quickSaveFrom = null;
104 protected boolean quickSaveNag(CampaignTutorialStage nagStage, CampaignTutorialStage next, float timeout) {
105 HintPanelAPI hints = Global.getSector().getCampaignUI().getHintPanel();
106
107 if (stage == nagStage) {
108 quickSaveFrom = nagStage;
109 hints.clearHints();
110
111 String control = Global.getSettings().getControlStringForEnumName("QUICK_SAVE");
112 if (timeout > 0) {
113 hints.setHint(0, "- Press %s to quick-save, if you like", true, Misc.getHighlightColor(), control);
114 } else {
115 hints.setHint(0, "- Press %s to quick-save and advance the tutorial", true, Misc.getHighlightColor(), control);
116 }
117
118 stage = CampaignTutorialStage.WAITING_TO_QUICKSAVE;
119 elapsed = 0f;
120 askedPlayerToSave = true;
121 playerSaved = false;
122
123 return true;
124 }
125
126 if (quickSaveFrom == nagStage && stage == CampaignTutorialStage.WAITING_TO_QUICKSAVE &&
127 (playerSaved || (timeout > 0 && elapsed > timeout))) {
128 hints.clearHints();
129 stage = next;
130 elapsed = 0f;
131 playerSaved = false;
132 askedPlayerToSave = false;
133 quickSaveFrom = null;
134 return true;
135 }
136
137 return false;
138 }
139
140 protected void leashToStartLocation() {
141 CampaignFleetAPI pf = Global.getSector().getPlayerFleet();
142 float dist = Misc.getDistance(pf.getLocation(), debrisField.getLocation());
143 if (dist > 1500) {
144 Vector2f loc = debrisField.getLocation();
145 pf.setLocation(loc.x, loc.y);
146 Global.getSector().getCampaignUI().showMessageDialog("Please follow the instructions near the bottom of the screen and quicksave to advance the tutorial.");
147 }
148 }
149
150 protected boolean charTabWasOpen = false;
151 public void advance(float amount) {
152 if (Global.getSector().isInFastAdvance()) return;
153
154 if (!orbitalResetDone) {
155 system.getEntityById("ancyra").setCircularOrbitAngle(55f);
156 system.getEntityById("ancyra_relay").setCircularOrbitAngle(55 - 60);;
157
158 system.getEntityById("pontus").setCircularOrbitAngle(230);
159 system.getEntityById("pontus_L4").setCircularOrbitAngle(230 + 60);
160 system.getEntityById("pontus_L5").setCircularOrbitAngle(230 - 60);
161 system.getEntityById("galatia_probe").setCircularOrbitAngle(230);
162 system.getEntityById("galatia_jump_point_alpha").setCircularOrbitAngle(230 + 180f);
163
164 system.getEntityById("tetra").setCircularOrbitAngle(340);
165 system.getEntityById("derinkuyu_station").setCircularOrbitAngle(135);
166 system.getEntityById("galatia_jump_point_fringe").setCircularOrbitAngle(160);;
167
168 orbitalResetDone = true;
169 }
170
171
172 if (amount == 0) return;
173
174 CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet();
175 if (playerFleet == null) return;
176
177 HintPanelAPI hints = Global.getSector().getCampaignUI().getHintPanel();
178 if (hints == null) return;
179
180 //playerFleet.addAbility(Abilities.SENSOR_BURST);
181
182 if (lastCheckDistToAncyra < 0) {
183 lastCheckDistToAncyra = Misc.getDistance(playerFleet.getLocation(), ancyra.getLocation());
184 }
185
186 elapsed += amount;
187
188 if (stage == CampaignTutorialStage.SHOW_WELCOME_DIALOG && elapsed > 1f) {
189 if (Global.getSector().getCampaignUI().showInteractionDialog(new TutorialWelcomeDialogPluginImpl(), null)) {
190 addFleets();
191 stage = CampaignTutorialStage.SHOW_DEBRIS_HINT;
192 }
193 return;
194 }
195
196 if (stage == CampaignTutorialStage.SHOW_DEBRIS_HINT) {
198 hints.setHint(1, "- Move up into the debris field");
199 hints.setHint(0, "- Press %s to start scavenging", false, Misc.getHighlightColor(), control);
200 hints.makeDim(0);
201 stage = CampaignTutorialStage.HEADING_TO_DEBRIS;
202 return;
203 }
204
205 if (stage == CampaignTutorialStage.HEADING_TO_DEBRIS) {
206 if (debrisField.getPlugin().containsEntity(playerFleet)) {
207 stage = CampaignTutorialStage.REACHED_DEBRIS;
208 hints.fadeOutHint(1);
209 //hints.makeNormal(0);
211 hints.setHint(0, "- Press %s to start scavenging", true, Misc.getHighlightColor(), control);
212 }
213 return;
214 }
215
216 if (stage == CampaignTutorialStage.REACHED_DEBRIS) {
217 AbilityPlugin scavenge = playerFleet.getAbility(Abilities.SCAVENGE);
218 if (scavenge != null && scavenge.isOnCooldown()) {
219 stage = CampaignTutorialStage.SAVE_NAG_1;
220 }
221 return;
222 }
223
224 if (quickSaveFrom == CampaignTutorialStage.SAVE_NAG_1) {
226 }
227 if (quickSaveNag(CampaignTutorialStage.SAVE_NAG_1, CampaignTutorialStage.SHOW_PIRATE_DIALOG, 0)) {
228 return;
229 }
230
231 if (stage == CampaignTutorialStage.SHOW_PIRATE_DIALOG && elapsed >= 1f) {
232 if (Global.getSector().getCampaignUI().showInteractionDialog(new TutorialPirateApproachesDialogPluginImpl(), null)) {
233 stage = CampaignTutorialStage.SHOW_PIRATE_HINT;
234 }
235 return;
236 }
237
238 if (stage == CampaignTutorialStage.SHOW_PIRATE_HINT) {
240
241 hints.setHint(0, "- Wait for the pirates to approach, then engage and defeat them!");
242 stage = CampaignTutorialStage.PIRATE_APPROACHES;
243 return;
244 }
245
246 if (stage == CampaignTutorialStage.PIRATE_APPROACHES) {
247 if (pirateFleet == null || !pirateFleet.isAlive()) {
248 hints.clearHints();
249 stage = CampaignTutorialStage.SAVE_NAG_2;
250 elapsed = 0f;
251
252 long xp = Global.getSector().getPlayerPerson().getStats().getXP();
253 long add = Global.getSettings().getLevelupPlugin().getXPForLevel(2) - xp;
254 if (add > 0) {
255 Global.getSector().getPlayerPerson().getStats().addPoints(1);
256 Global.getSector().getPlayerPerson().getStats().addXP(add);
257 }
258 }
259 return;
260 }
261
262 if (quickSaveNag(CampaignTutorialStage.SAVE_NAG_2, CampaignTutorialStage.SHOW_LEVELUP_DIALOG, 0)) {
263 return;
264 }
265
266 if (stage == CampaignTutorialStage.SHOW_LEVELUP_DIALOG && elapsed >= 1f) {
267 if (Global.getSector().getCampaignUI().showInteractionDialog(new TutorialLevelUpDialogPluginImpl(), null)) {
268 stage = CampaignTutorialStage.SHOW_LEVELUP_HINT;
269 }
270 return;
271 }
272
273 if (stage == CampaignTutorialStage.SHOW_LEVELUP_HINT) {
274 String character = Global.getSettings().getControlStringForEnumName("CORE_CHARACTER");
275 hints.setHint(0, "- Press %s to open the character tab and consider your options", true, Misc.getHighlightColor(), character);
276 stage = CampaignTutorialStage.WAIT_CHAR_TAB;
277 return;
278 }
279
280 if (stage == CampaignTutorialStage.WAIT_CHAR_TAB) {
281 CoreUITabId tab = Global.getSector().getCampaignUI().getCurrentCoreTab();
282 if (tab == CoreUITabId.CHARACTER) {
283 charTabWasOpen = true;
284 }
285 if (charTabWasOpen && !Global.getSector().getCampaignUI().isShowingDialog()) {
286 stage = CampaignTutorialStage.SHOW_LAY_IN_COURSE_DIALOG;
287 elapsed = 0f;
288 hints.clearHints();
289 }
290 }
291
292 if (stage == CampaignTutorialStage.SHOW_LAY_IN_COURSE_DIALOG && elapsed >= 1f) {
294 if (Global.getSector().getCampaignUI().showInteractionDialog(
296 stage = CampaignTutorialStage.SHOW_LAY_IN_COURSE_HINT;
297 }
298 return;
299 }
300
301
302 if (stage == CampaignTutorialStage.SHOW_LAY_IN_COURSE_HINT) {
303 String intel = Global.getSettings().getControlStringForEnumName("CORE_INTEL");
304 String map = Global.getSettings().getControlStringForEnumName("CORE_MAP");
305 String openMap = Global.getSettings().getControlStringForEnumName("SUBTAB_4");
306
307 hints.setHint(2, "- Press %s to open the intel tab, and select the mission", false, Misc.getHighlightColor(), intel);
308 hints.setHint(1, "- Press %s to open the map on the mission target", false, Misc.getHighlightColor(), openMap);
309 hints.setHint(0, "- Click on " + ancyra.getName() + " and select " +
310 "%s, then press %s to close the map", false, Misc.getHighlightColor(), "\"Lay in Course\"", map);
311 stage = CampaignTutorialStage.WAITING_TO_LAY_IN_COURSE;
312
313// hints.setHint(1, "- Press %s to open the map", Misc.getHighlightColor(), map);
314// hints.setHint(0, "- Find " + ancyra.getName() + ", left-click on it and select " +
315// "\"Lay in Course\", then close the map", Misc.getHighlightColor(), "\"Lay in Course\"");
316// stage = CampaignTutorialStage.WAITING_TO_LAY_IN_COURSE;
317 return;
318 }
319
320 if (stage == CampaignTutorialStage.WAITING_TO_LAY_IN_COURSE) {
321 float dist = Misc.getDistance(playerFleet.getLocation(), ancyra.getLocation());
322 boolean closedIn = dist < lastCheckDistToAncyra * 0.75f;
323 if (closedIn || (playerFleet.getInteractionTarget() != null &&
324 playerFleet.getInteractionTarget().getMarket() == ancyra.getMarket())) {
326 hints.clearHints();
327 stage = CampaignTutorialStage.SHOW_SUSTAINED_BURN_DIALOG;
328 elapsed = 0;
329 }
330 return;
331 }
332
333
334 if (stage == CampaignTutorialStage.SHOW_SUSTAINED_BURN_DIALOG && elapsed > 5f) {
335 if (Global.getSector().getCampaignUI().showInteractionDialog(new TutorialSustainedBurnDialogPluginImpl(ancyra.getMarket()), null)) {
336 stage = CampaignTutorialStage.SHOW_SUSTAINED_BURN_HINT;
337 }
338 return;
339 }
340
341 if (stage == CampaignTutorialStage.SHOW_SUSTAINED_BURN_HINT) {
343 hints.setHint(0, "- Press %s to engage sustained burn", true, Misc.getHighlightColor(), control);
344 stage = CampaignTutorialStage.WAIT_SUSTAINED_BURN_USE;
345 elapsed = 0;
346 return;
347 }
348
349 if (stage == CampaignTutorialStage.WAIT_SUSTAINED_BURN_USE) {
350 AbilityPlugin sb = playerFleet.getAbility(Abilities.SUSTAINED_BURN);
351 float dist = Misc.getDistance(playerFleet.getLocation(), ancyra.getLocation());
352 boolean closedIn = dist < lastCheckDistToAncyra * 0.75f;
353 if ((sb != null && sb.isActive() && elapsed > 5f) || closedIn) {
355 hints.clearHints();
356 stage = CampaignTutorialStage.SHOW_GO_SLOW_DIALOG;
357 elapsed = 0f;
358 }
359 return;
360 }
361
362
363 if (stage == CampaignTutorialStage.SHOW_GO_SLOW_DIALOG &&
364 Global.getSector().getPlayerFleet().getLocation().length() < 9300) {
365 if (Global.getSector().getCampaignUI().showInteractionDialog(new TutorialGoSlowDialogPluginImpl(), null)) {
366 stage = CampaignTutorialStage.SHOW_GO_SLOW_HINT;
367 }
368 return;
369 }
370
371 if (stage == CampaignTutorialStage.SHOW_GO_SLOW_HINT) {
372 String control = Global.getSettings().getControlStringForEnumName("GO_SLOW");
373 hints.clearHints();
374 hints.setHint(0, "- Press and hold %s to move slowly through the asteroid belt", true, Misc.getHighlightColor(), control);
375 stage = CampaignTutorialStage.WAITING_TO_GO_SLOW;
376 elapsed = 0;
377 return;
378 }
379
380
381 if (stage == CampaignTutorialStage.WAITING_TO_GO_SLOW &&
382 Global.getSector().getPlayerFleet().getLocation().length() < 7850) {
383 float dist = Misc.getDistance(playerFleet.getLocation(), ancyra.getLocation());
384 boolean closedIn = dist < lastCheckDistToAncyra * 0.75f;
385 if (closedIn || (playerFleet.getInteractionTarget() != null &&
386 playerFleet.getInteractionTarget().getMarket() == ancyra.getMarket())) {
388 hints.clearHints();
389 stage = CampaignTutorialStage.SHOW_TRANSPONDER_DIALOG;
390 elapsed = 0;
391 }
392 return;
393 }
394
395
396 if (stage == CampaignTutorialStage.SHOW_TRANSPONDER_DIALOG) {
397 float dist = Misc.getDistance(playerFleet.getLocation(), ancyra.getLocation());
398 if (dist < 6000) {
399 if (Global.getSector().getCampaignUI().showInteractionDialog(new TutorialTransponderDialogPluginImpl(ancyra.getMarket()), null)) {
400 stage = CampaignTutorialStage.SHOW_TRANSPONDER_HINT;
401 }
402 }
403 return;
404 }
405
406 if (stage == CampaignTutorialStage.SHOW_TRANSPONDER_HINT) {
408 hints.setHint(0, "- Press %s twice to turn on the transponder", true, Misc.getHighlightColor(), control);
409 stage = CampaignTutorialStage.WAIT_TRANSPONDER_USE;
410 elapsed = 0;
411 return;
412 }
413
414 if (stage == CampaignTutorialStage.WAIT_TRANSPONDER_USE) {
415 AbilityPlugin transponder = playerFleet.getAbility(Abilities.TRANSPONDER);
416 if ((transponder != null && transponder.isActive())) {
417 hints.clearHints();
418 stage = CampaignTutorialStage.DONE;
419 elapsed = 0f;
420 }
421 return;
422 }
423 }
424
425
426 protected void addFleets() {
428
429 SectorEntityToken inner = system.getEntityById("galatia_jump_point_alpha");
430 SectorEntityToken fringe = system.getEntityById("galatia_jump_point_fringe");
431 SectorEntityToken derinkuyu = system.getEntityById("derinkuyu_station");
432
433 CampaignFleetAPI g1 = RogueMinerMiscFleetManager.createGuardFleet(false);
434 g1.addScript(new TutorialLeashAssignmentAI(g1, system, derinkuyu));
435 system.addEntity(g1);
436 g1.setLocation(derinkuyu.getLocation().x, derinkuyu.getLocation().y);
437
438 CampaignFleetAPI g2 = RogueMinerMiscFleetManager.createGuardFleet(Misc.isEasy());
439
440 if (!Misc.isEasy()) {
441 FleetMemberAPI member = Global.getFactory().createFleetMember(FleetMemberType.SHIP, "venture_Outdated");
442 member.setVariant(member.getVariant().clone(), false, false);
443 DModManager.setDHull(member.getVariant());
444 member.getVariant().addPermaMod(HullMods.COMP_ARMOR, false);
445 member.getVariant().addPermaMod(HullMods.FAULTY_GRID, false);
446 g2.getFleetData().addFleetMember(member);
447 }
448
449 g2.getFleetData().sort();
450 g2.addScript(new TutorialLeashAssignmentAI(g2, system, inner));
451 system.addEntity(g2);
452 g2.setLocation(inner.getLocation().x, inner.getLocation().y);
453
454 CampaignFleetAPI g3 = RogueMinerMiscFleetManager.createGuardFleet(true);
455 g3.addScript(new TutorialLeashAssignmentAI(g3, system, inner));
456 system.addEntity(g3);
457 g3.setLocation(inner.getLocation().x, inner.getLocation().y);
458
459
460 CampaignFleetAPI g4 = RogueMinerMiscFleetManager.createGuardFleet(true);
461 g4.addScript(new TutorialLeashAssignmentAI(g4, system, fringe));
462 system.addEntity(g4);
463 g4.setLocation(fringe.getLocation().x, fringe.getLocation().y);
464
465 CampaignFleetAPI g5 = RogueMinerMiscFleetManager.createGuardFleet(true);
466 g5.addScript(new TutorialLeashAssignmentAI(g5, system, fringe));
467 system.addEntity(g5);
468 g5.setLocation(fringe.getLocation().x, fringe.getLocation().y);
469
470 }
471
472
473 protected void startTutorialMissionEvent() {
474 if (intel == null) intel = new TutorialMissionIntel();
475 }
476
477 protected void addPirateFleet() {
479 pirateFleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_NO_SHIP_RECOVERY, true);
480
481 FleetMemberAPI member = Global.getFactory().createFleetMember(FleetMemberType.SHIP, "cerberus_d_pirates_Standard");
482 pirateFleet.getFleetData().addFleetMember(member);
483
484 system.addEntity(pirateFleet);
485 CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet();
486 pirateFleet.setLocation(playerFleet.getLocation().x + 750f, playerFleet.getLocation().y + 750f);
487
488 TransmitterTrapSpecial.makeFleetInterceptPlayer(pirateFleet, true, true, 100f);
489 }
490
491 protected void addSecurityDetachment() {
492 detachment = FleetFactoryV3.createEmptyFleet(Factions.HEGEMONY, FleetTypes.PATROL_MEDIUM, ancyra.getMarket());
493 detachment.setName("Security Detachment");
494 detachment.setNoFactionInName(true);
495
496 //detachment.getFleetData().addFleetMember("eagle_xiv_Elite");
497 detachment.getFleetData().addFleetMember("dominator_XIV_Elite");
498 detachment.getFleetData().addFleetMember("mora_Strike");
499 detachment.getFleetData().addFleetMember("enforcer_Escort");
500 detachment.getFleetData().addFleetMember("enforcer_Assault");
501 detachment.getFleetData().addFleetMember("lasher_CS");
502 detachment.getFleetData().addFleetMember("lasher_CS");
503
504 detachment.clearAbilities();
505 detachment.addAbility(Abilities.TRANSPONDER);
506 detachment.addAbility(Abilities.GO_DARK);
507 detachment.addAbility(Abilities.SENSOR_BURST);
508 detachment.addAbility(Abilities.EMERGENCY_BURN);
509
510 detachment.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_PATROL_FLEET, true);
511 detachment.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_NO_JUMP, true);
512
513 system.addEntity(detachment);
514 detachment.setLocation(ancyra.getLocation().x, ancyra.getLocation().y);
515
517
518 detachment.setId("tutorial_security_detachment");
519 }
520
521
522
523 public boolean isDone() {
524 return stage == CampaignTutorialStage.DONE;
525 }
526
527 public boolean runWhilePaused() {
528 return stage == CampaignTutorialStage.WAIT_CHAR_TAB;
529 }
530
531}
static SettingsAPI getSettings()
Definition Global.java:51
static FactoryAPI getFactory()
Definition Global.java:35
static SectorAPI getSector()
Definition Global.java:59
static boolean setDHull(ShipVariantAPI variant)
boolean quickSaveNag(CampaignTutorialStage nagStage, CampaignTutorialStage next, float timeout)
static CampaignFleetAPI createEmptyRogueFleet(String name, boolean withFaction)
FleetMemberAPI createFleetMember(FleetMemberType type, String variantOrWingId)
String getControlStringForAbilitySlot(int index)
String getControlStringForEnumName(String name)