001package com.fs.starfarer.api.impl.campaign.intel.bar.events;
002
003import java.awt.Color;
004import java.util.Set;
005
006import org.apache.log4j.Logger;
007
008import com.fs.starfarer.api.Global;
009import com.fs.starfarer.api.campaign.CampaignFleetAPI;
010import com.fs.starfarer.api.campaign.CargoAPI;
011import com.fs.starfarer.api.campaign.CargoAPI.CargoItemType;
012import com.fs.starfarer.api.campaign.CargoStackAPI;
013import com.fs.starfarer.api.campaign.FactionAPI;
014import com.fs.starfarer.api.campaign.InteractionDialogAPI;
015import com.fs.starfarer.api.campaign.RepLevel;
016import com.fs.starfarer.api.campaign.ReputationActionResponsePlugin.ReputationAdjustmentResult;
017import com.fs.starfarer.api.campaign.SectorEntityToken;
018import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
019import com.fs.starfarer.api.campaign.econ.MarketAPI;
020import com.fs.starfarer.api.campaign.econ.SubmarketAPI;
021import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin;
022import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.MissionCompletionRep;
023import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActionEnvelope;
024import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActions;
025import com.fs.starfarer.api.impl.campaign.DebugFlags;
026import com.fs.starfarer.api.impl.campaign.ids.Factions;
027import com.fs.starfarer.api.impl.campaign.ids.Tags;
028import com.fs.starfarer.api.impl.campaign.intel.BaseMissionIntel;
029import com.fs.starfarer.api.impl.campaign.intel.contacts.ContactIntel;
030import com.fs.starfarer.api.impl.campaign.rulecmd.AddRemoveCommodity;
031import com.fs.starfarer.api.impl.campaign.shared.PlayerTradeDataForSubmarket;
032import com.fs.starfarer.api.impl.campaign.shared.SharedData;
033import com.fs.starfarer.api.ui.LabelAPI;
034import com.fs.starfarer.api.ui.SectorMapAPI;
035import com.fs.starfarer.api.ui.TooltipMakerAPI;
036import com.fs.starfarer.api.util.Misc;
037
038
039public class DeliveryMissionIntel extends BaseMissionIntel {
040        public static float PROB_PIRATE_ENCOUNTER = 0.5f;
041        
042        public static float PROB_CONSEQUENCES = 0.75f;
043        public static float PROB_CONSEQUENCES_ESCROW = 0.25f;
044        
045        public static Logger log = Global.getLogger(DeliveryMissionIntel.class);
046        
047        protected DeliveryBarEvent event;
048        
049        public DeliveryMissionIntel(DeliveryBarEvent event, InteractionDialogAPI dialog) {
050                this.event = event;
051                
052                setDuration(event.getDuration());
053                
054                Global.getSector().getIntelManager().addIntel(this, false, dialog == null ? null : dialog.getTextPanel());
055                
056                setImportant(true);
057                setMissionState(MissionState.ACCEPTED);
058                missionAccepted();
059                Global.getSector().addScript(this);
060
061                // doesn't quite connect up as far as easily making the mission fail etc
062//              if ((float) Math.random() < PROB_PIRATE_ENCOUNTER) {
063//                      Random random = new Random();
064//                      String id = "dmi_" + Misc.genUID();
065//                      
066//                      float reward = event.getReward();
067//                      FleetSize size = FleetSize.LARGE;
068//                      String type = FleetTypes.PATROL_LARGE;
069//                      String repLoss = DelayedFleetEncounter.TRIGGER_REP_LOSS_HIGH;
070//                      if (reward <= 20000) {
071//                              size = FleetSize.SMALL;
072//                              type = FleetTypes.PATROL_SMALL;
073//                              repLoss = DelayedFleetEncounter.TRIGGER_REP_LOSS_MINOR;
074//                      } else if (reward <= 50000) {
075//                              size = FleetSize.MEDIUM;
076//                              type = FleetTypes.PATROL_MEDIUM;
077//                              repLoss = DelayedFleetEncounter.TRIGGER_REP_LOSS_MEDIUM;
078//                      }
079//                      
080//                      
081//                      String comName = getCommodity().getCommodity().getLowerCaseName();
082//                      
083//                      DelayedFleetEncounter e = new DelayedFleetEncounter(random, id);
084//                      e.setDelayNone();
085//                      e.setLocationInnerSector(false, null);
086//                      e.beginCreate();
087//                      e.triggerCreateFleet(size, FleetQuality.DEFAULT, Factions.PIRATES, type, new Vector2f());
088//                      e.setFleetWantsThing(Factions.PIRATES, 
089//                                      "the " + comName + " shipment", "it",
090//                                      "the " + comName + " shipment you're running for " + event.getPerson().getNameString(),
091//                                      0,
092//                                      true, ComplicationRepImpact.FULL,
093//                                      repLoss, event.getPerson());
094//                      e.triggerSetFleetMemoryValue("$dmi_commodity", event.getCommodityId());
095//                      e.triggerSetFleetMemoryValue("$dmi_quantity", event.getQuantity());
096//                      e.triggerSetStandardAggroInterceptFlags();
097//                      e.triggerMakeLowRepImpact();
098//                      e.endCreate();
099//              }
100        }
101        
102        public void missionAccepted() {
103                Misc.makeImportant(event.getDestination().getPrimaryEntity(), "deliveryEvent");
104        }
105        
106        public DeliveryBarEvent getEvent() {
107                return event;
108        }
109
110        @Override
111        public void advanceMission(float amount) {
112                if (!event.getDestination().isInEconomy()) {
113                        setMissionResult(new MissionResult(0, null, null));
114                        setMissionState(MissionState.FAILED);
115                        endMission();
116                }
117        }
118
119        
120        public void performDelivery(InteractionDialogAPI dialog) {
121                CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet();
122                CargoAPI cargo = playerFleet.getCargo();
123                
124                cargo.removeItems(CargoItemType.RESOURCES, event.getCommodityId(), event.getQuantity());
125                cargo.getCredits().add(event.getReward() + event.getEscrow());
126                applyTradeValueImpact(event.getReward());
127                AddRemoveCommodity.addCommodityLossText(event.getCommodityId(), event.getQuantity(), dialog.getTextPanel());
128                if (event.getEscrow() > 0) {
129                        AddRemoveCommodity.addCreditsGainText(event.getEscrow(), dialog.getTextPanel());
130                }
131                AddRemoveCommodity.addCreditsGainText(event.getReward(), dialog.getTextPanel());
132                
133                float repAmount = 0.01f * event.getReward() / 10000f;
134                if (repAmount < 0.01f) repAmount = 0.01f;
135                if (repAmount > 0.05f) repAmount = 0.05f;
136                
137                MissionCompletionRep completionRep = new MissionCompletionRep(repAmount, RepLevel.COOPERATIVE, -repAmount, RepLevel.INHOSPITABLE);
138                
139                ReputationAdjustmentResult rep = null;
140                rep = Global.getSector().adjustPlayerReputation(
141                                new RepActionEnvelope(RepActions.MISSION_SUCCESS, completionRep,
142                                                null, dialog.getTextPanel(), true, true), 
143                                                getFactionForUIColors().getId());
144                
145                setMissionResult(new MissionResult(event.getReward() + event.getEscrow(), rep, null));
146                setMissionState(MissionState.COMPLETED);
147                endMission();
148                
149                ContactIntel.addPotentialContact(event.getPerson(), event.getMarket(), dialog.getTextPanel());
150        }
151        
152        public boolean hasEnough() {
153                CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet();
154                CargoAPI cargo = playerFleet.getCargo();
155                
156                return cargo.getCommodityQuantity(event.getCommodityId()) >= event.getQuantity();
157        }
158
159        
160        protected void applyTradeValueImpact(float totalReward) {
161                FactionAPI faction = getFactionForUIColors();
162                MarketAPI market = event.getDestination();
163                
164                boolean illegal = market.isIllegal(event.getCommodityId());
165                
166                SubmarketAPI submarket = null;
167                for (SubmarketAPI curr : market.getSubmarketsCopy()) {
168                        if (!curr.getPlugin().isParticipatesInEconomy()) continue;
169                        
170                        if (illegal && curr.getPlugin().isBlackMarket()) {
171                                submarket = curr;
172                                break;
173                        }
174                        if (!illegal && curr.getPlugin().isOpenMarket()) {
175                                submarket = curr;
176                                break;
177                        }
178                }
179                
180                if (submarket == null) return;
181                
182                PlayerTradeDataForSubmarket tradeData = SharedData.getData().getPlayerActivityTracker().getPlayerTradeData(submarket);
183                CargoStackAPI stack = Global.getFactory().createCargoStack(CargoItemType.RESOURCES, event.getCommodityId(), null);
184                stack.setSize(event.getQuantity());
185                tradeData.addToTrackedPlayerSold(stack, totalReward);
186                
187                Misc.affectAvailabilityWithinReason(getCommodity(), event.getQuantity());
188        }
189        
190        
191        public void endMission() {
192                if (event.getMarket() == null) {
193                        endAfterDelay();
194                        return; // to fix crash for saves that are already in a bad state
195                }
196                
197                Misc.makeUnimportant(event.getDestination().getPrimaryEntity(), "deliveryEvent");
198                
199                if (!event.getMarket().isPlayerOwned()) {
200                        if (isFailed() || isAbandoned()) {
201                                Global.getSector().getMemoryWithoutUpdate().set(
202                                                DeliveryBarEvent.KEY_FAILED_RECENTLY, true, 
203                                                DeliveryBarEvent.FAILED_RECENTLY_DURATION * (0.75f + (float) Math.random() * 0.5f));
204                                
205                                float p = PROB_CONSEQUENCES;
206                                if (event.getEscrow() > 0) {
207                                        p = PROB_CONSEQUENCES_ESCROW;
208                                }
209                                if ((float) Math.random() < p || DebugFlags.BAR_DEBUG) {
210                                        Global.getSector().addScript(new DeliveryFailureConsequences(this));
211                                }
212                        }
213                }
214                endAfterDelay();
215        }
216        
217        public boolean runWhilePaused() {
218                return false;
219        }
220        
221        protected void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode) {
222                
223                Color h = Misc.getHighlightColor();
224                Color g = Misc.getGrayColor();
225                float pad = 3f;
226                float opad = 10f;
227                
228                float initPad = pad;
229                if (mode == ListInfoMode.IN_DESC) initPad = opad;
230                
231                Color tc = getBulletColorForMode(mode);
232                
233                bullet(info);
234                boolean isUpdate = getListInfoParam() != null;
235                
236                FactionAPI faction = getFactionForUIColors();
237                if (isUpdate) {
238                        // 3 possible updates: de-posted/expired, failed, completed
239                        if (isFailed() || isCancelled()) {
240                                return;
241                        } else if (isCompleted() && missionResult != null) {
242                                if (missionResult.payment > 0) {
243                                        info.addPara("%s received", initPad, tc, h, Misc.getDGSCredits(missionResult.payment));
244                                }
245                                
246                                if (missionResult.rep1 != null && missionResult.rep1.delta != 0) {
247                                        CoreReputationPlugin.addAdjustmentMessage(missionResult.rep1.delta, faction, null, 
248                                                                                                                  null, null, info, tc, isUpdate, 0f);
249                                }
250                        }
251                } else {
252                        // either in small description, or in tooltip/intel list
253                        if (missionResult != null) {
254                                if (missionResult.payment > 0) {
255                                        info.addPara("%s received", initPad, tc, h, Misc.getDGSCredits(missionResult.payment));
256                                        initPad = 0f;
257                                }
258                                
259                                if (missionResult.rep1 != null && missionResult.rep1.delta != 0) {
260                                        CoreReputationPlugin.addAdjustmentMessage(missionResult.rep1.delta, faction, null, 
261                                                                                                          null, null, info, tc, isUpdate, initPad);
262                                        initPad = 0f;
263                                }
264                        } else {
265                                if (mode != ListInfoMode.IN_DESC) {
266                                        info.addPara("Faction: " + faction.getDisplayName(), initPad, tc,
267                                                                                                 faction.getBaseUIColor(),
268                                                                                                 faction.getDisplayName());
269                                        initPad = 0f;
270                                }
271                                
272                                LabelAPI label = info.addPara("%s units to " + event.getDestination().getName(), 
273                                                         initPad, tc, h, "" + (int) event.getQuantity());
274                                label.setHighlight("" + event.getQuantity(), event.getDestination().getName());
275                                label.setHighlightColors(h, event.getDestination().getFaction().getBaseUIColor());
276                                info.addPara("%s reward", 0f, tc, h, Misc.getDGSCredits(event.getReward()));
277                                if (event.getEscrow() > 0) {
278                                        info.addPara("%s held in escrow", 0f, tc, h, Misc.getDGSCredits(event.getEscrow()));
279                                }
280                                addDays(info, "to complete", duration - elapsedDays, tc, 0f);
281                        }
282                }
283                
284                unindent(info);
285        }
286        
287        @Override
288        public void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode) {
289                Color h = Misc.getHighlightColor();
290                Color g = Misc.getGrayColor();
291                Color c = getTitleColor(mode);
292                float pad = 3f;
293                float opad = 10f;
294                
295                info.addPara(getName(), c, 0f);
296                
297                addBulletPoints(info, mode);
298        }
299        
300        public String getSortString() {
301                return "Delivery";
302        }
303        
304        public String getName() {
305                if (isAccepted() || isPosted()) {
306                        return "Delivery - " + getCommodity().getCommodity().getName();
307                }
308                
309                return "Delivery " + getPostfixForState();
310        }
311        
312        @Override
313        public FactionAPI getFactionForUIColors() {
314                return event.getFaction();
315        }
316
317        public String getSmallDescriptionTitle() {
318                return getName();
319        }
320        
321        protected CommodityOnMarketAPI getCommodity() {
322                return event.getDestination().getCommodityData(event.getCommodityId());
323        }
324        
325
326        @Override
327        public void createSmallDescription(TooltipMakerAPI info, float width, float height) {
328                Color h = Misc.getHighlightColor();
329                Color g = Misc.getGrayColor();
330                Color tc = Misc.getTextColor();
331                float pad = 3f;
332                float opad = 10f;
333
334                FactionAPI faction = getFactionForUIColors();
335                
336                boolean illegal = event.getDestination().isIllegal(event.getCommodityId());
337                
338                //info.addImage(commodity.getCommodity().getIconName(), width, 80, opad);
339                
340                CommodityOnMarketAPI com = getCommodity();
341                MarketAPI market = event.getDestination();
342                
343                info.addImages(width, 80, opad, opad * 2f,
344                                           com.getCommodity().getIconName(),
345                                           faction.getCrest(),
346                                           market.getFaction().getCrest());
347
348                
349                String post = "";
350                if (Factions.PIRATES.equals(faction.getId())) {
351                        post = "-affiliated";
352                }
353                
354                //String desc = event.getPersonDesc();
355                String start = "You've";
356                if (!isPosted() && !isAccepted()) start = "You had";
357                
358                if (event.getMarket() == null) {
359                        return;
360                }
361                LabelAPI label = info.addPara(start + " accepted " + faction.getPersonNamePrefixAOrAn() + " " + 
362                                faction.getPersonNamePrefix() + post + " contract to deliver a quantity of " +
363                                com.getCommodity().getLowerCaseName() + 
364                                " from " + event.getMarket().getName() + " to " + market.getName() + ", " +
365                                                "which is under " + market.getFaction().getPersonNamePrefix() + " control.", opad,
366                                faction.getBaseUIColor(), faction.getPersonNamePrefix() + post);
367                
368                label.setHighlight(faction.getPersonNamePrefix() + post, market.getFaction().getPersonNamePrefix());
369                label.setHighlightColors(faction.getBaseUIColor(), market.getFaction().getBaseUIColor());
370                
371                if (isPosted() || isAccepted()) {
372                        addBulletPoints(info, ListInfoMode.IN_DESC);
373                        
374                        info.addPara("To make the delivery, either dock at " + market.getName() + " openly or approach it without " +
375                                                 "attracting the attention of nearby patrols.", opad);
376                        
377//                      if (illegal) {
378//                              info.addPara("The legality of the delivery is at best questionable and " +
379//                                              "it must be made with the transponder turned off.", opad);
380//                      } else {
381//                              info.addPara("The contract is above-board and the delivery may be made openly.", opad);
382//                      }
383                        
384                        //addGenericMissionState(info);
385                        addAcceptOrAbandonButton(info, width);
386                } else {
387                        if (isFailed() && !market.isInEconomy()) {
388                                info.addPara("You have failed this contract because " + market.getName() + 
389                                                     " no longer exists as a functional polity.", opad);        
390                        } else {
391                                addGenericMissionState(info);
392                        }
393                        
394                        addBulletPoints(info, ListInfoMode.IN_DESC);
395                }
396
397        }
398        
399        public String getIcon() {
400                return getCommodity().getCommodity().getIconName();
401        }
402        
403        public Set<String> getIntelTags(SectorMapAPI map) {
404                Set<String> tags = super.getIntelTags(map);
405                tags.add(Tags.INTEL_TRADE);
406                tags.add(getFactionForUIColors().getId());
407                return tags;
408        }
409        
410
411        @Override
412        public SectorEntityToken getMapLocation(SectorMapAPI map) {
413                return event.getDestination().getPrimaryEntity();
414        }
415        
416
417
418        @Override
419        protected String getMissionTypeNoun() {
420                return "contract";
421        }
422        
423
424        @Override
425        protected MissionResult createAbandonedResult(boolean withPenalty) {
426                if (withPenalty) {
427                        float repAmount = 0.01f * event.getReward() / 10000f;
428                        if (repAmount < 0.01f) repAmount = 0.01f;
429                        if (repAmount > 0.05f) repAmount = 0.05f;
430                        
431                        MissionCompletionRep completionRep = new MissionCompletionRep(repAmount, RepLevel.WELCOMING, -repAmount, RepLevel.INHOSPITABLE);
432                        
433                        ReputationAdjustmentResult rep = Global.getSector().adjustPlayerReputation(
434                                        new RepActionEnvelope(RepActions.MISSION_FAILURE, completionRep,
435                                                                                  null, null, true, false),
436                                                                                  getFactionForUIColors().getId());
437                        
438                        return new MissionResult(0, rep, null);
439                }
440                return new MissionResult();
441        }
442
443        @Override
444        public boolean canAbandonWithoutPenalty() {
445                return false;
446        }
447
448        @Override
449        protected MissionResult createTimeRanOutFailedResult() {
450                return createAbandonedResult(true);
451        }
452        
453        public MarketAPI getDestination() {
454                return event.getDestination();
455        }
456        
457}
458
459