001package com.fs.starfarer.api.impl.campaign.skills;
002
003import java.awt.Color;
004
005import org.lwjgl.util.vector.Vector2f;
006
007import com.fs.starfarer.api.characters.AfterShipCreationSkillEffect;
008import com.fs.starfarer.api.characters.DescriptionSkillEffect;
009import com.fs.starfarer.api.characters.MutableCharacterStatsAPI;
010import com.fs.starfarer.api.characters.ShipSkillEffect;
011import com.fs.starfarer.api.characters.SkillSpecAPI;
012import com.fs.starfarer.api.combat.CombatEntityAPI;
013import com.fs.starfarer.api.combat.DamageAPI;
014import com.fs.starfarer.api.combat.MutableShipStatsAPI;
015import com.fs.starfarer.api.combat.ShipAPI;
016import com.fs.starfarer.api.combat.ShipAPI.HullSize;
017import com.fs.starfarer.api.combat.listeners.AdvanceableListener;
018import com.fs.starfarer.api.combat.listeners.DamageTakenModifier;
019import com.fs.starfarer.api.impl.campaign.ids.Stats;
020import com.fs.starfarer.api.ui.TooltipMakerAPI;
021import com.fs.starfarer.api.util.Misc;
022
023public class DamageControl {
024        
025        public static float SECONDS_PER_PROC = 2f;
026        
027        public static float INSTA_REPAIR = 0.25f;
028        public static float CREW_LOSS_REDUCTION = 50;
029        public static float MODULE_REPAIR_BONUS = 50;
030        public static float HULL_DAMAGE_REDUCTION = 25;
031        public static float EMP_DAMAGE_REDUCTION = 25;
032        
033        public static float ELITE_DAMAGE_THRESHOLD = 500;
034        public static float ELITE_DAMAGE_REDUCTION_PERCENT = 60;
035        
036        public static float ELITE_DAMAGE_TO_HULL_PERCENT = 15;
037        
038        public static class Level2 implements ShipSkillEffect {
039
040                public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {
041                        stats.getCrewLossMult().modifyMult(id, 1f - CREW_LOSS_REDUCTION / 100f);
042                }
043                
044                public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {
045                        stats.getCrewLossMult().unmodify(id);
046                }
047                
048                public String getEffectDescription(float level) {
049                        return "-" + (int)(CREW_LOSS_REDUCTION) + "% crew lost due to hull damage in combat";
050                }
051                
052                public String getEffectPerLevelDescription() {
053                        return null;
054                }
055                
056                public ScopeDescription getScopeDescription() {
057                        return ScopeDescription.PILOTED_SHIP;
058                }
059        }
060        
061        public static class Level1 implements ShipSkillEffect {
062                
063                public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {
064                        stats.getDynamic().getMod(Stats.INDIVIDUAL_SHIP_RECOVERY_MOD).modifyFlat(id, 1000f);
065                }
066                
067                public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {
068                        stats.getDynamic().getMod(Stats.INDIVIDUAL_SHIP_RECOVERY_MOD).unmodify(id);
069                }
070                
071                public String getEffectDescription(float level) {
072                        return "If lost in combat, ship is almost always recoverable";
073                }
074                
075                public String getEffectPerLevelDescription() {
076                        return null;
077                }
078                
079                public ScopeDescription getScopeDescription() {
080                        return ScopeDescription.PILOTED_SHIP;
081                }
082        }
083
084        public static class Level3 implements ShipSkillEffect {
085
086                public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {
087                        float timeMult = 1f / ((100f + MODULE_REPAIR_BONUS) / 100f);
088                        stats.getCombatWeaponRepairTimeMult().modifyMult(id, timeMult);
089                        stats.getCombatEngineRepairTimeMult().modifyMult(id, timeMult);
090                }
091                
092                public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {
093                        stats.getCombatWeaponRepairTimeMult().unmodify(id);
094                        stats.getCombatEngineRepairTimeMult().unmodify(id);
095                }
096                
097                public String getEffectDescription(float level) {
098                        return "" + (int)(MODULE_REPAIR_BONUS) + "% faster in-combat weapon and engine repairs";
099                }
100                
101                public String getEffectPerLevelDescription() {
102                        return null;
103                }
104
105                public ScopeDescription getScopeDescription() {
106                        return ScopeDescription.PILOTED_SHIP;
107                }
108        }
109        
110        public static class Level4 implements ShipSkillEffect {
111
112                public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {
113                        stats.getHullDamageTakenMult().modifyMult(id, 1f - HULL_DAMAGE_REDUCTION / 100f);
114                }
115                
116                public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {
117                        stats.getHullDamageTakenMult().unmodify(id);
118                }       
119                
120                public String getEffectDescription(float level) {
121                        return "-" + (int)(HULL_DAMAGE_REDUCTION) + "% hull damage taken";
122                }
123                
124                public String getEffectPerLevelDescription() {
125                        return null;
126                }
127                
128                public ScopeDescription getScopeDescription() {
129                        return ScopeDescription.PILOTED_SHIP;
130                }
131        }
132        
133        public static class Level5 implements ShipSkillEffect {
134                public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {
135                        stats.getDynamic().getMod(Stats.INSTA_REPAIR_FRACTION).modifyFlat(id, INSTA_REPAIR);
136                }
137                
138                public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {
139                        stats.getDynamic().getMod(Stats.INSTA_REPAIR_FRACTION).unmodify(id);
140                }       
141                
142                public String getEffectDescription(float level) {
143                        return "" + (int) Math.round(INSTA_REPAIR * 100f) + "% of hull and armor damage taken repaired after combat ends, at no cost";
144                }
145                
146                public String getEffectPerLevelDescription() {
147                        return null;
148                }
149                
150                public ScopeDescription getScopeDescription() {
151                        return ScopeDescription.PILOTED_SHIP;
152                }
153        }
154        
155        public static class Level6 extends BaseSkillEffectDescription implements AfterShipCreationSkillEffect {
156                public void applyEffectsAfterShipCreation(ShipAPI ship, String id) {
157                        ship.addListener(new DamageControlDamageTakenMod(ship));
158                }
159
160                public void unapplyEffectsAfterShipCreation(ShipAPI ship, String id) {
161                        ship.removeListenerOfClass(DamageControlDamageTakenMod.class);
162                }
163                
164                public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {}
165                public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {}
166                
167                public String getEffectDescription(float level) {
168                        return null;
169                }
170                
171                public void createCustomDescription(MutableCharacterStatsAPI stats, SkillSpecAPI skill, 
172                                                                                        TooltipMakerAPI info, float width) {
173                        init(stats, skill);
174
175                        Color c = hc;
176                        float level = stats.getSkillLevel(skill.getId());
177                        if (level < 2) {
178                                c = dhc;
179                        }
180                        String seconds = "" + (int) SECONDS_PER_PROC + " seconds";
181                        if (SECONDS_PER_PROC == 1f) seconds = "second";
182                        //info.addPara("Single-hit hull damage above %s points has the portion above %s reduced by %s",
183                        info.addPara("At most once every " +  seconds + ", single-hit hull damage above %s points has the portion above %s reduced by %s",
184                                        0f, c, c,
185                                        "" + (int) ELITE_DAMAGE_THRESHOLD,
186                                        "" + (int) ELITE_DAMAGE_THRESHOLD,
187                                        "" + (int) ELITE_DAMAGE_REDUCTION_PERCENT + "%"
188                        );
189                }
190                
191                public ScopeDescription getScopeDescription() {
192                        return ScopeDescription.PILOTED_SHIP;
193                }
194        }
195        
196        
197        public static class DamageControlDamageTakenMod implements DamageTakenModifier, AdvanceableListener {
198                protected ShipAPI ship;
199                protected float sinceProc = SECONDS_PER_PROC + 1f;
200                public DamageControlDamageTakenMod(ShipAPI ship) {
201                        this.ship = ship;
202                }
203                
204                public void advance(float amount) {
205                        sinceProc += amount;
206                }
207                
208                public String modifyDamageTaken(Object param, CombatEntityAPI target, 
209                                                                                DamageAPI damage, Vector2f point,
210                                                                                boolean shieldHit) {
211                        if (!shieldHit && sinceProc > SECONDS_PER_PROC) {
212                                float mult = 1f - ELITE_DAMAGE_REDUCTION_PERCENT / 100f;
213                                ship.setNextHitHullDamageThresholdMult(ELITE_DAMAGE_THRESHOLD, mult);
214                                sinceProc = 0f;
215                        }
216                        return null;
217                }
218        }
219
220        public static class Level7 implements ShipSkillEffect {
221
222                public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {
223                        stats.getDamageToTargetHullMult().modifyPercent(id, ELITE_DAMAGE_TO_HULL_PERCENT);
224                }
225                
226                public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {
227                        stats.getDamageToTargetHullMult().unmodifyPercent(id);
228                }
229                
230                public String getEffectDescription(float level) {
231                        return "+" + (int)(ELITE_DAMAGE_TO_HULL_PERCENT) + "% damage dealt to hull";
232                }
233                
234                public String getEffectPerLevelDescription() {
235                        return null;
236                }
237                
238                public ScopeDescription getScopeDescription() {
239                        return ScopeDescription.PILOTED_SHIP;
240                }
241        }
242        
243        
244        
245        public static class Level8Desc implements DescriptionSkillEffect {
246                public String getString() {
247                        return "\n\n*Normally, a damaged but functional module will not be repaired until 5 seconds have passed "
248                                        + "without it taking damage.";
249                }
250                public Color[] getHighlightColors() {
251                        Color h = Misc.getHighlightColor();
252                        h = Misc.getDarkHighlightColor();
253                        return new Color[] {h};
254                }
255                public String[] getHighlights() {
256                        return new String [] {"5"};
257                }
258                public Color getTextColor() {
259                        return null;
260                }
261        }
262        public static class Level8 implements ShipSkillEffect {
263
264                public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {
265                        stats.getDynamic().getMod(Stats.CAN_REPAIR_MODULES_UNDER_FIRE).modifyFlat(id, 1f);
266                }
267                
268                public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {
269                        stats.getDynamic().getMod(Stats.CAN_REPAIR_MODULES_UNDER_FIRE).unmodifyFlat(id);
270                }       
271                
272                public String getEffectDescription(float level) {
273                        return "Repairs of damaged but functional weapons and engines can continue while they are under fire*";
274                }
275                
276                public String getEffectPerLevelDescription() {
277                        return null;
278                }
279                
280                public ScopeDescription getScopeDescription() {
281                        return ScopeDescription.PILOTED_SHIP;
282                }
283        }
284        
285        
286}
287
288
289
290
291
292