001package com.fs.starfarer.api.impl.campaign.missions.academy;
002
003import java.awt.Color;
004import java.util.ArrayList;
005import java.util.Arrays;
006import java.util.List;
007import java.util.Map;
008
009import org.lwjgl.util.vector.Vector2f;
010
011import com.fs.starfarer.api.Global;
012import com.fs.starfarer.api.campaign.BattleAPI;
013import com.fs.starfarer.api.campaign.CampaignEventListener.FleetDespawnReason;
014import com.fs.starfarer.api.campaign.CampaignFleetAPI;
015import com.fs.starfarer.api.campaign.CargoAPI;
016import com.fs.starfarer.api.campaign.CargoAPI.CargoItemType;
017import com.fs.starfarer.api.campaign.CargoStackAPI;
018import com.fs.starfarer.api.campaign.InteractionDialogAPI;
019import com.fs.starfarer.api.campaign.LocationAPI;
020import com.fs.starfarer.api.campaign.SectorEntityToken;
021import com.fs.starfarer.api.campaign.SpecialItemData;
022import com.fs.starfarer.api.campaign.StarSystemAPI;
023import com.fs.starfarer.api.campaign.TextPanelAPI;
024import com.fs.starfarer.api.campaign.econ.MarketAPI;
025import com.fs.starfarer.api.campaign.listeners.BaseFleetEventListener;
026import com.fs.starfarer.api.campaign.listeners.CurrentLocationChangedListener;
027import com.fs.starfarer.api.campaign.rules.MemoryAPI;
028import com.fs.starfarer.api.characters.PersonAPI;
029import com.fs.starfarer.api.impl.campaign.DerelictShipEntityPlugin.DerelictShipData;
030import com.fs.starfarer.api.impl.campaign.GateEntityPlugin;
031import com.fs.starfarer.api.impl.campaign.ids.Entities;
032import com.fs.starfarer.api.impl.campaign.ids.Factions;
033import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
034import com.fs.starfarer.api.impl.campaign.ids.Items;
035import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
036import com.fs.starfarer.api.impl.campaign.ids.People;
037import com.fs.starfarer.api.impl.campaign.ids.Ranks;
038import com.fs.starfarer.api.impl.campaign.ids.Tags;
039import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator;
040import com.fs.starfarer.api.impl.campaign.procgen.themes.SalvageSpecialAssigner.ShipRecoverySpecialCreator;
041import com.fs.starfarer.api.impl.campaign.rulecmd.AddRemoveCommodity;
042import com.fs.starfarer.api.impl.campaign.rulecmd.missions.GateCMD;
043import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.ShipRecoverySpecial.PerShipData;
044import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.ShipRecoverySpecial.ShipCondition;
045import com.fs.starfarer.api.ui.TooltipMakerAPI;
046import com.fs.starfarer.api.util.Misc;
047import com.fs.starfarer.api.util.Misc.Token;
048import com.fs.starfarer.api.util.WeightedRandomPicker;
049
050public class GAAtTheGates extends GABaseMission implements CurrentLocationChangedListener {
051
052        public static String SHOW_GATE_SCAN_COUNT = "show_gate_scan_count";
053        
054        public static enum Stage {
055                TALK_TO_COUREUSE,
056                TALK_TO_YARIBAY,
057                TALK_TO_HEGEMON,
058                MEET_DAUD,
059                DO_SCANS,
060                RETURN_WITH_DEAL_AND_SCANS,
061                FIRST_JANUS_EXPERIMENT,
062                FIRST_JANUS_RESULTS,
063                COUREUSE_MISSION,
064                TALK_TO_KANTA,
065                FINDING_LOKE,
066                RETURN_TO_KANTA,
067                GO_TO_MAGEC_GATE,
068                ZAL_TO_GALATIA,
069                COMPLETED,
070        }
071        
072        protected PersonAPI baird;
073        protected PersonAPI coureuse;
074        protected PersonAPI gargoyle;
075        
076        protected PersonAPI horus_yaribay;
077        protected PersonAPI siyavong;
078        protected MarketAPI kazeron;
079        //protected StarSystemAPI magec;
080        protected SectorEntityToken magecGate;
081        protected SectorEntityToken galatiaGate;
082        
083        protected PersonAPI daud;
084        protected MarketAPI chicomoztoc;
085        
086        protected PersonAPI kanta;
087        protected PersonAPI loke;
088        protected PersonAPI cotton;
089        protected PersonAPI zal;
090        protected PersonAPI kantasDenStationCommander;
091        protected MarketAPI kantasDen;
092        protected MarketAPI epiphany;
093        
094        protected SectorEntityToken encounterGateHegemony;
095        protected CampaignFleetAPI encounterHegemonyFleet;
096        
097        protected SectorEntityToken encounterGateLuddic;
098        protected CampaignFleetAPI encounterLuddicFleet;
099        
100        protected SectorEntityToken encounterGateTT;
101        protected CampaignFleetAPI encounterTTFleet;
102        protected int ttScanCost;
103        protected int pirateScanCost;
104        protected int coureuseCredits;
105        
106        protected SectorEntityToken encounterGatePirate;
107        protected CampaignFleetAPI encounterPirateFleet;
108        
109        //protected SectorEntityToken encounterGateAlarm;
110        //protected CampaignFleetAPI encounterHegemonyFleet;
111        
112        protected List<ScanEncounterVariation> scanEncounterVariations;
113        
114        public static float SYSTEM_NO_GATE_ENCOUNTER_CHANCE = 0.2f;
115        public static float FACTION_GATE_ENCOUNTER_CHANCE = 0.5f;
116
117        public static enum ScanEncounterVariation {
118                HEGEMONY,
119                TRITACHYON,
120                LUDDIC,
121                PIRATE,
122                DERELICT,
123                JAMMER,
124                SCAVENGER,
125                PATHER,
126                ALARM,
127        }
128        
129        public static float KANTA_RAID_DIFFICULTY = 1000f;
130        public static float COTTON_RAID_DIFFICULTY = 1000f;
131        
132        @Override
133        protected boolean create(MarketAPI createdAt, boolean barEvent) {
134                // if already accepted by the player, abort
135                if (!setGlobalReference("$gaATG_ref", "$gaATG_inProgress")) {
136                        return false;
137                }
138                
139                baird = getImportantPerson(People.BAIRD);
140                if (baird == null) return false;
141                
142                coureuse = getImportantPerson(People.COUREUSE);
143                if (coureuse == null) return false;
144                
145                gargoyle = getImportantPerson(People.GARGOYLE);
146                if (gargoyle == null) return false;
147                
148                horus_yaribay = getImportantPerson(People.HORUS_YARIBAY);
149                if (horus_yaribay == null) return false;
150                
151                siyavong = getImportantPerson(People.SIYAVONG);
152                if (siyavong == null) return false;
153                
154                daud = getImportantPerson(People.DAUD);
155                if (daud == null) return false;
156                
157                kanta = getImportantPerson(People.KANTA);
158                if (kanta == null) return false;
159                
160                loke = getImportantPerson(People.CLONE_LOKE);
161                if (loke == null) return false;
162                
163                cotton = getImportantPerson(People.COTTON);
164                if (cotton == null) return false;
165                
166                zal = getImportantPerson(People.ZAL);
167                if (zal == null) return false;
168                
169                kazeron = Global.getSector().getEconomy().getMarket("kazeron");
170                if (kazeron == null) return false;
171                
172                chicomoztoc = Global.getSector().getEconomy().getMarket("chicomoztoc");
173                if (chicomoztoc == null) return false;
174                
175                kantasDen = Global.getSector().getEconomy().getMarket("kantas_den");
176                if (kantasDen == null) return false;
177                
178                kantasDenStationCommander = getPersonAtMarketPost(kantasDen, Ranks.POST_STATION_COMMANDER);
179                if (kantasDenStationCommander == null) return false;
180                
181                epiphany = Global.getSector().getEconomy().getMarket("epiphany");
182                if (epiphany == null) return false;
183                
184                // find the Magec gate!
185                StarSystemAPI magec = kantasDen.getStarSystem();
186                for (SectorEntityToken curr : magec.getCustomEntitiesWithTag(Tags.GATE)) {
187                        //if (GateEntityPlugin.isScanned(curr)) continue;
188                        //if (GateEntityPlugin.isActive(curr)) continue;
189                        // plus whatever other checks are needed
190                        magecGate = curr;
191                        break;
192                }
193                if (magecGate == null) return false;
194                
195                // and Galatia Gate
196                StarSystemAPI galatia =  Global.getSector().getStarSystem("galatia");
197                for (SectorEntityToken curr : galatia.getCustomEntitiesWithTag(Tags.GATE)) {
198                        //if (GateEntityPlugin.isScanned(curr)) continue;
199                        //if (GateEntityPlugin.isActive(curr)) continue;
200                        // plus whatever other checks are needed
201                        galatiaGate = curr;
202                        break;
203                }
204                if (galatiaGate == null) return false;
205
206                setName("At The Gates");
207                setRepFactionChangesNone();
208                setRepPersonChangesNone();
209                
210                // set up our fleet spawns!
211                // Siyavong first
212                // Siyavong gets a patrol fleet to intercept player
213                //beginWithinHyperspaceRangeTrigger(kazeron, 1f, false, Stage.TALK_TO_HEGEMON);
214                //triggerCreateFleet(FleetSize.SMALL, FleetQuality.VERY_LOW, Factions.LUDDIC_PATH, FleetTypes.PATROL_SMALL, probeSystem);
215                
216                beginStageTrigger(Stage.TALK_TO_HEGEMON);
217                triggerCreateFleet(FleetSize.MEDIUM, FleetQuality.HIGHER, Factions.PERSEAN, FleetTypes.PATROL_MEDIUM, kazeron.getStarSystem());
218                triggerSetFleetOfficers(OfficerNum.MORE, OfficerQuality.HIGHER);
219                triggerMakeNonHostile();
220                triggerMakeFleetIgnoreOtherFleetsExceptPlayer(); // don't go chasing others, please.
221                triggerFleetAllowLongPursuit();
222                triggerSetFleetAlwaysPursue();
223                triggerFleetMakeFaster(true, 1, true);
224                
225                triggerPickLocationAroundEntity(kazeron.getStarSystem().getHyperspaceAnchor(), 250f);
226                triggerSpawnFleetAtPickedLocation("$gaATG_siyavongFleet", null);
227                //triggerSpawnFleetAtPickedLocation("$gaATG_pirateScanFleet", null);
228                
229                //triggerPickLocationTowardsEntity(kazeron.getStarSystem().getHyperspaceAnchor(), 90f, getUnits(1f));
230                triggerSetFleetMissionRef("$gaATG_ref"); // so they can be made unimportant
231                triggerOrderFleetInterceptPlayer();
232                triggerOrderFleetEBurn(1f);
233                triggerFleetMakeImportant(null, Stage.TALK_TO_HEGEMON);
234                endTrigger();
235
236                
237                // For the big showdown w/ Kanta
238                List<SectorEntityToken> jumpPoints = magecGate.getStarSystem().getJumpPoints();
239                for (SectorEntityToken point : jumpPoints) {
240                        spawnKantaVengeanceFleetPirateScout(point);
241                        spawnKantaVengeanceFleetPirateScout(point); // 2 scouts per.
242                        spawnKantaVengeanceFleetPirateArmada(point);
243                        spawnKantaVengeanceFleetMerc(point);
244                }
245                spawnKantaVengeanceFleetPirateArmada(kantasDen.getPrimaryEntity());
246                
247                //scanEncounterVariations = Arrays.asList(ScanEncounterVariation.values()); // NO. Bad list.
248                scanEncounterVariations = new ArrayList<ScanEncounterVariation>(Arrays.asList(ScanEncounterVariation.values()));
249                
250                ttScanCost = genRoundNumber(20000, 30000); // bribe for TT scanning fleet
251                pirateScanCost = genRoundNumber(10000, 20000); // bribe for Pirate gate-blockers
252                coureuseCredits = genRoundNumber(10000, 20000); // Coureuse's pathetic savings
253
254                setStoryMission();
255                
256                setStartingStage(Stage.TALK_TO_COUREUSE);
257                addSuccessStages(Stage.COMPLETED);
258                
259                makeImportant(coureuse, null, Stage.TALK_TO_COUREUSE);
260                makeImportant(horus_yaribay, null, Stage.TALK_TO_YARIBAY);
261                makeImportant(daud, null, Stage.TALK_TO_HEGEMON);
262                makeImportant(chicomoztoc, null, Stage.MEET_DAUD);
263                makeImportant(baird, null, Stage.RETURN_WITH_DEAL_AND_SCANS);
264                makeImportant(baird, null, Stage.FIRST_JANUS_RESULTS);
265                makeImportant(coureuse, null, Stage.COUREUSE_MISSION);
266                makeImportant(kantasDen, "$gaATG_talkToKanta", Stage.TALK_TO_KANTA);
267                makeImportant(epiphany, "$gaATG_findingLoke", Stage.FINDING_LOKE);
268                makeImportant(kanta.getMarket(), null, Stage.RETURN_TO_KANTA);
269                makeImportant(magecGate, null, Stage.GO_TO_MAGEC_GATE);
270                makeImportant(baird.getMarket(), null, Stage.ZAL_TO_GALATIA);
271                
272                //setStageOnGlobalFlag(Stage.TALK_TO_COUREUSE, "$gaATG_goTalkToCoureuse");
273                connectWithGlobalFlag(Stage.TALK_TO_COUREUSE, Stage.TALK_TO_YARIBAY, "$gaATG_goTalkToYaribay");
274                connectWithGlobalFlag(Stage.TALK_TO_YARIBAY, Stage.TALK_TO_HEGEMON, "$gaATG_goTalkToDaud");
275                connectWithGlobalFlag(Stage.TALK_TO_HEGEMON, Stage.MEET_DAUD, "$gaATG_goToDaudMeeting");
276                connectWithGlobalFlag(Stage.MEET_DAUD, Stage.DO_SCANS, "$gaATG_gotDaudDeal");
277                connectWithGlobalFlag(Stage.DO_SCANS, Stage.RETURN_WITH_DEAL_AND_SCANS, "$gaATG_scannedSixGates");
278                
279                setStageOnGlobalFlag(Stage.FIRST_JANUS_EXPERIMENT, "$gaATG_useJanusPrototype");
280                setStageOnGlobalFlag(Stage.FIRST_JANUS_RESULTS, "$gaATG_firstJanusResults");
281                setStageOnGlobalFlag(Stage.COUREUSE_MISSION, "$gaATG_getMissionFromCoureuse");
282                setStageOnGlobalFlag(Stage.TALK_TO_KANTA, "$gaATG_gotKantaToken");
283                setStageOnGlobalFlag(Stage.FINDING_LOKE, "$gaATG_findingLoke");
284                setStageOnGlobalFlag(Stage.RETURN_TO_KANTA, "$gaATG_foundLoke");
285                setStageOnGlobalFlag(Stage.GO_TO_MAGEC_GATE, "$gaATG_foundZal");
286                
287                connectWithEnteredLocation(Stage.GO_TO_MAGEC_GATE, Stage.ZAL_TO_GALATIA, galatia);
288                //setStageOnGlobalFlag(Stage.ZAL_TO_GALATIA, "$gaATG_zalToGalatia");
289                setStageOnGlobalFlag(Stage.COMPLETED, "$gaATG_completed");
290                
291                // so they can decivilize etc but not before this and any other story missions using these are completed
292                beginStageTrigger(Stage.COMPLETED);
293                triggerSetGlobalMemoryValue("$gaATG_missionCompleted", true);
294                triggerMakeNonStoryCritical(kazeron, chicomoztoc, epiphany, siyavong.getMarket(), kanta.getMarket());
295                endTrigger();
296                
297                return true;
298        }
299        @Override
300        protected boolean callAction(String action, String ruleId, InteractionDialogAPI dialog, List<Token> params,
301                                                                Map<String, MemoryAPI> memoryMap) {
302                
303                // $global.numGatesScanned tracks this too; maybe not ideal to dupe the var, but yolo -dgb
304                if ("scannedGateForCoureuse".equals(action)) {
305                        sendUpdate(SHOW_GATE_SCAN_COUNT, dialog.getTextPanel());
306                        return true;
307                }
308                else if ("setGalatiaGateScanned".equals(action))
309                {
310                        galatiaGate.getMemoryWithoutUpdate().set(GateEntityPlugin.GATE_SCANNED, true);
311                        GateCMD.notifyScanned(galatiaGate);
312                        return true;
313                }
314                else if ("clearedHegemonyGate".equals(action)) {
315                        encounterGateHegemony.getMemoryWithoutUpdate().unset("$GAATGhegemonyScanFleet");
316                        return true;
317                }
318                else if ("clearedHegemonyGateSendScans".equals(action)) {
319                        encounterGateHegemony.getMemoryWithoutUpdate().set("$GAATGhegSendScan", true);
320                        encounterGateHegemony.getMemoryWithoutUpdate().unset("$GAATGhegemonyScanFleet");
321                        encounterHegemonyFleet.getMemoryWithoutUpdate().unset("$youDoTheScan");
322                        encounterHegemonyFleet.getMemoryWithoutUpdate().set("$youDidTheScan", true);
323                        return true;
324                }
325                else if ("sentHegemonyScan".equals(action)) {
326                        encounterHegemonyFleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_IGNORE_PLAYER_COMMS, true);
327                        return true;
328                }
329                else if ("clearedLuddicGate".equals(action)) {
330                        encounterGateLuddic.getMemoryWithoutUpdate().unset("$GAATGluddicScanGate");
331                        return true;
332                }
333                else if ("luddicGateFleetMoveAway".equals(action)) {
334                        encounterGateLuddic.getMemoryWithoutUpdate().unset("$GAATGluddicScanGate");
335                        encounterGateLuddic.getMemoryWithoutUpdate().set("$GAATGluddicPostScan", true);
336                        encounterLuddicFleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_AVOID_PLAYER_SLOWLY, true);
337                        encounterLuddicFleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_IGNORE_PLAYER_COMMS, true);
338                        return true;
339                }
340                else if ("luddicGateFleetMoveBack".equals(action)) {
341                        //encounterGateLuddic.getMemoryWithoutUpdate().unset("$GAATGluddicScanGate");
342                        encounterLuddicFleet.getMemoryWithoutUpdate().unset(MemFlags.MEMORY_KEY_AVOID_PLAYER_SLOWLY);
343                        encounterLuddicFleet.getMemoryWithoutUpdate().unset(MemFlags.MEMORY_KEY_IGNORE_PLAYER_COMMS);
344                        encounterLuddicFleet.getMemoryWithoutUpdate().set("$resumedVigil", true);
345                        return true;
346                }
347                
348                else if ("boughtTTscan".equals(action)) {
349                        encounterGateTT.getMemoryWithoutUpdate().unset("$GAATGttScanGate");
350                        encounterGateTT.getMemoryWithoutUpdate().set(GateEntityPlugin.GATE_SCANNED, true);
351                        GateCMD.notifyScanned(encounterGateTT);
352                        sendUpdate(SHOW_GATE_SCAN_COUNT, dialog.getTextPanel());
353                        return true;
354                }
355                else if ("clearedTTGate".equals(action)) {
356                        encounterGateTT.getMemoryWithoutUpdate().unset("$GAATGttScanGate");
357                        return true;
358                }
359                else if ("clearedPirateGate".equals(action)) {
360                        encounterGatePirate.getMemoryWithoutUpdate().unset("$GAATGpirateScanGate");
361                        encounterPirateFleet.getMemoryWithoutUpdate().unset("$gaATG_pirateScanFleet");
362                        return true;
363                }
364                else if ("doZalEscape".equals(action)) {
365                        Global.getSector().layInCourseFor(magecGate);
366                        galatiaGate.getMemoryWithoutUpdate().set(GateEntityPlugin.GATE_SCANNED, true);
367                        return true;
368                }
369                else if ("giveJanusDevice".equals(action)) {
370                        CargoAPI cargo = Global.getSector().getPlayerFleet().getCargo();
371                        cargo.addSpecial(new SpecialItemData(Items.JANUS, null), 1);
372                        CargoStackAPI stack = Global.getFactory().createCargoStack(CargoItemType.SPECIAL, new SpecialItemData(Items.JANUS, null), null);
373                        AddRemoveCommodity.addStackGainText(stack, dialog.getTextPanel());
374                        return true;
375                }
376                else if ("endMissionCleanup".equals(action)){
377                        
378                        epiphany.getMemoryWithoutUpdate().unset("$askedForKidnapperCotton");
379                        epiphany.getMemoryWithoutUpdate().unset("$offeredBribeForCotton");
380                        epiphany.getMemoryWithoutUpdate().unset("$setUpCottonMeeting");
381                        epiphany.getMemoryWithoutUpdate().unset("$askedBarCotton");
382                        epiphany.getMemoryWithoutUpdate().unset("$setUpCottonMeeting");
383                        
384                        //magecGate.getMemoryWithoutUpdate().unset("$visitedWithZal");
385                        return true;
386                }
387                else if ("zalCommHack".equals(action)){
388                        
389                        TextPanelAPI text = dialog.getTextPanel();
390                        text.setFontVictor();
391                        Color red = Misc.getNegativeHighlightColor();
392                        text.addParagraph("COMM FEED 0 INTERRUPTED \nCOMM FEED 1 INTERRUPTED", red);
393                        //text.setFontSmallInsignia();
394                        text.setFontInsignia();
395                        return true;
396                }
397                else if ("zalMinesHack".equals(action))
398                {
399                        Global.getSoundPlayer().playSound("hit_heavy", 1, 1, Global.getSoundPlayer().getListenerPos(), new Vector2f());
400                        return true;
401                }
402                else if ("giveJanusDevice".equals(action))
403                {
404                        CargoAPI cargo = Global.getSector().getPlayerFleet().getCargo();
405                        cargo.addSpecial(new SpecialItemData(Items.JANUS, null), 1);
406                        CargoStackAPI stack = Global.getFactory().createCargoStack(CargoItemType.SPECIAL, new SpecialItemData(Items.JANUS, null), null);
407                        AddRemoveCommodity.addStackGainText(stack, dialog.getTextPanel());
408                        return true;
409                }
410                //else if ("addYaribayContact".equals(action))
411                //{
412                //      ContactIntel.addPotentialContact(horus_yaribay, kazeron, dialog.getTextPanel());
413                //      //setPersonIsPotentialContactOnSuccess(horus_yaribay, 1f); // probability = 1f, otherwise it's only a chance (default 0.25)
414                //      return true;
415                //}
416                
417                return false;
418        }
419        
420        protected void updateInteractionDataImpl() {
421                set("$gaATG_stage", getCurrentStage());
422                set("$gaATG_gatesScanned", GateEntityPlugin.getNumGatesScanned());
423                set("$gaATG_ttScanCost", Misc.getWithDGS(ttScanCost));
424                set("$gaATG_pirateScanCost", Misc.getWithDGS(pirateScanCost));
425                set("$gaATG_coureuseCredits", Misc.getWithDGS(coureuseCredits));
426                
427                set("$gaATG_kantaRaidDifficulty", KANTA_RAID_DIFFICULTY);
428                set("$gaATG_cottonRaidDifficulty", COTTON_RAID_DIFFICULTY);
429                set("$kantasDenStationCommander", kantasDenStationCommander.getId()); // kantasDenStationCommander);
430        }
431        
432        @Override
433        public void advance(float amount) {
434                super.advance(amount);
435                if ( currentStage == Stage.TALK_TO_COUREUSE || 
436                                 currentStage == Stage.TALK_TO_YARIBAY ||
437                                 currentStage == Stage.TALK_TO_HEGEMON || 
438                                 currentStage == Stage.DO_SCANS) { 
439                        int scanned = GateEntityPlugin.getNumGatesScanned();
440                        if (scanned >= 6 && 
441                                        !Global.getSector().getMemoryWithoutUpdate().contains("$gaATG_scannedSixGates")) { // failsafe; apparently possible to not have this be set?
442                                Global.getSector().getMemoryWithoutUpdate().set("$gaATG_scannedSixGates", true);
443                                checkStageChangesAndTriggers(null, null);
444                        }
445                }
446        }
447        
448        @Override
449        public void addDescriptionForNonEndStage(TooltipMakerAPI info, float width, float height) {
450                
451                
452                
453                float opad = 10f;
454                Color h = Misc.getHighlightColor();
455                
456                // Contact the High Hegemon
457                //if (currentStage == Stage.TALK_TO_COUREUSE || 
458                if (            currentStage == Stage.TALK_TO_YARIBAY ) {
459                        info.addPara("Contact Horus Yaribay to get envoy credentials so you can contact High Hegemon Daud.", opad);
460                        //info.addImages(width, 128, opad, opad, horus_yaribay.getPortraitSprite(),horus_yaribay.getFaction().getCrest());
461                        addStandardMarketDesc("Gens Yaribay is based " + kazeron.getOnOrAt(), kazeron, info, opad);
462                } 
463                else if (currentStage == Stage.TALK_TO_HEGEMON)
464                {
465                        info.addPara("Set up a private meeting with High Hegemon Baikal Daud and get him to accept the deal with Provost Baird.", opad);
466                        //info.addImages(width, 128, opad, opad, daud.getPortraitSprite(),daud.getFaction().getCrest());
467                        info.addPara("Optional: provide Daud with encrypted Yaribay comm codes.", opad);
468                        addStandardMarketDesc("The High Hegemon's office is based " + chicomoztoc.getOnOrAt(), chicomoztoc, info, opad);
469                }
470                else if (currentStage == Stage.MEET_DAUD)
471                {
472                        info.addPara("Meet with High Hegemon Baikal Daud on a shipyard orbiting Chicomoztoc.", opad);
473                        //info.addImages(width, 128, opad, opad, daud.getPortraitSprite(),daud.getFaction().getCrest());
474                        info.addPara("Optional: provide Daud with encrypted Yaribay comm codes.", opad);
475                        addStandardMarketDesc("The High Hegemon's office is based " + chicomoztoc.getOnOrAt(), chicomoztoc, info, opad);
476                }
477                else if (currentStage == Stage.RETURN_WITH_DEAL_AND_SCANS)
478                {
479                        info.addPara("You've arranged a deal between High Hegemon Daud and Provost Baird which allows "
480                                        + "the Galatia Academy to resume overt research on Gate technology.",opad);
481                }
482
483                
484                // Scan six Gates
485                if ( currentStage == Stage.TALK_TO_COUREUSE)
486                {
487                        info.addPara("Get the Gate scanning instrument from Academician Coureuse.", opad);
488                }
489                else if ( currentStage == Stage.TALK_TO_COUREUSE || 
490                         currentStage == Stage.TALK_TO_YARIBAY ||
491                         currentStage == Stage.TALK_TO_HEGEMON || 
492                         currentStage == Stage.DO_SCANS &&
493                                         GateEntityPlugin.getNumGatesScanned() < 6 )
494                {
495                        info.addPara("Scan six Gates with the instruments provided by Academician Coureuse.", opad);
496                        info.addPara("%s Gates scanned", opad, Misc.getHighlightColor(), 
497                                        "" + GateEntityPlugin.getNumGatesScanned() + " / 6");
498                        unindent(info);
499                        //info.addImage(Global.getSettings().getSpriteName("illustrations", "dead_gate"), width, opad);
500                        bullet(info);
501                }
502                
503                // Everything else in the mission arc.
504                if (currentStage == Stage.RETURN_WITH_DEAL_AND_SCANS)
505                {
506                        info.addPara("Return to the Galatia Academy with the six completed Gate scans.", opad);
507                }
508                else if (currentStage == Stage.FIRST_JANUS_EXPERIMENT)
509                {
510                        info.addPara("Use the prototype Janus Device on a Gate in an uninhabited system outside of the "
511                                        + "Core worlds.", opad);
512                }
513                else if (currentStage == Stage.FIRST_JANUS_RESULTS)
514                {
515                        info.addPara("Return to the Galatia Academy to report the results of the first Janus Prototype "
516                                        + "experiment.", opad);
517                }
518                else if (currentStage == Stage.COUREUSE_MISSION)
519                {
520                        info.addPara("Contact Academician Scylla Coureuse about what she needs you to do.", opad);
521                }
522                else if (currentStage == Stage.TALK_TO_KANTA)
523                {
524                        info.addPara("Use Gargoyle's token to arrange a meeting with Warlord Kanta in the Magec system - or find some other way to extract Zal.", opad);
525                }
526                else if (currentStage == Stage.FINDING_LOKE)
527                {
528                        info.addPara("Find and extract the clone of Loke from the Pather kidnappers.", opad);
529                }
530                else if (currentStage == Stage.RETURN_TO_KANTA)
531                {
532                        info.addPara("Return Clone Loke to Warlord Kanta.", opad);
533                        //info.addImages(width, 128, opad, opad, kanta.getPortraitSprite(), kanta.getFaction().getCrest());
534                }
535                else if (currentStage == Stage.GO_TO_MAGEC_GATE)
536                {
537                        info.addPara("Go to the Magec Gate and jump to Galatia.", opad);
538                }
539                else if (currentStage == Stage.ZAL_TO_GALATIA)
540                {
541                        info.addPara("Return to the Galatia Academy with Elissa Zal and the working Janus Device.", opad);
542                }
543        }
544        
545        @Override
546        protected boolean shouldSendUpdateForStage(Object id) {
547                if (getCurrentStage() == Stage.DO_SCANS && GateEntityPlugin.getNumGatesScanned() >= 6) {
548                        return false; // going straight to RETURN_WITH_DEAL_AND_SCANS
549                }
550                return super.shouldSendUpdateForStage(id);
551        }
552        @Override
553        public boolean addNextStepText(TooltipMakerAPI info, Color tc, float pad) {
554
555                Color h = Misc.getHighlightColor();
556                
557                if (getListInfoParam() == SHOW_GATE_SCAN_COUNT) {
558//                      if (GateEntityPlugin.getNumGatesScanned() >= 6)
559//                      {
560//                              // We don't want to end up writing 7/6 if the player gets excitable about scanning before talking to Daud -dgb
561                                // I kind of think we do - it looks confusing if they scan but the number doesn't go up
562                                // and in most cases there's no notification, if it's over 6, anyway -am
563//                              info.addPara("%s Gates scanned", pad, tc, Misc.getHighlightColor(), "6 / 6");
564//                      }
565//                      else
566//                      {
567                                info.addPara("%s Gates scanned", pad, tc, Misc.getHighlightColor(), 
568                                                "" + GateEntityPlugin.getNumGatesScanned() + " / 6");
569//                      }
570                        return true;
571                        
572                }
573                
574                // Scanning equipment
575                // Do this first because the player should talk to Coureuse while still at the GA -dgb
576                if (currentStage == Stage.TALK_TO_COUREUSE)
577                {
578                        info.addPara("Get the Gate scanning device from Scylla Coureuse", tc, pad);
579                        pad = 0; // the padding passed in is just for before the first item
580                }
581                
582                // High Hegemon contact
583                if (currentStage == Stage.TALK_TO_COUREUSE || 
584                                currentStage == Stage.TALK_TO_YARIBAY ) {
585                        info.addPara("Contact Horus Yaribay on Kazeron to get envoy credentials", tc, pad);
586                        
587                        pad = 0;
588                } 
589                else if (currentStage == Stage.TALK_TO_HEGEMON)
590                {
591                        info.addPara("Horus Yaribay has provided you with official envoy credentials to set up a private meeting with High "
592                                        + "Hegemon Baikal Daud", tc, pad);
593                        //info.addPara("Optional: provide Daud with encrypted Yaribay comm codes.", opad);
594                        //info.addPara("Use the gens Yaribay envoy credentials to set up a private meeting with High "
595                        //              + "Hegemon Baikal Daud. Get him to accept a new arrangement with Provost Baird.", opad);
596                        pad = 0;
597                }
598                else if (currentStage == Stage.MEET_DAUD)
599                {
600                        info.addPara("Meet with the High Hegemon in Chicomoztoc orbit and secure Baird's deal", tc, pad);
601                        pad = 0;
602                }
603                else if (currentStage == Stage.RETURN_WITH_DEAL_AND_SCANS)
604                {
605                        info.addPara("Return to Provost Baird at the Galatia Academy with news of the deal made with "
606                                        + "High Hegemon Daud", tc, pad);
607                        pad = 0;
608                }
609                
610                // ... Then scan six Gates; this appears below Yaribay/Daud stuff as it's the next objective -dgb       
611                if (    (       currentStage == Stage.TALK_TO_YARIBAY ||
612                                        currentStage == Stage.TALK_TO_HEGEMON || 
613                                        currentStage == Stage.MEET_DAUD || 
614                                        currentStage == Stage.DO_SCANS)
615                                && GateEntityPlugin.getNumGatesScanned() < 6) 
616                        // Though this last point is implicit in the Stage, perhaps? Maybe not though, 
617                        // because you can scan all the gates while doing the Hegemon stuff. So keep this. -dgb
618                {
619                        info.addPara("Scan six Gates with the instruments provided by Academician Coureuse", tc, pad);
620                        pad = 0;
621                }
622
623                if (currentStage == Stage.RETURN_WITH_DEAL_AND_SCANS)
624                {
625                        info.addPara("Return to the Galatia Academy with the six completed Gate scans", tc, pad);
626                }
627                else if (currentStage == Stage.FIRST_JANUS_EXPERIMENT)
628                {
629                        info.addPara("Use the prototype Janus Device on a Gate in an uninhabited system outside of the "
630                                        + "Core worlds", tc, pad);
631                }
632                else if (currentStage == Stage.FIRST_JANUS_RESULTS)
633                {
634                        info.addPara("Return to the Galatia Academy to report the results of the first Janus Prototype "
635                                        + "experiment", tc, pad);
636                }
637                else if (currentStage == Stage.COUREUSE_MISSION)
638                {
639                        info.addPara("Contact Academician Scylla Coureuse about what she needs you to do", tc, pad);
640                }
641                else if (currentStage == Stage.TALK_TO_KANTA)
642                {
643                        info.addPara("Use Gargoyle's token to arrange a meeting with Warlord Kanta in the Magec system - or find some other way to extract Zal", tc, pad);
644                }
645                else if (currentStage == Stage.FINDING_LOKE)
646                {
647                        info.addPara("Find and extract the clone of Loke from the Pather kidnappers", tc, pad);
648                }
649                else if (currentStage == Stage.RETURN_TO_KANTA)
650                {
651                        info.addPara("Return Clone Loke to Warlord Kanta", tc, pad);
652                }
653                else if (currentStage == Stage.GO_TO_MAGEC_GATE)
654                {
655                        info.addPara("Go to the Magec Gate", tc, pad);
656                }
657                else if (currentStage == Stage.ZAL_TO_GALATIA)
658                {
659                        info.addPara("Return to the Galatia Academy with Elissa Zal and the working Janus Device", tc, pad);
660                }
661                
662                return false;
663        }
664        
665        @Override
666        public String getBaseName() {
667                return "At The Gates";
668        }
669
670        @Override
671        public String getPostfixForState() {
672                if (startingStage != null) {
673                        return "";
674                }
675                return super.getPostfixForState();
676        }
677        
678        
679        @Override
680        public void acceptImpl(InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap) {
681                super.acceptImpl(dialog, memoryMap);
682                Global.getSector().getListenerManager().addListener(this);
683        }
684        
685        @Override
686        protected void notifyEnding() {
687                Global.getSector().getListenerManager().removeListener(this);
688                super.notifyEnding();
689        }
690        
691        // I guess either this doesn't need to be weighted, or I should integrate the weighted choice
692        // into this dang function. I'll do it ... later, maybe. -dgb, TODO
693        public ScanEncounterVariation pickGateEvent() {
694                WeightedRandomPicker<ScanEncounterVariation> picker = new WeightedRandomPicker<ScanEncounterVariation>(genRandom);
695                for (ScanEncounterVariation event : scanEncounterVariations) {
696                        picker.add(event, 1f);
697                }
698                /*FactionData data = FACTION_DATA.get(factionId);
699                if (data != null) {
700                        float w = Math.max(1f, data.events.length) / Math.max(1f, picker.getTotal());
701                        w *= SPECIFIC_FACTION_SUBJECT_EVENT_LIKELIHOOD; // faction-specific is more likely than generic, overall
702                        for (String event : data.events) {
703                                picker.add(event, w);
704                        }
705                }*/
706                return picker.pick();
707        }
708
709        public static String CHECKED_FOR_ENCOUNTER = "$gaATG_checkedForEncounter";
710        public void reportCurrentLocationChanged(LocationAPI prev, LocationAPI currLoc) {
711                if (getCurrentStage() == null) return;
712                
713                // if in the wrong stage for gate encounters: return
714                if (((Enum)getCurrentStage()).ordinal() >= Stage.RETURN_WITH_DEAL_AND_SCANS.ordinal()) return;
715                if (((Enum)getCurrentStage()).ordinal() < Stage.TALK_TO_YARIBAY.ordinal()) return;
716                
717                if(!(currLoc instanceof StarSystemAPI)) return;
718                
719                // if no gate encounters remain, return.
720                if (scanEncounterVariations.isEmpty()) return;
721                
722                StarSystemAPI system = (StarSystemAPI) currLoc;
723                if (system.getMemoryWithoutUpdate().getBoolean(CHECKED_FOR_ENCOUNTER)) return;
724                system.getMemoryWithoutUpdate().set(CHECKED_FOR_ENCOUNTER, true);
725                
726                // We don't want the encounter fleet to get destroyed by pulsars or Remnants. 
727                // Plus, this should make the Gate "interesting" enough already. 
728                if (system.hasTag(Tags.THEME_UNSAFE)) return;
729                if(Misc.hasPulsar(system)) return;
730
731                // if the system is unsuitable - no gate, or gate is scanned: return
732                SectorEntityToken gate = null;
733                for (SectorEntityToken curr : system.getCustomEntitiesWithTag(Tags.GATE)) {
734                        if (GateEntityPlugin.isScanned(curr)) continue;
735                        if (GateEntityPlugin.isActive(curr)) continue;
736                        // plus whatever other checks are needed
737                        gate = curr;
738                        break;
739                }
740                
741                if (gate == null) return;
742                
743                // Not every Gate has a cool story, right?
744                if (rollProbability(SYSTEM_NO_GATE_ENCOUNTER_CHANCE)) return;
745                
746                // pick what type of encounter to do and spawn it
747                // also add a temporary flag to the system to not spawn *another* encounter here
748                
749                ScanEncounterVariation chosenEncounter = null;
750                
751                // testing.
752                //chosenEncounter = ScanEncounterVariation.HEGEMONY;
753                
754
755                for (MarketAPI market : Global.getSector().getEconomy().getMarkets(system)) {
756                        if (scanEncounterVariations.contains(ScanEncounterVariation.HEGEMONY) && 
757                                market.getFactionId().equals(Factions.HEGEMONY) &&
758                                rollProbability(FACTION_GATE_ENCOUNTER_CHANCE))
759                        {
760                                chosenEncounter = ScanEncounterVariation.HEGEMONY;
761                                break;
762                        }
763                        else if (scanEncounterVariations.contains(ScanEncounterVariation.TRITACHYON) && 
764                                        market.getFactionId().equals(Factions.TRITACHYON) &&
765                                        rollProbability(FACTION_GATE_ENCOUNTER_CHANCE))
766                        {
767                                chosenEncounter = ScanEncounterVariation.TRITACHYON;
768                                break;
769                        }
770                        else if (scanEncounterVariations.contains(ScanEncounterVariation.LUDDIC) && 
771                                        market.getFactionId().equals(Factions.LUDDIC_CHURCH) &&
772                                        rollProbability(FACTION_GATE_ENCOUNTER_CHANCE))
773                        {
774                                chosenEncounter = ScanEncounterVariation.LUDDIC;
775                                break;
776                        }
777                        else if (scanEncounterVariations.contains(ScanEncounterVariation.LUDDIC) && 
778                                        market.getFactionId().equals(Factions.LUDDIC_CHURCH) &&
779                                        rollProbability(FACTION_GATE_ENCOUNTER_CHANCE))
780                        {
781                                chosenEncounter = ScanEncounterVariation.LUDDIC;
782                                break;
783                        }
784                        else if (scanEncounterVariations.contains(ScanEncounterVariation.PIRATE) && 
785                                        market.getFactionId().equals(Factions.PIRATES) &&
786                                        rollProbability(FACTION_GATE_ENCOUNTER_CHANCE))
787                        {
788                                chosenEncounter = ScanEncounterVariation.PIRATE;
789                                break;
790                        } 
791                }
792                
793                // Choose randomly from the remaining options if none was picked.
794                if( chosenEncounter == null)
795                {
796                                chosenEncounter = pickGateEvent();
797                }
798                
799                if( chosenEncounter == null) return; // Uh oh?
800                
801                scanEncounterVariations.remove(chosenEncounter);
802/*
803                System.out.println("scan chosen is " + chosenEncounter.toString());
804                System.out.println("remaining encounters:");
805                for (ScanEncounterVariation v : scanEncounterVariations) {
806                        System.out.println(v.toString());
807                }
808        */              
809
810                //              if (system.getId().equals("corvus")) {
811                //              // an alternate way to figure out what's appropriate where
812                //              hasHegemony = true;
813                //      }
814                
815                // of note: since this happens when the player enters a system - i.e. not during mission creation,
816                // but while the actual mission is in progress - it's also ok to do things here directly in code
817                // instead of having to use triggers. The above commented out block is using a trigger (+ runTriggers())
818                // just because it's an easy way to spawn a fleet.
819                
820                if(chosenEncounter == ScanEncounterVariation.DERELICT)
821                {
822                        DerelictShipData params = new DerelictShipData(new PerShipData("apogee_Balanced", ShipCondition.BATTERED, 0f), false);
823
824                        SectorEntityToken ship = BaseThemeGenerator.addSalvageEntity(system, Entities.WRECK, Factions.NEUTRAL, params);
825                        ship.setDiscoverable(true);
826
827                        ship.setCircularOrbit(gate, (float) Math.random() * 360f, 40f, 20f);
828
829                        // Eh, maybe some base chance of recoverable vs. not? -dgb
830                        ShipRecoverySpecialCreator creator = new ShipRecoverySpecialCreator(null, 0, 0, false, null, null);
831                        Misc.setSalvageSpecial(ship, creator.createSpecial(ship, null));
832                        
833                        ship.getMemoryWithoutUpdate().set("$gateScanDerelict", true);
834                }
835                else if(chosenEncounter == ScanEncounterVariation.HEGEMONY)
836                {
837                        //gate.addTag("GAATGhegemonyScanFleet");
838                        
839                        //if (hasHegemony) { // whatever conditions are appropriate
840                        beginStageTrigger(getCurrentStage());
841                        triggerCreateFleet(FleetSize.MEDIUM, FleetQuality.HIGHER, Factions.HEGEMONY, FleetTypes.PATROL_MEDIUM, gate);
842                        triggerMakeNonHostile(); // should it be hostile?
843                        //triggerMakeHostileAndAggressive();
844                        //triggerMakeLowRepImpact();
845                        //triggerFleetPatherNoDefaultTithe();
846                        
847                        triggerPickLocationAroundEntity(gate, 100f);
848                        triggerSpawnFleetAtPickedLocation("$gaATG_hegScanFleet", null);
849                        
850                        triggerFleetSetPatrolActionText("scanning");
851                        triggerFleetSetTravelActionText("repositioning");
852                        triggerOrderFleetPatrol(true, gate);
853                        triggerMakeFleetIgnoreOtherFleets(); // don't go chasing pirates, please.
854                        triggerMakeFleetGoAwayAfterDefeat();
855                        triggerFleetSetPatrolLeashRange(100f);
856                        
857                        //triggerMakeFleetIgnoredByOtherFleets();
858
859                        //triggerPickSetLocation(gate.getContainingLocation(), gate.getLocation()); // fleet should appear AT the gate.
860                        //triggerPickLocationAtClosestToPlayerJumpPoint(probeSystem);
861                        //triggerSetEntityToPickedJumpPoint();
862                        //triggerPickLocationTowardsEntity(gate, 15f, getUnits(1.0f));
863                        //triggerFleetMakeImportant(null, Stage.FOLLOW_THE_EXPERIMENTS);
864                        //triggerOrderFleetInterceptPlayer();
865                        
866                        triggerSetFleetMissionRef("$gaATG_ref"); // so they can be made unimportant
867                        triggerFleetAddDefeatTrigger("GAATGhegGateScanFleetDefeated");
868                        triggerFleetSetName("Special Task Force");
869                        endTrigger();
870                        
871                        // this'll execute the trigger added above immediately
872                        List<CampaignFleetAPI> fleets = runStageTriggersReturnFleets(getCurrentStage());
873                        if (fleets.isEmpty())
874                        {
875                                return; // something went wrong spawning a fleet, unlikely but technically possible
876                        }
877                        final CampaignFleetAPI fleet = fleets.get(0);
878                        
879                        fleet.addEventListener(new BaseFleetEventListener() {
880                                @Override
881                                public void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param) {
882                                        if (reason == FleetDespawnReason.DESTROYED_BY_BATTLE) {
883                                                // Cool! So now the fleet no longer blocks the Gate, and the Gate is no longer blocked. -dgb
884                                                fleet.getMemoryWithoutUpdate().unset("$gaATG_hegScanFleet");
885                                                encounterGateHegemony.getMemoryWithoutUpdate().unset("$GAATGhegemonyScanFleet");
886                                        }
887                                }
888                                
889                                @Override
890                                public void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle) {
891                                        if (battle.wasFleetDefeated(fleet, primaryWinner)) {
892                                                fleet.getMemoryWithoutUpdate().unset("$gaATG_hegScanFleet");
893                                                encounterGateHegemony.getMemoryWithoutUpdate().unset("$GAATGhegemonyScanFleet");
894                                        }
895                                }
896                        });
897                        
898                        encounterHegemonyFleet = fleets.get(0);
899                        
900                        // Let's do this after the potential abort, just to be safe.
901                        // If anything above fails, then the Gate isn't blocked -dgb.
902                        encounterGateHegemony = gate;
903                        setFlag(gate, "$GAATGhegemonyScanFleet", true);
904                }
905                else if(chosenEncounter == ScanEncounterVariation.JAMMER)
906                {
907                        setFlag(gate, "$GAATGscanJammer", true);
908                }
909                else if(chosenEncounter == ScanEncounterVariation.ALARM)
910                {
911                        setFlag(gate, "$GAATGscanAlarm", true);
912                }
913                else if(chosenEncounter == ScanEncounterVariation.LUDDIC)
914                {
915                        beginStageTrigger(getCurrentStage());
916                        triggerCreateFleet(FleetSize.MEDIUM, FleetQuality.LOWER, Factions.LUDDIC_CHURCH, FleetTypes.TRADE_LINER, gate);
917                        triggerMakeNonHostile();
918                        //triggerMakeLowRepImpact(); // Yeah uh, blowing away a civilian fleet would look bad.
919                        triggerSetFleetSizeFraction(0.5f);
920                        triggerSetFleetComposition(2f, 1f, 1f, 10f, 1f);
921                        triggerPickLocationAroundEntity(gate, 50f);
922                        triggerSpawnFleetAtPickedLocation("$gaATG_luddicScanFleet", null);
923                        triggerFleetSetTravelActionText("holding vigil");
924                        triggerFleetSetPatrolActionText("holding vigil");
925                        triggerOrderFleetPatrol(true, gate);
926                        triggerMakeFleetIgnoreOtherFleets(); // don't go chasing pirates, please.
927                        triggerMakeFleetGoAwayAfterDefeat();
928                        triggerFleetSetPatrolLeashRange(30f); // very close.
929                        //triggerMakeFleetIgnoredByOtherFleets();
930                        triggerSetFleetMissionRef("$gaATG_ref"); // so they can be made unimportant
931                        triggerFleetAddDefeatTrigger("GAATGluddicScanFleetDefeated");
932                        triggerFleetSetName("Sacred Vigil Flotilla");
933                        endTrigger();
934                        
935                        // this'll execute the trigger added above immediately
936                        List<CampaignFleetAPI> fleets = runStageTriggersReturnFleets(getCurrentStage());
937                        if (fleets.isEmpty())
938                        {
939                                return; // something went wrong spawning a fleet, unlikely but technically possible
940                        }
941                        final CampaignFleetAPI fleet = fleets.get(0);
942                        encounterLuddicFleet = fleet;
943                        encounterGateLuddic = gate;
944                        setFlag(gate, "$GAATGluddicScanGate", true);
945                        
946                        fleet.addEventListener(new BaseFleetEventListener() {
947                                public void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param) {
948                                        if (reason == FleetDespawnReason.DESTROYED_BY_BATTLE) {
949                                                fleet.getMemoryWithoutUpdate().unset("$gaATG_luddicScanFleet");
950                                                encounterGateLuddic.getMemoryWithoutUpdate().unset("$GAATGluddicScanGate");
951                                        }
952                                }
953                                
954                                public void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle) {
955                                        if (battle.wasFleetDefeated(fleet, primaryWinner)) {
956                                                fleet.getMemoryWithoutUpdate().unset("$gaATG_luddicScanFleet");
957                                                encounterGateLuddic.getMemoryWithoutUpdate().unset("$GAATGluddicScanGate");
958                                        }
959                                }
960                        });
961                }
962                else if(chosenEncounter == ScanEncounterVariation.PATHER)
963                {
964                        // Just hostile Pathers. Maybe they should share their feelings/motivations with the player.
965                        beginStageTrigger(getCurrentStage());
966                        triggerCreateFleet(FleetSize.MEDIUM, FleetQuality.HIGHER, Factions.LUDDIC_PATH, FleetTypes.MERC_PRIVATEER, gate);
967                        triggerFleetPatherNoDefaultTithe(); // They want to kill you.
968                        triggerPickLocationAroundEntity(gate, 200f);
969                        triggerSpawnFleetAtPickedLocation("$gaATG_patherScanFleet", null);
970                        triggerOrderFleetPatrol(true, gate);
971                        //triggerFleetSetPatrolActionText("guarding");
972                        //triggerMakeFleetIgnoreOtherFleets(); // actually yes, chase the player. Or anyone else, who cares.
973                        triggerMakeFleetGoAwayAfterDefeat();
974                        triggerFleetSetPatrolLeashRange(60f); // very close.
975                        triggerSetFleetMissionRef("$gaATG_ref"); // so they can be made unimportant
976                        //triggerFleetAddDefeatTrigger("GAATGpatherScanFleetDefeated"); // don't need it - they won't block the gate except via hostility.
977                        triggerFleetSetName("Ambush Fleet");
978                        endTrigger();
979                }
980                else if(chosenEncounter == ScanEncounterVariation.PIRATE)
981                {
982                        beginStageTrigger(getCurrentStage());
983                        triggerCreateFleet(FleetSize.MEDIUM, FleetQuality.VERY_HIGH, Factions.PIRATES, FleetTypes.PATROL_LARGE, gate);
984                        triggerMakeNonHostile(); // Will go hostile after yelling at you, or if you don't talk to them.
985                        triggerMakeLowRepImpact(); // Yeah uh, blowing away a civilian fleet would look bad.
986                        triggerPickLocationAroundEntity(gate, 250f);
987                        triggerSpawnFleetAtPickedLocation("$gaATG_pirateScanFleet", null);
988                        triggerFleetSetPatrolActionText("loitering");
989                        triggerFleetSetTravelActionText("maneuvering");
990                        triggerOrderFleetPatrol(true, gate);
991                        
992                        triggerFleetSetPatrolLeashRange(250f); // fairly close.
993                        triggerSetFleetMissionRef("$gaATG_ref"); // so they can be made unimportant
994                        triggerFleetAddDefeatTrigger("GAATGpirateScanFleetDefeated");
995                        triggerMakeFleetGoAwayAfterDefeat();
996                        endTrigger();
997                        
998                        // this'll execute the trigger added above immediately
999                        List<CampaignFleetAPI> fleets = runStageTriggersReturnFleets(getCurrentStage());
1000                        if (fleets.isEmpty())
1001                        {
1002                                return; // something went wrong spawning a fleet, unlikely but technically possible
1003                        }
1004                        final CampaignFleetAPI fleet = fleets.get(0);
1005                        
1006                        fleet.addEventListener(new BaseFleetEventListener() {
1007                                @Override
1008                                public void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param) {
1009                                        if (reason == FleetDespawnReason.DESTROYED_BY_BATTLE) {
1010                                                fleet.getMemoryWithoutUpdate().unset("$gaATG_pirateScanFleet");
1011                                                encounterGatePirate.getMemoryWithoutUpdate().unset("$GAATGpirateScanGate");
1012                                        }
1013                                }
1014                                @Override
1015                                public void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle) {
1016                                        // if our pirates get defeated in any battle...
1017                                        if (battle.wasFleetDefeated(fleet, primaryWinner)) {
1018                                                fleet.getMemoryWithoutUpdate().unset("$gaATG_pirateScanFleet");
1019                                                encounterGatePirate.getMemoryWithoutUpdate().unset("$GAATGpirateScanGate");
1020                                        }
1021                                }
1022                        });
1023                        
1024                        fleet.addEventListener(new BaseFleetEventListener() {
1025                                
1026                        });
1027                        
1028                        encounterGatePirate = gate;
1029                        encounterPirateFleet = fleet;
1030                        setFlag(gate, "$GAATGpirateScanGate", true);
1031                }
1032                else if(chosenEncounter == ScanEncounterVariation.SCAVENGER)
1033                {
1034                        // Just a scavenger suspiciously nearby. Doesn't block the gate.
1035                        beginStageTrigger(getCurrentStage());
1036                        triggerCreateFleet(FleetSize.SMALL, FleetQuality.DEFAULT, Factions.INDEPENDENT, FleetTypes.SCAVENGER_MEDIUM, gate);
1037                        triggerMakeNonHostile();
1038                        triggerMakeLowRepImpact(); 
1039                        triggerPickLocationAroundEntity(gate, 100f);
1040                        triggerSpawnFleetAtPickedLocation("$gaATG_scavScanFleet", null);
1041                        triggerFleetSetPatrolActionText("observing");
1042                        triggerFleetSetTravelActionText("observing");
1043                        triggerOrderFleetPatrol(true, gate);
1044                        triggerMakeFleetIgnoreOtherFleets(); // don't go chasing pirates, please.
1045                        triggerFleetSetPatrolLeashRange(250f);
1046                        triggerMakeFleetIgnoredByOtherFleets(); // would be disappointing if they just got blasted.
1047                        triggerSetFleetMissionRef("$gaATG_ref"); // so they can be made unimportant
1048                        //triggerFleetAddDefeatTrigger("GAATGluddicScanFleetDefeated"); n/a
1049                        triggerFleetSetName("Suspect Scavenger");
1050                        triggerMakeFleetGoAwayAfterDefeat();
1051                        endTrigger();
1052                        
1053                        List<CampaignFleetAPI> fleets = runStageTriggersReturnFleets(getCurrentStage());
1054                        if (fleets.isEmpty()) return;
1055                }
1056                else if(chosenEncounter == ScanEncounterVariation.TRITACHYON)
1057                {
1058                        beginStageTrigger(getCurrentStage());
1059                        triggerCreateFleet(FleetSize.LARGE, FleetQuality.HIGHER, Factions.TRITACHYON, FleetTypes.PATROL_LARGE, gate);
1060                        triggerMakeNonHostile();
1061                        //triggerMakeHostileAndAggressive();
1062                        //triggerMakeLowRepImpact();
1063                        //triggerFleetPatherNoDefaultTithe();
1064                        
1065                        triggerPickLocationAroundEntity(gate, 100f);
1066                        triggerSpawnFleetAtPickedLocation("$gaATG_ttScanFleet", null);
1067                        triggerFleetSetTravelActionText("repositioning");
1068                        triggerFleetSetPatrolActionText("scanning");
1069                        triggerOrderFleetPatrol(true, gate);
1070                        triggerMakeFleetIgnoreOtherFleets(); // don't go chasing pirates, please.
1071                        triggerMakeFleetGoAwayAfterDefeat();
1072                        triggerFleetSetPatrolLeashRange(100f);
1073                        
1074                        //triggerMakeFleetIgnoredByOtherFleets();
1075
1076                        triggerSetFleetMissionRef("$gaATG_ref"); // so they can be made unimportant
1077                        triggerFleetAddDefeatTrigger("GAATGttGateScanFleetDefeated");
1078                        triggerFleetSetName("Special Projects Detachment");
1079                        endTrigger();
1080                        
1081                        // this'll execute the trigger added above immediately
1082                        List<CampaignFleetAPI> fleets = runStageTriggersReturnFleets(getCurrentStage());
1083                        if (fleets.isEmpty())
1084                        {
1085                                return; // something went wrong spawning a fleet, unlikely but technically possible
1086                        }
1087                        final CampaignFleetAPI fleet = fleets.get(0);
1088                        
1089                        fleet.addEventListener(new BaseFleetEventListener() {
1090                                @Override
1091                                public void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param) {
1092                                        if (reason == FleetDespawnReason.DESTROYED_BY_BATTLE) {
1093                                                // Cool! So now the fleet no longer blocks the Gate, and the Gate is no longer blocked. -dgb
1094                                                fleet.getMemoryWithoutUpdate().unset("$gaATG_ttScanFleet");
1095                                                encounterGateTT.getMemoryWithoutUpdate().unset("$GAATGttScanGate");
1096                                        }
1097                                }
1098                                
1099                                @Override
1100                                public void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle) {
1101                                        if (battle.wasFleetDefeated(fleet, primaryWinner)) {
1102                                                fleet.getMemoryWithoutUpdate().unset("$gaATG_ttScanFleet");
1103                                                encounterGateTT.getMemoryWithoutUpdate().unset("$GAATGttScanGate");
1104                                        }
1105                                }
1106                        });
1107                        
1108                        fleet.addEventListener(new BaseFleetEventListener() {
1109                                
1110                        });
1111                        
1112                        //encounterHegemonyFleet = fleets.get(0);
1113
1114                        encounterGateTT = gate;
1115                        encounterTTFleet = fleet; // unused?
1116                        setFlag(gate, "$GAATGttScanGate", true);
1117                }
1118                else
1119                {
1120                        // none chosen? I guess don't do anything, huh. How'd you get here, anyway?
1121                        return;
1122                }
1123        }
1124        
1125        protected void spawnKantaVengeanceFleetPirateArmada(SectorEntityToken spawnPoint) {
1126                beginWithinHyperspaceRangeTrigger(magecGate, 3f, false, Stage.GO_TO_MAGEC_GATE);
1127                triggerCreateFleet(FleetSize.HUGE, FleetQuality.HIGHER, Factions.PIRATES, FleetTypes.PATROL_LARGE, spawnPoint);
1128                triggerSetFleetFaction(Factions.PIRATES);
1129                triggerSetFleetOfficers(OfficerNum.MORE, OfficerQuality.HIGHER);
1130                triggerAutoAdjustFleetStrengthMajor();
1131                triggerMakeHostileAndAggressive();
1132                triggerMakeNoRepImpact();
1133                triggerFleetAllowLongPursuit();
1134                triggerSetFleetAlwaysPursue();
1135                triggerPickLocationAroundEntity(spawnPoint, 100f);
1136                triggerSetFleetMissionRef("$gaATG_ref");
1137                triggerSpawnFleetAtPickedLocation("$gaATG_kantaVengeanceFleet", null);
1138                triggerOrderFleetInterceptPlayer();
1139                endTrigger();
1140        }
1141        
1142        protected void spawnKantaVengeanceFleetPirateScout(SectorEntityToken spawnPoint) {
1143                beginWithinHyperspaceRangeTrigger(magecGate, 3f, false, Stage.GO_TO_MAGEC_GATE);
1144                triggerCreateFleet(FleetSize.MEDIUM, FleetQuality.HIGHER, Factions.PIRATES, FleetTypes.PATROL_SMALL, spawnPoint);
1145                triggerSetFleetFaction(Factions.PIRATES);
1146                triggerSetFleetOfficers(OfficerNum.MORE, OfficerQuality.DEFAULT);
1147                triggerAutoAdjustFleetStrengthMajor();
1148                triggerMakeHostileAndAggressive();
1149                triggerMakeNoRepImpact();
1150                triggerFleetAllowLongPursuit();
1151                triggerSetFleetAlwaysPursue();
1152                triggerFleetMakeFaster(true, 0, true);
1153                triggerPickLocationAroundEntity(spawnPoint, 100f);
1154                triggerSetFleetMissionRef("$gaATG_ref");
1155                triggerSpawnFleetAtPickedLocation("$gaATG_kantaVengeanceFleet", null);
1156                triggerOrderFleetInterceptPlayer();
1157                endTrigger();
1158        }
1159        
1160        protected void spawnKantaVengeanceFleetMerc(SectorEntityToken spawnPoint) {
1161                beginWithinHyperspaceRangeTrigger(magecGate, 3f, false, Stage.GO_TO_MAGEC_GATE);
1162                triggerCreateFleet(FleetSize.LARGE, FleetQuality.VERY_HIGH, Factions.MERCENARY, FleetTypes.MERC_ARMADA, spawnPoint);
1163                triggerSetFleetFaction(Factions.PIRATES);
1164                triggerSetFleetOfficers(OfficerNum.MORE, OfficerQuality.HIGHER);
1165                triggerAutoAdjustFleetStrengthMajor();
1166                triggerMakeHostileAndAggressive();
1167                triggerMakeNoRepImpact();
1168                triggerFleetAllowLongPursuit();
1169                triggerSetFleetAlwaysPursue();
1170                triggerFleetMakeFaster(true, 1, true);
1171                triggerPickLocationAroundEntity(spawnPoint, 100f);
1172                triggerSetFleetMissionRef("$gaATG_ref");
1173                triggerSpawnFleetAtPickedLocation("$gaATG_kantaVengeanceFleet", null);
1174                triggerOrderFleetInterceptPlayer();
1175                endTrigger();
1176        }
1177}
1178
1179
1180
1181
1182