001package com.fs.starfarer.api.impl.campaign.missions.academy;
002
003import java.awt.Color;
004import java.util.ArrayList;
005import java.util.HashMap;
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.FactionAPI;
013import com.fs.starfarer.api.campaign.InteractionDialogAPI;
014import com.fs.starfarer.api.campaign.StarSystemAPI;
015import com.fs.starfarer.api.campaign.econ.MarketAPI;
016import com.fs.starfarer.api.campaign.rules.MemoryAPI;
017import com.fs.starfarer.api.characters.ImportantPeopleAPI.PersonDataAPI;
018import com.fs.starfarer.api.characters.PersonAPI;
019import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepRewards;
020import com.fs.starfarer.api.impl.campaign.ids.Factions;
021import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
022import com.fs.starfarer.api.impl.campaign.ids.Ranks;
023import com.fs.starfarer.api.impl.campaign.missions.DelayedFleetEncounter;
024import com.fs.starfarer.api.ui.TooltipMakerAPI;
025import com.fs.starfarer.api.util.Misc;
026import com.fs.starfarer.api.util.Misc.Token;
027import com.fs.starfarer.api.util.WeightedRandomPicker;
028
029@SuppressWarnings("unchecked")
030public class GADeliverVIP extends GABaseMission {
031
032
033        public static float MISSION_DAYS = 60f;
034        public static float PROB_KANTA = 0.1f;
035        public static float PROB_MERC_KIDNAPPER = 0.5f;
036        public static float PROB_PIRATE_KIDNAPPER = 0.5f;
037        
038        public static float SPECIFIC_FACTION_SUBJECT_EVENT_LIKELIHOOD = 2f;
039        
040
041        
042        public static class FactionData {
043                //public Pair<String, String>[] subjects; 
044                public String[] subjects; 
045                public String[] events; 
046        }
047        
048        public static FactionData ALL_FACTIONS;
049        public static Map<String, FactionData> FACTION_DATA = new HashMap<String, FactionData>();
050        public static List<String> ALLOWED_FACTIONS = new ArrayList<String>();
051        public static List<String> MERC_FACTIONS = new ArrayList<String>();
052        static {
053                ALLOWED_FACTIONS.add(Factions.INDEPENDENT);
054                ALLOWED_FACTIONS.add(Factions.PERSEAN);
055                ALLOWED_FACTIONS.add(Factions.TRITACHYON);
056                ALLOWED_FACTIONS.add(Factions.HEGEMONY);
057                ALLOWED_FACTIONS.add(Factions.LUDDIC_CHURCH);
058                
059                MERC_FACTIONS.add(Factions.TRITACHYON);
060                MERC_FACTIONS.add(Factions.HEGEMONY);
061                MERC_FACTIONS.add(Factions.DIKTAT);
062                MERC_FACTIONS.add(Factions.LUDDIC_CHURCH);
063                
064                ALL_FACTIONS = new FactionData();
065                ALL_FACTIONS.subjects = new String[] {
066                        "child",        
067                        "son",
068                        "daughter",
069                        "niece",        
070                        "nephew",       
071                        "ward",
072                };
073                ALL_FACTIONS.events = new String [] {
074                                "a wedding", "a funeral", "a reunion", "a judicial procedure", "an operation", "a family gathering", "their legitimation"  
075                };
076                
077                FactionData luddic = new FactionData();
078                FACTION_DATA.put(Factions.LUDDIC_CHURCH, luddic);
079                luddic.subjects = new String[] {
080                        "godchild",     
081                        "goddaughter",  
082                        "godson",       
083                        "apprentice",   
084                };
085                luddic.events = new String [] {
086                                "a spiritual retreat", "a penitent seclusion", "their Path-stepping", "their godnaming", "their blessing", "their contemplation", 
087                                "their consecration", "their invocation", "their witnessing", "their ministration", "an ordination ceremony", "an Exodus Fast"
088                };
089                
090                FactionData hegemony = new FactionData();
091                FACTION_DATA.put(Factions.HEGEMONY, hegemony);
092                hegemony.subjects = new String[] {
093                                "unit-ward",    
094                };
095                hegemony.events = new String [] {
096                                "their service induction", "cadet training", "survival school", "a warship launching", "a COMSEC interview",
097                                "a unit commemoration", "Legion remembrance day"
098                };
099                
100                FactionData tritach = new FactionData();
101                FACTION_DATA.put(Factions.TRITACHYON, tritach);
102                tritach.subjects = new String[] {
103                                "contract-ward",        
104                };
105                tritach.events = new String [] {
106                                "a cybernetic enhancement", "gene therapy", "an enrichment retreat", "a cryo-sabbatical ceremony",
107                                "a promotion celebration"
108                };
109                
110                FactionData league = new FactionData();
111                FACTION_DATA.put(Factions.PERSEAN, league);
112                league.subjects = new String[] {
113                                "gensheir",     
114                };
115                league.events = new String [] {
116                                "a coronation", "a premiere", "their coming-of-majority", "a landing commemoration", "a titanium jubilee",
117                                "a grand fete", "a carnival"
118                };
119                
120                FactionData pirates = new FactionData();
121                FACTION_DATA.put(Factions.PIRATES, pirates);
122                pirates.subjects = new String[] {
123                                "clanward", "clone-variant",
124                };
125                pirates.events = new String [] {
126                                "a \"blooding\"", "their induction", "their \"making\"", "a grand castigation", "a Grand Division", "an \"unmaking\""
127                };
128        }
129        
130        public String pickSubject(String factionId) {
131                WeightedRandomPicker<String> picker = new WeightedRandomPicker<String>(genRandom);
132                for (String p : ALL_FACTIONS.subjects) {
133                        picker.add(p, 1f);
134                }
135                FactionData data = FACTION_DATA.get(factionId);
136                if (data != null) {
137                        float w = Math.max(1f, data.subjects.length) / Math.max(1f, picker.getTotal());
138                        w *= SPECIFIC_FACTION_SUBJECT_EVENT_LIKELIHOOD; // faction-specific is more likely than generic, overall
139                        for (String p : data.subjects) {
140                                picker.add(p, w);
141                        }
142                }
143                return picker.pick();
144        }
145        
146        public String pickEvent(String factionId) {
147                WeightedRandomPicker<String> picker = new WeightedRandomPicker<String>(genRandom);
148                for (String event : ALL_FACTIONS.events) {
149                        picker.add(event, 1f);
150                }
151                FactionData data = FACTION_DATA.get(factionId);
152                if (data != null) {
153                        float w = Math.max(1f, data.events.length) / Math.max(1f, picker.getTotal());
154                        w *= SPECIFIC_FACTION_SUBJECT_EVENT_LIKELIHOOD; // faction-specific is more likely than generic, overall
155                        for (String event : data.events) {
156                                picker.add(event, w);
157                        }
158                }
159                return picker.pick();
160        }
161        
162        
163        public static enum Stage {
164                DELIVER_VIP,
165                COMPLETED,
166                FAILED,
167                FAILED_DECIV,
168        }
169        
170        public static enum Variation {
171                BASIC,
172                KANTA,
173        }
174        
175        protected StarSystemAPI system;
176        protected MarketAPI destination;
177        protected Variation variation;
178        protected FactionAPI faction;
179        protected String theMercFaction;
180        protected String mercFactionId;
181        
182        protected String subjectRelation;
183        protected String event;
184        protected PersonAPI target;
185        protected String kantaRelationFirstName;
186
187        protected int piratePayment;
188        protected int mercPayment;
189        
190        @Override
191        protected boolean create(MarketAPI createdAt, boolean barEvent) {
192                // if this mission type was already accepted by the player, abort
193                if (!setGlobalReference("$gaVIP_ref")) {
194                        return false;
195                }
196
197                requireMarketFaction(ALLOWED_FACTIONS.toArray(new String [0]));
198                requireMarketLocationNot("galatia");
199                requireMarketNotHidden();
200                requireMarketNotInHyperspace();
201                preferMarketInDirectionOfOtherMissions();
202                
203//              PROB_KANTA = 1f;
204//              PROB_MERC_KIDNAPPER = 1f;
205                
206                destination = pickMarket();
207                variation = Variation.BASIC;
208                if (rollProbability(PROB_KANTA)) {
209                        MarketAPI kantasDen = Global.getSector().getEconomy().getMarket("kantas_den");
210                        if (kantasDen != null) {
211                                destination = kantasDen;
212                                variation = Variation.KANTA;
213                                kantaRelationFirstName = Global.getSector().getFaction(Factions.PIRATES).createRandomPerson(genRandom).getName().getFirst();
214                        }
215                }
216                if (destination == null) return false;
217                
218                faction = destination.getFaction();
219                subjectRelation = pickSubject(faction.getId());
220                if (subjectRelation == null) return false;
221                
222                event = pickEvent(faction.getId());
223                if (event == null) return false;
224                
225                if (variation == Variation.BASIC) {
226                        target = findOrCreatePerson(faction.getId(), destination, true, Ranks.CITIZEN, 
227                                                        Ranks.POST_ADMINISTRATOR, Ranks.POST_BASE_COMMANDER, Ranks.POST_STATION_COMMANDER,
228                                                        Ranks.POST_OUTPOST_COMMANDER, Ranks.POST_PORTMASTER, Ranks.POST_FACTION_LEADER
229                                                        );
230//                      target.addTag(Tags.CONTACT_TRADE);
231//                      setPersonIsPotentialContactOnSuccess(target);
232                } else if (variation == Variation.KANTA) {
233                        // set the VIP to Kanta, for rep purposes, since the sub-boss that's the actual relation doesn't exist
234                        PersonDataAPI pd = Global.getSector().getImportantPeople().getData("kanta");
235                        if (pd != null) target = pd.getPerson();
236                }
237                if (target == null) return false;
238                
239                
240                system = destination.getStarSystem();
241                
242                setStartingStage(Stage.DELIVER_VIP);
243                addSuccessStages(Stage.COMPLETED);
244                addFailureStages(Stage.FAILED);
245                addNoPenaltyFailureStages(Stage.FAILED_DECIV);
246                
247                // used for generic pirate reaction
248                if (variation == Variation.KANTA) {
249                        setGlobalFlag("$gaVIP_workingForKanta", true, Stage.DELIVER_VIP);
250                }
251                
252                makeImportant(destination, "$gaVIP_target", Stage.DELIVER_VIP);
253                
254                setStageOnGlobalFlag(Stage.COMPLETED, "$gaVIP_delivered");
255                setStageOnGlobalFlag(Stage.FAILED, "$gaVIP_failed");
256                connectWithMarketDecivilized(Stage.DELIVER_VIP, Stage.FAILED_DECIV, destination);
257                
258                setTimeLimit(Stage.FAILED, MISSION_DAYS, null);
259                if (variation == Variation.BASIC) {
260                        //setCreditReward(30000, 40000);
261                        setCreditReward(CreditReward.AVERAGE);
262                        setRepPenaltyPerson(RepRewards.VERY_HIGH);
263                        setRepPenaltyFaction(RepRewards.HIGH);
264                } else {
265                        //setCreditReward(50000, 70000);
266                        setCreditReward(CreditReward.HIGH);
267                        setRepPenaltyPerson(RepRewards.EXTREME);
268                        setRepPenaltyFaction(RepRewards.HIGH);
269                }
270                
271                setDefaultGARepRewards();
272                
273//              beginStageTrigger(Stage.DELIVER_VIP);
274//              LocData data = new LocData(EntityLocationType.HIDDEN_NOT_NEAR_STAR, null, system);
275//              triggerSpawnShipGraveyard(Factions.REMNANTS, 10, 10, data);
276//              endTrigger();
277                
278                piratePayment = genRoundNumber(40000, 60000);
279                mercPayment = getCreditsReward() / 2;
280                
281                if (variation == Variation.BASIC && rollProbability(PROB_PIRATE_KIDNAPPER)) {
282                        beginWithinHyperspaceRangeTrigger(destination, 3f, false, Stage.DELIVER_VIP);
283                        triggerCreateFleet(FleetSize.LARGE, FleetQuality.HIGHER, Factions.PIRATES, FleetTypes.PATROL_MEDIUM, system);
284                        triggerSetFleetOfficers(OfficerNum.MORE, OfficerQuality.HIGHER);
285                        triggerAutoAdjustFleetStrengthMajor();
286                        triggerSetStandardAggroPirateFlags();
287                        triggerFleetAllowLongPursuit();
288                        triggerSetFleetAlwaysPursue();
289                        triggerPickLocationTowardsPlayer(system.getHyperspaceAnchor(), 90f, getUnits(1.5f));
290                        triggerSpawnFleetAtPickedLocation("$gaVIP_pirate", null);
291                        triggerOrderFleetInterceptPlayer();
292                        triggerFleetMakeImportant(null, Stage.DELIVER_VIP);
293                        endTrigger();
294                }
295                
296                if (variation == Variation.KANTA && rollProbability(PROB_MERC_KIDNAPPER)) {
297                        mercFactionId = pickOne(MERC_FACTIONS.toArray(new String[0]));
298                        FactionAPI mercFaction = Global.getSector().getFaction(mercFactionId);
299                        theMercFaction = mercFaction.getDisplayNameWithArticle();
300                        
301                        beginWithinHyperspaceRangeTrigger(destination, 3f, true, Stage.DELIVER_VIP);
302                        triggerCreateFleet(FleetSize.VERY_LARGE, FleetQuality.VERY_HIGH, Factions.MERCENARY, FleetTypes.PATROL_LARGE, system);
303                        triggerSetFleetFaction(Factions.INDEPENDENT);
304                        triggerSetFleetOfficers(OfficerNum.MORE, OfficerQuality.HIGHER);
305                        triggerAutoAdjustFleetStrengthMajor();
306                        triggerMakeHostileAndAggressive();
307                        triggerFleetMakeFaster(true, 2, true);
308                        //triggerMakeNoRepImpact(); // this happens in dialog instead
309                        triggerFleetAllowLongPursuit();
310                        triggerSetFleetAlwaysPursue();
311                        triggerPickLocationTowardsPlayer(system.getHyperspaceAnchor(), 90f, getUnits(1.5f));
312                        triggerSpawnFleetAtPickedLocation("$gaVIP_merc", null);
313                        triggerOrderFleetInterceptPlayer();
314                        triggerFleetMakeImportant(null, Stage.DELIVER_VIP);
315                        endTrigger();
316                }
317                
318                return true;
319        }
320
321        @Override
322        protected boolean callAction(String action, String ruleId, InteractionDialogAPI dialog, List<Token> params,
323                                                                 Map<String, MemoryAPI> memoryMap) {
324                if (action.equals("betrayal")) {
325                        DelayedFleetEncounter e = new DelayedFleetEncounter(genRandom, getMissionId());
326                        e.setDelayMedium();
327                        e.setLocationInnerSector(false, Factions.INDEPENDENT);
328                        e.beginCreate();
329                        e.triggerCreateFleet(FleetSize.LARGE, FleetQuality.SMOD_3, Factions.MERCENARY, FleetTypes.PATROL_LARGE, new Vector2f());
330                        e.triggerSetFleetOfficers(OfficerNum.MORE, OfficerQuality.UNUSUALLY_HIGH);
331                        e.triggerFleetSetFaction(Factions.INDEPENDENT);
332                        e.triggerFleetMakeFaster(true, 2, true);
333                        e.triggerSetFleetFlag("$gaVIP_kantaConsequences");
334                        e.triggerMakeNoRepImpact();
335                        e.triggerSetStandardAggroInterceptFlags();
336                        e.endCreate();
337                        return true;
338                }
339                return false;
340        }
341
342        protected void updateInteractionDataImpl() {
343                if (getCurrentStage() != null) {
344                        set("$gaVIP_stage", ((Enum)getCurrentStage()).name());
345                }
346                set("$gaVIP_starName", system.getNameWithNoType());
347                set("$gaVIP_marketName", destination.getName());
348                set("$gaVIP_systemName", system.getNameWithLowercaseTypeShort());
349                
350                set("$gaVIP_subjectRelation", subjectRelation);
351                set("$gaVIP_kantaRelationFirstName", kantaRelationFirstName);
352                set("$gaVIP_VIP", target);
353                set("$gaVIP_VIP_faction", target.getFaction().getId());
354                set("$gaVIP_VIPName", target.getNameString());
355                set("$gaVIP_VIPhisOrHer", target.getHisOrHer());
356                set("$gaVIP_VIPPost", target.getPost().toLowerCase());
357                set("$gaVIP_event", event);
358                
359                set("$gaVIP_reward", Misc.getWithDGS(getCreditsReward()));
360                set("$gaVIP_piratePayment", Misc.getWithDGS(piratePayment));
361                set("$gaVIP_mercPayment", Misc.getWithDGS(mercPayment));
362                set("$gaVIP_theMercFaction", theMercFaction);
363                set("$gaVIP_mercFactionId", mercFactionId);
364                set("$gaVIP_timeLimit", (int)MISSION_DAYS);
365                set("$gaVIP_variation", variation);
366        }
367        
368        @Override
369        public void addDescriptionForNonEndStage(TooltipMakerAPI info, float width, float height) {
370                float opad = 10f;
371                Color h = Misc.getHighlightColor();
372                if (currentStage == Stage.DELIVER_VIP) {
373                        if (variation == Variation.BASIC) {
374                                info.addPara("Deliver the " + subjectRelation + " of " + target.getNameString() + " to " + 
375                                                destination.getName() + " in the " + system.getNameWithLowercaseTypeShort() + ", for " +
376                                                event + ". " +
377                                                target.getNameString() + " is the " + target.getPost().toLowerCase() + ".", opad);
378                        } else if (variation == Variation.KANTA) {
379                                info.addPara("Deliver the " + subjectRelation + " of " + kantaRelationFirstName + " Kanta to " + 
380                                                destination.getName() + " in the " + system.getNameWithLowercaseTypeShort() + ", for " +
381                                                event + ". " +
382                                                kantaRelationFirstName + " is kin to Kanta herself.", opad);
383                        }
384                }
385        }
386
387        @Override
388        public boolean addNextStepText(TooltipMakerAPI info, Color tc, float pad) {
389                Color h = Misc.getHighlightColor();
390                if (currentStage == Stage.DELIVER_VIP) {
391                        info.addPara("Deliver student to " + destination.getName() + " in the " + system.getNameWithLowercaseTypeShort(), tc, pad);
392                        return true;
393                }
394                return false;
395        }
396        
397        
398        @Override
399        public String getBaseName() {
400                return "Deliver VIP";
401        }
402        
403}
404
405