001package com.fs.starfarer.api.impl.campaign.fleets; 002 003import com.fs.starfarer.api.Global; 004import com.fs.starfarer.api.campaign.CampaignFleetAPI; 005import com.fs.starfarer.api.campaign.StarSystemAPI; 006import com.fs.starfarer.api.campaign.econ.MarketAPI; 007import com.fs.starfarer.api.campaign.econ.MarketConditionAPI; 008import com.fs.starfarer.api.impl.campaign.fleets.FleetFactory.MercType; 009import com.fs.starfarer.api.impl.campaign.ids.Conditions; 010import com.fs.starfarer.api.impl.campaign.ids.Factions; 011import com.fs.starfarer.api.impl.campaign.ids.MemFlags; 012import com.fs.starfarer.api.impl.campaign.intel.SystemBountyManager; 013import com.fs.starfarer.api.impl.campaign.intel.bases.PirateActivity; 014import com.fs.starfarer.api.impl.campaign.intel.bases.PirateBaseIntel.PirateBaseTier; 015import com.fs.starfarer.api.impl.campaign.intel.bases.PirateBaseManager; 016import com.fs.starfarer.api.util.Misc; 017 018/** 019 * Adds the following types of fleets: 020 * 1) Weak pirates to any nearby populated system, sometimes. 021 * 2) Pirates to systems with markets with Pirate Activity; number/strength depends on base level 022 * 3) Systems with a bounty; number/strength depends on size of markets. 023 * 024 * @author Alex Mosolov 025 * 026 * Copyright 2018 Fractal Softworks, LLC 027 */ 028public class DisposablePirateFleetManager extends DisposableFleetManager { 029 030 protected Object readResolve() { 031 super.readResolve(); 032 return this; 033 } 034 035 @Override 036 protected String getSpawnId() { 037 return "pirates"; 038 } 039 040 041 @Override 042 public void advance(float amount) { 043 super.advance(amount); 044 } 045 046 @Override 047 protected int getDesiredNumFleetsForSpawnLocation() { 048 PirateBaseTier tier = getPirateActivityTier(); 049 MarketAPI largestBounty = getLargestMarketIfSystemHasBounty(); 050 051 float tierMult = getMultForTier(tier); 052 float bountyMult = largestBounty == null ? 0 : largestBounty.getSize(); 053 054 float desiredNumFleets = 1f; 055 056 desiredNumFleets += tierMult > 0 ? 3f + tierMult : 0; 057 desiredNumFleets += bountyMult; 058 059 return (int) Math.round(desiredNumFleets); 060 } 061 062 protected float getMultForTier(PirateBaseTier tier) { 063 if (tier == null) return 0f; 064 return tier.ordinal() + 1f; 065 } 066 067 protected PirateBaseTier getPirateActivityTier() { 068 if (currSpawnLoc == null) return null; 069 for (MarketAPI market : Global.getSector().getEconomy().getMarkets(currSpawnLoc)) { 070 if (market.isHidden()) continue; 071 if (market.getFactionId().equals(Factions.PIRATES)) continue; 072 MarketConditionAPI mc = market.getCondition(Conditions.PIRATE_ACTIVITY); 073 if (mc != null && mc.getPlugin() instanceof PirateActivity) { 074 PirateActivity pa = (PirateActivity) mc.getPlugin(); 075 return pa.getIntel() == null ? null : pa.getIntel().getTier(); 076 } 077 } 078 return null; 079 } 080 protected boolean hasPirateActivity() { 081 return getPirateActivityTier() != null; 082 } 083 084 protected MarketAPI getLargestMarketIfSystemHasBounty() { 085 if (currSpawnLoc == null) return null; 086 MarketAPI largest = null; 087 boolean bounty = false; 088 int maxSize = 0; 089 for (MarketAPI market : Global.getSector().getEconomy().getMarkets(currSpawnLoc)) { 090 if (market.isHidden()) continue; 091 if (market.getFactionId().equals(Factions.PIRATES)) continue; 092 093 if (SystemBountyManager.getInstance().isActive(market)) bounty = true; 094 095 if (market.getSize() > maxSize) { 096 maxSize = market.getSize(); 097 largest = market; 098 } 099 } 100 if (!bounty) largest = null; 101 return largest; 102 } 103 104 protected CampaignFleetAPI spawnFleetImpl() { 105 StarSystemAPI system = currSpawnLoc; 106 if (system == null) return null; 107 108 CampaignFleetAPI player = Global.getSector().getPlayerFleet(); 109 if (player == null) return null; 110 111 int num = Misc.getMarketsInLocation(system).size(); 112 if (Misc.getMarketsInLocation(system, Factions.PLAYER).size() == num && num > 0) { 113 return null; // handled by HostileActivityIntel, DisposableHostileActivityFleetManager, etc 114 } 115 116// float distToPlayerLY = Misc.getDistanceLY(player.getLocationInHyperspace(), system.getLocation()); 117// if (distToPlayerLY > 1f) return null; 118 119 PirateBaseTier tier = getPirateActivityTier(); 120 MarketAPI largestBounty = getLargestMarketIfSystemHasBounty(); 121 float tierMult = getMultForTier(tier); 122 float bountyMult = 0f; 123 if (largestBounty != null) { 124 bountyMult = largestBounty.getSize(); 125 } 126 //float recentSpawns = getRecentSpawnsForSystem(currSpawnLoc); 127 128 // up to 5 for tier and 8 for market, so max is 13; reasonable avg/high value maybe 10 129 float bonus = tierMult + bountyMult; 130 131 132 float timeFactor = (PirateBaseManager.getInstance().getDaysSinceStart() - 180f) / (365f * 2f); 133 if (timeFactor < 0) timeFactor = 0; 134 if (timeFactor > 1) timeFactor = 1; 135 136 float earlyTimeFactor = (PirateBaseManager.getInstance().getDaysSinceStart() - 60f) / 120f; 137 if (earlyTimeFactor < 0) earlyTimeFactor = 0; 138 if (earlyTimeFactor > 1) earlyTimeFactor = 1; 139 140 //timeFactor = 1f; 141 142 float r = (float) Math.random(); 143 //r = (float) Math.sqrt(r); 144 145 //float fp = 15f + 30f * (float) Math.random() + bonus * 15f * r * timeFactor; 146 147 float fp = (10f + bonus) * earlyTimeFactor + 148 (5f + bonus) * (0.5f + 0.5f * (float) Math.random()) + 149 50f * (0.5f + 0.5f * r) * timeFactor; 150 151 // larger fleets if more fleets 152 float desired = getDesiredNumFleetsForSpawnLocation(); 153 if (desired > 2) { 154 fp += ((desired - 2) * (0.5f + (float) Math.random() * 0.5f)) * 2f * timeFactor; 155 } 156 157 if (fp < 10) fp = 10; 158 159 MercType type; 160 if (fp < 25) { 161 type = MercType.SCOUT; 162 } else if (fp < 75) { 163 type = MercType.PRIVATEER; 164 } else if (fp < 125) { 165 type = MercType.PATROL; 166 } else { 167 type = MercType.ARMADA; 168 } 169 170 String fleetType = type.fleetType; 171 172 float combat = fp; 173 float tanker = 0f; 174 175 if (type == MercType.PATROL || type == MercType.ARMADA) { 176 tanker = combat * 0.1f; 177 } 178 179 combat = Math.round(combat); 180 tanker = Math.round(tanker); 181 182 FleetParamsV3 params = new FleetParamsV3( 183 null, 184 system.getLocation(), // location 185 Factions.PIRATES, 186 null, // quality override 187 fleetType, 188 combat, // combatPts 189 0f, // freighterPts 190 tanker, // tankerPts 191 0f, // transportPts 192 0f, // linerPts 193 0f, // utilityPts 194 0f // qualityMod 195 ); 196 params.ignoreMarketFleetSizeMult = true; 197 if (timeFactor <= 0) { 198 params.maxShipSize = 1; 199 } 200 CampaignFleetAPI fleet = FleetFactoryV3.createFleet(params); 201 202 if (fleet == null || fleet.isEmpty()) return null; 203 204 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_PIRATE, true); 205 fleet.getMemoryWithoutUpdate().set(MemFlags.FLEET_NO_MILITARY_RESPONSE, true); 206 207 setLocationAndOrders(fleet, 0.25f, 0.25f); 208 209 return fleet; 210 } 211 212} 213 214 215 216 217 218 219 220