001package com.fs.starfarer.api.impl.campaign.intel.events;
002
003import java.awt.Color;
004import java.util.Random;
005
006import com.fs.starfarer.api.Global;
007import com.fs.starfarer.api.campaign.CampaignFleetAPI;
008import com.fs.starfarer.api.campaign.StarSystemAPI;
009import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin.ListInfoMode;
010import com.fs.starfarer.api.campaign.econ.MarketAPI;
011import com.fs.starfarer.api.impl.campaign.ids.Factions;
012import com.fs.starfarer.api.impl.campaign.ids.Stats;
013import com.fs.starfarer.api.impl.campaign.intel.events.BaseEventIntel.EventStageData;
014import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.HAERandomEventData;
015import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.Stage;
016import com.fs.starfarer.api.impl.campaign.intel.group.FGRaidAction.FGRaidType;
017import com.fs.starfarer.api.impl.campaign.intel.group.FleetGroupIntel;
018import com.fs.starfarer.api.impl.campaign.intel.group.FleetGroupIntel.FGIEventListener;
019import com.fs.starfarer.api.impl.campaign.intel.group.GenericRaidFGI;
020import com.fs.starfarer.api.impl.campaign.intel.group.GenericRaidFGI.GenericRaidParams;
021import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission.FleetStyle;
022import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.ComplicationRepImpact;
023import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD.BombardType;
024import com.fs.starfarer.api.ui.LabelAPI;
025import com.fs.starfarer.api.ui.TooltipMakerAPI;
026import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipCreator;
027import com.fs.starfarer.api.util.Misc;
028import com.fs.starfarer.api.util.WeightedRandomPicker;
029
030public class RemnantHostileActivityFactor extends BaseHostileActivityFactor 
031                                                        implements FGIEventListener {
032
033        public RemnantHostileActivityFactor(HostileActivityEventIntel intel) {
034                super(intel);
035                
036                //Global.getSector().getListenerManager().addListener(this);
037        }
038        
039        public String getProgressStr(BaseEventIntel intel) {
040                return "";
041        }
042        
043        public String getDesc(BaseEventIntel intel) {
044                return "Remnant";
045        }
046        
047        public String getNameForThreatList(boolean first) {
048                return "Remnant";
049        }
050
051
052        public Color getDescColor(BaseEventIntel intel) {
053                if (getProgress(intel) <= 0) {
054                        return Misc.getGrayColor();
055                }
056                return Global.getSector().getFaction(Factions.REMNANTS).getBaseUIColor();
057        }
058
059        public TooltipCreator getMainRowTooltip(BaseEventIntel intel) {
060                return new BaseFactorTooltip() {
061                        public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
062                                float opad = 10f;
063                                tooltip.addPara("Remnant fleets have been sighted in your space.", opad);
064                        }
065                };
066        }
067
068        public boolean shouldShow(BaseEventIntel intel) {
069                return getProgress(intel) > 0;
070        }
071
072        @Override
073        public int getProgress(BaseEventIntel intel) {
074                return super.getProgress(intel);
075        }
076        
077        public Color getNameColor(float mag) {
078                if (mag <= 0f) {
079                        return Misc.getGrayColor();
080                }
081                return Global.getSector().getFaction(Factions.REMNANTS).getBaseUIColor();
082        }
083        
084        
085        @Override
086        public int getMaxNumFleets(StarSystemAPI system) {
087                return 0; // being spawned normally already
088        }
089        
090        public CampaignFleetAPI createFleet(StarSystemAPI system, Random random) {
091        
092//              float f = intel.getMarketPresenceFactor(system);
093//              
094//              int difficulty = 4 + (int) Math.round(f * 4f);
095//              
096//              FleetCreatorMission m = new FleetCreatorMission(random);
097//              m.beginFleet();
098//              
099//              Vector2f loc = system.getLocation();
100//              String factionId = Factions.REMNANTS;
101//              
102//              m.createQualityFleet(difficulty, factionId, loc);
103//              
104//              m.triggerSetFleetType(FleetTypes.RAIDER);
105//              
106//              m.triggerSetPirateFleet();
107//              m.triggerMakeHostile();
108//              m.triggerMakeNonHostileToFaction(Factions.REMNANTS);
109//              m.triggerMakeHostileToAllTradeFleets();
110//              m.triggerMakeNonHostileToFaction(Factions.PIRATES);
111//              m.triggerMakeLowRepImpact();
112//              m.triggerFleetAllowLongPursuit();
113//              
114//              m.triggerSetFleetFlag(RAIDER_FLEET);
115//              
116//              m.triggerFleetMakeFaster(true, 0, true);
117//              
118//              //m.triggerSetFleetMaxShipSize(3);
119//              
120//              
121//              CampaignFleetAPI fleet = m.createFleet();
122//
123//              return fleet;
124                
125                return null;
126        }
127        
128
129        
130        
131        public void addBulletPointForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info,
132                                                                                 ListInfoMode mode, boolean isUpdate, Color tc, float initPad) {
133                Color c = Global.getSector().getFaction(Factions.REMNANTS).getBaseUIColor();
134                info.addPara("Impending Remnant attack", initPad, tc, c, "Remnant");
135        }
136        
137        public void addBulletPointForEventReset(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info,
138                        ListInfoMode mode, boolean isUpdate, Color tc, float initPad) {
139                info.addPara("Remnant attack averted", tc, initPad);
140        }
141        
142        public void addStageDescriptionForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info) {
143                float small = 0f;
144                float opad = 10f;
145                
146                small = 8f;
147
148                Color c = Global.getSector().getFaction(Factions.REMNANTS).getBaseUIColor();
149
150                if (!(stage.rollData instanceof HAERandomEventData)) return;
151                HAERandomEventData data = (HAERandomEventData) stage.rollData;
152                if (!(data.custom instanceof MarketAPI)) return;
153                
154                MarketAPI target = (MarketAPI) data.custom;
155                
156                Color h = Misc.getHighlightColor();
157                info.addPara("There are signs of activity at a Remnant Nexus in your system. Intel evaluates "
158                                + "a high probability of an attack fleet being assembled to saturation-bombard " +
159                                target.getName() + ".",
160                                small, Misc.getNegativeHighlightColor(), "saturation-bombard");
161                
162                LabelAPI label = info.addPara("Defeating the attack fleet would only put off the problem, "
163                                + "but destroying the Remnant Nexus will end the threat for good.", 
164                                opad);
165                label.setHighlight("Remnant Nexus", "end the threat");
166                label.setHighlightColors(
167                                Global.getSector().getFaction(Factions.REMNANTS).getBaseUIColor(),
168                                Misc.getPositiveHighlightColor());
169                
170                c = Global.getSector().getFaction(Factions.REMNANTS).getBaseUIColor();
171                stage.beginResetReqList(info, true, "crisis", opad);
172                info.addPara("The %s is destroyed", 0f, c, "Remnant Nexus");
173                stage.endResetReqList(info, false, "crisis", -1, -1);
174                
175                addBorder(info, Global.getSector().getFaction(Factions.REMNANTS).getBaseUIColor());
176        }
177        
178        
179        public String getEventStageIcon(HostileActivityEventIntel intel, EventStageData stage) {
180                return Global.getSector().getFaction(Factions.REMNANTS).getCrest();
181        }
182
183        public TooltipCreator getStageTooltipImpl(final HostileActivityEventIntel intel, final EventStageData stage) {
184                if (stage.id == Stage.HA_EVENT) {
185                        return getDefaultEventTooltip("Remnant attack", intel, stage);
186                }
187                return null;
188        }
189
190        public static CampaignFleetAPI getRemnantNexus(StarSystemAPI system) {
191                if (system == null) return null;
192//              if (!system.hasTag(Tags.THEME_REMNANT_MAIN)) return null;
193//              if (system.hasTag(Tags.THEME_REMNANT_DESTROYED)) return null;
194                        
195                for (CampaignFleetAPI fleet : system.getFleets()) {
196                        if (!fleet.isStationMode()) continue;
197                        if (!Factions.REMNANTS.equals(fleet.getFaction().getId())) continue;
198                        
199                        return fleet;
200                }
201                return null;
202        }
203        
204        
205        public float getEventFrequency(HostileActivityEventIntel intel, EventStageData stage) {
206                if (stage.id == Stage.HA_EVENT) {
207                        
208                        MarketAPI target = findAttackTarget(intel, stage);
209                        if (target == null || target.getStarSystem() == null) return 0f;
210                        
211                        CampaignFleetAPI nexus = getRemnantNexus(target.getStarSystem());
212                        if (nexus == null) return 0f;
213                        
214                        return 10f;
215                }
216                return 0f;
217        }
218        
219
220        public void rollEvent(HostileActivityEventIntel intel, EventStageData stage) {
221                MarketAPI target = findAttackTarget(intel, stage);
222                if (target == null) return;
223                
224                HAERandomEventData data = new HAERandomEventData(this, stage);
225                data.custom = target;
226                stage.rollData = data;
227                intel.sendUpdateIfPlayerHasIntel(data, false);
228        }
229        
230        public boolean fireEvent(HostileActivityEventIntel intel, EventStageData stage) {
231                MarketAPI target = findAttackTarget(intel, stage);
232                if (target == null || target.getStarSystem() == null) return false;
233                
234                CampaignFleetAPI nexus = getRemnantNexus(target.getStarSystem());
235                if (nexus == null) return false;
236        
237                stage.rollData = null;
238                return startAttack(nexus, target, target.getStarSystem(), stage, getRandomizedStageRandom(3));
239        }
240        
241        
242        public MarketAPI findAttackTarget(HostileActivityEventIntel intel, EventStageData stage) {
243                WeightedRandomPicker<MarketAPI> picker = new WeightedRandomPicker<MarketAPI>(getRandomizedStageRandom(3));
244                
245                for (StarSystemAPI system : Misc.getPlayerSystems(false)) {
246                        CampaignFleetAPI nexus = getRemnantNexus(system);
247                        if (nexus != null) {
248                                for (MarketAPI curr : Misc.getMarketsInLocation(system, Factions.PLAYER)) {
249                                        picker.add(curr, curr.getSize() * curr.getSize() * curr.getSize());
250                                }
251                        }
252                }
253                return picker.pick();
254        }
255        
256        
257        
258        @Override
259        public void notifyFactorRemoved() {
260                //Global.getSector().getListenerManager().removeListener(this);
261        }
262
263        public void notifyEventEnding() {
264                notifyFactorRemoved();
265        }
266
267        @Override
268        public void advance(float amount) {
269                super.advance(amount);
270                
271                EventStageData stage = intel.getDataFor(Stage.HA_EVENT);
272                if (stage != null && stage.rollData instanceof HAERandomEventData && 
273                                ((HAERandomEventData)stage.rollData).factor == this) {
274                        
275                        HAERandomEventData data = (HAERandomEventData) stage.rollData;
276                        if (data.custom instanceof MarketAPI) {
277                                MarketAPI target = (MarketAPI) data.custom;
278                                if (getRemnantNexus(target.getStarSystem()) == null) {
279                                        intel.resetHA_EVENT();
280                                }
281                        }
282                }
283
284        }
285        
286
287        
288        public boolean startAttack(CampaignFleetAPI nexus, MarketAPI target, StarSystemAPI system, EventStageData stage, Random random) {
289                //System.out.println("RANDOM: " + random.nextLong());
290                
291                GenericRaidParams params = new GenericRaidParams(new Random(random.nextLong()), true);
292                
293                params.makeFleetsHostile = true;
294                params.remnant = true;
295                
296                params.factionId = nexus.getFaction().getId();
297                
298                MarketAPI fake = Global.getFactory().createMarket(nexus.getId(), nexus.getName(), 3);
299                fake.setPrimaryEntity(nexus);
300                fake.setFactionId(params.factionId);
301                fake.getStats().getDynamic().getMod(Stats.FLEET_QUALITY_MOD).modifyFlat(
302                                "nexus_" + nexus.getId(), 1f);
303                
304                //nexus.setMarket(fake); // can actually trade etc then, no good
305                
306                params.source = fake;
307                
308                params.prepDays = 0f;
309                params.payloadDays = 27f + 7f * random.nextFloat();
310                
311                params.raidParams.where = system;
312                params.raidParams.type = FGRaidType.SEQUENTIAL;
313                params.raidParams.tryToCaptureObjectives = false;
314                params.raidParams.allowedTargets.add(target);
315                params.raidParams.allowNonHostileTargets = true;
316                params.raidParams.setBombardment(BombardType.SATURATION);
317                params.forcesNoun = "remnant forces";
318                
319                params.style = FleetStyle.STANDARD;
320                params.repImpact = ComplicationRepImpact.FULL;
321                
322                
323                // standard Askonia fleet size multiplier with no shortages/issues is a bit over 230%
324                float fleetSizeMult = 1f;
325                boolean damaged = nexus.getMemoryWithoutUpdate().getBoolean("$damagedStation");
326                if (damaged) {
327                        fleetSizeMult = 0.5f;
328                }
329                
330                float totalDifficulty = fleetSizeMult * 50f;
331                
332                totalDifficulty -= 10;
333                params.fleetSizes.add(10);
334                
335                while (totalDifficulty > 0) {
336                        int min = 6;
337                        int max = 10;
338                        
339                        int diff = min + random.nextInt(max - min + 1);
340                        
341                        params.fleetSizes.add(diff);
342                        totalDifficulty -= diff;
343                }
344                
345                
346//              SindrianDiktatPunitiveExpedition punex = new SindrianDiktatPunitiveExpedition(params);
347//              punex.setListener(this);
348//              Global.getSector().getIntelManager().addIntel(punex);
349                
350                GenericRaidFGI raid = new GenericRaidFGI(params);
351                raid.setListener(this);
352                Global.getSector().getIntelManager().addIntel(raid);
353                
354                return true;
355        }
356
357        public void reportFGIAborted(FleetGroupIntel intel) {
358                // TODO: anything? Nothing happens if you defeat it, it's purely avoiding a bombardment
359        }
360
361}
362
363
364
365