1package com.fs.starfarer.api.impl.campaign.tutorial;
6import java.util.Random;
9import com.fs.starfarer.api.EveryFrameScript;
10import com.fs.starfarer.api.Global;
11import com.fs.starfarer.api.campaign.CampaignFleetAPI;
12import com.fs.starfarer.api.campaign.CargoAPI;
13import com.fs.starfarer.api.campaign.CommDirectoryEntryAPI;
14import com.fs.starfarer.api.campaign.CommDirectoryEntryAPI.EntryType;
15import com.fs.starfarer.api.campaign.FactionAPI;
16import com.fs.starfarer.api.campaign.InteractionDialogAPI;
17import com.fs.starfarer.api.campaign.PlanetAPI;
18import com.fs.starfarer.api.campaign.SectorEntityToken;
19import com.fs.starfarer.api.campaign.StarSystemAPI;
20import com.fs.starfarer.api.campaign.TextPanelAPI;
21import com.fs.starfarer.api.campaign.econ.MarketAPI;
22import com.fs.starfarer.api.campaign.rules.MemoryAPI;
23import com.fs.starfarer.api.characters.PersonAPI;
24import com.fs.starfarer.api.fleet.FleetMemberAPI;
25import com.fs.starfarer.api.fleet.FleetMemberType;
26import com.fs.starfarer.api.impl.campaign.JumpPointInteractionDialogPluginImpl;
27import com.fs.starfarer.api.impl.campaign.ids.Abilities;
28import com.fs.starfarer.api.impl.campaign.ids.Commodities;
29import com.fs.starfarer.api.impl.campaign.ids.Entities;
30import com.fs.starfarer.api.impl.campaign.ids.Factions;
31import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
32import com.fs.starfarer.api.impl.campaign.ids.Ranks;
33import com.fs.starfarer.api.impl.campaign.ids.Stats;
34import com.fs.starfarer.api.impl.campaign.ids.Submarkets;
35import com.fs.starfarer.api.impl.campaign.ids.Tags;
36import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
37import com.fs.starfarer.api.impl.campaign.intel.SystemBountyIntel;
38import com.fs.starfarer.api.impl.campaign.intel.SystemBountyManager;
39import com.fs.starfarer.api.impl.campaign.rulecmd.AddRemoveCommodity;
40import com.fs.starfarer.api.impl.campaign.submarkets.StoragePlugin;
41import com.fs.starfarer.api.loading.WeaponSlotAPI;
42import com.fs.starfarer.api.ui.HintPanelAPI;
43import com.fs.starfarer.api.ui.SectorMapAPI;
44import com.fs.starfarer.api.ui.TooltipMakerAPI;
45import com.fs.starfarer.api.util.Misc;
46import com.fs.starfarer.api.util.Misc.Token;
52 public static final String
REASON =
"tut";
54 public static enum TutorialMissionStage {
77 protected SectorEntityToken
probe;
78 protected SectorEntityToken
inner;
81 protected SectorEntityToken
relay;
90 protected TutorialMissionStage
stage = TutorialMissionStage.INIT;
109 inner =
system.getEntityById(
"galatia_jump_point_alpha");
110 fringe =
system.getEntityById(
"galatia_jump_point_fringe");
126 mainContact.getMemoryWithoutUpdate().set(
"$tut_mainContact",
true);
127 mainContact.getMemoryWithoutUpdate().set(
"$tut_eventRef",
this);
144 mainContact.setPostId(Ranks.POST_STATION_COMMANDER);
153 PlanetAPI
jangala = (PlanetAPI) corvus.getEntityById(
"jangala");
155 for (CommDirectoryEntryAPI entry :
jangala.getMarket().getCommDirectory().getEntriesCopy()) {
156 if (entry.getType() == EntryType.PERSON && entry.getEntryData() instanceof PersonAPI) {
157 PersonAPI curr = (PersonAPI) entry.getEntryData();
158 if (Ranks.POST_STATION_COMMANDER.equals(curr.getPostId())) {
174 if (
stage != TutorialMissionStage.INIT) {
176 sendUpdateIfPlayerHasIntel(
stage, text);
199 if (player ==
null)
return;
207 if (
inner ==
null)
inner =
system.getEntityById(
"galatia_jump_point_alpha");
211 if (
stage == TutorialMissionStage.GO_GET_AI_CORE) {
212 int cores = (int) player.getCargo().getCommodityQuantity(Commodities.GAMMA_CORE);
213 float distToProbe = Misc.getDistance(player.getLocation(),
probe.getLocation());
214 if (cores > 0 && (!
probe.isAlive() || distToProbe < 300)) {
218 updateStage(TutorialMissionStage.GOT_AI_CORE,
null);
222 if (
stage == TutorialMissionStage.GO_RECOVER_SHIPS) {
224 for (FleetMemberAPI member : player.getFleetData().getMembersListCopy()) {
230 for (SectorEntityToken entity :
system.getEntitiesWithTag(Tags.SALVAGEABLE)) {
231 String
id = entity.getCustomEntityType();
232 if (
id ==
null)
continue;
233 if (Entities.WRECK.equals(
id)) {
243 updateStage(TutorialMissionStage.RECOVERED_SHIPS,
null);
247 if (
stage == TutorialMissionStage.GO_STABILIZE) {
251 if (innerStable || fringeStable) {
256 updateStage(TutorialMissionStage.STABILIZED,
null);
264 public boolean callEvent(String ruleId,
final InteractionDialogAPI dialog, List<Token> params, Map<String, MemoryAPI> memoryMap) {
265 String action = params.get(0).getString(memoryMap);
268 CargoAPI cargo = playerFleet.getCargo();
270 TextPanelAPI text =
null;
271 if (dialog !=
null) text = dialog.getTextPanel();
273 if (action.equals(
"startGetData")) {
277 dataContact.getMemoryWithoutUpdate().set(
"$tut_dataContact",
true);
278 dataContact.getMemoryWithoutUpdate().set(
"$tut_eventRef",
this);
282 detachment.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_PATROL_ALLOW_TOFF,
true);
284 updateStage(TutorialMissionStage.GO_GET_DATA, text);
286 Global.
getSector().getMemoryWithoutUpdate().set(
"$tutMadeContactAtAncyra",
true);
289 }
else if (action.equals(
"endGetData")) {
293 Misc.cleanUpMissionMemory(
dataContact.getMemoryWithoutUpdate(),
"tut_");
300 }
else if (action.equals(
"goSalvage")) {
306 updateStage(TutorialMissionStage.GO_GET_AI_CORE, text);
309 }
else if (action.equals(
"goRecover")) {
316 playerFleet.getFleetData().addFleetMember(member);
317 AddRemoveCommodity.addFleetMemberGainText(member, dialog.getTextPanel());
321 updateStage(TutorialMissionStage.GO_RECOVER_SHIPS, text);
322 }
else if (action.equals(
"goStabilize")) {
333 updateStage(TutorialMissionStage.GO_STABILIZE, text);
337 }
else if (action.equals(
"pickJangalaContact")) {
340 jangala = (PlanetAPI) corvus.getEntityById(
"jangala");
344 MemoryAPI mem =
mainContact.getMemoryWithoutUpdate();
345 mem.set(
"$jangalaContactPost",
jangalaContact.getPost().toLowerCase(), 0);
346 mem.set(
"$jangalaContactLastName",
jangalaContact.getName().getLast(), 0);
348 float distLY = Misc.getDistanceLY(playerFleet.getLocationInHyperspace(),
jangala.getLocationInHyperspace());
351 float fuel = playerFleet.getLogistics().getFuelCostPerLightYear() * distLY;
352 fuel = (float) (Math.ceil(fuel / 10) * 10);
353 mem.set(
"$jangalaFuel", (
int) fuel);
354 }
else if (action.equals(
"deliverReport")) {
362 jangalaContact.getMemoryWithoutUpdate().set(
"$tut_jangalaContact",
true);
363 jangalaContact.getMemoryWithoutUpdate().set(
"$tut_eventRef",
this);
366 updateStage(TutorialMissionStage.DELIVER_REPORT, text);
372 }
else if (action.equals(
"reportDelivered")) {
384 SystemBountyManager.getInstance().addOrResetBounty(
jangala);
388 }
else if (action.equals(
"doRepairs")) {
389 for (FleetMemberAPI member : playerFleet.getFleetData().getMembersListCopy()) {
390 member.getRepairTracker().setMothballed(
false);
391 member.getStatus().repairFully();
392 float max = member.getRepairTracker().getMaxCR();
393 max = Math.max(max, .7f);
394 float curr = member.getRepairTracker().getBaseCR();
396 member.getRepairTracker().applyCREvent(max - curr,
"Repaired at dockyard");
399 }
else if (action.equals(
"printRefitHint")) {
402 String transponder =
"";
403 if (!playerFleet.isTransponderOn()) {
404 transponder =
"\n\nAlso: you'll need to re-dock with your transponder turned on to take advantage of Ancyra's facilities.";
406 dialog.getTextPanel().addPara(
"(Once this conversation is over, press %s to open the refit screen. " +
407 "After selecting a specific ship, you can press %s to %s - pick a desired loadout, " +
408 "and the ship will be automatically refitted to match it, using what weapons are available." +
410 Misc.getHighlightColor(), refit, autofit,
"\"autofit\"");
412 dialog.getTextPanel().addPara(
"In addition, you now have access to local storage at Ancyra, " +
413 "and some weapons and supplies have been placed there. To access it, click on the " +
414 "\"Storage\" button in the trade screen.)",
415 Misc.getHighlightColor(), refit, autofit,
"\"Storage\"");
428 PlanetAPI
ancyra = (PlanetAPI)
system.getEntityById(
"ancyra");
429 PlanetAPI
pontus = (PlanetAPI)
system.getEntityById(
"pontus");
430 PlanetAPI
tetra = (PlanetAPI)
system.getEntityById(
"tetra");
431 SectorEntityToken
derinkuyu =
system.getEntityById(
"derinkuyu_station");
432 SectorEntityToken
probe =
system.getEntityById(
"galatia_probe");
433 SectorEntityToken
inner =
system.getEntityById(
"galatia_jump_point_alpha");
434 SectorEntityToken
fringe =
system.getEntityById(
"galatia_jump_point_fringe");
435 SectorEntityToken
relay =
system.getEntityById(
"ancyra_relay");
437 relay.getMemoryWithoutUpdate().unset(MemFlags.OBJECTIVE_NON_FUNCTIONAL);
439 Global.
getSector().getCharacterData().addAbility(Abilities.TRANSPONDER);
441 Global.
getSector().getCharacterData().addAbility(Abilities.SENSOR_BURST);
442 Global.
getSector().getCharacterData().addAbility(Abilities.EMERGENCY_BURN);
443 Global.
getSector().getCharacterData().addAbility(Abilities.SUSTAINED_BURN);
445 Global.
getSector().getCharacterData().addAbility(Abilities.INTERDICTION_PULSE);
446 Global.
getSector().getCharacterData().addAbility(Abilities.DISTRESS_CALL);
448 FactionAPI hegemony =
Global.
getSector().getFaction(Factions.HEGEMONY);
449 if (hegemony.getRelToPlayer().getRel() < 0) {
450 hegemony.getRelToPlayer().setRel(0);
459 HintPanelAPI hints =
Global.
getSector().getCampaignUI().getHintPanel();
461 hints.clearHints(
false);
464 if (!SystemBountyManager.getInstance().isActive(
ancyra.getMarket())) {
465 SystemBountyManager.getInstance().addActive(
new SystemBountyIntel(
ancyra.getMarket()));
471 for (
int i = 0; i < 20; i++) {
476 for (CampaignFleetAPI fleet :
system.getFleets()) {
477 if (Factions.PIRATES.equals(fleet.getFaction().getId())) {
488 system.removeTag(Tags.SYSTEM_CUT_OFF_FROM_HYPER);
490 MarketAPI market =
ancyra.getMarket();
491 market.getMemoryWithoutUpdate().unset(MemFlags.MARKET_DO_NOT_INIT_COMM_LISTINGS);
492 market.getStats().getDynamic().getMod(Stats.PATROL_NUM_LIGHT_MOD).unmodifyMult(
"tut");
493 market.getStats().getDynamic().getMod(Stats.PATROL_NUM_MEDIUM_MOD).unmodifyMult(
"tut");
494 market.getStats().getDynamic().getMod(Stats.PATROL_NUM_HEAVY_MOD).unmodifyMult(
"tut");
495 market.setEconGroup(
null);
497 derinkuyu.getMarket().setEconGroup(
null);
515 StoragePlugin plugin = ((StoragePlugin)
ancyra.getMarket().getSubmarket(Submarkets.SUBMARKET_STORAGE).getPlugin());
516 plugin.setPlayerPaidToUnlock(
true);
518 CargoAPI cargo = plugin.getCargo();
521 for (FleetMemberAPI member : player.getFleetData().getMembersListCopy()) {
522 if (!member.getVariant().hasTag(Tags.SHIP_RECOVERABLE))
continue;
525 for (WeaponSlotAPI slot : member.getVariant().getHullSpec().getAllWeaponSlotsCopy()) {
528 if (weaponId !=
null) {
529 cargo.addWeapons(weaponId, 1);
536 cargo.addFighters(
"broadsword_wing", 1);
537 cargo.addFighters(
"piranha_wing", 1);
539 cargo.addSupplies(100);
544 switch (slot.getWeaponType()) {
549 switch (slot.getSlotSize()) {
550 case LARGE:
return pick(
"mark9",
"hephag",
"hellbore");
551 case MEDIUM:
return pick(
"arbalest",
"heavymortar",
"shredder");
552 case SMALL:
return pick(
"lightmg",
"lightac",
"lightmortar");
557 switch (slot.getSlotSize()) {
558 case LARGE:
return pick(
"hammerrack");
559 case MEDIUM:
return pick(
"pilum",
"annihilatorpod");
560 case SMALL:
return pick(
"harpoon",
"sabot",
"annihilator");
564 switch (slot.getSlotSize()) {
565 case LARGE:
return pick(
"autopulse",
"hil");
566 case MEDIUM:
return pick(
"miningblaster",
"gravitonbeam",
"pulselaser");
567 case SMALL:
return pick(
"mininglaser",
"taclaser",
"pdlaser",
"ioncannon");
576 public String
pick(String ...strings) {
577 return strings[
new Random().nextInt(strings.length)];
582 Color h = Misc.getHighlightColor();
583 Color g = Misc.getGrayColor();
584 Color c = getTitleColor(mode);
585 Color tc = Misc.getTextColor();
589 info.setParaSmallInsignia();
590 info.addPara(
getName(), c, 0f);
591 info.setParaFontDefault();
597 Color h = Misc.getHighlightColor();
598 Color g = Misc.getGrayColor();
599 Color c = getTitleColor(mode);
604 if (mode == ListInfoMode.IN_DESC) pad = 10f;
606 Color tc = getBulletColorForMode(mode);
615 info.addPara(
"Sneak into " +
derinkuyu.getName(), tc, pad);
616 info.addPara(
"Contact " +
dataContact.getNameString() +
" and retrieve data", tc, 0f);
622 info.addPara(
"Retrieve AI core from derelict probe beyond the orbit of Pontus", tc, pad);
627 case GO_RECOVER_SHIPS:
628 info.addPara(
"Recover at least %s ships at Tetra", pad, tc, h,
"" + 2);
630 case RECOVERED_SHIPS:
634 info.addPara(
"Stabilize the inner-system jump-point", tc, pad);
637 info.addPara(
"Return to Ancyra and report your success", tc, pad);
643 info.addPara(
"Completed", tc, pad);
651 return "Stabilize the Jump-points";
672 Color h = Misc.getHighlightColor();
673 Color g = Misc.getGrayColor();
674 Color tc = Misc.getTextColor();
680 boolean addedBullets =
false;
683 info.addPara(
"You receive a tight-beam communication from the system's main inhabited world, Ancyra.", opad);
685 info.addPara(
"The message is brief and asks you to travel there and contact " +
689 info.addPara(
"Contact " +
dataContact.getNameString() +
" at Derinkuyu Mining Station " +
690 "to acquire the raw jump-point readings.", opad);
692 info.addPara(
"Contact must be made with the transponder off as the miners of Derinkuyu have " +
693 "turned pirate and your fleet will be attacked otherwise.", opad);
698 info.addPara(
"Use %s to avoid detection, and %s to get away if you are seen.", opad, h,
699 "Go Dark",
"Emergency Burn");
703 " to deliver the jump-point data.", opad);
706 info.addPara(
"Analyzing the jump-point data requires an AI Core.", opad);
708 info.addPara(
"There's a Domain-era survey probe outside the orbit of Pontus. If salvaged, " +
709 "it's likely to yield a gamma AI core, which should be sufficient for the task.", opad);
711 info.addPara(
"Go to Pontus, head out towards the asteroid belt, and then use an " +
712 "%s to locate the probe. ", opad, h,
"Active Sensor Burst");
714 info.addPara(
"Approach the probe and salvage it to recover the gamma core.", opad);
716 info.addPara(
"It's likely that you will have to overcome some automated defenses first.", opad);
720 " to deliver the AI core.", opad);
722 case GO_RECOVER_SHIPS:
723 info.addPara(
"Go to the ship graveyard around Tetra and recover as many ships as possible.", opad);
725 info.addPara(
"Bring extra crew to man the recovered ships, and extra supplies to " +
726 " help restore their combat readiness.", opad);
728 case RECOVERED_SHIPS:
730 " at Ancyra for help with outfitting the recovered ships with weapons.", opad);
733 info.addPara(
"Use the hyperwave sequence produced by the AI core " +
734 "to stabilize the inner-system jump-point.", opad);
736 info.addPara(
"You will have to defeat the pirates guarding it first.", opad);
739 info.addPara(
"Galatia's connection with hyperspace has been restored, " +
740 "and trade fleets are once again able to enter and leave the system.", opad);
742 info.addPara(
"The Derinkuyu leadership will surely soon be toppled by rank-and-file " +
743 "miners eager to get on the right side of the law once again.", opad);
749 info.addPara(
"Make sure you have enough fuel to make the trip successfully.", opad);
752 info.addPara(
"You have delivered the report and " +
753 "your standing with the Hegemony has increased substantially.", opad);
755 info.addPara(
"Galatia's connection with hyperspace has been restored, " +
756 "and trade fleets are once again able to enter and leave the system.", opad);
772 Set<String> tags = super.getIntelTags(map);
773 tags.add(Tags.INTEL_STORY);
774 tags.add(Factions.HEGEMONY);
780 if (isSendingUpdate()) {
781 return getSoundStandardUpdate();
783 return getSoundMajorPosting();
792 case GOT_DATA:
return ancyra;
793 case GO_GET_AI_CORE:
return pontus;
794 case GOT_AI_CORE:
return ancyra;
795 case GO_RECOVER_SHIPS:
return tetra;
796 case RECOVERED_SHIPS:
return ancyra;
797 case GO_STABILIZE:
return inner;
798 case STABILIZED:
return ancyra;
799 case DELIVER_REPORT:
return jangala;
815 return IntelSortTier.TIER_2;
static SettingsAPI getSettings()
static FactoryAPI getFactory()
static SectorAPI getSector()
static final String CAN_STABILIZE
static final String UNSTABLE_KEY
static final String USE_TUTORIAL_RESPAWN
void advance(float amount)
static final String REASON
void advanceImpl(float amount)
static boolean isTutorialInProgress()
void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode)
String getMainContactPostName()
String getJangalaContactPostName()
void updateStage(TutorialMissionStage stage, TextPanelAPI text)
String getCommMessageSound()
PersonAPI getMainContact()
static final String TUT_STAGE
SectorEntityToken detachment
void createSmallDescription(TooltipMakerAPI info, float width, float height)
static void endGalatiaPortionOfMission(boolean withStipend, boolean didTutorial)
String pick(String ...strings)
IntelSortTier getSortTier()
SectorEntityToken derinkuyu
Set< String > getIntelTags(SectorMapAPI map)
static PersonAPI getJangalaContact()
String getSmallDescriptionTitle()
static PersonAPI createMainContact(PlanetAPI ancyra)
TutorialMissionStage stage
SectorEntityToken getMapLocation(SectorMapAPI map)
boolean callEvent(String ruleId, final InteractionDialogAPI dialog, List< Token > params, Map< String, MemoryAPI > memoryMap)
String getWeaponForSlot(WeaponSlotAPI slot)
void addWeaponsToStorage()
boolean canTurnImportantOff()
FactionAPI getFactionForUIColors()
void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode)
FleetMemberAPI createFleetMember(FleetMemberType type, String variantOrWingId)
String getSpriteName(String category, String id)
String getControlStringForEnumName(String name)