001package com.fs.starfarer.api.impl.campaign.graid;
002
003import java.awt.Color;
004import java.util.Random;
005
006import com.fs.starfarer.api.Global;
007import com.fs.starfarer.api.campaign.CargoAPI;
008import com.fs.starfarer.api.campaign.CargoAPI.CargoItemType;
009import com.fs.starfarer.api.campaign.CargoStackAPI;
010import com.fs.starfarer.api.campaign.TextPanelAPI;
011import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
012import com.fs.starfarer.api.campaign.econ.CommoditySpecAPI;
013import com.fs.starfarer.api.campaign.econ.Industry;
014import com.fs.starfarer.api.campaign.econ.MarketAPI;
015import com.fs.starfarer.api.impl.campaign.econ.CommodityIconCounts;
016import com.fs.starfarer.api.impl.campaign.econ.ShippingDisruption;
017import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD.RaidDangerLevel;
018import com.fs.starfarer.api.loading.Description;
019import com.fs.starfarer.api.loading.Description.Type;
020import com.fs.starfarer.api.ui.IconGroupAPI;
021import com.fs.starfarer.api.ui.IconRenderMode;
022import com.fs.starfarer.api.ui.TooltipMakerAPI;
023import com.fs.starfarer.api.util.Misc;
024
025public class CommodityGroundRaidObjectivePluginImpl extends BaseGroundRaidObjectivePluginImpl {
026        // for causing deficit; higher value means less units need to be raided to cause same deficit   
027        public static float ECON_IMPACT_MULT = 1f;
028        
029        public static float QUANTITY_MULT_NORMAL = 0.1f; 
030        //public static float QUANTITY_MULT_NORMAL_FOR_DEFICIT = 0.5f; 
031        public static float QUANTITY_MULT_NORMAL_FOR_DEFICIT = 1f; 
032        public static float QUANTITY_MULT_EXCESS = 1f; 
033        public static float QUANTITY_MULT_DEFICIT = -0.1f; 
034        public static float QUANTITY_MULT_OVERALL = 0.1f;
035        
036        protected CommodityOnMarketAPI com;
037        private int deficitActuallyCaused;
038        
039        public CommodityGroundRaidObjectivePluginImpl(MarketAPI market, String commodityId) {
040                super(market, commodityId);
041                com = market.getCommodityData(commodityId);
042                setSource(computeCommoditySource(market, com));
043        }
044
045        public void addIcons(IconGroupAPI iconGroup) {
046                CommoditySpecAPI spec = getCommoditySpec();
047                if (spec == null) return;
048                
049                CommodityOnMarketAPI com = market.getCommodityData(id);
050                CommodityIconCounts counts = new CommodityIconCounts(com);
051                
052                int deficit = counts.deficit;
053                int available = Math.max(0, counts.available - counts.extra);
054                int extra = counts.extra;
055                
056                if (available > 0) {
057                        if (counts.production >= counts.available) {
058                                Color c = Misc.interpolateColor(Misc.getPositiveHighlightColor(), Misc.zeroColor, 0.5f);
059                                iconGroup.addIconGroup(id, IconRenderMode.OUTLINE_CUSTOM, available, c);
060                        } else {
061                                iconGroup.addIconGroup(id, IconRenderMode.NORMAL, available, null);
062                        }
063                }
064                if (deficit > 0) {
065                        iconGroup.addIconGroup(id, IconRenderMode.RED, deficit, null);
066                }
067                if (extra > 0) {
068                        iconGroup.addIconGroup(id, IconRenderMode.GREEN, extra, null);
069                }
070        }
071
072        public int getCargoSpaceNeeded() {
073                CommoditySpecAPI spec = getCommoditySpec();
074                if (!spec.isFuel() && !spec.isPersonnel()) {
075                        return (int) (spec.getCargoSpace() * getQuantity(getMarinesAssigned()));
076                }
077                return 0;
078        }
079        
080        public int getFuelSpaceNeeded() {
081                CommoditySpecAPI spec = getCommoditySpec();
082                if (spec.isFuel()) {
083                        return (int) (spec.getCargoSpace() * getQuantity(getMarinesAssigned()));
084                }
085                return 0;
086        }
087        
088        public int getProjectedCreditsValue() {
089                CommoditySpecAPI spec = getCommoditySpec();
090                return (int) (spec.getBasePrice() * getQuantity(getMarinesAssigned()));
091        }
092        
093        public int getDeficitCaused() {
094                float quantity = getQuantity(getMarinesAssigned(), true);
095                quantity *= ECON_IMPACT_MULT;
096                int diff = Misc.computeEconUnitChangeFromTradeModChange(com, -(int)quantity);
097                diff = -diff;
098                if (diff < 0) diff = 0;
099                if (diff == 0 && getProjectedCreditsValue() > 1000) diff = 1;
100                return diff;
101        }
102        
103        public CommoditySpecAPI getCommoditySpec() {
104                return com.getCommodity();
105        }
106        
107        public RaidDangerLevel getDangerLevel() {
108//              if (id.equals(Commodities.HAND_WEAPONS)) {
109//                      System.out.println("wefwefwe");
110//              }
111                RaidDangerLevel danger = com.getCommodity().getBaseDanger();
112                CommodityIconCounts counts = new CommodityIconCounts(com);
113                if (counts.production >= counts.available) {
114                        danger = danger.prev();
115                }
116                if (counts.deficit > 0) {
117                        danger = danger.next();
118                }
119                if (counts.extra > 0) {
120                        danger = danger.prev();
121                }
122                if (source != null) {
123                        danger = source.adjustCommodityDangerLevel(id, danger);
124                }
125                return danger;
126        }
127
128        public float getQuantitySortValue() {
129                return QUANTITY_SORT_TIER_0 + getQuantity(1);
130        }
131        
132        public float getQuantity(int marines) {
133                return getQuantity(marines, false);
134        }
135        
136        public float getQuantity(int marines, boolean forDeficit) {
137                float base = getBaseRaidQuantity(forDeficit);
138                return base * marines;
139        }
140        
141        public int getValue(int marines) {
142                return (int) (getQuantity(marines) * getCommoditySpec().getBasePrice());
143        }
144        
145        
146        public float getBaseRaidQuantity(boolean forDeficit) {
147                //CommodityOnMarketAPI com = market.getCommodityData(id);
148                float unit = com.getCommodity().getEconUnit();
149                
150                CommodityIconCounts counts = new CommodityIconCounts(com);
151                
152                float result = 0f;
153                
154                if (forDeficit) {
155                        result += Math.max(0, counts.available - counts.extra) * unit * QUANTITY_MULT_NORMAL_FOR_DEFICIT;
156                } else {
157                        result += Math.max(0, counts.available - counts.extra) * unit * QUANTITY_MULT_NORMAL;
158                }
159                result += counts.extra * unit * QUANTITY_MULT_EXCESS;
160                result += counts.deficit * unit * QUANTITY_MULT_DEFICIT;
161                
162                result *= QUANTITY_MULT_OVERALL;
163                
164                if (result < 0) result = 0;
165                
166                return result;
167        }
168
169        public static Industry computeCommoditySource(MarketAPI market, CommodityOnMarketAPI com) {
170                Industry best = null;
171                int score = 0;
172                int available = com.getAvailable();
173                RaidDangerLevel base = com.getCommodity().getBaseDanger();
174                for (Industry ind : market.getIndustries()) {
175                        int supply = ind.getSupply(com.getId()).getQuantity().getModifiedInt();
176                        int metDemand = Math.min(available, ind.getDemand(com.getId()).getQuantity().getModifiedInt());
177                        int currScore = Math.max(supply, metDemand) * 1000;
178                        RaidDangerLevel danger = ind.adjustCommodityDangerLevel(com.getId(), base);
179                        currScore += 1000 - danger.ordinal();
180                        if (currScore > score) {
181                                score = currScore;
182                                best = ind;
183                        }
184                }
185                return best;
186        }
187
188        public String getName() {
189                return com.getCommodity().getName();
190        }
191
192        public CargoStackAPI getStackForIcon() {
193                CargoStackAPI stack = Global.getFactory().createCargoStack(CargoItemType.RESOURCES, getId(), null);
194                return stack;
195        }
196        
197        public String getCommodityIdForDeficitIcons() {
198                return com.getId();
199        }
200
201        
202        public int performRaid(CargoAPI loot, Random random, float lootMult, TextPanelAPI text) {
203                if (marinesAssigned <= 0) return 0;
204                
205                float base = getQuantity(marinesAssigned);
206                base *= lootMult;
207                
208                float mult = 0.9f + random.nextFloat() * 0.2f;
209                base *= mult;
210                
211                quantityLooted = (int) base;
212                if (quantityLooted < 1) quantityLooted = 1;
213                
214                loot.addCommodity(getId(), quantityLooted);
215                
216                deficitActuallyCaused = getDeficitCaused();
217                if (deficitActuallyCaused > 0) {
218                        com.getAvailableStat().addTemporaryModFlat(
219                                        ShippingDisruption.ACCESS_LOSS_DURATION,
220                                        Misc.genUID(), "Recent raid", -deficitActuallyCaused);
221                }
222                
223                xpGained = (int) (quantityLooted * getCommoditySpec().getBasePrice() * XP_GAIN_VALUE_MULT);
224                return xpGained;
225        }
226
227        public int getDeficitActuallyCaused() {
228                return deficitActuallyCaused;
229        }
230
231        public void setDeficitActuallyCaused(int deficitActuallyCaused) {
232                this.deficitActuallyCaused = deficitActuallyCaused;
233        }
234        
235        @Override
236        public boolean hasTooltip() {
237                return true;
238        }
239
240        @Override
241        public void createTooltip(TooltipMakerAPI t, boolean expanded) {
242                float opad = 10f;
243                float pad = 3f;
244                Color h = Misc.getHighlightColor();
245                Color bad = Misc.getNegativeHighlightColor();
246                Color good = Misc.getPositiveHighlightColor();
247
248                Description desc = Global.getSettings().getDescription(id, Type.RESOURCE);
249                
250                t.addPara(desc.getText1FirstPara(), 0f);
251                
252                t.addPara("Base value: %s per unit", opad, h, Misc.getDGSCredits(com.getCommodity().getBasePrice()));
253        }
254        
255}
256
257
258
259
260
261
262
263