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