001package com.fs.starfarer.api.impl.campaign.skills;
002
003import org.lwjgl.util.vector.Vector2f;
004
005import com.fs.starfarer.api.GameState;
006import com.fs.starfarer.api.Global;
007import com.fs.starfarer.api.characters.AfterShipCreationSkillEffect;
008import com.fs.starfarer.api.characters.MutableCharacterStatsAPI;
009import com.fs.starfarer.api.characters.ShipSkillEffect;
010import com.fs.starfarer.api.characters.SkillSpecAPI;
011import com.fs.starfarer.api.combat.BeamAPI;
012import com.fs.starfarer.api.combat.CombatEntityAPI;
013import com.fs.starfarer.api.combat.DamageAPI;
014import com.fs.starfarer.api.combat.DamagingProjectileAPI;
015import com.fs.starfarer.api.combat.MutableShipStatsAPI;
016import com.fs.starfarer.api.combat.ShipAPI;
017import com.fs.starfarer.api.combat.ShipAPI.HullSize;
018import com.fs.starfarer.api.combat.WeaponAPI;
019import com.fs.starfarer.api.combat.WeaponAPI.WeaponType;
020import com.fs.starfarer.api.combat.listeners.AdvanceableListener;
021import com.fs.starfarer.api.combat.listeners.DamageDealtModifier;
022import com.fs.starfarer.api.ui.TooltipMakerAPI;
023import com.fs.starfarer.api.util.Misc;
024
025public class EnergyWeaponMastery {
026        
027        public static float FLUX_COST_MULT = .9f;
028        
029        public static float MIN_RANGE = 600;
030        public static float MAX_RANGE = 1000;
031        
032        public static float ENERGY_DAMAGE_PERCENT = 30;
033        //public static float ENERGY_DAMAGE_MIN_FLUX_LEVEL = 0.25f;
034        public static float ENERGY_DAMAGE_MIN_FLUX_LEVEL = 0f;
035        
036        
037
038        public static class Level1 extends BaseSkillEffectDescription implements AfterShipCreationSkillEffect {
039                public void applyEffectsAfterShipCreation(ShipAPI ship, String id) {
040                        ship.addListener(new EWMDamageDealtMod(ship));
041                }
042
043                public void unapplyEffectsAfterShipCreation(ShipAPI ship, String id) {
044                        ship.removeListenerOfClass(EWMDamageDealtMod.class);
045                }
046                
047                public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {
048                        stats.getEnergyWeaponFluxBasedBonusDamageMagnitude().modifyFlat(id, ENERGY_DAMAGE_PERCENT * .01f);
049                        stats.getEnergyWeaponFluxBasedBonusDamageMinLevel().modifyFlat(id, ENERGY_DAMAGE_MIN_FLUX_LEVEL);
050                }
051                public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {
052                        stats.getEnergyWeaponFluxBasedBonusDamageMagnitude().unmodifyFlat(id);
053                        stats.getEnergyWeaponFluxBasedBonusDamageMinLevel().unmodifyFlat(id);
054                }
055                
056                public String getEffectDescription(float level) {
057                        return null;
058                }
059                
060                public void createCustomDescription(MutableCharacterStatsAPI stats, SkillSpecAPI skill, 
061                                                                                        TooltipMakerAPI info, float width) {
062                        init(stats, skill);
063                        
064                        if (ENERGY_DAMAGE_MIN_FLUX_LEVEL > 0) {
065                                info.addPara("Energy weapons deal up to %s damage at close range as the firing ship's flux level increases above %s",
066                                                0f, hc, hc,
067                                                "+" + (int) ENERGY_DAMAGE_PERCENT + "%",
068                                                (int) Math.round(ENERGY_DAMAGE_MIN_FLUX_LEVEL * 100f) + "%"
069                                );
070                        } else {
071                                info.addPara("Energy weapons deal up to %s damage at close range, based on the firing ship's flux level",
072                                                0f, hc, hc,
073                                                "+" + (int) ENERGY_DAMAGE_PERCENT + "%"
074                                );
075                        }
076                        info.addPara(indent + "Full bonus damage at %s range and below, " +
077                                           "no bonus damage at %s range and above",
078                                        0f, tc, hc, 
079                                        "" + (int) MIN_RANGE,
080                                        "" + (int) MAX_RANGE
081                                        );
082                }
083                
084                public ScopeDescription getScopeDescription() {
085                        return ScopeDescription.PILOTED_SHIP;
086                }
087        }
088        
089        public static class Level2 implements ShipSkillEffect {
090                public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {
091                        stats.getEnergyWeaponFluxCostMod().modifyMult(id, FLUX_COST_MULT);
092                }
093                
094                public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {
095                        stats.getEnergyWeaponFluxCostMod().unmodify(id);
096                }
097                
098                public String getEffectDescription(float level) {
099                        return "-" + (int)Math.round((1f - FLUX_COST_MULT) * 100f) + "% flux generated by energy weapons";
100                }
101                
102                public String getEffectPerLevelDescription() {
103                        return null;
104                }
105                
106                public ScopeDescription getScopeDescription() {
107                        return ScopeDescription.PILOTED_SHIP;
108                }
109
110        }
111
112        public static Object DAM_BONUS_STATUS_KEY = new Object();
113        
114        public static class EWMDamageDealtMod implements DamageDealtModifier, AdvanceableListener {
115                protected ShipAPI ship;
116                public EWMDamageDealtMod(ShipAPI ship) {
117                        this.ship = ship;
118                }
119                
120                public void advance(float amount) {
121                        if (Global.getCurrentState() == GameState.COMBAT &&
122                                        Global.getCombatEngine() != null && Global.getCombatEngine().getPlayerShip() == ship) {
123
124                                int damageBonus = (int) Math.round((ship.getFluxBasedEnergyWeaponDamageMultiplier() * 100f - 100f));
125                                if (damageBonus > 0) {
126                                        Global.getCombatEngine().maintainStatusForPlayerShip(DAM_BONUS_STATUS_KEY,
127                                                        Global.getSettings().getSpriteName("ui", "icon_energy"),
128                                                        "Energy weapon mastery", 
129                                                        "+" + damageBonus + "% energy weapon damage", false);
130                                }
131                                
132                        }
133                }
134
135                public String modifyDamageDealt(Object param,
136                                                                                CombatEntityAPI target, DamageAPI damage,
137                                                                                Vector2f point, boolean shieldHit) {
138                        
139                        //if (param instanceof MissileAPI) return null;
140                        
141                        Vector2f from = null;
142                        WeaponAPI weapon = null;
143                        if (param instanceof DamagingProjectileAPI) {
144                                from = ((DamagingProjectileAPI)param).getSpawnLocation();
145                                weapon = ((DamagingProjectileAPI)param).getWeapon();
146                        } else if (param instanceof BeamAPI) {
147                                from = ((BeamAPI)param).getFrom();
148                                weapon = ((BeamAPI)param).getWeapon();
149                        } else {
150                                return null;
151                        }
152                        
153                        if (weapon == null || ship == null) return null;
154                        if (weapon.getSpec().getType() != WeaponType.ENERGY) return null;
155                        
156                        float mag = ship.getFluxBasedEnergyWeaponDamageMultiplier() - 1f;
157                        if (mag <= 0) return null;
158                        
159                        float dist = Misc.getDistance(from, point);
160                        float f = 1f;
161                        if (dist > MAX_RANGE) {
162                                f = 0f;
163                        } else if (dist > MIN_RANGE) {
164                                f = 1f - (dist - MIN_RANGE) / (MAX_RANGE - MIN_RANGE);
165                        }
166                        if (f < 0) f = 0;
167                        if (f > 1) f = 1;
168                        
169//                      Vector2f vel = new Vector2f();
170//                      if (target instanceof ShipAPI) {
171//                              vel.set(target.getVelocity());
172//                      }
173                        
174                        String id = "ewm_dam_mod";
175                        damage.getModifier().modifyPercent(id, (mag * f) * 100f);
176                        return id;
177                }
178        }
179        
180}
181
182
183
184
185
186
187
188
189
190
191