001package com.fs.starfarer.api.impl.campaign.intel.misc;
002
003import java.awt.Color;
004import java.util.ArrayList;
005import java.util.List;
006import java.util.Set;
007
008import com.fs.starfarer.api.Global;
009import com.fs.starfarer.api.campaign.FactionAPI;
010import com.fs.starfarer.api.campaign.SectorEntityToken;
011import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
012import com.fs.starfarer.api.campaign.econ.CommoditySpecAPI;
013import com.fs.starfarer.api.impl.campaign.fleets.EconomyFleetAssignmentAI.CargoQuantityData;
014import com.fs.starfarer.api.impl.campaign.fleets.EconomyFleetAssignmentAI.EconomyRouteData;
015import com.fs.starfarer.api.impl.campaign.fleets.EconomyFleetRouteManager;
016import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
017import com.fs.starfarer.api.impl.campaign.ids.Tags;
018import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
019import com.fs.starfarer.api.ui.IconRenderMode;
020import com.fs.starfarer.api.ui.LabelAPI;
021import com.fs.starfarer.api.ui.SectorMapAPI;
022import com.fs.starfarer.api.ui.TooltipMakerAPI;
023import com.fs.starfarer.api.util.Misc;
024
025public class TradeFleetDepartureIntel extends BaseIntelPlugin {
026
027        protected RouteData route;
028        
029        transient protected List<CargoQuantityData> deliverList;
030        transient protected List<CargoQuantityData> returnList;
031        transient protected boolean goods;
032        transient protected boolean materiel;
033        transient protected boolean valuable;
034        transient protected boolean large;
035        transient protected FactionAPI faction;
036        transient protected EconomyRouteData data;
037        
038
039        public TradeFleetDepartureIntel(RouteData route) {
040                this.route = route;
041                
042                initTransientData();
043                
044                //if (deliverList.isEmpty() && returnList.isEmpty()) {
045                if (deliverList.isEmpty()) {
046                        return;
047                }
048
049                float prob = 0.1f;
050                if (valuable) prob += 0.1f;
051                if (large) prob += 0.1f;
052                if (!deliverList.isEmpty() && !returnList.isEmpty()) {
053                        prob += 0.2f;
054                }
055                
056                boolean sameLoc = data.from.getPrimaryEntity().getContainingLocation() != null &&
057                                                  data.from.getPrimaryEntity().getContainingLocation() == 
058                                                          Global.getSector().getPlayerFleet().getContainingLocation() &&
059                                                  !data.from.getPrimaryEntity().getContainingLocation().isHyperspace();
060                if (sameLoc) prob = 1f;
061                
062                float target = Global.getSettings().getFloat("targetNumTradeFleetNotifications");
063                float numAlready = Global.getSector().getIntelManager().getIntelCount(TradeFleetDepartureIntel.class, true);
064                
065                float probMult = Misc.getProbabilityMult(target, numAlready, 0.5f);
066                if (probMult > 1) probMult = 1; // just making it less likely if there's a bunch of these already
067                
068                prob *= probMult;
069                
070                
071                
072                
073                if (Math.random() > prob) {
074                        return;
075                }
076                
077                float postingRange = Math.max(0f, data.size - 6f);
078                if (valuable) {
079                        postingRange = Math.max(3f, postingRange);
080                }
081                setPostingRangeLY(postingRange, true);
082                
083                setPostingLocation(data.from.getPrimaryEntity());
084                
085                Global.getSector().getIntelManager().queueIntel(this);
086        }
087        
088        
089        protected void initTransientData() {
090                data = (EconomyRouteData) route.getCustom();
091
092                deliverList = new ArrayList<CargoQuantityData>();
093                returnList = new ArrayList<CargoQuantityData>();
094                goods = false;
095                materiel = false;
096                valuable = false;
097                large = data.size >= 6;
098
099                for (CargoQuantityData curr : data.cargoDeliver) {
100                        CommoditySpecAPI c = curr.getCommodity();
101                        if (c.getBasePrice() >= 100 && !c.isPersonnel()) {
102                                valuable = true;
103                        }
104
105                        if (c.isMeta()) {
106                                materiel = true;
107                        } else if (!c.isPersonnel()) {
108                                goods = true;
109                        }
110                        deliverList.add(curr);
111                }
112                for (CargoQuantityData curr : data.cargoReturn) {
113                        // don't care about return list too much, it's nowhere near as timely
114//                      CommoditySpecAPI c = curr.getCommodity();
115//                      if (c.getBasePrice() >= 100 && !c.isPersonnel()) {
116//                              valuable = true;
117//                      }
118//
119//                      if (c.isMeta()) {
120//                              materiel = true;
121//                      } else if (!c.isPersonnel()) {
122//                              goods = true;
123//                      }
124                        returnList.add(curr);
125                }
126                
127                faction = Global.getSector().getFaction(route.getFactionId());
128        }
129        
130        protected void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode) {
131                
132                Color h = Misc.getHighlightColor();
133                Color g = Misc.getGrayColor();
134                float pad = 3f;
135                float opad = 10f;
136                
137                float initPad = pad;
138                if (mode == ListInfoMode.IN_DESC) initPad = opad;
139                
140                Color tc = getBulletColorForMode(mode);
141                
142                bullet(info);
143                boolean isUpdate = getListInfoParam() != null;
144                
145                if (mode != ListInfoMode.IN_DESC) {
146                        info.addPara("Faction: " + faction.getDisplayName(), initPad, tc,
147                                                 faction.getBaseUIColor(), faction.getDisplayName());
148                        initPad = 0f;
149                }
150                
151//              String what = getWhat();
152//              if (valuable) {
153//                      info.addPara("Carrying valuable " + what, tc, initPad);
154//                      initPad = 0f;
155//              } else if (large) {
156//                      info.addPara("Large volume of " + what, tc, initPad);
157//                      initPad = 0f;
158//              }
159                
160                if (mode != ListInfoMode.IN_DESC) {
161                        LabelAPI label = info.addPara("From " + data.from.getName() + " to " + data.to.getName(), tc, initPad);
162                        label.setHighlight(data.from.getName(), data.to.getName());
163                        label.setHighlightColors(data.from.getFaction().getBaseUIColor(), data.to.getFaction().getBaseUIColor());
164                        initPad = 0f;
165                }
166                
167                if (isUpdate) {
168                        info.addPara("Fleet launched", tc, initPad);
169                } else {
170                        float delay = route.getDelay();
171                        if (delay > 0) {
172                                addDays(info, "until departure", delay, tc, initPad);
173                        } else {
174                                info.addPara("Recently launched", tc, initPad);
175                        }
176                }
177                
178                unindent(info);
179        }
180        
181        protected String getWhat() {
182                String what = "goods and materiel";
183                if (!materiel) what = "goods";
184                if (!goods) what = "materiel";
185                return what;
186        }
187        
188        @Override
189        public void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode) {
190                Color h = Misc.getHighlightColor();
191                Color g = Misc.getGrayColor();
192                Color c = getTitleColor(mode);
193                float pad = 3f;
194                float opad = 10f;
195                
196                initTransientData();
197                
198                LabelAPI label = info.addPara(getName(), c, 0f);
199//              label.setHighlight(Misc.ucFirst(getFactionForUIColors().getPersonNamePrefix()));
200//              label.setHighlightColor(getFactionForUIColors().getBaseUIColor());
201                
202                addBulletPoints(info, mode);
203        }
204        
205        @Override
206        public void createSmallDescription(TooltipMakerAPI info, float width, float height) {
207                initTransientData();
208                
209                Color h = Misc.getHighlightColor();
210                Color g = Misc.getGrayColor();
211                Color tc = Misc.getTextColor();
212                float pad = 3f;
213                float opad = 10f;
214                
215                info.addImage(faction.getLogo(), width, 128, opad);
216                
217                float tier = data.size;
218                String fleetType = getFleetTypeName().toLowerCase();
219                
220                
221//              LabelAPI label = info.addPara(Misc.ucFirst(faction.getPersonNamePrefixAOrAn()) + " " + 
222//                                       faction.getPersonNamePrefix() + " " + fleetType + " is departing from " +
223//                                       data.from.getName() + " and heading to " + data.to.getName() + ".",
224//                                       opad, tc, 
225//                                       faction.getBaseUIColor(),
226//                                       faction.getPersonNamePrefix());
227//              label.setHighlight(faction.getPersonNamePrefix(), data.from.getName(), data.to.getName());
228//              label.setHighlightColors(data.from.getFaction().getBaseUIColor(), data.from.getFaction().getBaseUIColor(), data.to.getFaction().getBaseUIColor());
229                
230                LabelAPI label = info.addPara("Your contacts " + data.from.getOnOrAt() + " " + data.from.getName() + 
231                                 " let you know that " + 
232                                 faction.getPersonNamePrefixAOrAn() + " " + 
233                                 faction.getPersonNamePrefix() + " " + fleetType + " is preparing for a voyage and will soon depart for " + 
234                                 data.to.getName() + ".",
235                                 opad, tc, 
236                                 faction.getBaseUIColor(),
237                                 faction.getPersonNamePrefix());
238                
239                label.setHighlight(data.from.getName(), faction.getPersonNamePrefix(), data.to.getName());
240                label.setHighlightColors(data.from.getFaction().getBaseUIColor(), faction.getBaseUIColor(), data.to.getFaction().getBaseUIColor());
241                
242                addBulletPoints(info, ListInfoMode.IN_DESC);
243                
244                
245                String what = getWhat();
246                
247                if (!deliverList.isEmpty()) {
248                        info.addPara("On the outward trip to " + data.to.getName() + " the fleet will carry " + 
249                                        EconomyRouteData.getCargoList(deliverList) + ".", opad);
250                        
251                        info.beginIconGroup();
252                        info.setIconSpacingMedium();
253                        
254                        for (CargoQuantityData curr : deliverList) {
255                                CommodityOnMarketAPI com = data.from.getCommodityData(curr.cargo);
256                                info.addIcons(com, curr.units, IconRenderMode.NORMAL);
257                        }
258                        info.addIconGroup(32, 1, opad);
259                } else {
260                        info.addPara("The fleet will carry nothing of note on the trip to " + data.to.getName() + ".", opad);
261                }
262                if (!returnList.isEmpty()) {
263                        info.addPara("On the trip back to " + data.from.getName() + " the fleet will carry " + 
264                                        EconomyRouteData.getCargoList(returnList) + ".", opad);
265                        
266                        info.beginIconGroup();
267                        info.setIconSpacingMedium();
268                        for (CargoQuantityData curr : returnList) {
269                                CommodityOnMarketAPI com = data.to.getCommodityData(curr.cargo);
270                                info.addIcons(com, curr.units, IconRenderMode.NORMAL);
271                        }
272                        info.addIconGroup(32, 1, opad);
273                } else {
274                        info.addPara("The fleet will carry nothing of note on the trip back to " + data.from.getName() + ".", opad);
275                }
276                
277                if (valuable && large) {
278                        info.addPara("It's noteworthy because it's carrying a large quantity of valuable " + what + ".", opad);
279                } else if (valuable) {
280                        info.addPara("It's noteworthy because it's carrying valuable " + what + ".", opad);
281                } else if (large) {
282                        info.addPara("It's noteworthy because it's carrying a large quantity of " + what + ".", opad);
283                }
284                
285                if (data.smuggling) {
286                        info.addPara("Smugglers often operate in a gray legal and moral area. " +
287                                                 "Thus, if one comes to an unfortunate end - as so often happens in their line of work - " +
288                                                 "it's unlikely to cause a unified response from whatever " +
289                                                 "faction or organization they're nominally affiliated with.", g, opad);
290                }
291        }
292        
293        @Override
294        public String getIcon() {
295                initTransientData();
296                if (data.smuggling) {
297                        return Global.getSettings().getSpriteName("intel", "tradeFleet_smuggling");
298                } else if (valuable) {
299                        return Global.getSettings().getSpriteName("intel", "tradeFleet_valuable");
300                } else if (large) {
301                        return Global.getSettings().getSpriteName("intel", "tradeFleet_large");
302                } 
303                return Global.getSettings().getSpriteName("intel", "tradeFleet_other");
304        }
305        
306        @Override
307        public Set<String> getIntelTags(SectorMapAPI map) {
308                Set<String> tags = super.getIntelTags(map);
309                tags.add(Tags.INTEL_FLEET_DEPARTURES);
310                
311                faction = Global.getSector().getFaction(route.getFactionId());
312                tags.add(faction.getId());
313                
314                data = (EconomyRouteData) route.getCustom();
315                if (data.smuggling) {
316                        tags.add(Tags.INTEL_SMUGGLING);
317                }
318                
319                return tags;
320        }
321        
322        
323        public String getSortString() {
324                return "Trade Fleet Departure";
325        }
326        
327        public String getFleetTypeName() {
328                float tier = data.size;
329                String typeId = EconomyFleetRouteManager.getFleetTypeIdForTier(tier, data.smuggling);
330                String fleetType = faction.getFleetTypeName(typeId);
331                if (fleetType == null) {
332                        fleetType = "Trade Fleet";
333                }
334                return fleetType;
335        }
336        
337        public String getName() {
338                //return Misc.ucFirst(getFactionForUIColors().getPersonNamePrefix()) + " " + getFleetTypeName();
339                return getFleetTypeName();
340                //return "Trade Fleet Departure";
341        }
342        
343        @Override
344        public FactionAPI getFactionForUIColors() {
345                faction = Global.getSector().getFaction(route.getFactionId());
346                return faction;
347        }
348
349        public String getSmallDescriptionTitle() {
350                return getName();
351        }
352
353        @Override
354        public SectorEntityToken getMapLocation(SectorMapAPI map) {
355                return route.getMarket().getPrimaryEntity();
356        }
357        
358        
359        protected Float sinceLaunched = null;
360        @Override
361        protected void advanceImpl(float amount) {
362                super.advanceImpl(amount);
363                
364                if (route.getDelay() > 0) return;
365                
366                if (sinceLaunched == null) sinceLaunched = 0f;
367                
368                if (sinceLaunched <= 0 && amount > 0) {
369                        sendUpdateIfPlayerHasIntel(new Object(), true);
370                }
371                
372                float days = Misc.getDays(amount);
373                sinceLaunched += days;
374        }
375        
376        public float getTimeRemainingFraction() {
377                float f = route.getDelay() / 30f;
378                return f;
379        }
380        
381
382        @Override
383        public boolean shouldRemoveIntel() {
384                if (route.getDelay() > 0) return false;
385                if (isImportant()) return false;
386                if (sinceLaunched != null && sinceLaunched < getBaseDaysAfterEnd()) {
387                        return false;
388                }
389                return true;
390        }
391        
392
393        @Override
394        public void setImportant(Boolean important) {
395                super.setImportant(important);
396                if (isImportant()) {
397                        if (!Global.getSector().getScripts().contains(this)) {
398                                Global.getSector().addScript(this);
399                        }
400                } else {
401                        Global.getSector().removeScript(this);
402                }
403        }
404
405        @Override
406        public void reportRemovedIntel() {
407                super.reportRemovedIntel();
408                Global.getSector().removeScript(this);
409        }
410        
411        
412        public List<ArrowData> getArrowData(SectorMapAPI map) {
413                List<ArrowData> result = new ArrayList<ArrowData>();
414                
415                if (data.from.getContainingLocation() == data.to.getContainingLocation() &&
416                                data.from.getContainingLocation() != null &&
417                                !data.from.getContainingLocation().isHyperspace()) {
418                        return null;
419                }
420                
421                SectorEntityToken entityFrom = data.from.getPrimaryEntity();
422                if (map != null) {
423                        SectorEntityToken iconEntity = map.getIntelIconEntity(this);
424                        if (iconEntity != null) {
425                                entityFrom = iconEntity;
426                        }
427                }
428                
429                data = (EconomyRouteData) route.getCustom();
430                ArrowData arrow = new ArrowData(entityFrom, data.to.getPrimaryEntity());
431                arrow.color = getFactionForUIColors().getBaseUIColor();
432                result.add(arrow);
433                
434                return result;
435        }
436
437
438        public RouteData getRoute() {
439                return route;
440        }
441        
442}
443
444
445
446
447
448
449