001package com.fs.starfarer.api.impl.campaign.intel.events; 002 003import java.util.Random; 004 005import com.fs.starfarer.api.Global; 006import com.fs.starfarer.api.campaign.CampaignFleetAPI; 007import com.fs.starfarer.api.campaign.StarSystemAPI; 008import com.fs.starfarer.api.campaign.econ.MarketAPI; 009import com.fs.starfarer.api.impl.campaign.fleets.DisposableFleetManager; 010import com.fs.starfarer.api.impl.campaign.ids.Factions; 011import com.fs.starfarer.api.util.Misc; 012import com.fs.starfarer.api.util.WeightedRandomPicker; 013 014/** 015 * @author Alex Mosolov 016 * 017 * Copyright 2022 Fractal Softworks, LLC 018 */ 019public class DisposableHostileActivityFleetManager extends DisposableFleetManager { 020 021 protected Random random = new Random(); 022 023 public DisposableHostileActivityFleetManager() { 024 //updateSpawnRateMult(); 025 } 026 027 protected Object readResolve() { 028 super.readResolve(); 029 return this; 030 } 031 032 033 @Override 034 protected String getSpawnId() { 035 return "hostile_activity"; 036 } 037 038 protected HostileActivityEventIntel getIntel() { 039 if (currSpawnLoc == null) return null; 040 return HostileActivityEventIntel.get(); 041 } 042 043 @Override 044 protected int getDesiredNumFleetsForSpawnLocation() { 045 HostileActivityEventIntel intel = getIntel(); 046 if (intel == null) return 0; 047 048 float delay = 30f; 049 if (!Global.getSettings().isDevMode()) { 050 delay = 90f; 051 } 052 Long timestamp = intel.getPlayerVisibleTimestamp(); 053 if (timestamp != null) { 054 float daysSince = Global.getSector().getClock().getElapsedDaysSince(timestamp); 055 if (daysSince < delay) return 0; 056 } 057 058 if (currSpawnLoc != null) { 059 boolean longEnough = false; 060 for (MarketAPI market : Misc.getMarketsInLocation(currSpawnLoc, Factions.PLAYER)) { 061 if (market.getDaysInExistence() >= delay) { 062 longEnough = true; 063 } 064 } 065 if (!longEnough) { 066 return 0; 067 } 068 } 069 070 float mag = intel.getTotalActivityMagnitude(currSpawnLoc); 071 072 // less than half the fleets when market presence is minimal 073 float mag2 = intel.getMarketPresenceFactor(currSpawnLoc); 074 mag = Misc.interpolate(mag, mag2, 0.6f); 075 076 //float mag2 = intel.getTotalActivityMagnitude(true); 077 // about half the fleets when effect is fully suppressed 078 // keeping the fleets the same size as w/o suppression, though; this is handled 079 // in BaseHostileActivityPlugin.getEffectMagnitudeAdjustedBySuppression() 080 //mag = Misc.interpolate(mag, mag2, 0.5f); 081 082 if (mag <= 0f) return 0; 083 //if (mag > 2f) mag = 2f; 084 if (mag > 1f) mag = 1f; 085 086 float desiredNumFleets = 1f; 087 088 float max = Global.getSettings().getFloat("maxHostileActivityFleetsPerSystem"); 089 090 float mult = intel.getNumFleetsMultiplier(currSpawnLoc); 091 092 desiredNumFleets += (int)Math.round(mag * (max - 1f) * mult); 093 094 return (int) Math.round(desiredNumFleets); 095 } 096 097 098 protected StarSystemAPI pickCurrentSpawnLocation() { 099 return pickNearestPopulatedSystem(); 100 } 101 protected StarSystemAPI pickNearestPopulatedSystem() { 102 if (Global.getSector().isInNewGameAdvance()) return null; 103 CampaignFleetAPI player = Global.getSector().getPlayerFleet(); 104 if (player == null) return null; 105 StarSystemAPI nearest = null; 106 107 float minDist = Float.MAX_VALUE; 108 109 110// List<MarketAPI> markets = Misc.getPlayerMarkets(false); 111// List<StarSystemAPI> systems = new ArrayList<StarSystemAPI>(); 112// for (MarketAPI market : markets) { 113// StarSystemAPI system = market.getStarSystem(); 114// if (system != null && !systems.contains(system)) { 115// systems.add(system); 116// } 117// } 118 119// for (IntelInfoPlugin intel : Global.getSector().getIntelManager().getIntel(HostileActivityIntel.class)) { 120// StarSystemAPI system = ((HostileActivityIntel)intel).getSystem(); 121 for (StarSystemAPI system : Misc.getSystemsWithPlayerColonies(false)) { 122 123 float distToPlayerLY = Misc.getDistanceLY(player.getLocationInHyperspace(), system.getLocation()); 124 if (distToPlayerLY > MAX_RANGE_FROM_PLAYER_LY) continue; 125 126 if (distToPlayerLY < minDist) { 127 //if (system.getStar() != null && system.getStar().getSpec().isPulsar()) continue; 128 nearest = system; 129 minDist = distToPlayerLY; 130 } 131 } 132 133 // stick with current system longer unless something else is closer 134 if (nearest == null && currSpawnLoc != null) { 135 float distToPlayerLY = Misc.getDistanceLY(player.getLocationInHyperspace(), currSpawnLoc.getLocation()); 136 if (distToPlayerLY <= DESPAWN_RANGE_LY) { 137 nearest = currSpawnLoc; 138 } 139 } 140 141 return nearest; 142 } 143 144 protected CampaignFleetAPI spawnFleetImpl() { 145 StarSystemAPI system = currSpawnLoc; 146 if (system == null) return null; 147 148 CampaignFleetAPI player = Global.getSector().getPlayerFleet(); 149 if (player == null) return null; 150 151 HostileActivityEventIntel intel = getIntel(); 152 if (intel == null) return null; 153 154 String idKey = "$dhafm_ID"; 155 156 WeightedRandomPicker<HostileActivityFactor> picker = new WeightedRandomPicker<HostileActivityFactor>(random); 157 158 for (EventFactor factor : intel.getFactors()) { 159 if (!(factor instanceof HostileActivityFactor)) { 160 continue; 161 } 162 //if (factor instanceof LuddicPathHostileActivityFactor) continue; 163 164 HostileActivityFactor curr = (HostileActivityFactor) factor; 165 int count = 0; 166 for (ManagedFleetData data : active) { 167 if (data.fleet != null && 168 curr.getId().equals(data.fleet.getMemoryWithoutUpdate().getString(idKey))) { 169 count++; 170 } 171 } 172 if (count < curr.getMaxNumFleets(currSpawnLoc)) { 173 picker.add(curr, curr.getSpawnFrequency(currSpawnLoc)); 174 } 175 } 176 177 HostileActivityFactor pick = picker.pick(); 178 if (pick == null) return null; 179 180 181 CampaignFleetAPI fleet = pick.createFleet(currSpawnLoc, random); 182 if (fleet == null || fleet.isEmpty()) return null; 183 184 fleet.getMemoryWithoutUpdate().set(idKey, pick.getId()); 185 186 setLocationAndOrders(fleet, pick.getSpawnInHyperProbability(currSpawnLoc), pick.getStayInHyperProbability(currSpawnLoc)); 187 188 return fleet; 189 } 190 191} 192 193 194 195 196 197 198 199