001package com.fs.starfarer.api.impl.campaign.fleets; 002 003import java.util.ArrayList; 004import java.util.List; 005import java.util.Random; 006 007import org.apache.log4j.Logger; 008import org.lwjgl.util.vector.Vector2f; 009 010import com.fs.starfarer.api.Global; 011import com.fs.starfarer.api.campaign.BattleAPI; 012import com.fs.starfarer.api.campaign.CampaignEventListener.FleetDespawnReason; 013import com.fs.starfarer.api.campaign.CampaignFleetAPI; 014import com.fs.starfarer.api.campaign.SectorEntityToken; 015import com.fs.starfarer.api.campaign.econ.MarketAPI; 016import com.fs.starfarer.api.campaign.listeners.FleetEventListener; 017import com.fs.starfarer.api.impl.campaign.fleets.PilgrimageFleetAssignmentAI.PilgrimageRouteData; 018import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.OptionalFleetData; 019import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData; 020import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment; 021import com.fs.starfarer.api.impl.campaign.ids.Conditions; 022import com.fs.starfarer.api.impl.campaign.ids.Factions; 023import com.fs.starfarer.api.impl.campaign.ids.FleetTypes; 024import com.fs.starfarer.api.impl.campaign.ids.MemFlags; 025import com.fs.starfarer.api.impl.campaign.ids.Tags; 026import com.fs.starfarer.api.impl.campaign.missions.DelayedFleetEncounter; 027import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission; 028import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.FleetQuality; 029import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.FleetSize; 030import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.OfficerNum; 031import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.OfficerQuality; 032import com.fs.starfarer.api.impl.campaign.missions.hub.MissionFleetAutoDespawn; 033import com.fs.starfarer.api.impl.campaign.shared.SharedData; 034import com.fs.starfarer.api.util.Misc; 035import com.fs.starfarer.api.util.TimeoutTracker; 036import com.fs.starfarer.api.util.WeightedRandomPicker; 037 038/** 039 * Replaced by MiscFleetRouteManager. 040 */ 041@Deprecated 042public class PilgrimageFleetRouteManager extends BaseRouteFleetManager implements FleetEventListener { 043 044// public static int MIN_PILGRIMS = 5; 045// public static int MAX_PILGRIMS = 5; 046 047 public static final Integer ROUTE_SRC_LOAD = 1; 048 public static final Integer ROUTE_TRAVEL_DST = 2; 049 public static final Integer ROUTE_DST_UNLOAD = 5; 050 public static final Integer ROUTE_DST_LOAD = 6; 051 public static final Integer ROUTE_TRAVEL_BACK_WS = 7; 052 public static final Integer ROUTE_RESUPPLY_BACK_WS = 8; 053 public static final Integer ROUTE_TRAVEL_SRC = 9; 054 public static final Integer ROUTE_SRC_UNLOAD = 10; 055 056 public static final String SOURCE_ID = "pilgrimage"; 057 public static Logger log = Global.getLogger(PilgrimageFleetRouteManager.class); 058 059 060 protected TimeoutTracker<String> recentlySentPilgrims = new TimeoutTracker<String>(); 061 protected List<SectorEntityToken> shrines = null; 062 063 public PilgrimageFleetRouteManager() { 064 //super(0.2f, 0.3f); 065 super(1f, 14f); 066 } 067 068 protected Object readResolve() { 069 if (recentlySentPilgrims == null) { 070 recentlySentPilgrims = new TimeoutTracker<String>(); 071 } 072 return this; 073 } 074 075 @Override 076 public void advance(float amount) { 077 if (shrines == null) { 078 shrines = Global.getSector().getEntitiesWithTag(Tags.LUDDIC_SHRINE); 079 } 080 //super.advance(amount * 10f); 081 super.advance(amount); 082 083 float days = Global.getSector().getClock().convertToDays(amount); 084 recentlySentPilgrims.advance(days); 085 086// MarketAPI from = pickSourceMarket(); 087// MarketAPI to = pickDestMarket(from); 088 } 089 090 protected String getRouteSourceId() { 091 return SOURCE_ID; 092 } 093 094 protected int getMaxFleets() { 095 //if (true) return 1; 096 int numMarkets = Global.getSector().getEconomy().getNumMarkets(); 097 int maxBasedOnMarkets = numMarkets * 1; 098 return Math.min(maxBasedOnMarkets, Global.getSettings().getInt("maxPilgrimageFleets")); 099 } 100 101 102 protected void addRouteFleetIfPossible() { 103 MarketAPI from = pickSourceMarket(); 104 SectorEntityToken to = pickDestShrine(from); 105 106// from = Global.getSector().getEconomy().getMarket("chalcedon"); 107// to = Global.getSector().getEntityById("beholder_station"); 108 109 if (from != null && to != null) { 110 111 PilgrimageRouteData data = createData(from, to); 112 if (data == null) return; 113 114 log.info("Added shrine pilgrimage fleet route from " + from.getName() + " to " + to.getName()); 115 116 Long seed = Misc.genRandomSeed(); 117 String id = getRouteSourceId(); 118 119 OptionalFleetData extra = new OptionalFleetData(from); 120 //float tier = data.size; 121 //float stability = from.getStabilityValue(); 122 String factionId = from.getFactionId(); 123// if (!from.getFaction().isHostileTo(Factions.INDEPENDENT) && 124// !to.getFaction().isHostileTo(Factions.INDEPENDENT)) { 125// if ((float) Math.random() * 10f > stability + tier) { 126// factionId = Factions.INDEPENDENT; 127// } 128// } 129// if (data.smuggling) { 130// factionId = Factions.INDEPENDENT; 131// } 132 extra.factionId = factionId; 133 134 RouteData route = RouteManager.getInstance().addRoute(id, from, seed, extra, this); 135 route.setCustom(data); 136 137 float orbitDays = data.size * (0.75f + (float) Math.random() * 0.5f); 138 orbitDays *= 30f; 139 if (orbitDays < 1f) orbitDays = 1f; 140 if (orbitDays > 3f) orbitDays = 3f; 141 142 route.addSegment(new RouteSegment(ROUTE_SRC_LOAD, orbitDays, from.getPrimaryEntity())); 143 route.addSegment(new RouteSegment(ROUTE_TRAVEL_DST, from.getPrimaryEntity(), to)); 144 route.addSegment(new RouteSegment(ROUTE_DST_UNLOAD, orbitDays * 0.5f, to)); 145 route.addSegment(new RouteSegment(ROUTE_DST_LOAD, orbitDays * 0.5f, to)); 146 route.addSegment(new RouteSegment(ROUTE_TRAVEL_SRC, to, from.getPrimaryEntity())); 147 route.addSegment(new RouteSegment(ROUTE_SRC_UNLOAD, orbitDays, from.getPrimaryEntity())); 148 149 recentlySentPilgrims.add(from.getId(), Global.getSettings().getFloat("minPilgrimSpawnIntervalPerMarket")); 150 } 151 } 152 153 154 155 public MarketAPI pickSourceMarket() { 156 //return Global.getSector().getEconomy().getMarket("jangala"); 157 //return Global.getSector().getEconomy().getMarket("sindria"); 158 //if (true) return Global.getSector().getEconomy().getMarket("chicomoztoc"); 159 160 WeightedRandomPicker<MarketAPI> markets = new WeightedRandomPicker<MarketAPI>(); 161 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) { 162 if (market.isHidden()) continue; 163 if (!market.hasSpaceport()) continue; // markets w/o spaceports don't launch fleets 164 if (recentlySentPilgrims.contains(market.getId())) continue; 165 166 167 // use this for shrines also 168 if (SharedData.getData().getMarketsWithoutTradeFleetSpawn().contains(market.getId())) continue; 169 170 float distLY = Misc.getDistanceToPlayerLY(market.getPrimaryEntity()); 171 float mult = 1f - Math.min(0.99f, distLY / 10f); 172 173 String fid = market.getFactionId(); 174 if (Factions.LUDDIC_CHURCH.equals(fid) || 175 Factions.LUDDIC_PATH.equals(fid) || 176 Factions.KOL.equals(fid)) { 177 mult *= 10f; 178 } 179 180 markets.add(market, market.getSize() * mult); 181 182// if (market.getName().toLowerCase().equals("jannow")) { 183// markets.add(market, 100000f); 184// } 185 } 186 return markets.pick(); 187 } 188 189 public SectorEntityToken pickDestShrine(MarketAPI from) { 190 if (from == null) return null; 191 192 WeightedRandomPicker<SectorEntityToken> picker = new WeightedRandomPicker<SectorEntityToken>(); 193 194 for (SectorEntityToken shrine : new ArrayList<SectorEntityToken>(shrines)) { 195 if (!shrine.isAlive()) continue; 196 197 MarketAPI market = shrine.getMarket(); 198 boolean realMarket = market != null && !market.isPlanetConditionMarketOnly(); 199 if (realMarket && market.hasCondition(Conditions.DECIVILIZED)) continue; 200 201 float mult = 1f; 202 if (realMarket) { 203 mult = 10f * market.getSize(); 204 } else { 205 //mult *= 100f; 206 } 207 picker.add(shrine, mult); 208 } 209 210 return picker.pick(); 211 } 212 213 214 public static PilgrimageRouteData createData(MarketAPI from, SectorEntityToken to) { 215 PilgrimageRouteData data = new PilgrimageRouteData(); 216 data.from = from; 217 data.to = to; 218 data.factionId = Factions.LUDDIC_CHURCH; 219 220 MarketAPI market = to.getMarket(); 221 boolean realMarket = market != null && !market.isPlanetConditionMarketOnly(); 222 if (realMarket && market.getFaction().isHostileTo(from.getFaction())) { 223 if (market.getFaction().isHostileTo(Factions.INDEPENDENT)) { 224 data.smuggling = true; 225 } else { 226 data.factionId = Factions.INDEPENDENT; 227 } 228 } 229 230 231 float sizeBasis; 232 if (realMarket) { 233 sizeBasis = market.getSize() + from.getSize(); 234 } else { 235 sizeBasis = from.getSize() * 0.5f; 236 } 237 data.size = sizeBasis / 40f; 238 239 return data; 240 } 241 242 public boolean shouldCancelRouteAfterDelayCheck(RouteData route) { 243 return false; 244 } 245 246 247 public CampaignFleetAPI spawnFleet(RouteData route) { 248 Random random = new Random(); 249 if (route.getSeed() != null) { 250 random = new Random(route.getSeed()); 251 } 252 253 CampaignFleetAPI fleet = createPilgrimRouteFleet(route, random); 254 if (fleet == null) return null;; 255 256 //fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_TRADE_FLEET, true); 257 258 fleet.addEventListener(this); 259 260 fleet.addScript(new PilgrimageFleetAssignmentAI(fleet, route)); 261 return fleet; 262 } 263 264 public static CampaignFleetAPI createPilgrimRouteFleet(RouteData route, Random random) { 265 PilgrimageRouteData data = (PilgrimageRouteData) route.getCustom(); 266 267 FleetCreatorMission m = new FleetCreatorMission(random); 268 m.beginFleet(); 269 270 271 m.triggerCreateFleet(FleetSize.MEDIUM, FleetQuality.LOWER, data.factionId, 272 FleetTypes.SHRINE_PILGRIMS, data.from.getLocationInHyperspace()); 273 m.triggerSetFleetOfficers(OfficerNum.FC_ONLY, OfficerQuality.LOWER); 274 m.triggerSetFleetSizeFraction(data.size * 0.5f * (0.5f + random.nextFloat() * 0.5f)); 275 m.triggerFleetSetNoFactionInName(); 276 m.triggerSetTraderFleet(); 277 m.triggerSetFleetComposition(0f, 0f, 0f, 1f, 0f); 278 m.triggerSetFleetMemoryValue(MemFlags.MEMORY_KEY_SOURCE_MARKET, data.from); 279 m.triggerSetFleetMemoryValue("$destShrine", data.to.getId()); 280 m.triggerSetFleetMemoryValue(MemFlags.SHRINE_PILGRIM_FLEET, true); 281 282 CampaignFleetAPI fleet = m.createFleet(); 283 fleet.removeScriptsOfClass(MissionFleetAutoDespawn.class); 284 285 return fleet; 286 287 } 288 289 public void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle) { 290 RouteData route = RouteManager.getInstance().getRoute(getRouteSourceId(), fleet); 291 if (route == null || !(route.getCustom() instanceof PilgrimageRouteData)) return; 292 293 if (route.isExpired()) return; 294 if (!battle.isPlayerInvolved()) return; 295 296 // player was involved, on the opposite side of the pilgrim fleet 297 if (battle.getNonPlayerSideSnapshot().contains(fleet)) { 298 PilgrimageRouteData data = (PilgrimageRouteData) route.getCustom(); 299 300 DelayedFleetEncounter e = new DelayedFleetEncounter(new Random(), "luddicPilgrims"); 301 e.setDelayShort(); 302 //e.setDelayNone(); 303 e.setLocationCoreOnly(true, Factions.LUDDIC_CHURCH); 304 e.beginCreate(); 305 e.triggerCreateFleet(FleetSize.MEDIUM, FleetQuality.DEFAULT, Factions.LUDDIC_CHURCH, FleetTypes.PATROL_MEDIUM, new Vector2f()); 306 e.triggerSetFleetSizeFraction(Math.min(1f, data.size * 3f)); 307 e.autoAdjustFleetTypeName(); 308 e.triggerSetPatrol(); 309 e.triggerSetStandardAggroInterceptFlags(); 310 e.triggerSetFleetGenericHailPermanent("PilgrimRevengeHail"); 311 e.endCreate(); 312 } 313 } 314 315 public void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param) { 316 317 } 318 319 public boolean shouldRepeat(RouteData route) { 320 return false; 321 } 322 323 public void reportAboutToBeDespawnedByRouteManager(RouteData route) { 324 325 } 326 327} 328 329 330 331 332 333 334