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