001package com.fs.starfarer.api.impl.campaign.skills;
002
003import com.fs.starfarer.api.Global;
004import com.fs.starfarer.api.campaign.FleetDataAPI;
005import com.fs.starfarer.api.characters.CharacterStatsSkillEffect;
006import com.fs.starfarer.api.characters.FleetStatsSkillEffect;
007import com.fs.starfarer.api.characters.MutableCharacterStatsAPI;
008import com.fs.starfarer.api.characters.ShipSkillEffect;
009import com.fs.starfarer.api.characters.SkillSpecAPI;
010import com.fs.starfarer.api.combat.MutableShipStatsAPI;
011import com.fs.starfarer.api.combat.StatBonus;
012import com.fs.starfarer.api.combat.MutableStat.StatMod;
013import com.fs.starfarer.api.combat.ShipAPI.HullSize;
014import com.fs.starfarer.api.fleet.FleetMemberAPI;
015import com.fs.starfarer.api.fleet.MutableFleetStatsAPI;
016import com.fs.starfarer.api.impl.campaign.ids.Stats;
017import com.fs.starfarer.api.ui.TooltipMakerAPI;
018import com.fs.starfarer.api.util.Misc;
019
020public class Navigation {
021        
022        public static float TERRAIN_PENALTY_REDUCTION = 30f;
023        public static float FUEL_USE_REDUCTION = 25;
024        //public static final float SUSTAINED_BURN_BONUS = 5;
025        public static float FLEET_BURN_BONUS = 1;
026        public static float SB_BURN_BONUS = 1;
027        
028        public static float FUEL_USE_REDUCTION_MAX_PERCENT = 50;
029        public static float FUEL_USE_REDUCTION_MAX_FUEL = 25;
030        
031        public static String FUEL_EFFECT_ID = "nav_fuel_use_mod";
032        
033        public static class Level4 extends BaseSkillEffectDescription implements ShipSkillEffect {
034                public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {
035                        id = FUEL_EFFECT_ID;
036                        float useMult = getFuelUseMult(id, getFleetData(stats));
037                        stats.getFuelUseMod().modifyMult(id, useMult);
038                }
039                
040                public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {
041                        id = FUEL_EFFECT_ID;
042                        stats.getFuelUseMod().unmodifyMult(id);
043                }
044                
045                public String getEffectDescription(float level) {
046                        return null;
047                }
048                
049                protected float getFuelUseBase(String id, FleetDataAPI data) {
050                        if (data == null) return 0f;
051                        
052                        float fuelUse = 0;
053                        for (FleetMemberAPI curr : data.getMembersListCopy()) {
054                                StatBonus stat = curr.getStats().getFuelUseMod();
055                                StatMod mod = stat.getMultBonus(id);
056                                if (mod != null) {
057                                        stat.unmodifyMult(mod.source);
058                                }
059                                fuelUse += curr.getFuelUse();
060                                if (mod != null) {
061                                        stat.modifyMult(mod.source, mod.value, mod.desc);
062                                }
063                        }
064                        return fuelUse;
065                }
066                
067                protected float getFuelUseMult(String id, FleetDataAPI data) {
068                        if (data == null) return 0f;
069                        
070                        String key = "nav1";
071                        Float bonus = (Float) data.getCacheClearedOnSync().get(key);
072                        if (bonus != null) return bonus;
073                        
074                        float fuelUse = getFuelUseBase(id, data);
075
076                        float useMult = 0f;
077                        
078                        if (fuelUse > 0) {
079                                float maxReduced = Math.min(fuelUse * (FUEL_USE_REDUCTION_MAX_PERCENT * 0.01f), 
080                                                                                        FUEL_USE_REDUCTION_MAX_FUEL);
081                                useMult = 1f - maxReduced / fuelUse;
082                                useMult = Math.round(useMult * 100f) / 100f;
083                        }
084                        
085                        data.getCacheClearedOnSync().put(key, useMult);
086                        return useMult;
087                }
088                
089                public void createCustomDescription(MutableCharacterStatsAPI stats, SkillSpecAPI skill, 
090                                                                                        TooltipMakerAPI info, float width) {
091                        init(stats, skill);
092                        
093                        info.addPara("Reduces fuel consumption by %s or %s units, whichever is lower",
094                                        0f, hc, hc,
095                                        "" + (int) FUEL_USE_REDUCTION_MAX_PERCENT + "%", 
096                                        "" + (int) FUEL_USE_REDUCTION_MAX_FUEL
097                                        );
098                        
099                        if (isInCampaign()) {
100                                FleetDataAPI data = Global.getSector().getPlayerFleet().getFleetData();
101                                String id = FUEL_EFFECT_ID;
102                                float fuelUse = getFuelUseBase(id, data);
103                                float useMult = getFuelUseMult(id, data);
104                                
105                                float reduction = fuelUse * (1f - useMult);
106                                
107                                boolean has = stats.getSkillLevel(skill.getId()) > 0;
108                                String is = "is";
109                                if (!has) is = "would be";
110                                info.addPara(indent + "Your fleet has a base fuel consumption of %s, which " + is + " reduced by %s, or %s units",
111                                                0f, tc, hc, 
112                                                "" + Misc.getRoundedValueMaxOneAfterDecimal(fuelUse), 
113                                                "" + (int)(Math.round((1f - useMult) * 100f)) + "%",
114                                                "" + Misc.getRoundedValueMaxOneAfterDecimal(reduction) 
115                                                );
116                                info.addSpacer(5f);
117                        }
118                }
119                
120                public ScopeDescription getScopeDescription() {
121                        return ScopeDescription.FLEET;
122                }
123        }
124        
125
126        public static class Level1 implements CharacterStatsSkillEffect {
127                public void apply(MutableCharacterStatsAPI stats, String id, float level) {
128                        stats.getDynamic().getStat(Stats.NAVIGATION_PENALTY_MULT).modifyFlat(id,
129                                                                        -0.01f * TERRAIN_PENALTY_REDUCTION);
130                }
131
132                public void unapply(MutableCharacterStatsAPI stats, String id) {
133                        stats.getDynamic().getStat(Stats.NAVIGATION_PENALTY_MULT).unmodify(id);
134                }
135                
136                public String getEffectDescription(float level) {
137                        return "-" + (int) (TERRAIN_PENALTY_REDUCTION) + "% terrain movement penalty from all applicable terrain";
138                }
139
140                public String getEffectPerLevelDescription() {
141                        return null;
142                }
143
144                public ScopeDescription getScopeDescription() {
145                        return ScopeDescription.FLEET;
146                }
147        }
148        
149        public static class Level1B implements FleetStatsSkillEffect {
150                public void apply(MutableFleetStatsAPI stats, String id, float level) {
151                        stats.getDynamic().getMod(Stats.CAN_SEE_NASCENT_POINTS).modifyFlat(id, 1);
152                }
153                
154                public void unapply(MutableFleetStatsAPI stats, String id) {
155                        stats.getDynamic().getMod(Stats.CAN_SEE_NASCENT_POINTS).unmodify(id);
156                }
157                
158                public String getEffectDescription(float level) {
159                        return "Can detect nascent gravity wells in hyperspace around star systems";
160                }
161                
162                public String getEffectPerLevelDescription() {
163                        return null;
164                }
165                
166                public ScopeDescription getScopeDescription() {
167                        return ScopeDescription.FLEET;
168                }
169        }
170        
171//      public static class Level1B implements FleetStatsSkillEffect {
172//              public void apply(MutableFleetStatsAPI stats, String id, float level) {
173//                      stats.getDynamic().getMod(Stats.CAN_SEE_NASCENT_POINTS).modifyFlat(id, 1);
174//              }
175//              
176//              public void unapply(MutableFleetStatsAPI stats, String id) {
177//                      stats.getDynamic().getMod(Stats.CAN_SEE_NASCENT_POINTS).unmodify(id);
178//              }
179//              
180//              public String getEffectDescription(float level) {
181//                      return "Can detect nascent gravity wells around star systems";
182//              }
183//              
184//              public String getEffectPerLevelDescription() {
185//                      return null;
186//              }
187//              
188//              public ScopeDescription getScopeDescription() {
189//                      return ScopeDescription.FLEET;
190//              }
191//      }
192        
193//      public static class Level2 implements FleetStatsSkillEffect {
194//              public void apply(MutableFleetStatsAPI stats, String id, float level) {
195//                      stats.getFuelUseHyperMult().modifyMult(id, 1f - FUEL_USE_REDUCTION / 100f);
196//                      stats.getFuelUseNormalMult().modifyMult(id, 1f - FUEL_USE_REDUCTION / 100f);
197//              }
198//              
199//              public void unapply(MutableFleetStatsAPI stats, String id) {
200//                      stats.getFuelUseHyperMult().unmodify(id);
201//                      stats.getFuelUseNormalMult().unmodify(id);
202//              }
203//              
204//              public String getEffectDescription(float level) {
205//                      return "-" + (int) FUEL_USE_REDUCTION + "% fuel consumption";
206//              }
207//              
208//              public String getEffectPerLevelDescription() {
209//                      return null;
210//              }
211//              
212//              public ScopeDescription getScopeDescription() {
213//                      return ScopeDescription.FLEET;
214//              }
215//      }
216        
217        public static class Level2 implements ShipSkillEffect {
218                public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {
219                        stats.getFuelUseMod().modifyMult(id, 1f - FUEL_USE_REDUCTION / 100f);
220                }
221                
222                public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {
223                        stats.getFuelUseMod().unmodify(id);
224                }       
225                
226                public String getEffectDescription(float level) {
227                        return "-" + (int) FUEL_USE_REDUCTION + "% fuel consumption";
228                }
229                
230                public String getEffectPerLevelDescription() {
231                        return null;
232                }
233                
234                public ScopeDescription getScopeDescription() {
235                        return ScopeDescription.ALL_SHIPS;
236                }
237        }
238        
239        
240        public static class Level3A implements FleetStatsSkillEffect {
241                public void apply(MutableFleetStatsAPI stats, String id, float level) {
242                        stats.getFleetwideMaxBurnMod().modifyFlat(id, FLEET_BURN_BONUS, "Navigation");
243                }
244                
245                public void unapply(MutableFleetStatsAPI stats, String id) {
246                        stats.getFleetwideMaxBurnMod().unmodifyFlat(id);
247                }
248                
249                public String getEffectDescription(float level) {
250                        return "+" + (int) FLEET_BURN_BONUS + " maximum burn level";
251                }
252                
253                public String getEffectPerLevelDescription() {
254                        return null;
255                }
256                
257                public ScopeDescription getScopeDescription() {
258                        return ScopeDescription.FLEET;
259                }
260        }
261        
262        public static class Level3B implements FleetStatsSkillEffect {
263                public void apply(MutableFleetStatsAPI stats, String id, float level) {
264                        stats.getDynamic().getMod(Stats.SUSTAINED_BURN_BONUS).modifyFlat(id, SB_BURN_BONUS);
265                }
266                
267                public void unapply(MutableFleetStatsAPI stats, String id) {
268                        stats.getDynamic().getMod(Stats.SUSTAINED_BURN_BONUS).unmodifyFlat(id);
269                }
270                
271                public String getEffectDescription(float level) {
272                        return "Increases the burn bonus of the \"Sustained Burn\" ability by " + (int) SB_BURN_BONUS;
273                }
274                
275                public String getEffectPerLevelDescription() {
276                        return null;
277                }
278                
279                public ScopeDescription getScopeDescription() {
280                        return ScopeDescription.FLEET;
281                }
282        }
283}
284
285
286