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