001package com.fs.starfarer.api.impl.campaign.fleets;
002
003import java.util.ArrayList;
004import java.util.List;
005import java.util.Random;
006
007import org.apache.log4j.Logger;
008import org.lwjgl.util.vector.Vector2f;
009
010import com.fs.starfarer.api.Global;
011import com.fs.starfarer.api.campaign.BattleAPI;
012import com.fs.starfarer.api.campaign.CampaignEventListener.FleetDespawnReason;
013import com.fs.starfarer.api.campaign.CampaignFleetAPI;
014import com.fs.starfarer.api.campaign.SectorEntityToken;
015import com.fs.starfarer.api.campaign.econ.MarketAPI;
016import com.fs.starfarer.api.campaign.listeners.FleetEventListener;
017import com.fs.starfarer.api.impl.campaign.fleets.PilgrimageFleetAssignmentAI.PilgrimageRouteData;
018import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.OptionalFleetData;
019import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
020import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment;
021import com.fs.starfarer.api.impl.campaign.ids.Conditions;
022import com.fs.starfarer.api.impl.campaign.ids.Factions;
023import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
024import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
025import com.fs.starfarer.api.impl.campaign.ids.Tags;
026import com.fs.starfarer.api.impl.campaign.missions.DelayedFleetEncounter;
027import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission;
028import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.FleetQuality;
029import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.FleetSize;
030import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.OfficerNum;
031import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.OfficerQuality;
032import com.fs.starfarer.api.impl.campaign.missions.hub.MissionFleetAutoDespawn;
033import com.fs.starfarer.api.impl.campaign.shared.SharedData;
034import com.fs.starfarer.api.util.Misc;
035import com.fs.starfarer.api.util.TimeoutTracker;
036import com.fs.starfarer.api.util.WeightedRandomPicker;
037
038/**
039 * Replaced by MiscFleetRouteManager.
040 */
041@Deprecated
042public class PilgrimageFleetRouteManager extends BaseRouteFleetManager implements FleetEventListener {
043        
044//      public static int MIN_PILGRIMS = 5;
045//      public static int MAX_PILGRIMS = 5;
046        
047        public static final Integer ROUTE_SRC_LOAD = 1;
048        public static final Integer ROUTE_TRAVEL_DST = 2;
049        public static final Integer ROUTE_DST_UNLOAD = 5;
050        public static final Integer ROUTE_DST_LOAD = 6;
051        public static final Integer ROUTE_TRAVEL_BACK_WS = 7;
052        public static final Integer ROUTE_RESUPPLY_BACK_WS = 8;
053        public static final Integer ROUTE_TRAVEL_SRC = 9;
054        public static final Integer ROUTE_SRC_UNLOAD = 10;
055        
056        public static final String SOURCE_ID = "pilgrimage";
057        public static Logger log = Global.getLogger(PilgrimageFleetRouteManager.class);
058        
059        
060        protected TimeoutTracker<String> recentlySentPilgrims = new TimeoutTracker<String>();
061        protected List<SectorEntityToken> shrines = null;
062        
063        public PilgrimageFleetRouteManager() {
064                //super(0.2f, 0.3f);
065                super(1f, 14f);
066        }
067        
068        protected Object readResolve() {
069                if (recentlySentPilgrims == null) {
070                        recentlySentPilgrims = new TimeoutTracker<String>();
071                }
072                return this;
073        }
074
075        @Override
076        public void advance(float amount) {
077                if (shrines == null) {
078                        shrines = Global.getSector().getEntitiesWithTag(Tags.LUDDIC_SHRINE);
079                }
080                //super.advance(amount * 10f);
081                super.advance(amount);
082                
083                float days = Global.getSector().getClock().convertToDays(amount);
084                recentlySentPilgrims.advance(days);
085                
086//              MarketAPI from = pickSourceMarket();
087//              MarketAPI to = pickDestMarket(from);
088        }
089
090        protected String getRouteSourceId() {
091                return SOURCE_ID;
092        }
093        
094        protected int getMaxFleets() {
095                //if (true) return 1;
096                int numMarkets = Global.getSector().getEconomy().getNumMarkets();
097                int maxBasedOnMarkets = numMarkets * 1;
098                return Math.min(maxBasedOnMarkets, Global.getSettings().getInt("maxPilgrimageFleets"));
099        }
100        
101        
102        protected void addRouteFleetIfPossible() {
103                MarketAPI from = pickSourceMarket();
104                SectorEntityToken to = pickDestShrine(from);
105                
106//              from = Global.getSector().getEconomy().getMarket("chalcedon");
107//              to = Global.getSector().getEntityById("beholder_station");
108                
109                if (from != null && to != null) {
110                        
111                        PilgrimageRouteData data = createData(from, to);
112                        if (data == null) return;
113                        
114                        log.info("Added shrine pilgrimage fleet route from " + from.getName() + " to " + to.getName());
115                        
116                        Long seed = Misc.genRandomSeed();
117                        String id = getRouteSourceId();
118                        
119                        OptionalFleetData extra = new OptionalFleetData(from);
120                        //float tier = data.size;
121                        //float stability = from.getStabilityValue();
122                        String factionId = from.getFactionId();
123//                      if (!from.getFaction().isHostileTo(Factions.INDEPENDENT) && 
124//                                      !to.getFaction().isHostileTo(Factions.INDEPENDENT)) {
125//                              if ((float) Math.random() * 10f > stability + tier) {
126//                                      factionId = Factions.INDEPENDENT;
127//                              }
128//                      }
129//                      if (data.smuggling) {
130//                              factionId = Factions.INDEPENDENT;
131//                      }
132                        extra.factionId = factionId;
133                        
134                        RouteData route = RouteManager.getInstance().addRoute(id, from, seed, extra, this);
135                        route.setCustom(data);
136                        
137                        float orbitDays = data.size * (0.75f + (float) Math.random() * 0.5f);
138                        orbitDays *= 30f;
139                        if (orbitDays < 1f) orbitDays = 1f;
140                        if (orbitDays > 3f) orbitDays = 3f;
141                        
142                        route.addSegment(new RouteSegment(ROUTE_SRC_LOAD, orbitDays, from.getPrimaryEntity()));
143                        route.addSegment(new RouteSegment(ROUTE_TRAVEL_DST, from.getPrimaryEntity(), to));
144                        route.addSegment(new RouteSegment(ROUTE_DST_UNLOAD, orbitDays * 0.5f, to));
145                        route.addSegment(new RouteSegment(ROUTE_DST_LOAD, orbitDays * 0.5f, to));
146                        route.addSegment(new RouteSegment(ROUTE_TRAVEL_SRC, to, from.getPrimaryEntity()));
147                        route.addSegment(new RouteSegment(ROUTE_SRC_UNLOAD, orbitDays, from.getPrimaryEntity()));
148                        
149                        recentlySentPilgrims.add(from.getId(), Global.getSettings().getFloat("minPilgrimSpawnIntervalPerMarket"));
150                }
151        }
152        
153        
154        
155        public MarketAPI pickSourceMarket() {
156                //return Global.getSector().getEconomy().getMarket("jangala");
157                //return Global.getSector().getEconomy().getMarket("sindria");
158                //if (true) return Global.getSector().getEconomy().getMarket("chicomoztoc");
159                
160                WeightedRandomPicker<MarketAPI> markets = new WeightedRandomPicker<MarketAPI>();
161                for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
162                        if (market.isHidden()) continue;
163                        if (!market.hasSpaceport()) continue; // markets w/o spaceports don't launch fleets
164                        if (recentlySentPilgrims.contains(market.getId())) continue;
165                        
166                        
167                        // use this for shrines also
168                        if (SharedData.getData().getMarketsWithoutTradeFleetSpawn().contains(market.getId())) continue;
169                        
170                        float distLY = Misc.getDistanceToPlayerLY(market.getPrimaryEntity());
171                        float mult = 1f - Math.min(0.99f, distLY / 10f);
172                        
173                        String fid = market.getFactionId();
174                        if (Factions.LUDDIC_CHURCH.equals(fid) ||
175                                        Factions.LUDDIC_PATH.equals(fid) ||
176                                        Factions.KOL.equals(fid)) {
177                                mult *= 10f;
178                        }
179                        
180                        markets.add(market, market.getSize() * mult);
181                        
182//                      if (market.getName().toLowerCase().equals("jannow")) {
183//                              markets.add(market, 100000f);
184//                      }
185                }
186                return markets.pick();
187        }
188        
189        public SectorEntityToken pickDestShrine(MarketAPI from) {
190                if (from == null) return null;
191                
192                WeightedRandomPicker<SectorEntityToken> picker = new WeightedRandomPicker<SectorEntityToken>();
193                
194                for (SectorEntityToken shrine : new ArrayList<SectorEntityToken>(shrines)) {
195                        if (!shrine.isAlive()) continue;
196                        
197                        MarketAPI market = shrine.getMarket();
198                        boolean realMarket = market != null && !market.isPlanetConditionMarketOnly();
199                        if (realMarket && market.hasCondition(Conditions.DECIVILIZED)) continue;
200                        
201                        float mult = 1f;
202                        if (realMarket) {
203                                mult = 10f * market.getSize();
204                        } else {
205                                //mult *= 100f;
206                        }
207                        picker.add(shrine, mult);
208                }
209                
210                return picker.pick();
211        }
212        
213        
214        public static PilgrimageRouteData createData(MarketAPI from, SectorEntityToken to) {
215                PilgrimageRouteData data = new PilgrimageRouteData();
216                data.from = from;
217                data.to = to;
218                data.factionId = Factions.LUDDIC_CHURCH;
219                
220                MarketAPI market = to.getMarket();
221                boolean realMarket = market != null && !market.isPlanetConditionMarketOnly();
222                if (realMarket && market.getFaction().isHostileTo(from.getFaction())) {
223                        if (market.getFaction().isHostileTo(Factions.INDEPENDENT)) {
224                                data.smuggling = true;
225                        } else {
226                                data.factionId = Factions.INDEPENDENT;
227                        }
228                }
229                
230                
231                float sizeBasis;
232                if (realMarket) {
233                        sizeBasis = market.getSize() + from.getSize();
234                } else {
235                        sizeBasis = from.getSize() * 0.5f;
236                }
237                data.size = sizeBasis / 40f;
238                
239                return data;
240        }
241        
242        public boolean shouldCancelRouteAfterDelayCheck(RouteData route) {
243                return false;
244        }
245        
246        
247        public CampaignFleetAPI spawnFleet(RouteData route) {
248                Random random = new Random();
249                if (route.getSeed() != null) {
250                        random = new Random(route.getSeed());
251                }
252                
253                CampaignFleetAPI fleet = createPilgrimRouteFleet(route, random);
254                if (fleet == null) return null;;
255                
256                //fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_TRADE_FLEET, true);
257                
258                fleet.addEventListener(this);
259                
260                fleet.addScript(new PilgrimageFleetAssignmentAI(fleet, route));
261                return fleet;
262        }
263        
264        public static CampaignFleetAPI createPilgrimRouteFleet(RouteData route, Random random) {
265                PilgrimageRouteData data = (PilgrimageRouteData) route.getCustom();
266
267                FleetCreatorMission m = new FleetCreatorMission(random);
268                m.beginFleet();
269                
270                
271                m.triggerCreateFleet(FleetSize.MEDIUM, FleetQuality.LOWER, data.factionId, 
272                                                         FleetTypes.SHRINE_PILGRIMS, data.from.getLocationInHyperspace());
273                m.triggerSetFleetOfficers(OfficerNum.FC_ONLY, OfficerQuality.LOWER);
274                m.triggerSetFleetSizeFraction(data.size * 0.5f * (0.5f + random.nextFloat() * 0.5f));
275                m.triggerFleetSetNoFactionInName();
276                m.triggerSetTraderFleet();
277                m.triggerSetFleetComposition(0f, 0f, 0f, 1f, 0f);
278                m.triggerSetFleetMemoryValue(MemFlags.MEMORY_KEY_SOURCE_MARKET, data.from);
279                m.triggerSetFleetMemoryValue("$destShrine", data.to.getId());
280                m.triggerSetFleetMemoryValue(MemFlags.SHRINE_PILGRIM_FLEET, true);
281                
282                CampaignFleetAPI fleet = m.createFleet();
283                fleet.removeScriptsOfClass(MissionFleetAutoDespawn.class);
284                
285                return fleet;
286                
287        }
288
289        public void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle) {
290                RouteData route = RouteManager.getInstance().getRoute(getRouteSourceId(), fleet);
291                if (route == null || !(route.getCustom() instanceof PilgrimageRouteData)) return;
292                
293                if (route.isExpired()) return;
294                if (!battle.isPlayerInvolved()) return;
295
296                // player was involved, on the opposite side of the pilgrim fleet
297                if (battle.getNonPlayerSideSnapshot().contains(fleet)) {
298                        PilgrimageRouteData data = (PilgrimageRouteData) route.getCustom();
299                        
300                        DelayedFleetEncounter e = new DelayedFleetEncounter(new Random(), "luddicPilgrims");
301                        e.setDelayShort();
302                        //e.setDelayNone();
303                        e.setLocationCoreOnly(true, Factions.LUDDIC_CHURCH);
304                        e.beginCreate();
305                        e.triggerCreateFleet(FleetSize.MEDIUM, FleetQuality.DEFAULT, Factions.LUDDIC_CHURCH, FleetTypes.PATROL_MEDIUM, new Vector2f());
306                        e.triggerSetFleetSizeFraction(Math.min(1f, data.size * 3f));
307                        e.autoAdjustFleetTypeName();
308                        e.triggerSetPatrol();
309                        e.triggerSetStandardAggroInterceptFlags();
310                        e.triggerSetFleetGenericHailPermanent("PilgrimRevengeHail");
311                        e.endCreate();                  
312                }
313        }
314
315        public void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param) {
316                
317        }
318
319        public boolean shouldRepeat(RouteData route) {
320                return false;
321        }
322        
323        public void reportAboutToBeDespawnedByRouteManager(RouteData route) {
324                
325        }
326        
327}
328
329
330
331
332
333
334