001package com.fs.starfarer.api.impl.campaign.fleets.misc;
002
003import java.util.ArrayList;
004import java.util.List;
005import java.util.Random;
006
007import org.lwjgl.util.vector.Vector2f;
008
009import com.fs.starfarer.api.Global;
010import com.fs.starfarer.api.campaign.BattleAPI;
011import com.fs.starfarer.api.campaign.CampaignFleetAPI;
012import com.fs.starfarer.api.campaign.SectorEntityToken;
013import com.fs.starfarer.api.campaign.econ.MarketAPI;
014import com.fs.starfarer.api.impl.campaign.fleets.RouteManager;
015import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
016import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment;
017import com.fs.starfarer.api.impl.campaign.fleets.misc.MiscFleetRouteManager.MiscRouteData;
018import com.fs.starfarer.api.impl.campaign.ids.Conditions;
019import com.fs.starfarer.api.impl.campaign.ids.Factions;
020import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
021import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
022import com.fs.starfarer.api.impl.campaign.ids.Tags;
023import com.fs.starfarer.api.impl.campaign.missions.DelayedFleetEncounter;
024import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission;
025import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.FleetQuality;
026import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.FleetSize;
027import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.OfficerNum;
028import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.OfficerQuality;
029import com.fs.starfarer.api.impl.campaign.missions.hub.MissionFleetAutoDespawn;
030import com.fs.starfarer.api.impl.campaign.shared.SharedData;
031import com.fs.starfarer.api.util.Misc;
032import com.fs.starfarer.api.util.WeightedRandomPicker;
033
034public class MiscPilgrimFleetCreator extends BaseMiscFleetCreatorPlugin {
035
036        public String SHRINE_LIST_KEY = "shrine_list_key";
037        
038        
039        @Override
040        public float getFrequency() {
041                return Global.getSettings().getFloat("miscFleetPilgrimFrequency");
042        }
043
044        @Override
045        public int getMaxFleetsForThisCreator() {
046                return Global.getSettings().getInt("miscFleetPilgrimMaxFleets");
047        }
048
049
050
051        public List<SectorEntityToken> getShrines(MiscFleetRouteManager manager) {
052                List<SectorEntityToken> shrines = (List<SectorEntityToken>) manager.getData().get(SHRINE_LIST_KEY);
053                if (shrines == null) {
054                        shrines = Global.getSector().getEntitiesWithTag(Tags.LUDDIC_SHRINE);
055                        manager.getData().put(SHRINE_LIST_KEY, shrines);
056                }
057                return shrines;
058        }
059        
060        
061        @Override
062        public MiscRouteData createRouteParams(MiscFleetRouteManager manager, Random random) {
063                MarketAPI from = pickSourceMarket(manager);
064                if (from == null) return null;
065                SectorEntityToken to = pickDestShrine(manager, from);
066                if (to == null) return null;
067                
068//              from = Global.getSector().getEconomy().getMarket("chalcedon");
069//              to = Global.getSector().getEconomy().getMarket("eochu_bres").getPrimaryEntity();
070//              to = Global.getSector().getEntityById("beholder_station");
071                
072                MiscRouteData result = createData(from, to);
073                
074                return result;
075        }
076        
077
078        @Override
079        public CampaignFleetAPI createFleet(MiscFleetRouteManager manager, RouteData route, Random random) {
080                MiscRouteData data = (MiscRouteData) route.getCustom();
081
082                FleetCreatorMission m = new FleetCreatorMission(random);
083                m.beginFleet();
084                
085                
086                m.triggerCreateFleet(FleetSize.MEDIUM, FleetQuality.LOWER, data.factionId, 
087                                                         FleetTypes.SHRINE_PILGRIMS, data.from.getLocationInHyperspace());
088                m.triggerSetFleetOfficers(OfficerNum.FC_ONLY, OfficerQuality.LOWER);
089                m.triggerSetFleetSizeFraction(data.size * 0.5f * (0.5f + random.nextFloat() * 0.5f));
090                m.triggerFleetSetNoFactionInName();
091                m.triggerSetTraderFleet();
092                m.triggerSetFleetComposition(0f, 0f, 0f, 1f, 0f);
093                m.triggerSetFleetMemoryValue(MemFlags.MEMORY_KEY_SOURCE_MARKET, data.from);
094                m.triggerSetFleetMemoryValue("$destShrine", data.to.getId());
095                m.triggerSetFleetMemoryValue(MemFlags.SHRINE_PILGRIM_FLEET, true);
096                
097                CampaignFleetAPI fleet = m.createFleet();
098                fleet.removeScriptsOfClass(MissionFleetAutoDespawn.class);
099                
100                return fleet;
101        }
102
103        
104        public MiscRouteData createData(MarketAPI from, SectorEntityToken to) {
105                MiscRouteData data = new MiscRouteData(getId());
106                data.from = from;
107                data.to = to;
108                
109                if (from.getFaction().isHostileTo(Factions.LUDDIC_CHURCH)) {
110                        data.factionId = Factions.INDEPENDENT;
111                } else {
112                        data.factionId = Factions.LUDDIC_CHURCH;
113                }
114                
115                
116                MarketAPI market = to.getMarket();
117                boolean realMarket = market != null && !market.isPlanetConditionMarketOnly();
118                if (realMarket && market.getFaction().isHostileTo(from.getFaction())) {
119                        if (market.getFaction().isHostileTo(data.factionId)) {
120                                data.smuggling = true;
121                        }
122//                      if (market.getFaction().isHostileTo(Factions.INDEPENDENT)) {
123//                              data.smuggling = true;
124//                      } else {
125//                              data.factionId = Factions.INDEPENDENT;
126//                      }
127                }
128                
129                
130                float sizeBasis;
131                if (realMarket) {
132                        sizeBasis = market.getSize() + from.getSize();
133                } else {
134                        sizeBasis = from.getSize() * 0.5f;
135                }
136                data.size = sizeBasis / 40f;
137                
138                return data;
139        }
140        
141        public MarketAPI pickSourceMarket(MiscFleetRouteManager manager) {
142                
143                WeightedRandomPicker<MarketAPI> markets = new WeightedRandomPicker<MarketAPI>(manager.getRandom());
144                for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
145                        if (market.isHidden()) continue;
146                        if (!market.hasSpaceport()) continue; // markets w/o spaceports don't launch fleets
147                        if (manager.getTimeout(getId()).contains(market.getId())) continue;
148                        if (market.getContainingLocation().hasTag(Tags.SYSTEM_CUT_OFF_FROM_HYPER)) continue;
149                        if (market.getFaction().isHostileTo(Factions.INDEPENDENT) &&
150                                market.getFaction().isHostileTo(Factions.LUDDIC_CHURCH)) {
151                                continue;
152                        }
153                        
154                        // use this for shrines also
155                        if (SharedData.getData().getMarketsWithoutTradeFleetSpawn().contains(market.getId())) continue;
156                        
157                        float distLY = Misc.getDistanceToPlayerLY(market.getPrimaryEntity());
158                        float mult = 1f - Math.min(0.99f, distLY / 10f);
159                        
160                        String fid = market.getFactionId();
161                        if (Factions.LUDDIC_CHURCH.equals(fid) ||
162                                        Factions.LUDDIC_PATH.equals(fid) ||
163                                        Factions.KOL.equals(fid)) {
164                                mult *= 10f;
165                        }
166                        
167                        markets.add(market, market.getSize() * mult);
168                        
169//                      if (market.getName().toLowerCase().equals("jannow")) {
170//                              markets.add(market, 100000f);
171//                      }
172                }
173                return markets.pick();
174        }
175        
176        public SectorEntityToken pickDestShrine(MiscFleetRouteManager manager, MarketAPI from) {
177                if (from == null) return null;
178                
179                WeightedRandomPicker<SectorEntityToken> picker = new WeightedRandomPicker<SectorEntityToken>(manager.getRandom());
180                
181                for (SectorEntityToken shrine : new ArrayList<SectorEntityToken>(getShrines(manager))) {
182                        if (!shrine.isAlive()) continue;
183                        if (shrine.getContainingLocation().hasTag(Tags.SYSTEM_CUT_OFF_FROM_HYPER)) continue;
184                        
185                        MarketAPI market = shrine.getMarket();
186                        boolean realMarket = market != null && !market.isPlanetConditionMarketOnly();
187                        if (realMarket) {
188                                if (market.hasCondition(Conditions.DECIVILIZED)) continue;
189                                if (market.getFaction().isHostileTo(Factions.INDEPENDENT) &&
190                                                market.getFaction().isHostileTo(Factions.LUDDIC_CHURCH)) {
191                                                continue;
192                                        }
193                        }
194                        
195                        float mult = 1f;
196                        if (realMarket) {
197                                mult = 10f * market.getSize();
198                        } else {
199                                //mult *= 100f;
200                        }
201                        picker.add(shrine, mult);
202                }
203                
204                return picker.pick();
205        }
206        
207        @Override
208        public void reportBattleOccurred(MiscFleetRouteManager manager, CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle) {
209                RouteData route = RouteManager.getInstance().getRoute(manager.getRouteSourceId(), fleet);
210                if (route == null || !(route.getCustom() instanceof MiscRouteData)) return;
211                
212                if (route.isExpired()) return;
213                if (!battle.isPlayerInvolved()) return;
214
215                // player was involved, no the opposite side of the pilgrim fleet
216                if (battle.getNonPlayerSideSnapshot().contains(fleet)) {
217                        MiscRouteData data = (MiscRouteData) route.getCustom();
218                        
219                        DelayedFleetEncounter e = new DelayedFleetEncounter(new Random(), "luddicPilgrims");
220                        e.setDelayShort();
221                        //e.setDelayNone();
222                        e.setLocationCoreOnly(true, Factions.LUDDIC_CHURCH);
223                        e.beginCreate();
224                        e.triggerCreateFleet(FleetSize.MEDIUM, FleetQuality.DEFAULT, Factions.LUDDIC_CHURCH, FleetTypes.PATROL_MEDIUM, new Vector2f());
225                        e.triggerSetFleetSizeFraction(Math.min(1f, data.size * 3f));
226                        e.autoAdjustFleetTypeName();
227                        e.triggerSetPatrol();
228                        e.triggerSetStandardAggroInterceptFlags();
229                        e.triggerSetFleetGenericHailPermanent("PilgrimRevengeHail");
230                        e.endCreate();                  
231                }
232        }
233        
234        
235        public String getStartingActionText(CampaignFleetAPI fleet, RouteSegment segment, MiscRouteData data) {
236                return "preparing for pilgrimage to shrine on " + data.to.getName();
237        }
238
239        public String getEndingActionText(CampaignFleetAPI fleet, RouteSegment segment, MiscRouteData data) {
240                return "disembarking pilgrims at " + data.from.getName();
241        }
242
243        public String getTravelToDestActionText(CampaignFleetAPI fleet, RouteSegment segment, MiscRouteData data) {
244                return "taking pilgrims to shrine on " + data.to.getName();
245        }
246
247        public String getTravelReturnActionText(CampaignFleetAPI fleet, RouteSegment segment, MiscRouteData data) {
248                return "returning pilgrims to " + data.from.getName();
249        }
250
251        public String getAtDestUnloadActionText(CampaignFleetAPI fleet, RouteSegment segment, MiscRouteData data) {
252                return "disembarking pilgrims at shrine on " + data.to.getName();
253        }
254
255        public String getAtDestLoadActionText(CampaignFleetAPI fleet, RouteSegment segment, MiscRouteData data) {
256                return "embarking pilgrims for return voyage to " + data.from.getName();
257        }
258        
259}