001package com.fs.starfarer.api.impl.campaign.submarkets;
002
003import java.awt.Color;
004import java.util.Random;
005
006import org.apache.log4j.Logger;
007
008import com.fs.starfarer.api.Global;
009import com.fs.starfarer.api.campaign.CampaignUIAPI.CoreUITradeMode;
010import com.fs.starfarer.api.campaign.CargoStackAPI;
011import com.fs.starfarer.api.campaign.CoreUIAPI;
012import com.fs.starfarer.api.campaign.FactionDoctrineAPI;
013import com.fs.starfarer.api.campaign.RepLevel;
014import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
015import com.fs.starfarer.api.campaign.econ.SubmarketAPI;
016import com.fs.starfarer.api.combat.ShipAPI.HullSize;
017import com.fs.starfarer.api.fleet.FleetMemberAPI;
018import com.fs.starfarer.api.impl.campaign.ids.Commodities;
019import com.fs.starfarer.api.impl.campaign.ids.Factions;
020import com.fs.starfarer.api.loading.FighterWingSpecAPI;
021import com.fs.starfarer.api.loading.HullModSpecAPI;
022import com.fs.starfarer.api.loading.WeaponSpecAPI;
023import com.fs.starfarer.api.util.Highlights;
024import com.fs.starfarer.api.util.Misc;
025
026public class MilitarySubmarketPlugin extends BaseSubmarketPlugin {
027        
028        public static Logger log = Global.getLogger(MilitarySubmarketPlugin.class);
029        
030        public void init(SubmarketAPI submarket) {
031                super.init(submarket);
032        }
033
034        public void updateCargoPrePlayerInteraction() {
035                float seconds = Global.getSector().getClock().convertToSeconds(sinceLastCargoUpdate);
036                addAndRemoveStockpiledResources(seconds, false, true, true);
037                sinceLastCargoUpdate = 0f;
038                
039                if (okToUpdateShipsAndWeapons()) {
040                        sinceSWUpdate = 0f;
041                        
042                        pruneWeapons(0f);
043                        
044                        int weapons = 7 + Math.max(0, market.getSize() - 1) * 2;
045                        int fighters = 2 + Math.max(0, market.getSize() - 3);
046                        
047                        addWeapons(weapons, weapons + 2, 3, submarket.getFaction().getId());
048                        addFighters(fighters, fighters + 2, 3, market.getFactionId());
049
050                        float stability = market.getStabilityValue();
051                        float sMult = Math.max(0.1f, stability / 10f);
052                        getCargo().getMothballedShips().clear();
053                        
054                        // larger ships at lower stability to compensate for the reduced number of ships
055                        // so that low stability doesn't restrict the options to more or less just frigates 
056                        // and the occasional destroyer
057                        int size = submarket.getFaction().getDoctrine().getShipSize();
058                        int add = 0;
059                        if (stability <= 4) {
060                                add = 2;
061                        } else if (stability <= 6) {
062                                add = 1;
063                        }
064                        
065                        size += add;
066                        if (size > 5) size = 5;
067                        
068                        FactionDoctrineAPI doctrineOverride = submarket.getFaction().getDoctrine().clone();
069                        doctrineOverride.setShipSize(size);
070                        
071                        addShips(submarket.getFaction().getId(),
072                                        //(150f + market.getSize() * 25f) * sMult, // combat
073                                        200f * sMult, // combat
074                                        15f, // freighter 
075                                        10f, // tanker
076                                        20f, // transport
077                                        10f, // liner
078                                        10f, // utilityPts
079                                        null, // qualityOverride
080                                        0f, // qualityMod
081                                        null,
082                                        doctrineOverride);
083                                
084                        addHullMods(4, 2 + itemGenRandom.nextInt(4), submarket.getFaction().getId());
085                }
086                
087                getCargo().sort();
088        }
089        
090        protected Object writeReplace() {
091                if (okToUpdateShipsAndWeapons()) {
092                        pruneWeapons(0f);
093                        getCargo().getMothballedShips().clear();
094                }
095                return this;
096        }
097        
098        
099        @Override
100        public String getName() {
101                if (submarket.getFaction().getId().equals(Factions.LUDDIC_CHURCH)) {
102                        return "Knights of Ludd";
103                }
104                return Misc.ucFirst(submarket.getFaction().getPersonNamePrefix()) + "\n" + "Military";
105        }
106
107        protected boolean requiresCommission(RepLevel req) {
108                if (!submarket.getFaction().getCustomBoolean(Factions.CUSTOM_OFFERS_COMMISSIONS)) return false;
109                
110                if (req.isAtWorst(RepLevel.WELCOMING)) return true;
111                return false;
112        }
113        
114        protected boolean hasCommission() {
115                return submarket.getFaction().getId().equals(Misc.getCommissionFactionId());
116        }
117        
118        
119        public boolean shouldHaveCommodity(CommodityOnMarketAPI com) {
120                if (Commodities.CREW.equals(com.getId())) return true;
121                return com.getCommodity().hasTag(Commodities.TAG_MILITARY);
122        }
123        
124        @Override
125        public int getStockpileLimit(CommodityOnMarketAPI com) {
126//              int demand = com.getMaxDemand();
127//              int available = com.getAvailable();
128//              
129//              float limit = BaseIndustry.getSizeMult(available) - BaseIndustry.getSizeMult(Math.max(0, demand - 2));
130//              limit *= com.getCommodity().getEconUnit();
131                
132                float limit = OpenMarketPlugin.getBaseStockpileLimit(com);
133                
134                //limit *= com.getMarket().getStockpileMult().getModifiedValue();
135                
136                Random random = new Random(market.getId().hashCode() + submarket.getSpecId().hashCode() + Global.getSector().getClock().getMonth() * 170000);
137                limit *= 0.9f + 0.2f * random.nextFloat();
138                
139                float sm = market.getStabilityValue() / 10f;
140                limit *= (0.25f + 0.75f * sm);
141                
142                if (limit < 0) limit = 0;
143                
144                return (int) limit;
145        }
146        
147        public boolean isIllegalOnSubmarket(String commodityId, TransferAction action) {
148                //boolean illegal = submarket.getFaction().isIllegal(commodityId);
149                boolean illegal = market.isIllegal(commodityId);
150                RepLevel req = getRequiredLevelAssumingLegal(commodityId, action);
151                
152                if (req == null) return illegal;
153                
154                RepLevel level = submarket.getFaction().getRelationshipLevel(Global.getSector().getFaction(Factions.PLAYER));
155                boolean legal = level.isAtWorst(req);
156                if (requiresCommission(req)) {
157                        legal &= hasCommission();
158                }
159                return !legal;
160        }
161
162        public boolean isIllegalOnSubmarket(CargoStackAPI stack, TransferAction action) {
163                if (stack.isCommodityStack()) {
164                        return isIllegalOnSubmarket((String) stack.getData(), action);
165                }
166                
167                RepLevel req = getRequiredLevelAssumingLegal(stack, action);
168                if (req == null) return false;
169                
170                RepLevel level = submarket.getFaction().getRelationshipLevel(Global.getSector().getFaction(Factions.PLAYER));
171                
172                boolean legal = level.isAtWorst(req);
173                if (requiresCommission(req)) {
174                        legal &= hasCommission();
175                }
176                
177                return !legal;
178        }
179        
180        public String getIllegalTransferText(CargoStackAPI stack, TransferAction action) {
181                RepLevel req = getRequiredLevelAssumingLegal(stack, action);
182
183                if (req != null) {
184                        if (requiresCommission(req)) {
185                                return "Req: " +
186                                                submarket.getFaction().getDisplayName() + " - " + req.getDisplayName().toLowerCase() + ", " +
187                                                " commission";
188                        }
189                        return "Req: " + 
190                                        submarket.getFaction().getDisplayName() + " - " + req.getDisplayName().toLowerCase();
191                }
192                
193                return "Illegal to trade in " + stack.getDisplayName() + " here";
194        }
195        
196
197        public Highlights getIllegalTransferTextHighlights(CargoStackAPI stack, TransferAction action) {
198                RepLevel req = getRequiredLevelAssumingLegal(stack, action);
199                if (req != null) {
200                        Color c = Misc.getNegativeHighlightColor();
201                        Highlights h = new Highlights();
202                        RepLevel level = submarket.getFaction().getRelationshipLevel(Global.getSector().getFaction(Factions.PLAYER));
203                        if (!level.isAtWorst(req)) {
204                                h.append(submarket.getFaction().getDisplayName() + " - " + req.getDisplayName().toLowerCase(), c);
205                        }
206                        if (requiresCommission(req) && !hasCommission()) {
207                                h.append("commission", c);
208                        }
209                        return h;
210                }
211                return null;
212        }
213        
214        private RepLevel getRequiredLevelAssumingLegal(CargoStackAPI stack, TransferAction action) {
215                int tier = -1;
216                if (stack.isWeaponStack()) {
217                        WeaponSpecAPI spec = stack.getWeaponSpecIfWeapon();
218                        tier = spec.getTier();
219                } else if (stack.isModSpecStack()) {
220                        HullModSpecAPI spec = stack.getHullModSpecIfHullMod();
221                        tier = spec.getTier();
222                } else if (stack.isFighterWingStack()) {
223                        FighterWingSpecAPI spec = stack.getFighterWingSpecIfWing();
224                        tier = spec.getTier();
225                }
226                
227                if (tier >= 0) {
228                        if (action == TransferAction.PLAYER_BUY) {
229                                switch (tier) {
230                                case 0: return RepLevel.FAVORABLE;
231                                case 1: return RepLevel.WELCOMING;
232                                case 2: return RepLevel.FRIENDLY;
233                                case 3: return RepLevel.COOPERATIVE;
234                                }
235                        }
236                        return RepLevel.VENGEFUL;
237                }
238                
239                if (!stack.isCommodityStack()) return null;
240                return getRequiredLevelAssumingLegal((String) stack.getData(), action);
241        }
242        
243        private RepLevel getRequiredLevelAssumingLegal(String commodityId, TransferAction action) {
244                if (action == TransferAction.PLAYER_SELL) {
245                        //return null;
246                        return RepLevel.VENGEFUL;
247                }
248                
249                CommodityOnMarketAPI com = market.getCommodityData(commodityId);
250                boolean isMilitary = com.getCommodity().getTags().contains(Commodities.TAG_MILITARY);
251                if (isMilitary) {
252                        if (com.isPersonnel()) {
253                                return RepLevel.COOPERATIVE;
254                        }
255                        return RepLevel.FAVORABLE;
256                }
257                return null;
258        }
259        
260        public boolean isIllegalOnSubmarket(FleetMemberAPI member, TransferAction action) {
261                if (action == TransferAction.PLAYER_SELL && Misc.isAutomated(member)) {
262                        return true;
263                }
264                
265                RepLevel req = getRequiredLevelAssumingLegal(member, action);
266                if (req == null) return false;
267                
268                RepLevel level = submarket.getFaction().getRelationshipLevel(Global.getSector().getFaction(Factions.PLAYER));
269                
270                boolean legal = level.isAtWorst(req);
271                if (requiresCommission(req)) {
272                        legal &= hasCommission();
273                }
274                
275                return !legal;
276        }
277        
278        public String getIllegalTransferText(FleetMemberAPI member, TransferAction action) {
279                RepLevel req = getRequiredLevelAssumingLegal(member, action);
280                if (req != null) {
281                        String str = "";
282                        RepLevel level = submarket.getFaction().getRelationshipLevel(Global.getSector().getFaction(Factions.PLAYER));
283                        if (!level.isAtWorst(req)) {
284                                str += "Req: " + submarket.getFaction().getDisplayName() + " - " + req.getDisplayName().toLowerCase();                          
285                        }
286                        if (requiresCommission(req) && !hasCommission()) {
287                                if (!str.isEmpty()) str += "\n";
288                                str += "Req: " + submarket.getFaction().getDisplayName() + " - " + "commission";
289                        }
290                        return str;
291//                      if (requiresCommission(req)) {
292//                              return //"Requires:\n" +
293//                                              "Req: " + submarket.getFaction().getDisplayName() + " - " + req.getDisplayName().toLowerCase() + "\n" +
294//                                              "Req: " + submarket.getFaction().getDisplayName() + " - " + "commission";
295//                      }
296//                      return "Requires: " + 
297//                                      submarket.getFaction().getDisplayName() + " - " + req.getDisplayName().toLowerCase();
298                }
299                
300                if (action == TransferAction.PLAYER_BUY) {
301                        return "Illegal to buy"; // this shouldn't happen
302                } else {
303                        return "Illegal to sell";
304                }
305        }
306
307        public Highlights getIllegalTransferTextHighlights(FleetMemberAPI member, TransferAction action) {
308                if (isIllegalOnSubmarket(member, action)) return null;
309                
310                RepLevel req = getRequiredLevelAssumingLegal(member, action);
311                if (req != null) {
312                        Color c = Misc.getNegativeHighlightColor();
313                        Highlights h = new Highlights();
314                        RepLevel level = submarket.getFaction().getRelationshipLevel(Global.getSector().getFaction(Factions.PLAYER));
315                        if (!level.isAtWorst(req)) {
316                                h.append("Req: " + submarket.getFaction().getDisplayName() + " - " + req.getDisplayName().toLowerCase(), c);
317                        }
318                        if (requiresCommission(req) && !hasCommission()) {
319                                h.append("Req: " + submarket.getFaction().getDisplayName() + " - commission", c);
320                        }
321                        return h;
322                }
323                return null;
324        }
325        
326        private RepLevel getRequiredLevelAssumingLegal(FleetMemberAPI member, TransferAction action) {
327                if (action == TransferAction.PLAYER_BUY) {
328                        int fp = member.getFleetPointCost();
329                        HullSize size = member.getHullSpec().getHullSize();
330                        
331                        if (size == HullSize.CAPITAL_SHIP || fp > 15) return RepLevel.COOPERATIVE;
332                        if (size == HullSize.CRUISER || fp > 10) return RepLevel.FRIENDLY;
333                        if (size == HullSize.DESTROYER || fp > 5) return RepLevel.WELCOMING;
334                        return RepLevel.FAVORABLE;
335                }
336                return null;
337        }
338        
339        
340        
341        private RepLevel minStanding = RepLevel.FAVORABLE;
342        public boolean isEnabled(CoreUIAPI ui) {
343                //if (mode == CoreUITradeMode.OPEN) return false;
344                if (ui.getTradeMode() == CoreUITradeMode.SNEAK) return false;
345                
346                RepLevel level = submarket.getFaction().getRelationshipLevel(Global.getSector().getFaction(Factions.PLAYER));
347                return level.isAtWorst(minStanding);
348        }
349        
350        public OnClickAction getOnClickAction(CoreUIAPI ui) {
351                return OnClickAction.OPEN_SUBMARKET;
352        }
353        
354        public String getTooltipAppendix(CoreUIAPI ui) {
355                if (!isEnabled(ui)) {
356                        return "Requires: " + submarket.getFaction().getDisplayName() + " - " + minStanding.getDisplayName().toLowerCase();
357                }
358                if (ui.getTradeMode() == CoreUITradeMode.SNEAK) {
359                        return "Requires: proper docking authorization";
360                }
361                return null;
362        }
363        
364        public Highlights getTooltipAppendixHighlights(CoreUIAPI ui) {
365                String appendix = getTooltipAppendix(ui);
366                if (appendix == null) return null;
367                
368                Highlights h = new Highlights();
369                h.setText(appendix);
370                h.setColors(Misc.getNegativeHighlightColor());
371                return h;
372        }
373        
374        @Override
375        public PlayerEconomyImpactMode getPlayerEconomyImpactMode() {
376                return PlayerEconomyImpactMode.PLAYER_SELL_ONLY;
377        }
378        
379        public boolean isMilitaryMarket() {
380                return true;
381        }
382}
383
384
385