001package com.fs.starfarer.api.impl.campaign.procgen.themes; 002 003import java.util.Random; 004 005import org.lwjgl.util.vector.Vector2f; 006 007import com.fs.starfarer.api.Global; 008import com.fs.starfarer.api.campaign.CampaignFleetAPI; 009import com.fs.starfarer.api.campaign.StarSystemAPI; 010import com.fs.starfarer.api.campaign.econ.MarketAPI; 011import com.fs.starfarer.api.impl.campaign.fleets.BaseRouteFleetManager; 012import com.fs.starfarer.api.impl.campaign.fleets.FleetFactoryV3; 013import com.fs.starfarer.api.impl.campaign.fleets.FleetParamsV3; 014import com.fs.starfarer.api.impl.campaign.fleets.RouteManager; 015import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.OptionalFleetData; 016import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData; 017import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment; 018import com.fs.starfarer.api.impl.campaign.ids.Factions; 019import com.fs.starfarer.api.impl.campaign.ids.FleetTypes; 020import com.fs.starfarer.api.impl.campaign.ids.MemFlags; 021import com.fs.starfarer.api.impl.campaign.ids.Tags; 022import com.fs.starfarer.api.impl.campaign.tutorial.TutorialMissionIntel; 023import com.fs.starfarer.api.util.Misc; 024import com.fs.starfarer.api.util.WeightedRandomPicker; 025 026public class RuinsFleetRouteManager extends BaseRouteFleetManager { 027 028 protected StarSystemAPI system; 029 030 public RuinsFleetRouteManager(StarSystemAPI system) { 031 super(1f, 14f); 032 this.system = system; 033 } 034 035 protected String getRouteSourceId() { 036 return "salvage_" + system.getId(); 037 } 038 039 protected int getMaxFleets() { 040 //if (true) return 0; 041 042 float salvage = getVeryApproximateSalvageValue(system); 043 return (int) (1 + Math.min(salvage / 2, 7)); 044 } 045 046 protected void addRouteFleetIfPossible() { 047 if (TutorialMissionIntel.isTutorialInProgress()) { 048 return; 049 } 050 051 MarketAPI market = pickSourceMarket(); 052 if (market == null) return; 053 054 Long seed = new Random().nextLong(); 055 String id = getRouteSourceId(); 056 057 OptionalFleetData extra = new OptionalFleetData(market); 058 059 RouteData route = RouteManager.getInstance().addRoute(id, market, seed, extra, this); 060 061 float distLY = Misc.getDistanceLY(market.getLocationInHyperspace(), system.getLocation()); 062 float travelDays = distLY * 1.5f; 063 064 float prepDays = 2f + (float) Math.random() * 3f; 065 float endDays = 8f + (float) Math.random() * 3f; // longer since includes time from jump-point to source 066 067 float totalTravelTime = prepDays + endDays + travelDays * 2f; 068 float stayDays = Math.max(20f, totalTravelTime); 069 070 route.addSegment(new RouteSegment(prepDays, market.getPrimaryEntity())); 071 route.addSegment(new RouteSegment(travelDays, market.getPrimaryEntity(), system.getCenter())); 072 route.addSegment(new RouteSegment(stayDays, system.getCenter())); 073 route.addSegment(new RouteSegment(travelDays, system.getCenter(), market.getPrimaryEntity())); 074 route.addSegment(new RouteSegment(endDays, market.getPrimaryEntity())); 075 } 076 077 078 public static float getVeryApproximateSalvageValue(StarSystemAPI system) { 079 return system.getEntitiesWithTag(Tags.SALVAGEABLE).size(); 080 } 081 082 public MarketAPI pickSourceMarket() { 083// if (true) { 084// return Global.getSector().getEconomy().getMarket("jangala"); 085// } 086 087 WeightedRandomPicker<MarketAPI> markets = new WeightedRandomPicker<MarketAPI>(); 088 089 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) { 090 if (market.getFaction().isHostileTo(Factions.INDEPENDENT)) continue; 091 if (market.getContainingLocation() == null) continue; 092 if (market.getContainingLocation().isHyperspace()) continue; 093 if (market.isHidden()) continue; 094 095 float distLY = Misc.getDistanceLY(system.getLocation(), market.getLocationInHyperspace()); 096 float weight = market.getSize(); 097 098 float f = Math.max(0.1f, 1f - Math.min(1f, distLY / 20f)); 099 f *= f; 100 weight *= f; 101 102 markets.add(market, weight); 103 } 104 105 return markets.pick(); 106 } 107 108 109 public CampaignFleetAPI spawnFleet(RouteData route) { 110 Random random = route.getRandom(); 111 112 WeightedRandomPicker<String> picker = new WeightedRandomPicker<String>(random); 113 picker.add(FleetTypes.SCAVENGER_SMALL, 10f); 114 picker.add(FleetTypes.SCAVENGER_MEDIUM, 15f); 115 picker.add(FleetTypes.SCAVENGER_LARGE, 5f); 116 117 String type = picker.pick(); 118 119 boolean pirate = random.nextBoolean(); 120 CampaignFleetAPI fleet = createScavenger(type, system.getLocation(), route, route.getMarket(), pirate, random); 121 if (fleet == null) return null;; 122 123 fleet.addScript(new ScavengerFleetAssignmentAI(fleet, route, pirate)); 124 125 return fleet; 126 } 127 128 public static CampaignFleetAPI createScavenger(String type, Vector2f locInHyper, MarketAPI source, boolean pirate, Random random) { 129 return createScavenger(type, locInHyper, null, source, pirate, random); 130 } 131 public static CampaignFleetAPI createScavenger(String type, Vector2f locInHyper, RouteData route, MarketAPI source, boolean pirate, Random random) { 132 if (random == null) random = new Random(); 133 134 135 if (type == null) { 136 WeightedRandomPicker<String> picker = new WeightedRandomPicker<String>(random); 137 picker.add(FleetTypes.SCAVENGER_SMALL, 10f); 138 picker.add(FleetTypes.SCAVENGER_MEDIUM, 15f); 139 picker.add(FleetTypes.SCAVENGER_LARGE, 5f); 140 type = picker.pick(); 141 } 142 143 144 int combat = 0; 145 int freighter = 0; 146 int tanker = 0; 147 int transport = 0; 148 int utility = 0; 149 150 151 if (type.equals(FleetTypes.SCAVENGER_SMALL)) { 152 combat = random.nextInt(2) + 1; 153 tanker = random.nextInt(2) + 1; 154 utility = random.nextInt(2) + 1; 155 } else if (type.equals(FleetTypes.SCAVENGER_MEDIUM)) { 156 combat = 4 + random.nextInt(5); 157 freighter = 4 + random.nextInt(5); 158 tanker = 3 + random.nextInt(4); 159 transport = random.nextInt(2); 160 utility = 2 + random.nextInt(3); 161 } else if (type.equals(FleetTypes.SCAVENGER_LARGE)) { 162 combat = 7 + random.nextInt(8); 163 freighter = 6 + random.nextInt(7); 164 tanker = 5 + random.nextInt(6); 165 transport = 3 + random.nextInt(8); 166 utility = 4 + random.nextInt(5); 167 } 168 169 if (pirate) { 170// combat += transport; 171// combat += utility; 172 transport = utility = 0; 173 } 174 175 combat *= 5f; 176 freighter *= 3f; 177 tanker *= 3f; 178 transport *= 1.5f; 179 180 FleetParamsV3 params = new FleetParamsV3( 181 route != null ? route.getMarket() : source, 182 locInHyper, 183 Factions.SCAVENGERS, // quality will always be reduced by non-market-faction penalty, which is what we want 184 route == null ? null : route.getQualityOverride(), 185 type, 186 combat, // combatPts 187 freighter, // freighterPts 188 tanker, // tankerPts 189 transport, // transportPts 190 0f, // linerPts 191 utility, // utilityPts 192 0f // qualityMod 193 ); 194 if (route != null) { 195 params.timestamp = route.getTimestamp(); 196 } 197 params.random = random; 198 CampaignFleetAPI fleet = FleetFactoryV3.createFleet(params); 199 200 if (fleet == null || fleet.isEmpty()) return null; 201 202 fleet.setFaction(Factions.INDEPENDENT, true); 203 204 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_SCAVENGER, true); 205 206 if (pirate || true) { 207 Misc.makeLowRepImpact(fleet, "scav"); 208 } 209 210 return fleet; 211 } 212 213 public boolean shouldCancelRouteAfterDelayCheck(RouteData data) { 214 return false; 215 } 216 217 public boolean shouldRepeat(RouteData route) { 218 return false; 219 } 220 221 public void reportAboutToBeDespawnedByRouteManager(RouteData route) { 222 223 } 224} 225 226 227 228 229 230 231