001package com.fs.starfarer.api.impl.campaign.fleets;
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.SectorEntityToken;
008import com.fs.starfarer.api.campaign.econ.MarketAPI;
009import com.fs.starfarer.api.impl.campaign.fleets.FleetFactory.MercType;
010import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.OptionalFleetData;
011import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
012import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment;
013import com.fs.starfarer.api.impl.campaign.ids.Factions;
014import com.fs.starfarer.api.impl.campaign.ids.Tags;
015import com.fs.starfarer.api.impl.campaign.intel.SystemBountyManager;
016import com.fs.starfarer.api.util.Misc;
017import com.fs.starfarer.api.util.WeightedRandomPicker;
018
019public class MercFleetManagerV2 extends BaseRouteFleetManager {
020
021        public static final Integer ROUTE_PREPARE = 1;
022        public static final Integer ROUTE_TRAVEL = 2;
023        public static final Integer ROUTE_PATROL = 3;
024        public static final Integer ROUTE_RETURN = 4;
025        public static final Integer ROUTE_STAND_DOWN = 5;
026        
027        public MercFleetManagerV2() {
028                super(0.5f, 1.5f);
029        }
030        
031        @Override
032        protected void addRouteFleetIfPossible() {
033                MarketAPI from = pickMarket();
034                if (from == null) return;
035                
036                MarketAPI to = pickNearbyMarketToDefend(from);
037                if (to == null) return;
038                
039                Long seed = new Random().nextLong();
040                String id = getRouteSourceId();
041                
042                OptionalFleetData extra = new OptionalFleetData(from);
043                
044                RouteData route = RouteManager.getInstance().addRoute(id, from, seed, extra, this);
045                
046                float orbitDays = 2f + (float) Math.random() * 3f;
047                float deorbitDays = 2f + (float) Math.random() * 3f;
048                float patrolDays = 2f + (float) Math.random() * 3f;
049                
050                SectorEntityToken target = to.getPrimaryEntity();
051                if ((float) Math.random() > 0.25f && to.getStarSystem() != null) {
052                        if ((float) Math.random() > 0.25f) {
053                                target = to.getStarSystem().getCenter();
054                        } else {
055                                target = to.getStarSystem().getHyperspaceAnchor();
056                        }
057                }
058                
059                if (from.getContainingLocation() == to.getContainingLocation() && !from.getContainingLocation().isHyperspace()) {
060                        route.addSegment(new RouteSegment(ROUTE_PREPARE, orbitDays, from.getPrimaryEntity()));
061                        route.addSegment(new RouteSegment(ROUTE_PATROL, patrolDays, target));
062                        route.addSegment(new RouteSegment(ROUTE_STAND_DOWN, deorbitDays, from.getPrimaryEntity()));
063                } else {
064                        route.addSegment(new RouteSegment(ROUTE_PREPARE, orbitDays, from.getPrimaryEntity()));
065                        route.addSegment(new RouteSegment(ROUTE_TRAVEL, from.getPrimaryEntity(), to.getPrimaryEntity()));
066                        route.addSegment(new RouteSegment(ROUTE_PATROL, patrolDays, target));
067                        route.addSegment(new RouteSegment(ROUTE_RETURN, to.getPrimaryEntity(), from.getPrimaryEntity()));
068                        route.addSegment(new RouteSegment(ROUTE_STAND_DOWN, deorbitDays, from.getPrimaryEntity()));
069                }
070        }
071        
072        public MercType pickFleetType(Random random) {
073                WeightedRandomPicker<MercType> picker = new WeightedRandomPicker<MercType>(random);
074                picker.add(MercType.SCOUT, 10f); 
075                picker.add(MercType.BOUNTY_HUNTER, 10f); 
076                picker.add(MercType.PRIVATEER, 10f); 
077                picker.add(MercType.PATROL, 10f); 
078                picker.add(MercType.ARMADA, 3f); 
079                MercType type = picker.pick();
080                return type;
081        }
082        
083        public CampaignFleetAPI spawnFleet(RouteData route) {
084                Random random = route.getRandom();
085                
086                MercType type = pickFleetType(random);
087                
088                float combat = 0f;
089                float tanker = 0f;
090                float freighter = 0f;
091                String fleetType = type.fleetType;
092                switch (type) {
093                case SCOUT:
094                        combat = Math.round(1f + random.nextFloat() * 2f);
095                        break;
096                case PRIVATEER:
097                case BOUNTY_HUNTER:
098                        combat = Math.round(3f + random.nextFloat() * 2f);
099                        break;
100                case PATROL:
101                        combat = Math.round(9f + random.nextFloat() * 3f);
102                        tanker = Math.round(random.nextFloat()) * 5f;
103                        break;
104                case ARMADA:
105                        combat = Math.round(10f + random.nextFloat() * 4f);
106                        tanker = Math.round(random.nextFloat()) * 10f;
107                        freighter = Math.round(random.nextFloat()) * 10f;
108                        break;
109                }
110
111                combat *= 5f;
112                
113                FleetParamsV3 params = new FleetParamsV3(
114                                route.getMarket(), 
115                                null,
116                                Factions.INDEPENDENT,
117                                route.getQualityOverride() + 0.2f,
118                                fleetType,
119                                combat, // combatPts
120                                freighter, // freighterPts 
121                                tanker, // tankerPts
122                                0f, // transportPts
123                                0f, // linerPts
124                                0f, // utilityPts
125                                0f // qualityMod
126                                );
127                params.timestamp = route.getTimestamp();
128                params.random = random;
129                CampaignFleetAPI fleet = FleetFactoryV3.createFleet(params);
130                
131                if (fleet == null || fleet.isEmpty()) return null;
132                
133                route.getMarket().getContainingLocation().addEntity(fleet);
134                fleet.setFacing((float) Math.random() * 360f);
135                // this will get overridden by the patrol assignment AI, depending on route-time elapsed etc
136                fleet.setLocation(route.getMarket().getPrimaryEntity().getLocation().x, route.getMarket().getPrimaryEntity().getLocation().x);
137                
138                MercAssignmentAIV2 ai = new MercAssignmentAIV2(fleet, route);
139                fleet.addScript(ai);
140                
141                
142                return fleet;
143        }
144
145        
146        protected MarketAPI pickMarket() {
147                WeightedRandomPicker<MarketAPI> picker = new WeightedRandomPicker<MarketAPI>();
148                for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
149                        if (market.isHidden()) continue;
150                        if (market.getFactionId().equals(Factions.PIRATES)) continue;
151                        if (market.getFaction().isHostileTo(Factions.INDEPENDENT)) continue;
152                        
153                        if (!market.hasSpaceport()) continue;
154                        
155                        if (market.getStarSystem() != null && market.getStarSystem().hasTag(Tags.SYSTEM_CUT_OFF_FROM_HYPER)) {
156                                continue;
157                        }
158                        
159                        if (market.getDaysInExistence() < Global.getSettings().getFloat("minMarketExistenceDaysForMercs")) {
160                                continue;
161                        }
162                        if (market.getSize() < Global.getSettings().getFloat("minMarketSizeForMercs")) {
163                                continue;
164                        }
165                        
166                        
167                        float mult = Misc.getSpawnChanceMult(market.getLocationInHyperspace());
168                        float w = market.getStabilityValue() + market.getSize();
169                        
170                        w *= mult;
171                        picker.add(market, w);
172                }
173                return picker.pick();
174        }
175
176        
177        protected MarketAPI pickNearbyMarketToDefend(MarketAPI source) {
178                WeightedRandomPicker<MarketAPI> picker = new WeightedRandomPicker<MarketAPI>();
179                
180                //CampaignEventManagerAPI eventManager = Global.getSector().getEventManager();
181                
182                for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
183                        //if (market.getFactionId().equals(Factions.PIRATES)) continue;
184                        if (market.getFaction().isHostileTo(Factions.INDEPENDENT)) continue;
185                        if (market.getStarSystem() == null) continue;
186                        if (market.isHidden()) continue;
187                        
188                        if (market.getStarSystem() != null && market.getStarSystem().hasTag(Tags.SYSTEM_CUT_OFF_FROM_HYPER)) {
189                                continue;
190                        }
191                        
192                        float dist = Misc.getDistance(market.getLocationInHyperspace(), source.getLocationInHyperspace());
193                        if (dist < 1000) dist = 1000;
194                        float weight = 10000f / dist;
195                        
196                        if (SystemBountyManager.getInstance().isActive(market)) {
197                                weight *= 5f;
198                        }
199                        
200                        picker.add(market, weight);
201                }
202                MarketAPI market = picker.pick();
203//              if (market == null) return null;
204//              return market.getStarSystem();
205                return market;
206        }
207        
208        
209        
210        @Override
211        protected int getMaxFleets() {
212                return (int) Global.getSettings().getFloat("maxMercFleets");
213        }
214
215        @Override
216        protected String getRouteSourceId() {
217                return "mercs_global";
218        }
219
220        public void reportAboutToBeDespawnedByRouteManager(RouteData route) {
221                
222        }
223
224        public boolean shouldCancelRouteAfterDelayCheck(RouteData route) {
225                return false;
226        }
227
228        public boolean shouldRepeat(RouteData route) {
229                return false;
230        }
231
232
233        
234}
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249