001package com.fs.starfarer.api.impl.campaign.intel.events;
002
003import java.util.Random;
004
005import java.awt.Color;
006
007import org.lwjgl.util.vector.Vector2f;
008
009import com.fs.starfarer.api.Global;
010import com.fs.starfarer.api.campaign.CampaignFleetAPI;
011import com.fs.starfarer.api.campaign.StarSystemAPI;
012import com.fs.starfarer.api.campaign.comm.CommMessageAPI.MessageClickAction;
013import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin.ListInfoMode;
014import com.fs.starfarer.api.campaign.econ.Industry;
015import com.fs.starfarer.api.campaign.econ.MarketAPI;
016import com.fs.starfarer.api.impl.campaign.NPCHassler;
017import com.fs.starfarer.api.impl.campaign.ids.Factions;
018import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
019import com.fs.starfarer.api.impl.campaign.ids.Industries;
020import com.fs.starfarer.api.impl.campaign.ids.Sounds;
021import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
022import com.fs.starfarer.api.impl.campaign.intel.MessageIntel;
023import com.fs.starfarer.api.impl.campaign.intel.events.BaseEventIntel.EventStageData;
024import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.HAERandomEventData;
025import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.Stage;
026import com.fs.starfarer.api.impl.campaign.intel.inspection.HegemonyInspectionIntel;
027import com.fs.starfarer.api.impl.campaign.intel.inspection.HegemonyInspectionIntel.HegemonyInspectionOutcome;
028import com.fs.starfarer.api.impl.campaign.intel.inspection.HegemonyInspectionIntel.InspectionEndedListener;
029import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission;
030import com.fs.starfarer.api.ui.LabelAPI;
031import com.fs.starfarer.api.ui.TooltipMakerAPI;
032import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipCreator;
033import com.fs.starfarer.api.util.DelayedActionScript;
034import com.fs.starfarer.api.util.Misc;
035import com.fs.starfarer.api.util.WeightedRandomPicker;
036
037public class HegemonyHostileActivityFactor extends BaseHostileActivityFactor implements InspectionEndedListener {
038
039        public static final String HASSLE_REASON = "hegemonyInvestigator";
040        
041        public static String DEFEATED_HEGEMONY = "$defeatedHegemony";
042        
043        public static String INSPECTION_ATTEMPTS = "$hegemonyInspectionAttempts";
044        public static String INSPECTIONS_DEFEATED = "$hegemonyInspectionsDefeated";
045        
046        public static int INSPECTIONS_TO_DEFEAT = 3;
047        
048        public static float INSPECTION_STRENGTH_FIRST = 150;
049        public static float INSPECTION_STRENGTH_SECOND = 600;
050        public static float INSPECTION_STRENGTH_FINAL = 1400;
051        
052        public static boolean isPlayerDefeatedHegemony() {
053                return Global.getSector().getPlayerMemoryWithoutUpdate().getBoolean(DEFEATED_HEGEMONY);
054        }
055        public static void setPlayerDefeatedHegemony() {
056                Global.getSector().getPlayerMemoryWithoutUpdate().set(DEFEATED_HEGEMONY, true);
057        }
058        
059        public static int getInspectionAttempts() {
060                return Global.getSector().getPlayerMemoryWithoutUpdate().getInt(INSPECTION_ATTEMPTS);
061        }
062        public static void incrInspectionAttempts() {
063                Global.getSector().getPlayerMemoryWithoutUpdate().set(INSPECTION_ATTEMPTS, getInspectionAttempts() + 1);
064        }
065        
066        public static int getInspectionsDefeated() {
067                return Global.getSector().getPlayerMemoryWithoutUpdate().getInt(INSPECTIONS_DEFEATED);
068        }
069        public static void incrInspectionsDefeated() {
070                Global.getSector().getPlayerMemoryWithoutUpdate().set(INSPECTIONS_DEFEATED, getInspectionsDefeated() + 1);
071        }
072        
073        
074        public HegemonyHostileActivityFactor(HostileActivityEventIntel intel) {
075                super(intel);
076                
077                //Global.getSector().getListenerManager().addListener(this);
078        }
079        
080        public String getProgressStr(BaseEventIntel intel) {
081                return "";
082        }
083        
084        @Override
085        public int getProgress(BaseEventIntel intel) {
086                if (!checkFactionExists(Factions.HEGEMONY, true)) {
087                        return 0;
088                }
089                return super.getProgress(intel);
090        }
091        
092        public float getEffectMagnitude(StarSystemAPI system) {//, boolean adjustByEventProgress) {
093                if (!checkFactionExists(Factions.HEGEMONY, true)) {
094                        return 0;
095                }
096                return super.getEffectMagnitude(system);
097        }
098        
099        public String getDesc(BaseEventIntel intel) {
100                return "Hegemony";
101        }
102        
103        public String getNameForThreatList(boolean first) {
104                return "Hegemony";
105        }
106
107
108        public Color getDescColor(BaseEventIntel intel) {
109                if (getProgress(intel) <= 0) {
110                        return Misc.getGrayColor();
111                }
112                return Global.getSector().getFaction(Factions.HEGEMONY).getBaseUIColor();
113        }
114
115        public TooltipCreator getMainRowTooltip(BaseEventIntel intel) {
116                return new BaseFactorTooltip() {
117                        public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
118                                float opad = 10f;
119                                
120                                tooltip.addPara("The Hegemony considers the use of AI cores illegal and will not tolerate it "
121                                                + "even outside the volume of the core worlds.", 0f);
122                                tooltip.addPara("Fleets investigating your AI core use can sometimes be found in your space, not overtly "
123                                                + "hostile, but harassing your shipping and generally acting in a high-handed way.", opad);
124                        }
125                };
126        }
127
128        public boolean shouldShow(BaseEventIntel intel) {
129                boolean shouldShowDueToCause = false;
130                for (HostileActivityCause2 cause : getCauses()) {
131                        shouldShowDueToCause |= cause.shouldShow();
132                }
133                return getProgress(intel) > 0 || shouldShowDueToCause;
134        }
135
136
137
138        @Override
139        public int getMaxNumFleets(StarSystemAPI system) {
140                return Global.getSettings().getInt("hegemonyMaxFleets");
141        }
142
143        public CampaignFleetAPI createFleet(StarSystemAPI system, Random random) {
144                
145                float f = 0f;
146                //f += getEffectMagnitude(system);
147                f += intel.getMarketPresenceFactor(system);
148                
149                if (f > 1f) f = 1f;
150                
151//              float fInvestigators = Global.getSettings().getFloat("hegemonyInvestigatorsFreq");
152//              float fRecon = Global.getSettings().getFloat("hegemonyReconFreq");
153//
154//              WeightedRandomPicker<Integer> picker = new WeightedRandomPicker<Integer>(random);
155//              picker.add(1, fInvestigators);
156//              picker.add(2, fRecon);
157//
158//              int pick = picker.pick();
159//              boolean recon = pick == 2;
160                boolean recon = false;
161                
162                int difficulty = 0;
163                
164                if (recon) {
165                        difficulty = 1 + random.nextInt(2);
166                } else {
167                        difficulty = 3;
168                        difficulty += (int) Math.round(f * 5f);
169                        difficulty += random.nextInt(4);
170                }
171                
172                
173                FleetCreatorMission m = new FleetCreatorMission(random);
174                m.beginFleet();
175                
176                Vector2f loc = system.getLocation();
177                String factionId = Factions.HEGEMONY;
178                
179                if (recon) {
180                        m.createStandardFleet(difficulty, factionId, loc);
181                } else {
182                        m.createStandardFleet(difficulty, factionId, loc);
183                }
184                
185                m.triggerSetFleetType(FleetTypes.INVESTIGATORS);
186                m.triggerSetPatrol();
187                
188                if (!recon) {
189                        m.triggerSetFleetHasslePlayer(HASSLE_REASON);
190                        m.triggerSetFleetFlag("$hegemonyInvestigator");
191                        m.triggerFleetAllowLongPursuit();
192                }
193                
194                m.triggerMakeLowRepImpact();
195                
196                CampaignFleetAPI fleet = m.createFleet();
197                
198                if (fleet != null && !recon) {
199                        fleet.addScript(new NPCHassler(fleet, system));
200                }
201                
202                return fleet;
203        }
204        
205
206        @Override
207        public void notifyFactorRemoved() {
208                //Global.getSector().getListenerManager().removeListener(this);
209        }
210
211        public void notifyEventEnding() {
212                notifyFactorRemoved();
213        }
214        
215        
216        public void addBulletPointForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info,
217                        ListInfoMode mode, boolean isUpdate, Color tc, float initPad) {
218
219                if (!(stage.rollData instanceof HAERandomEventData)) return;
220                HAERandomEventData data = (HAERandomEventData) stage.rollData;
221                MarketAPI target = (MarketAPI) data.custom;
222                
223                //MarketAPI target = pickTargetMarket();
224                if (target == null) return;
225                
226                MarketAPI from = pickSourceMarket();
227                if (from == null) return;
228                
229                Color c = Global.getSector().getFaction(Factions.HEGEMONY).getBaseUIColor();
230                
231                LabelAPI label = info.addPara("Upcoming Hegemony AI inspection targeting %s",
232                                                                                initPad, tc, tc, target.getName());
233                label.setHighlight("Hegemony", target.getName());
234                label.setHighlightColors(c, Misc.getBasePlayerColor());
235        }
236
237        public void addBulletPointForEventReset(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info,
238                        ListInfoMode mode, boolean isUpdate, Color tc, float initPad) {
239                info.addPara("Hegemony AI inspection averted", tc, initPad);
240        }
241
242        public void addStageDescriptionForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info) {
243                if (!(stage.rollData instanceof HAERandomEventData)) return;
244                HAERandomEventData data = (HAERandomEventData) stage.rollData;
245                MarketAPI target = (MarketAPI) data.custom;
246                
247                //MarketAPI target = pickTargetMarket();
248                if (target == null) return;
249                
250                MarketAPI from = pickSourceMarket();
251                if (from == null) return;
252                
253                Color c = Global.getSector().getFaction(Factions.HEGEMONY).getBaseUIColor();
254                
255                float small = 0f;
256                float opad = 10f;
257                
258                small = 8f;
259                
260                LabelAPI label = info.addPara("You've received intel that the Hegemony is planning "
261                                + "an AI insprection targeting %s. If the inspection arrives at your colony, "
262                                + "your options would include open hostilities with the Hegemony, or the loss of "
263                                + "at least some of your AI cores.",
264                                                                small, c, target.getName());
265                label.setHighlight(target.getName(), "open hostilities", "loss of at least some of your AI cores");
266                label.setHighlightColors(Misc.getBasePlayerColor(), Misc.getNegativeHighlightColor(), Misc.getNegativeHighlightColor());
267                
268                int defeated = getInspectionsDefeated();
269                if (defeated < INSPECTIONS_TO_DEFEAT - 1) {
270                        label = info.addPara("If this inspection is defeated by military means, the Hegemony is likely to "
271                                        + "escalate the conflict, although only up to a point.", 
272                                        opad, Misc.getNegativeHighlightColor(), "escalate the conflict");
273                        label.setHighlight("escalate the conflict", "up to a point");
274                        label.setHighlightColors(Misc.getNegativeHighlightColor(), Misc.getPositiveHighlightColor());
275                } else {
276                        info.addPara("If this massive inspection force - a declaration of war in all but name - is defeated,"
277                                        + " the Hegemony is likely to reconsider the viability of their approach.", 
278                                        opad, Misc.getPositiveHighlightColor(), "reconsider");
279                }
280                
281                
282                stage.beginResetReqList(info, true, "crisis", opad);
283                info.addPara("The %s has no functional military bases", 0f, c, "Hegemony");
284                stage.endResetReqList(info, false, "crisis", -1, -1); 
285                
286                addBorder(info, Global.getSector().getFaction(Factions.HEGEMONY).getBaseUIColor());
287        }
288        
289        
290        public String getEventStageIcon(HostileActivityEventIntel intel, EventStageData stage) {
291                return Global.getSector().getFaction(Factions.HEGEMONY).getCrest();
292        }
293
294        public TooltipCreator getStageTooltipImpl(final HostileActivityEventIntel intel, final EventStageData stage) {
295                if (stage.id == Stage.HA_EVENT) {
296                        return getDefaultEventTooltip("Hegemony AI inspection", intel, stage);
297                }
298                return null;
299        }
300        
301        
302        public float getEventFrequency(HostileActivityEventIntel intel, EventStageData stage) {
303                if (stage.id == Stage.HA_EVENT) {
304                        if (pickTargetMarket() != null && pickSourceMarket() != null) {
305                                return 10f;
306                        }
307                }
308                return 0;
309        }
310        
311        public MarketAPI pickTargetMarket() {
312                WeightedRandomPicker<MarketAPI> picker = new WeightedRandomPicker<MarketAPI>(getRandomizedStageRandom());
313                
314                float alpha = Global.getSettings().getFloat("hegemonyPointsAlpha");
315                float beta = Global.getSettings().getFloat("hegemonyPointsBeta");
316                float gamma = Global.getSettings().getFloat("hegemonyPointsGamma");
317                
318                float threshold = alpha + beta + gamma; 
319                for (MarketAPI market : Misc.getPlayerMarkets(false)) {
320                        // to put a damper on shenanigans with establishing and abandoning a colony 
321                        // with an Alpha Core admin to bait an attack
322                        if (market.getDaysInExistence() < 180f && !Global.getSettings().isDevMode()) continue;
323                        
324                        float w = HegemonyAICoresActivityCause.getAICorePoints(market);
325                        if (w <= threshold) continue;
326                        picker.add(market, w * w);
327                }
328                return picker.pick();
329        }
330        
331        public MarketAPI pickSourceMarket() {
332                WeightedRandomPicker<MarketAPI> picker = new WeightedRandomPicker<MarketAPI>(getRandomizedStageRandom(7));
333                for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
334                        if (market.getFactionId().equals(Factions.HEGEMONY)) {
335                                Industry b = market.getIndustry(Industries.MILITARYBASE);
336                                if (b == null) b = market.getIndustry(Industries.HIGHCOMMAND);
337                                if (b == null || b.isDisrupted() || !b.isFunctional()) {
338                                        continue;
339                                }
340                                picker.add(market, market.getSize());
341                        }
342                }       
343                MarketAPI from = picker.pick();
344                return from;
345        }
346
347        
348        public void rollEvent(HostileActivityEventIntel intel, EventStageData stage) {
349//              if (true) return;
350                
351                if (isPlayerDefeatedHegemony()) return;
352                
353                MarketAPI market = pickTargetMarket();
354                if (market == null) return;
355                
356                MarketAPI from = pickSourceMarket();
357                if (from == null) return;
358                
359                HAERandomEventData data = new HAERandomEventData(this, stage);
360                data.custom = market;
361                stage.rollData = data;
362                intel.sendUpdateIfPlayerHasIntel(data, false);
363        }
364        
365        public boolean fireEvent(HostileActivityEventIntel intel, EventStageData stage) {
366                //if (true) return false;
367                
368                if (isPlayerDefeatedHegemony()) return false;
369                
370                //MarketAPI market = pickTargetMarket();
371                if (!(stage.rollData instanceof HAERandomEventData)) return false;
372                HAERandomEventData data = (HAERandomEventData) stage.rollData;
373                MarketAPI market = (MarketAPI) data.custom;
374                
375                if (market == null) return false;
376                if (!market.isInEconomy()) return false;
377                
378                MarketAPI from = pickSourceMarket();
379                if (from == null) return false;
380                
381                StarSystemAPI system = market.getStarSystem();
382                if (system == null) return false;
383                
384                return createInspection(market, null);
385        }
386
387        
388        public boolean createInspection(MarketAPI target, Integer fpOverride) {
389                
390//              MarketAPI target = pickTargetMarket();
391//              if (target == null) return false;
392                
393                MarketAPI from = pickSourceMarket();
394                if (from == null) return false;
395                        
396                
397                float fp;
398                int defeated = getInspectionsDefeated();
399                //defeated = 2;
400                
401                if (defeated <= 0) {
402                        fp = INSPECTION_STRENGTH_FIRST;
403                } else if (defeated == 1) {
404                        fp = INSPECTION_STRENGTH_SECOND;
405                } else {
406                        fp = INSPECTION_STRENGTH_FINAL;
407                }
408                
409                //fp = 500;
410                if (fpOverride != null) {
411                        fp = fpOverride;
412                }
413                HegemonyInspectionIntel inspection = new HegemonyInspectionIntel(from, target, fp);
414                if (inspection.isDone()) {
415                        inspection = null;
416                        return false;
417                }
418                
419                inspection.setListener(this);
420                
421                incrInspectionAttempts();
422                
423                return true;
424        }
425
426        
427        @Override
428        public void advance(float amount) {
429                super.advance(amount);
430                
431                EventStageData stage = intel.getDataFor(Stage.HA_EVENT);
432                if (stage != null && stage.rollData instanceof HAERandomEventData && 
433                                ((HAERandomEventData)stage.rollData).factor == this) {
434                        if (pickSourceMarket() == null) {
435                                intel.resetHA_EVENT();
436                        }                       
437                }
438        }
439        
440        public static void avertInspectionIfNotInProgress() {
441                HostileActivityEventIntel intel = HostileActivityEventIntel.get();
442                if (intel == null) return;
443                
444                HAERandomEventData data = intel.getRollDataForEvent();
445                if (data != null && data.factor instanceof HegemonyHostileActivityFactor) {
446                        intel.resetHA_EVENT();
447                }
448        }
449        
450        
451        public void notifyInspectionEnded(HegemonyInspectionOutcome outcome) {
452                // also called when aborted from military base being destroyed, with same outcome enum 
453                if (outcome == HegemonyInspectionOutcome.TASK_FORCE_DESTROYED) {
454                        incrInspectionsDefeated();
455                        int defeated = getInspectionsDefeated();
456                        if (defeated >= INSPECTIONS_TO_DEFEAT) {
457                                setPlayerDefeatedHegemony();
458
459                                Global.getSector().addScript(new DelayedActionScript(0.1f) {
460                                        @Override
461                                        public void doAction() {
462                                                MessageIntel msg = new MessageIntel();
463                                                msg.addLine("Major Hegemony defeat!", Misc.getBasePlayerColor());
464                                                msg.addLine(BaseIntelPlugin.BULLET + 
465                                                                "You may be able to discuss the situation with the High Hegemon on Chicomoztoc");
466                                                msg.setIcon(Global.getSector().getFaction(Factions.HEGEMONY).getCrest());
467                                                msg.setSound(Sounds.REP_GAIN);
468                                                Global.getSector().getCampaignUI().addMessage(msg, MessageClickAction.NOTHING);
469                                        }
470                                });
471                        }
472                }
473        }
474        
475}
476
477
478
479