001package com.fs.starfarer.api.impl.campaign.missions;
002
003import java.util.ArrayList;
004import java.util.List;
005import java.util.Map;
006import java.util.Random;
007
008import com.fs.starfarer.api.Global;
009import com.fs.starfarer.api.campaign.FactionAPI;
010import com.fs.starfarer.api.campaign.FactionAPI.ShipPickMode;
011import com.fs.starfarer.api.campaign.FactionAPI.ShipPickParams;
012import com.fs.starfarer.api.campaign.InteractionDialogAPI;
013import com.fs.starfarer.api.campaign.PersonImportance;
014import com.fs.starfarer.api.campaign.econ.MarketAPI;
015import com.fs.starfarer.api.campaign.rules.MemoryAPI;
016import com.fs.starfarer.api.characters.PersonAPI;
017import com.fs.starfarer.api.combat.ShipVariantAPI;
018import com.fs.starfarer.api.fleet.FleetMemberAPI;
019import com.fs.starfarer.api.fleet.FleetMemberType;
020import com.fs.starfarer.api.fleet.ShipRolePick;
021import com.fs.starfarer.api.impl.campaign.DModManager;
022import com.fs.starfarer.api.impl.campaign.econ.impl.ShipQuality;
023import com.fs.starfarer.api.impl.campaign.fleets.DefaultFleetInflater;
024import com.fs.starfarer.api.impl.campaign.ids.Factions;
025import com.fs.starfarer.api.impl.campaign.ids.Ranks;
026import com.fs.starfarer.api.impl.campaign.ids.ShipRoles;
027import com.fs.starfarer.api.impl.campaign.ids.Tags;
028import com.fs.starfarer.api.impl.campaign.intel.bases.PirateBaseManager;
029import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithBarEvent;
030import com.fs.starfarer.api.util.Misc;
031import com.fs.starfarer.api.util.Misc.Token;
032import com.fs.starfarer.api.util.WeightedRandomPicker;
033
034public class SurplusShipHull extends HubMissionWithBarEvent {
035
036        public static float BASE_PRICE_MULT = 0.5f;
037        
038        protected FleetMemberAPI member;
039        protected int price;
040        
041        @Override
042        protected boolean create(MarketAPI createdAt, boolean barEvent) {
043                if (barEvent) {
044                        List<String> posts = new ArrayList<String>();
045                        posts.add(Ranks.POST_SUPPLY_OFFICER);
046                        if (Misc.isMilitary(createdAt)) {
047                                posts.add(Ranks.POST_BASE_COMMANDER);
048                        }
049                        if (Misc.hasOrbitalStation(createdAt)) {
050                                posts.add(Ranks.POST_STATION_COMMANDER);
051                        }
052                        
053                        String post = pickOne(posts);
054                        setGiverPost(post);
055                        if (post.equals(Ranks.POST_SUPPLY_OFFICER)) {
056                                setGiverRank(Ranks.SPACE_COMMANDER);
057                                setGiverImportance(pickImportance());
058                        } else if (post.equals(Ranks.POST_BASE_COMMANDER)) {
059                                setGiverRank(Ranks.GROUND_COLONEL);
060                                setGiverImportance(pickImportance());
061                        } else if (post.equals(Ranks.POST_STATION_COMMANDER)) {
062                                setGiverRank(Ranks.SPACE_CAPTAIN);
063                                setGiverImportance(pickHighImportance());
064                        }
065                        if (Factions.PIRATES.equals(createdAt.getFaction().getId())) {
066                                setGiverTags(Tags.CONTACT_UNDERWORLD);
067                                setGiverFaction(Factions.PIRATES);
068                        } else {
069                                setGiverTags(Tags.CONTACT_MILITARY);
070                        }
071                        findOrCreateGiver(createdAt, false, false);
072                }
073                
074                PersonAPI person = getPerson();
075                if (person == null) return false;
076                MarketAPI market = person.getMarket();
077                if (market == null) return false;
078                
079                if (market.isPlayerOwned()) return false;
080                if (!Misc.isMilitary(market) && market.getSize() < 7) return false;
081                
082                if (!setPersonMissionRef(person, "$sShip_ref")) {
083                        return false;
084                }
085                
086                if (barEvent) {
087                        setGiverIsPotentialContactOnSuccess();
088                }
089                
090                //genRandom = Misc.random;
091                
092                
093                ShipPickParams params = new ShipPickParams(ShipPickMode.PRIORITY_THEN_ALL);
094                String role = pickRole(getQuality(), person.getFaction(), person.getImportance(), genRandom);
095                
096                ShipVariantAPI variant = null;
097                for (int i = 0; i < 10; i++) {
098                        List<ShipRolePick> picks = market.getFaction().pickShip(role, params, null, genRandom);
099                        if (picks.isEmpty()) return false;
100                        String variantId = picks.get(0).variantId;
101                        variant = Global.getSettings().getVariant(variantId);
102                        variant = Global.getSettings().getVariant(variant.getHullSpec().getHullId() + "_Hull").clone();
103                        if (variant.getHullSpec().hasTag(Tags.NO_SELL)) {
104                                variant = null;
105                                continue;
106                        }
107                        break;
108                }
109                if (variant == null) return false;
110                        
111                member = Global.getFactory().createFleetMember(FleetMemberType.SHIP, variant);
112                assignShipName(member, Factions.INDEPENDENT);
113                
114                float quality = ShipQuality.getShipQuality(market, person.getFaction().getId());
115                float averageDmods = DefaultFleetInflater.getAverageDmodsForQuality(quality);
116                int addDmods = DefaultFleetInflater.getNumDModsToAdd(variant, averageDmods, genRandom);
117                if (addDmods > 0) {
118                        DModManager.setDHull(variant);
119                        DModManager.addDMods(member, true, addDmods, genRandom);
120                }
121                member.getCrewComposition().setCrew(100000);
122                member.getRepairTracker().setCR(0.7f);
123                
124                if (BASE_PRICE_MULT == 1f) {
125                        price = (int) Math.round(variant.getHullSpec().getBaseValue());
126                } else {
127                        price = getRoundNumber(variant.getHullSpec().getBaseValue() * BASE_PRICE_MULT);
128                }
129                
130                setRepFactionChangesTiny();
131                setRepPersonChangesVeryLow();
132                
133                return true;
134        }
135        
136        protected void updateInteractionDataImpl() {
137                // this is weird - in the accept() method, the mission is aborted, which unsets
138                // $sShip_ref. So: we use $sShip_ref2 in the ContactPostAccept rule
139                // and $sShip_ref2 has an expiration of 0, so it'll get unset on its own later.
140                set("$sShip_ref2", this);
141                
142                set("$sShip_barEvent", isBarEvent());
143                set("$sShip_hullSize", member.getHullSpec().getDesignation().toLowerCase());
144                set("$sShip_hullClass", member.getHullSpec().getHullNameWithDashClass());
145                set("$sShip_price", Misc.getWithDGS(price));
146                set("$sShip_manOrWoman", getPerson().getManOrWoman());
147                set("$sShip_rank", getPerson().getRank().toLowerCase());
148                set("$sShip_rankAOrAn", getPerson().getRankArticle());
149                set("$sShip_hisOrHer", getPerson().getHisOrHer());
150                set("$sShip_member", member);
151        }
152        
153        @Override
154        protected boolean callAction(String action, String ruleId, InteractionDialogAPI dialog, List<Token> params,
155                                                             Map<String, MemoryAPI> memoryMap) {
156                if ("showShip".equals(action)) {
157                        dialog.getVisualPanel().showFleetMemberInfo(member, true);
158                        return true;
159                } else if ("showPerson".equals(action)) {
160                        dialog.getVisualPanel().showPersonInfo(getPerson(), true);
161                        return true;
162                }
163                return false;
164        }
165
166        @Override
167        public String getBaseName() {
168                return "Surplus Ship Hull"; // not used I don't think
169        }
170        
171        @Override
172        public void accept(InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap) {
173                // it's just an transaction immediate transaction handled in rules.csv
174                // no intel item etc
175                
176                currentStage = new Object(); // so that the abort() assumes the mission was successful
177                abort();
178        }
179        
180        public static String pickRole(float quality, FactionAPI faction, PersonImportance imp, Random random) {
181                WeightedRandomPicker<String> picker = new WeightedRandomPicker<String>(random);
182                
183                float cycles = PirateBaseManager.getInstance().getDaysSinceStart() / 365f;
184                
185                if (imp == PersonImportance.VERY_HIGH && cycles < 3) imp = PersonImportance.HIGH;
186                if (imp == PersonImportance.HIGH && cycles < 1) imp = PersonImportance.MEDIUM;
187                
188                if (quality < 0.5f && imp.ordinal() > PersonImportance.MEDIUM.ordinal()) {
189                        imp = PersonImportance.MEDIUM;
190                }
191                
192                float w = faction.getDoctrine().getWarships() - 1f;
193                float c = faction.getDoctrine().getCarriers() - 1f;
194                float p = faction.getDoctrine().getPhaseShips() - 1f;
195                if (w + c + p < 1) w = 1;
196                
197                switch (imp) {
198                case VERY_LOW:
199                        picker.add(ShipRoles.COMBAT_SMALL, w);
200                        picker.add(ShipRoles.COMBAT_MEDIUM, w/2f);
201                        picker.add(ShipRoles.CARRIER_SMALL, c);
202                        picker.add(ShipRoles.PHASE_SMALL, p);
203                        break;
204                case LOW:
205                        picker.add(ShipRoles.COMBAT_SMALL, w/2f);
206                        picker.add(ShipRoles.COMBAT_MEDIUM, w);
207                        picker.add(ShipRoles.CARRIER_SMALL, c);
208                        picker.add(ShipRoles.PHASE_SMALL, p);
209                        break;
210                case MEDIUM:
211                        picker.add(ShipRoles.COMBAT_MEDIUM, w/2f);
212                        picker.add(ShipRoles.COMBAT_LARGE, w);
213                        picker.add(ShipRoles.CARRIER_SMALL, c/2f);
214                        picker.add(ShipRoles.CARRIER_MEDIUM, c);
215                        picker.add(ShipRoles.PHASE_SMALL, p/2f);
216                        picker.add(ShipRoles.PHASE_MEDIUM, p);
217                        break;
218                case HIGH:
219                        picker.add(ShipRoles.COMBAT_MEDIUM, w/4f);
220                        picker.add(ShipRoles.COMBAT_LARGE, w);
221                        picker.add(ShipRoles.COMBAT_CAPITAL, w/2f);
222                        picker.add(ShipRoles.CARRIER_MEDIUM, c);
223                        picker.add(ShipRoles.CARRIER_LARGE, c/2f);
224                        picker.add(ShipRoles.PHASE_MEDIUM, p);
225                        picker.add(ShipRoles.PHASE_LARGE, p/2f);
226                        break;
227                case VERY_HIGH:
228                        picker.add(ShipRoles.COMBAT_MEDIUM, w/4f);
229                        picker.add(ShipRoles.COMBAT_LARGE, w/2f);
230                        picker.add(ShipRoles.COMBAT_CAPITAL, w);
231                        picker.add(ShipRoles.CARRIER_MEDIUM, c/2f);
232                        picker.add(ShipRoles.CARRIER_LARGE, c);
233                        picker.add(ShipRoles.PHASE_MEDIUM, p/2f);
234                        picker.add(ShipRoles.PHASE_LARGE, p);
235                        picker.add(ShipRoles.PHASE_CAPITAL, p/2f);
236                        break;
237                }
238                return picker.pick();
239        }
240        
241}
242