001package com.fs.starfarer.api.impl.campaign.fleets;
002
003import com.fs.starfarer.api.Global;
004import com.fs.starfarer.api.campaign.CampaignFleetAPI;
005import com.fs.starfarer.api.campaign.StarSystemAPI;
006import com.fs.starfarer.api.campaign.econ.MarketAPI;
007import com.fs.starfarer.api.campaign.econ.MarketConditionAPI;
008import com.fs.starfarer.api.impl.campaign.fleets.FleetFactory.MercType;
009import com.fs.starfarer.api.impl.campaign.ids.Conditions;
010import com.fs.starfarer.api.impl.campaign.ids.Factions;
011import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
012import com.fs.starfarer.api.impl.campaign.intel.SystemBountyManager;
013import com.fs.starfarer.api.impl.campaign.intel.bases.PirateActivity;
014import com.fs.starfarer.api.impl.campaign.intel.bases.PirateBaseIntel.PirateBaseTier;
015import com.fs.starfarer.api.impl.campaign.intel.bases.PirateBaseManager;
016import com.fs.starfarer.api.util.Misc;
017
018/**
019 * Adds the following types of fleets:
020 * 1) Weak pirates to any nearby populated system, sometimes.
021 * 2) Pirates to systems with markets with Pirate Activity; number/strength depends on base level
022 * 3) Systems with a bounty; number/strength depends on size of markets.
023 *  
024 * @author Alex Mosolov
025 *
026 * Copyright 2018 Fractal Softworks, LLC
027 */
028public class DisposablePirateFleetManager extends DisposableFleetManager {
029
030        protected Object readResolve() {
031                super.readResolve();
032                return this;
033        }
034        
035        @Override
036        protected String getSpawnId() {
037                return "pirates";
038        }
039        
040        
041        @Override
042        public void advance(float amount) {
043                super.advance(amount);
044        }
045
046        @Override
047        protected int getDesiredNumFleetsForSpawnLocation() {
048                PirateBaseTier tier = getPirateActivityTier();
049                MarketAPI largestBounty = getLargestMarketIfSystemHasBounty();
050                
051                float tierMult = getMultForTier(tier);
052                float bountyMult = largestBounty == null ? 0 : largestBounty.getSize();
053                
054                float desiredNumFleets = 1f;
055                
056                desiredNumFleets += tierMult > 0 ? 3f + tierMult : 0;
057                desiredNumFleets += bountyMult;
058                
059                return (int) Math.round(desiredNumFleets);
060        }
061
062        protected float getMultForTier(PirateBaseTier tier) {
063                if (tier == null) return 0f;
064                return tier.ordinal() + 1f;
065        }
066
067        protected PirateBaseTier getPirateActivityTier() {
068                if (currSpawnLoc == null) return null;
069                for (MarketAPI market : Global.getSector().getEconomy().getMarkets(currSpawnLoc)) {
070                        if (market.isHidden()) continue;
071                        if (market.getFactionId().equals(Factions.PIRATES)) continue;
072                        MarketConditionAPI mc = market.getCondition(Conditions.PIRATE_ACTIVITY);
073                        if (mc != null && mc.getPlugin() instanceof PirateActivity) {
074                                PirateActivity pa = (PirateActivity) mc.getPlugin();
075                                return pa.getIntel() == null ? null : pa.getIntel().getTier();
076                        }
077                }
078                return null;
079        }
080        protected boolean hasPirateActivity() {
081                return getPirateActivityTier() != null;
082        }
083        
084        protected MarketAPI getLargestMarketIfSystemHasBounty() {
085                if (currSpawnLoc == null) return null;
086                MarketAPI largest = null;
087                boolean bounty = false;
088                int maxSize = 0;
089                for (MarketAPI market : Global.getSector().getEconomy().getMarkets(currSpawnLoc)) {
090                        if (market.isHidden()) continue;
091                        if (market.getFactionId().equals(Factions.PIRATES)) continue;
092                        
093                        if (SystemBountyManager.getInstance().isActive(market)) bounty = true;
094                        
095                        if (market.getSize() > maxSize) {
096                                maxSize = market.getSize();
097                                largest = market;
098                        }
099                }
100                if (!bounty) largest = null;
101                return largest;
102        }
103        
104        protected CampaignFleetAPI spawnFleetImpl() {
105                StarSystemAPI system = currSpawnLoc;
106                if (system == null) return null;
107                
108                CampaignFleetAPI player = Global.getSector().getPlayerFleet();
109                if (player == null) return null;
110                
111                int num = Misc.getMarketsInLocation(system).size();
112                if (Misc.getMarketsInLocation(system, Factions.PLAYER).size() == num && num > 0) { 
113                        return null; // handled by HostileActivityIntel, DisposableHostileActivityFleetManager, etc
114                }
115                
116//              float distToPlayerLY = Misc.getDistanceLY(player.getLocationInHyperspace(), system.getLocation());
117//              if (distToPlayerLY > 1f) return null;
118                
119                PirateBaseTier tier = getPirateActivityTier();
120                MarketAPI largestBounty = getLargestMarketIfSystemHasBounty();
121                float tierMult = getMultForTier(tier);
122                float bountyMult = 0f;
123                if (largestBounty != null) {
124                        bountyMult = largestBounty.getSize();
125                }
126                //float recentSpawns = getRecentSpawnsForSystem(currSpawnLoc);
127                
128                // up to 5 for tier and 8 for market, so max is 13; reasonable avg/high value maybe 10
129                float bonus = tierMult + bountyMult; 
130                
131                
132                float timeFactor = (PirateBaseManager.getInstance().getDaysSinceStart() - 180f) / (365f * 2f);
133                if (timeFactor < 0) timeFactor = 0;
134                if (timeFactor > 1) timeFactor = 1;
135                
136                float earlyTimeFactor = (PirateBaseManager.getInstance().getDaysSinceStart() - 60f) / 120f;
137                if (earlyTimeFactor < 0) earlyTimeFactor = 0;
138                if (earlyTimeFactor > 1) earlyTimeFactor = 1;
139                
140                //timeFactor = 1f;
141                
142                float r = (float) Math.random();
143                //r = (float) Math.sqrt(r);
144                
145                //float fp = 15f + 30f * (float) Math.random() + bonus * 15f * r * timeFactor;
146                
147                float fp = (10f + bonus) * earlyTimeFactor +
148                                   (5f + bonus) * (0.5f + 0.5f * (float) Math.random()) + 
149                                   50f * (0.5f + 0.5f * r) * timeFactor;
150                
151                // larger fleets if more fleets
152                float desired = getDesiredNumFleetsForSpawnLocation();
153                if (desired > 2) {
154                        fp += ((desired - 2) * (0.5f + (float) Math.random() * 0.5f)) * 2f * timeFactor;
155                }
156                
157                if (fp < 10) fp = 10;
158                
159                MercType type;
160                if (fp < 25) {
161                        type = MercType.SCOUT;
162                } else if (fp < 75) {
163                        type = MercType.PRIVATEER;
164                } else if (fp < 125) {
165                        type = MercType.PATROL;
166                } else {
167                        type = MercType.ARMADA;
168                }
169                
170                String fleetType = type.fleetType;
171                
172                float combat = fp;
173                float tanker = 0f;
174                
175                if (type == MercType.PATROL || type == MercType.ARMADA) {
176                        tanker = combat * 0.1f;
177                }
178                
179                combat = Math.round(combat);
180                tanker = Math.round(tanker);
181                
182                FleetParamsV3 params = new FleetParamsV3(
183                                null,
184                                system.getLocation(), // location
185                                Factions.PIRATES,
186                                null, // quality override
187                                fleetType,
188                                combat, // combatPts
189                                0f, // freighterPts 
190                                tanker, // tankerPts
191                                0f, // transportPts
192                                0f, // linerPts
193                                0f, // utilityPts
194                                0f // qualityMod
195                                );
196                params.ignoreMarketFleetSizeMult = true;
197                if (timeFactor <= 0) {
198                        params.maxShipSize = 1;
199                }
200                CampaignFleetAPI fleet = FleetFactoryV3.createFleet(params);
201                
202                if (fleet == null || fleet.isEmpty()) return null;
203                
204                fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_PIRATE, true);
205                fleet.getMemoryWithoutUpdate().set(MemFlags.FLEET_NO_MILITARY_RESPONSE, true);
206                
207                setLocationAndOrders(fleet, 0.25f, 0.25f);
208                
209                return fleet;
210        }
211        
212}
213
214
215
216
217
218
219
220