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