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.CargoAPI;
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.comm.IntelInfoPlugin.ListInfoMode;
016import com.fs.starfarer.api.campaign.econ.Industry;
017import com.fs.starfarer.api.campaign.econ.MarketAPI;
018import com.fs.starfarer.api.campaign.listeners.ColonyPlayerHostileActListener;
019import com.fs.starfarer.api.impl.campaign.NPCHassler;
020import com.fs.starfarer.api.impl.campaign.ids.Conditions;
021import com.fs.starfarer.api.impl.campaign.ids.Factions;
022import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
023import com.fs.starfarer.api.impl.campaign.ids.Industries;
024import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
025import com.fs.starfarer.api.impl.campaign.ids.Stats;
026import com.fs.starfarer.api.impl.campaign.intel.PerseanLeagueMembership;
027import com.fs.starfarer.api.impl.campaign.intel.events.BaseEventIntel.EventStageData;
028import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.HAERandomEventData;
029import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.Stage;
030import com.fs.starfarer.api.impl.campaign.intel.group.FGBlockadeAction.FGBlockadeParams;
031import com.fs.starfarer.api.impl.campaign.intel.group.FleetGroupIntel;
032import com.fs.starfarer.api.impl.campaign.intel.group.FleetGroupIntel.FGIEventListener;
033import com.fs.starfarer.api.impl.campaign.intel.group.GenericRaidFGI.GenericRaidParams;
034import com.fs.starfarer.api.impl.campaign.intel.group.PerseanLeagueBlockade;
035import com.fs.starfarer.api.impl.campaign.intel.group.PerseanLeaguePunitiveExpedition;
036import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission;
037import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission.FleetStyle;
038import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator;
039import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD.TempData;
040import com.fs.starfarer.api.ui.LabelAPI;
041import com.fs.starfarer.api.ui.TooltipMakerAPI;
042import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipCreator;
043import com.fs.starfarer.api.util.Misc;
044
045public class PerseanLeagueHostileActivityFactor extends BaseHostileActivityFactor implements
046                                                FGIEventListener, ColonyPlayerHostileActListener {
047
048        //public static final String DEFEATED_BLOCKADE = "$defeatedLeagueBlockade";
049        public static final String HASSLE_REASON = "leagueEnforcer";
050        
051//      public static float INDEPENDENT_REP_FOR_DEFEATING = 0.5f;
052//      public static float HEGEMONY_REP_FOR_DEFEATING = 0.3f;
053        
054        public PerseanLeagueHostileActivityFactor(HostileActivityEventIntel intel) {
055                super(intel);
056                
057                Global.getSector().getListenerManager().addListener(this);
058        }
059        
060        public String getProgressStr(BaseEventIntel intel) {
061                return "";
062        }
063        
064        @Override
065        public int getProgress(BaseEventIntel intel) {
066                if (!checkFactionExists(Factions.PERSEAN, true)) {
067                        return 0;
068                }
069                return super.getProgress(intel);
070        }
071        
072        public String getDesc(BaseEventIntel intel) {
073                return "Persean League";
074        }
075        
076        public String getNameForThreatList(boolean first) {
077                return "Persean League";
078        }
079
080
081        public Color getDescColor(BaseEventIntel intel) {
082                if (getProgress(intel) <= 0) {
083                        return Misc.getGrayColor();
084                }
085                return Global.getSector().getFaction(Factions.PERSEAN).getBaseUIColor();
086        }
087
088        public TooltipCreator getMainRowTooltip(BaseEventIntel intel) {
089                return new BaseFactorTooltip() {
090                        public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
091                                float opad = 10f;
092                                tooltip.addPara("A large independent polity is a tantalizing prize for the Persean League, and "
093                                                + "they will go quite far in exerting pressure for you to join them. League "
094                                                + "\"enforcer\" fleets prowl your systems, ostensibly to protect the League's "
095                                                + "interests in \"unclaimed territory\".", 0f);
096                                
097//                              tooltip.addPara("Going to Kazeron and negotiating to join the League is likely to get "
098//                                              + "this harassment to stop. A saturation bombardment of a League world would make your "
099//                                              + "joining the league politically impossible, but of course has other ramifications. If "
100//                                              + "left unchecked, the conflict will eventually come to a head and is likely to "
101//                                              + "be resolved one way or another.", opad, Misc.getHighlightColor(),
102//                                              "join the League", "saturation bombardment");
103                        }
104                };
105        }
106
107        public boolean shouldShow(BaseEventIntel intel) {
108                return getProgress(intel) > 0;
109        }
110
111
112        public Color getNameColor(float mag) {
113                if (mag <= 0f) {
114                        return Misc.getGrayColor();
115                }
116                return Global.getSector().getFaction(Factions.PERSEAN).getBaseUIColor();
117        }
118        
119        
120        @Override
121        public int getMaxNumFleets(StarSystemAPI system) {
122                return Global.getSettings().getInt("perseanLeagueMaxFleets");
123        }
124        
125        
126        @Override
127        public float getSpawnInHyperProbability(StarSystemAPI system) {
128                return 0f;
129        }
130        
131        public CampaignFleetAPI createFleet(StarSystemAPI system, Random random) {
132        
133                // minimum is 0.66f for this factor due to it requiring some market presence
134                float f = intel.getMarketPresenceFactor(system);
135                
136                int difficulty = 0 + (int) Math.max(1f, Math.round(f * 4f));
137                difficulty += random.nextInt(6);
138                
139                FleetCreatorMission m = new FleetCreatorMission(random);
140                m.beginFleet();
141                
142                Vector2f loc = system.getLocation();
143                String factionId = Factions.PERSEAN;
144                
145                m.createStandardFleet(difficulty, factionId, loc);
146                m.triggerSetFleetType(FleetTypes.LEAGUE_ENFORCER);
147                m.triggerSetPatrol();
148                m.triggerSetFleetHasslePlayer(HASSLE_REASON);
149                m.triggerSetFleetFlag("$leagueEnforcer");
150                
151                m.triggerFleetAllowLongPursuit();
152                m.triggerMakeLowRepImpact();
153                
154                //m.triggerMakeHostile();
155                //m.triggerMakeHostileWhileTransponderOff();
156                
157                CampaignFleetAPI fleet = m.createFleet();
158                
159                if (fleet != null) {
160                        fleet.addScript(new NPCHassler(fleet, system));
161                }
162
163                return fleet;
164        }
165        
166
167        
168        
169        public void addBulletPointForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info,
170                                                                                 ListInfoMode mode, boolean isUpdate, Color tc, float initPad) {
171                //info.addPara("Rumors of Persean League blockade", tc, initPad);
172                Color c = Global.getSector().getFaction(Factions.PERSEAN).getBaseUIColor();
173                info.addPara("Impending Persean League blockade", initPad, tc, c, "Persean League");
174        }
175        
176        public void addBulletPointForEventReset(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info,
177                        ListInfoMode mode, boolean isUpdate, Color tc, float initPad) {
178                info.addPara("Persean League blockade averted", tc, initPad);
179        }
180        
181        public void addStageDescriptionForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info) {
182                float small = 0f;
183                float opad = 10f;
184                
185                small = 8f;
186
187                info.addPara("You've received intel that the Persean League is planning a lengthy blockade of one of your systems. "
188                                + "Colonies in that system will suffer a major accessibility penalty for as long as the blockade lasts.",
189                                small, Misc.getNegativeHighlightColor(), "major accessibility penalty");
190                
191//              LabelAPI label = info.addPara("If the blockading force is defeated, your standing with the Hegemony "
192//                              + "and the independents will increase substantially, and the Persean League will likely abandon "
193//                              + "further efforts to strong-arm you and be more open to negotiation.", 
194//                              opad);
195//              label.setHighlight("Hegemony", "independents", "increase substantially", "Persean League");
196//              label.setHighlightColors(Global.getSector().getFaction(Factions.HEGEMONY).getBaseUIColor(),
197//                              Global.getSector().getFaction(Factions.INDEPENDENT).getBaseUIColor(),
198//                              Misc.getPositiveHighlightColor(),
199//                              Global.getSector().getFaction(Factions.PERSEAN).getBaseUIColor());
200                
201                LabelAPI label = info.addPara("If the blockading force is defeated, your colonies will be viewed as "
202                                + "a more stable trading partner, resulting in increased accessibility, "
203                                + "and the Persean League will likely abandon "
204                                + "further efforts to strong-arm you and be more open to negotiation.", 
205                                opad);
206                label.setHighlight("increased accessibility", "Persean League");
207                label.setHighlightColors(Misc.getPositiveHighlightColor(),
208                                                                 Global.getSector().getFaction(Factions.PERSEAN).getBaseUIColor());             
209                
210                Color c = Global.getSector().getFaction(Factions.PERSEAN).getBaseUIColor();
211                stage.beginResetReqList(info, true, "crisis", opad);
212                info.addPara("You go to %s and make an agreement about joining the League", 0f, c, "Kazeron");
213                info.addPara("%s is tactically bombarded", 0f, c, "Kazeron");
214                //info.addPara("Performing a saturation bombardment of a %s world", 0f, c, "Persean League");
215                stage.endResetReqList(info, false, "crisis", -1, -1);
216                
217                addBorder(info, Global.getSector().getFaction(Factions.PERSEAN).getBaseUIColor());
218        }
219        
220        
221        public String getEventStageIcon(HostileActivityEventIntel intel, EventStageData stage) {
222                return Global.getSector().getFaction(Factions.PERSEAN).getCrest();
223        }
224
225        public TooltipCreator getStageTooltipImpl(final HostileActivityEventIntel intel, final EventStageData stage) {
226                if (stage.id == Stage.HA_EVENT) {
227                        return getDefaultEventTooltip("Persean League blockade", intel, stage);
228                }
229                return null;
230        }
231        
232        
233        public float getEventFrequency(HostileActivityEventIntel intel, EventStageData stage) {
234                if (stage.id == Stage.HA_EVENT) {
235                        if (wasPLEverSatBombardedByPlayer() || getKazeron(true) == null) {
236                                return 0f;
237                        }
238                        
239                        if (PerseanLeagueBlockade.get() != null) {
240                                return 0f;
241                        }
242                        if (PerseanLeaguePunitiveExpedition.get() != null) {
243                                return 0f;
244                        }
245                        
246                        StarSystemAPI target = findBlockadeTarget(intel, stage);
247                        MarketAPI source = getBlockadeSource(intel, stage, target);
248                        if (target != null && source != null) {
249                                return 10f;
250                        }
251                }
252                return 0;
253        }
254        
255
256        public void rollEvent(HostileActivityEventIntel intel, EventStageData stage) {
257                HAERandomEventData data = new HAERandomEventData(this, stage);
258                stage.rollData = data;
259                intel.sendUpdateIfPlayerHasIntel(data, false);
260        }
261        
262        public boolean fireEvent(HostileActivityEventIntel intel, EventStageData stage) {
263                StarSystemAPI target = findBlockadeTarget(intel, stage);
264                MarketAPI source = getBlockadeSource(intel, stage, target);
265                if (source == null || target == null) {
266                        return false;
267                }
268        
269                stage.rollData = null;
270                return startBlockade(source, target, stage, getRandomizedStageRandom(3));
271        }
272        
273        
274        public static StarSystemAPI findBlockadeTarget(HostileActivityEventIntel intel, EventStageData stage) {
275                float max = 0f;
276                StarSystemAPI best = null;
277                for (StarSystemAPI system : Misc.getPlayerSystems(false)) {
278                        float w = intel.getMarketPresenceFactor(system);
279                        if (w > max) {
280                                max = w;
281                                best = system;
282                        }
283                }
284                return best;
285        }
286        
287        public MarketAPI getBlockadeSource(HostileActivityEventIntel intel, EventStageData stage, final StarSystemAPI target) {
288                return getKazeron(true);
289        }
290        
291        public static MarketAPI getKazeron(boolean requireMilitaryBase) {
292                MarketAPI kazeron = Global.getSector().getEconomy().getMarket("kazeron");
293                if (kazeron == null || kazeron.hasCondition(Conditions.DECIVILIZED) || 
294                                !kazeron.getFactionId().equals(Factions.PERSEAN)) {
295                        return null;
296                }
297                if (requireMilitaryBase) {
298                        Industry b = kazeron.getIndustry(Industries.MILITARYBASE);
299                        if (b == null) b = kazeron.getIndustry(Industries.HIGHCOMMAND);
300                        if (b == null || b.isDisrupted() || !b.isFunctional()) {
301                                return null;
302                        }
303                }
304                return kazeron;
305        }
306        
307        public static boolean wasPLEverSatBombardedByPlayer() {
308                FactionAPI faction = Global.getSector().getFaction(Factions.PERSEAN);
309                if (faction != null) {
310                        return faction.getMemoryWithoutUpdate().getInt(MemFlags.FACTION_SATURATION_BOMBARED_BY_PLAYER) > 0;
311                }
312                return false;
313        }
314        
315        
316        public boolean startBlockade(MarketAPI source, StarSystemAPI target, EventStageData stage, Random random) {
317                GenericRaidParams params = new GenericRaidParams(new Random(random.nextLong()), true);
318                params.factionId = source.getFactionId();
319                params.source = source;
320                
321                params.prepDays = 7f + random.nextFloat() * 14f;
322                params.payloadDays = 365f;
323                
324                params.makeFleetsHostile = false;
325                
326                FGBlockadeParams bParams = new FGBlockadeParams();
327                bParams.where = target;
328                bParams.targetFaction = Factions.PLAYER;
329                
330                
331                params.style = FleetStyle.STANDARD;
332                
333                
334                // standard Kazeron fleet size multiplier with no shortages/issues is a bit over 200%
335                float fleetSizeMult = source.getStats().getDynamic().getMod(Stats.COMBAT_FLEET_SIZE_MULT).computeEffective(0f);
336                
337                float f = intel.getMarketPresenceFactor(target);
338                
339                float totalDifficulty = fleetSizeMult * 50f * (0.5f + 0.5f * f);
340                if (totalDifficulty < 30) {
341                        return false;
342                }
343                if (totalDifficulty > 100) {
344                        totalDifficulty = 100;
345                }
346                
347                
348                totalDifficulty -= 10;
349                totalDifficulty -= 5;
350                totalDifficulty -= 4;
351                totalDifficulty -= 1;
352                totalDifficulty -= 1;
353                params.fleetSizes.add(10); // first size 10 pick becomes the Grand Armada
354                params.fleetSizes.add(5);
355                params.fleetSizes.add(4);
356                params.fleetSizes.add(1); // supply fleets #1
357                params.fleetSizes.add(1); // supply fleets #2
358                
359                Random r = getRandomizedStageRandom(7);
360                
361                // mostly maxed-out fleets, some smaller ones
362                while (totalDifficulty > 0) {
363                        float max = 5f;
364                        float min = 3f;
365                        
366                        if (r.nextFloat() > 0.3f) {
367                                min = (int) Math.min(totalDifficulty, 10f);
368                                max = (int) Math.min(totalDifficulty, 10f);
369                        }
370                        
371                        int diff = Math.round(StarSystemGenerator.getNormalRandom(r, min, max));
372                        
373                        
374                        params.fleetSizes.add(diff);
375                        totalDifficulty -= diff;
376                }
377                
378                PerseanLeagueBlockade blockade = new PerseanLeagueBlockade(params, bParams);
379                blockade.setListener(this);
380                Global.getSector().getIntelManager().addIntel(blockade);
381                
382                return true;
383        }
384        
385        public void reportFGIAborted(FleetGroupIntel intel) {
386                PerseanLeagueMembership.setDefeatedBlockade(true);
387                new EstablishedPolityScript();
388//              Misc.adjustRep(Factions.HEGEMONY, HEGEMONY_REP_FOR_DEFEATING, null);
389//              Misc.adjustRep(Factions.INDEPENDENT, INDEPENDENT_REP_FOR_DEFEATING, null);
390        }
391        
392        
393        
394        @Override
395        public void notifyFactorRemoved() {
396                Global.getSector().getListenerManager().removeListener(this);
397        }
398
399        public void notifyEventEnding() {
400                notifyFactorRemoved();
401        }
402
403        
404        public void reportRaidForValuablesFinishedBeforeCargoShown(InteractionDialogAPI dialog, MarketAPI market,
405                        TempData actionData, CargoAPI cargo) {
406                
407        }
408
409        public void reportRaidToDisruptFinished(InteractionDialogAPI dialog, MarketAPI market, TempData actionData, Industry industry) {
410                
411        }
412
413        public void reportTacticalBombardmentFinished(InteractionDialogAPI dialog, MarketAPI market, TempData actionData) {
414                MarketAPI kazeron = getKazeron(false);
415                if (market != null && market == kazeron) {
416                        EventStageData stage = intel.getDataFor(Stage.HA_EVENT);
417                        if (stage != null) {
418                                boolean thisEvent = stage.rollData instanceof HAERandomEventData && 
419                                                ((HAERandomEventData)stage.rollData).factor == this;
420                                // no points if blockade is the event since it'll lead to a reset anyway
421                                if (!thisEvent) {
422                                        int points = Global.getSettings().getInt("HA_tacBombardKazeron");
423                                        if (points > 0) {
424                                                intel.addFactor(new HAKazeronTacBombardmentFactor(-points));
425                                        }
426                                }
427                        }
428//                      intel.resetHA_EVENTIfFromFactor(this);
429//                      EventStageData stage = intel.getDataFor(Stage.HA_EVENT);
430//                      if (stage != null && stage.rollData instanceof HAERandomEventData && 
431//                                      ((HAERandomEventData)stage.rollData).factor == this) {
432//                              intel.resetHA_EVENT();
433//                      }
434                }
435        }
436
437        public void reportSaturationBombardmentFinished(InteractionDialogAPI dialog, MarketAPI market, TempData actionData) {
438                
439        }
440
441        @Override
442        public void advance(float amount) {
443                super.advance(amount);
444                
445//              if (!Global.getSector().getListenerManager().hasListener(this)) {
446//                      Global.getSector().getListenerManager().addListener(this);
447//              }
448                
449                EventStageData stage = intel.getDataFor(Stage.HA_EVENT);
450                if (stage != null && stage.rollData instanceof HAERandomEventData && 
451                                ((HAERandomEventData)stage.rollData).factor == this) {
452                        MarketAPI kazeron = getKazeron(true);
453                        
454                        if (kazeron == null || wasPLEverSatBombardedByPlayer()) {
455                                intel.resetHA_EVENT();
456                        }                       
457                }
458        }
459        
460        
461}
462
463
464
465