001package com.fs.starfarer.api.impl.campaign.skills;
002
003import org.lwjgl.util.vector.Vector2f;
004
005import com.fs.starfarer.api.characters.AfterShipCreationSkillEffect;
006import com.fs.starfarer.api.characters.MutableCharacterStatsAPI;
007import com.fs.starfarer.api.characters.ShipSkillEffect;
008import com.fs.starfarer.api.characters.SkillSpecAPI;
009import com.fs.starfarer.api.combat.BeamAPI;
010import com.fs.starfarer.api.combat.CombatEntityAPI;
011import com.fs.starfarer.api.combat.DamageAPI;
012import com.fs.starfarer.api.combat.DamagingProjectileAPI;
013import com.fs.starfarer.api.combat.MissileAPI;
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.DamageDealtModifier;
018import com.fs.starfarer.api.ui.TooltipMakerAPI;
019import com.fs.starfarer.api.util.Misc;
020
021public class RangedSpecialization {
022        
023        public static boolean CRITS = false;
024        
025        public static float PROJ_SPEED_BONUS = 30;
026        
027        public static float MIN_RANGE = 800;
028        public static float MAX_RANGE = 1600;
029        public static float MAX_CHANCE_PERCENT = 30; // used as damage percent mod when CRITS == false
030        public static float CRIT_DAMAGE_BONUS_PERCENT = 100;
031        
032        
033
034        public static class Level1 extends BaseSkillEffectDescription implements AfterShipCreationSkillEffect {
035                public void applyEffectsAfterShipCreation(ShipAPI ship, String id) {
036                        ship.addListener(new RangedSpecDamageDealtMod());
037                }
038
039                public void unapplyEffectsAfterShipCreation(ShipAPI ship, String id) {
040                        ship.removeListenerOfClass(RangedSpecDamageDealtMod.class);
041                }
042                
043                public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {}
044                public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {}
045                
046                public String getEffectDescription(float level) {
047                        return null;
048                }
049                
050                public void createCustomDescription(MutableCharacterStatsAPI stats, SkillSpecAPI skill, 
051                                                                                        TooltipMakerAPI info, float width) {
052                        init(stats, skill);
053                        
054                        if (CRITS) {
055                                info.addPara("Ballistic and energy weapons have a chance to deal %s damage at long range",
056                                                0f, hc, hc, "+" + (int) CRIT_DAMAGE_BONUS_PERCENT + "%");
057                                info.addPara(indent + "%s chance at %s range and below, " +
058                                                   "%s chance at %s range and above",
059                                                0f, tc, hc, 
060                                                "0%",
061                                                "" + (int) MIN_RANGE,
062                                                "" + (int) MAX_CHANCE_PERCENT + "%",
063                                                "" + (int) MAX_RANGE
064                                                );
065                        } else {
066                                info.addPara("Ballistic and energy weapons deal up to %s damage at long range",
067                                                0f, hc, hc, "+" + (int) MAX_CHANCE_PERCENT + "%");
068                                info.addPara(indent + "%s at %s range and below, " +
069                                                   "%s at %s range and above",
070                                                0f, tc, hc, 
071                                                "0%",
072                                                "" + (int) MIN_RANGE,
073                                                "" + (int) MAX_CHANCE_PERCENT + "%",
074                                                "" + (int) MAX_RANGE
075                                                );
076                        }
077                        //info.addPara(indent + "Beam weapons have their damage increased by the chance percentage instead", tc, 0f);
078                }
079                
080                public ScopeDescription getScopeDescription() {
081                        return ScopeDescription.PILOTED_SHIP;
082                }
083        }
084        
085        public static class Level2 implements ShipSkillEffect {
086                public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {
087                        stats.getProjectileSpeedMult().modifyPercent(id, PROJ_SPEED_BONUS);
088                }
089                
090                public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {
091                        stats.getProjectileSpeedMult().unmodify(id);
092                }
093                
094                public String getEffectDescription(float level) {
095                        return "+" + (int)(PROJ_SPEED_BONUS) + "% ballistic and energy projectile speed";
096                }
097                
098                public String getEffectPerLevelDescription() {
099                        return null;
100                }
101                
102                public ScopeDescription getScopeDescription() {
103                        return ScopeDescription.PILOTED_SHIP;
104                }
105
106        }
107
108        public static class RangedSpecDamageDealtMod implements DamageDealtModifier {
109                public String modifyDamageDealt(Object param,
110                                                                                CombatEntityAPI target, DamageAPI damage,
111                                                                                Vector2f point, boolean shieldHit) {
112                        if (param instanceof MissileAPI) return null;
113                        
114                        Vector2f from = null;
115                        if (param instanceof DamagingProjectileAPI) {
116                                from = ((DamagingProjectileAPI)param).getSpawnLocation();
117                        } else if (param instanceof BeamAPI) {
118                                from = ((BeamAPI)param).getFrom();
119                        } else {
120                                return null;
121                        }
122                        
123                        float chancePercent = 0f;
124                        float dist = Misc.getDistance(from, point);
125                        float f = (dist - MIN_RANGE) / (MAX_RANGE - MIN_RANGE);
126                        if (f < 0) f = 0;
127                        if (f > 1) f = 1;
128                        
129                        //f = 0.5f;
130                        //f = 1f;
131                        //System.out.println("RangedSpec mult: " + f);
132                        
133                        String id = null;
134                        
135                        chancePercent = (int) Math.round(MAX_CHANCE_PERCENT * f);
136                        if (chancePercent <= 0) return null;
137                        
138                        //System.out.println("Chance: " + chancePercent);
139                        
140                        Vector2f vel = new Vector2f();
141                        if (target instanceof ShipAPI) {
142                                vel.set(target.getVelocity());
143                        }
144                        
145                        if (param instanceof DamagingProjectileAPI) {
146                                if (CRITS) {
147                                        if ((float) Math.random() < chancePercent * 0.01f) {
148                                                id = "ranged_spec_dam_mod";
149                                                damage.getModifier().modifyPercent(id, CRIT_DAMAGE_BONUS_PERCENT);
150                                                //Misc.spawnExtraHitGlow(param, point, vel, f);
151                                        }
152                                } else {
153                                        id = "ranged_spec_dam_mod";
154                                        damage.getModifier().modifyPercent(id, chancePercent);
155                                        //Misc.spawnExtraHitGlow(param, point, vel, f);
156                                }
157                        } else if (param instanceof BeamAPI) {
158                                if (CRITS) {
159                                        if ((float) Math.random() < chancePercent * 0.01f) {
160                                                id = "ranged_spec_dam_mod";
161                                                damage.getModifier().modifyPercent(id, CRIT_DAMAGE_BONUS_PERCENT);
162                                                //Misc.spawnExtraHitGlow(param, point, vel, f);
163                                        }
164                                } else {
165                                        id = "ranged_spec_dam_mod";
166                                        damage.getModifier().modifyPercent(id, chancePercent);
167                                        //Misc.spawnExtraHitGlow(param, point, vel, f);
168                                }
169                        }
170                        
171                        return id;
172                }
173        }
174        
175        
176        
177//      public static class TestDamageModifier implements DamageDealtModifier {
178//              public String modifyDamageDealt(Object param,
179//                                                                              CombatEntityAPI target, DamageAPI damage,
180//                                                                              Vector2f point, boolean shieldHit) {
181//                      //if (true) return null;
182//                      String id = "dam_mod1" + (float) Math.random();
183//                      damage.getModifier().modifyMult(id, 0.1f);
184//                      return id;
185//              }
186//      }
187//      
188//      public static class TestDamageModifierTaken implements DamageTakenModifier {
189//              public String modifyDamageTaken(Object param,
190//                              CombatEntityAPI target, DamageAPI damage,
191//                              Vector2f point, boolean shieldHit) {
192//                      //if (true) return null;
193//                      String id = "dam_mod2" + (float) Math.random();
194//                      damage.getModifier().modifyMult(id, 10f);
195//                      return id;
196//              }
197//      }
198        
199}
200
201
202
203
204
205
206
207
208
209
210