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