001package com.fs.starfarer.api.impl.campaign.procgen.themes;
002
003import java.util.Random;
004
005import org.lwjgl.util.vector.Vector2f;
006
007import com.fs.starfarer.api.Global;
008import com.fs.starfarer.api.campaign.CampaignFleetAPI;
009import com.fs.starfarer.api.campaign.StarSystemAPI;
010import com.fs.starfarer.api.campaign.econ.MarketAPI;
011import com.fs.starfarer.api.impl.campaign.fleets.BaseRouteFleetManager;
012import com.fs.starfarer.api.impl.campaign.fleets.FleetFactoryV3;
013import com.fs.starfarer.api.impl.campaign.fleets.FleetParamsV3;
014import com.fs.starfarer.api.impl.campaign.fleets.RouteManager;
015import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.OptionalFleetData;
016import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
017import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment;
018import com.fs.starfarer.api.impl.campaign.ids.Factions;
019import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
020import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
021import com.fs.starfarer.api.impl.campaign.ids.Tags;
022import com.fs.starfarer.api.impl.campaign.tutorial.TutorialMissionIntel;
023import com.fs.starfarer.api.util.Misc;
024import com.fs.starfarer.api.util.WeightedRandomPicker;
025
026public class RuinsFleetRouteManager extends BaseRouteFleetManager {
027
028        protected StarSystemAPI system;
029        
030        public RuinsFleetRouteManager(StarSystemAPI system) {
031                super(1f, 14f);
032                this.system = system;
033        }
034
035        protected String getRouteSourceId() {
036                return "salvage_" + system.getId();
037        }
038        
039        protected int getMaxFleets() {
040                //if (true) return 0;
041                
042                float salvage = getVeryApproximateSalvageValue(system);
043                return (int) (1 + Math.min(salvage / 2, 7));
044        }
045        
046        protected void addRouteFleetIfPossible() {
047                if (TutorialMissionIntel.isTutorialInProgress()) {
048                        return;
049                }
050                
051                MarketAPI market = pickSourceMarket();
052                if (market == null) return;
053                
054                Long seed = new Random().nextLong();
055                String id = getRouteSourceId();
056                
057                OptionalFleetData extra = new OptionalFleetData(market);
058                
059                RouteData route = RouteManager.getInstance().addRoute(id, market, seed, extra, this);
060                
061                float distLY = Misc.getDistanceLY(market.getLocationInHyperspace(), system.getLocation());
062                float travelDays = distLY * 1.5f;
063                
064                float prepDays = 2f + (float) Math.random() * 3f;
065                float endDays = 8f + (float) Math.random() * 3f; // longer since includes time from jump-point to source
066
067                float totalTravelTime = prepDays + endDays + travelDays * 2f;
068                float stayDays = Math.max(20f, totalTravelTime);
069                
070                route.addSegment(new RouteSegment(prepDays, market.getPrimaryEntity()));
071                route.addSegment(new RouteSegment(travelDays, market.getPrimaryEntity(), system.getCenter()));
072                route.addSegment(new RouteSegment(stayDays, system.getCenter()));
073                route.addSegment(new RouteSegment(travelDays, system.getCenter(), market.getPrimaryEntity()));
074                route.addSegment(new RouteSegment(endDays, market.getPrimaryEntity()));
075        }
076        
077        
078        public static float getVeryApproximateSalvageValue(StarSystemAPI system) {
079                return system.getEntitiesWithTag(Tags.SALVAGEABLE).size();
080        }
081        
082        public MarketAPI pickSourceMarket() {
083//              if (true) {
084//                      return Global.getSector().getEconomy().getMarket("jangala");
085//              }
086                
087                WeightedRandomPicker<MarketAPI> markets = new WeightedRandomPicker<MarketAPI>();
088                
089                for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
090                        if (market.getFaction().isHostileTo(Factions.INDEPENDENT)) continue;
091                        if (market.getContainingLocation() == null) continue;
092                        if (market.getContainingLocation().isHyperspace()) continue;
093                        if (market.isHidden()) continue;
094                        
095                        float distLY = Misc.getDistanceLY(system.getLocation(), market.getLocationInHyperspace());
096                        float weight = market.getSize();
097                        
098                        float f = Math.max(0.1f, 1f - Math.min(1f, distLY / 20f));
099                        f *= f;
100                        weight *= f;
101                        
102                        markets.add(market, weight);
103                }
104                
105                return markets.pick();
106        }
107        
108
109        public CampaignFleetAPI spawnFleet(RouteData route) {
110                Random random = route.getRandom();
111                
112                WeightedRandomPicker<String> picker = new WeightedRandomPicker<String>(random);
113                picker.add(FleetTypes.SCAVENGER_SMALL, 10f);
114                picker.add(FleetTypes.SCAVENGER_MEDIUM, 15f);
115                picker.add(FleetTypes.SCAVENGER_LARGE, 5f);
116                
117                String type = picker.pick();
118                
119                boolean pirate = random.nextBoolean();
120                CampaignFleetAPI fleet = createScavenger(type, system.getLocation(), route, route.getMarket(), pirate, random);
121                if (fleet == null) return null;;
122                
123                fleet.addScript(new ScavengerFleetAssignmentAI(fleet, route, pirate));
124                
125                return fleet;
126        }
127        
128        public static CampaignFleetAPI createScavenger(String type, Vector2f locInHyper, MarketAPI source, boolean pirate, Random random) {
129                return createScavenger(type, locInHyper, null, source, pirate, random);
130        }
131        public static CampaignFleetAPI createScavenger(String type, Vector2f locInHyper, RouteData route, MarketAPI source, boolean pirate, Random random) {
132                if (random == null) random = new Random();
133
134                
135                if (type == null) {
136                        WeightedRandomPicker<String> picker = new WeightedRandomPicker<String>(random);
137                        picker.add(FleetTypes.SCAVENGER_SMALL, 10f);
138                        picker.add(FleetTypes.SCAVENGER_MEDIUM, 15f);
139                        picker.add(FleetTypes.SCAVENGER_LARGE, 5f);
140                        type = picker.pick();
141                }
142                
143                
144                int combat = 0;
145                int freighter = 0;
146                int tanker = 0;
147                int transport = 0;
148                int utility = 0;
149                
150                
151                if (type.equals(FleetTypes.SCAVENGER_SMALL)) {
152                        combat = random.nextInt(2) + 1;
153                        tanker = random.nextInt(2) + 1;
154                        utility = random.nextInt(2) + 1;
155                } else if (type.equals(FleetTypes.SCAVENGER_MEDIUM)) {
156                        combat = 4 + random.nextInt(5);
157                        freighter = 4 + random.nextInt(5);
158                        tanker = 3 + random.nextInt(4);
159                        transport = random.nextInt(2);
160                        utility = 2 + random.nextInt(3);
161                } else if (type.equals(FleetTypes.SCAVENGER_LARGE)) {
162                        combat = 7 + random.nextInt(8);
163                        freighter = 6 + random.nextInt(7);
164                        tanker = 5 + random.nextInt(6);
165                        transport = 3 + random.nextInt(8);
166                        utility = 4 + random.nextInt(5);
167                }
168                
169                if (pirate) {
170//                      combat += transport;
171//                      combat += utility;
172                        transport = utility = 0;
173                }
174                
175                combat *= 5f;
176                freighter *= 3f;
177                tanker *= 3f;
178                transport *= 1.5f;
179                
180                FleetParamsV3 params = new FleetParamsV3(
181                                route != null ? route.getMarket() : source, 
182                                locInHyper,
183                                Factions.SCAVENGERS, // quality will always be reduced by non-market-faction penalty, which is what we want 
184                                route == null ? null : route.getQualityOverride(),
185                                type,
186                                combat, // combatPts
187                                freighter, // freighterPts 
188                                tanker, // tankerPts
189                                transport, // transportPts
190                                0f, // linerPts
191                                utility, // utilityPts
192                                0f // qualityMod
193                                );
194                if (route != null) {
195                        params.timestamp = route.getTimestamp();
196                }
197                params.random = random;
198                CampaignFleetAPI fleet = FleetFactoryV3.createFleet(params);
199                
200                if (fleet == null || fleet.isEmpty()) return null;
201                
202                fleet.setFaction(Factions.INDEPENDENT, true);
203                
204                fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_SCAVENGER, true);
205                
206                if (pirate || true) {
207                        Misc.makeLowRepImpact(fleet, "scav");
208                }
209                
210                return fleet;
211        }
212
213        public boolean shouldCancelRouteAfterDelayCheck(RouteData data) {
214                return false;
215        }
216
217        public boolean shouldRepeat(RouteData route) {
218                return false;
219        }
220        
221        public void reportAboutToBeDespawnedByRouteManager(RouteData route) {
222                
223        }
224}
225
226
227
228
229
230
231