001package com.fs.starfarer.api.impl.campaign.fleets;
002
003import java.util.ArrayList;
004import java.util.List;
005
006import org.apache.log4j.Logger;
007
008import com.fs.starfarer.api.EveryFrameScript;
009import com.fs.starfarer.api.Global;
010import com.fs.starfarer.api.campaign.BattleAPI;
011import com.fs.starfarer.api.campaign.CampaignEventListener.FleetDespawnReason;
012import com.fs.starfarer.api.campaign.CampaignFleetAPI;
013import com.fs.starfarer.api.campaign.LocationAPI;
014import com.fs.starfarer.api.campaign.listeners.FleetEventListener;
015import com.fs.starfarer.api.util.IntervalUtil;
016
017//public abstract class BaseLimitedFleetManager extends BaseCampaignEventListener implements EveryFrameScript {
018/**
019 * Default spawn rate is on average one fleet every month. 
020 * Deriving classes should boost this as necessary via getSpawnRateMult().
021 * @author Alex Mosolov
022 *
023 * Copyright 2018 Fractal Softworks, LLC
024 */
025public abstract class BaseLimitedFleetManager implements EveryFrameScript, FleetEventListener {
026
027        public static Logger log = Global.getLogger(BaseLimitedFleetManager.class);
028        
029        public static class ManagedFleetData {
030                //public float startingFleetPoints = 0;
031                public CampaignFleetAPI fleet;
032                public LocationAPI spawnedFor;
033                public ManagedFleetData(CampaignFleetAPI fleet, LocationAPI spawnedFor) {
034                        this.fleet = fleet;
035                        this.spawnedFor = spawnedFor;
036                        //startingFleetPoints = fleet.getFleetPoints();
037                }
038        }
039        
040        protected List<ManagedFleetData> active = new ArrayList<ManagedFleetData>();
041        protected IntervalUtil tracker;
042
043        public BaseLimitedFleetManager() {
044                float interval = 30f;
045                tracker = new IntervalUtil(interval * 0.75f, interval * 1.25f);
046                readResolve();
047        }
048        
049        protected Object readResolve() {
050                return this;
051        }
052        
053        protected abstract int getMaxFleets();
054        protected abstract CampaignFleetAPI spawnFleet();
055        
056        protected float getNextInterval() {
057                return 30f * (0.75f + (float) Math.random() * 0.5f); 
058        }
059        
060        protected float getSpawnRateMult() {
061                return 1f;
062        }
063        
064        public void advance(float amount) {
065                float days = Global.getSector().getClock().convertToDays(amount);
066                
067                tracker.advance(days * getSpawnRateMult());
068                if (!tracker.intervalElapsed()) return;
069                
070                float next = getNextInterval();
071                tracker.setInterval(next, next);
072                
073                Global.getSettings().profilerBegin(this.getClass().getSimpleName() + ".advance()");
074                List<ManagedFleetData> remove = new ArrayList<ManagedFleetData>();
075                for (ManagedFleetData data : active) {
076                        if (data.fleet.getContainingLocation() == null ||
077                                !data.fleet.getContainingLocation().getFleets().contains(data.fleet)) {
078                                remove.add(data);
079                                log.info("Cleaning up orphaned fleet [" + data.fleet.getNameWithFaction() + "]");
080                        }
081                }
082                active.removeAll(remove);
083                
084                int max = getMaxFleets();
085                
086                if (active.size() < max) {
087                        //log.info(active.size() + " out of a maximum " + max + " fleets in play for [" + getClass().getName() + "]");
088                        CampaignFleetAPI fleet = spawnFleet();
089                        if (fleet != null) {
090                                fleet.addEventListener(this);
091                                LocationAPI spawnLoc = null;
092                                if (this instanceof DisposableFleetManager) {
093                                        spawnLoc = ((DisposableFleetManager)this).getCurrSpawnLoc();
094                                }
095                                ManagedFleetData data = new ManagedFleetData(fleet, spawnLoc);
096                                active.add(data);
097                                log.info("Spawned fleet [" + fleet.getNameWithFaction() + "] at hyperloc " + fleet.getLocationInHyperspace());
098                        } else {
099                                //log.info("Could not spawn fleet - returned null");
100                        }
101                } else {
102                        log.debug("Maximum number of " + max + " fleets already in play for [" + getClass().getName() + "]");
103                }
104                Global.getSettings().profilerEnd();
105        }
106        
107        public boolean isDone() {
108                return false;
109        }
110
111        public boolean runWhilePaused() {
112                return false;
113        }
114        
115        public void reportFleetDespawned(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param) {
116                for (ManagedFleetData data : active) {
117                        if (data.fleet == fleet) {
118                                active.remove(data);
119                                break;
120                        }
121                }
122        }
123
124        public void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle) {
125        }
126
127        public void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param) {
128        }
129
130}
131
132
133
134
135
136
137
138
139
140
141
142
143
144