001package com.fs.starfarer.api.impl.campaign.skills; 002 003import com.fs.starfarer.api.characters.AfterShipCreationSkillEffect; 004import com.fs.starfarer.api.characters.MutableCharacterStatsAPI; 005import com.fs.starfarer.api.characters.ShipSkillEffect; 006import com.fs.starfarer.api.characters.SkillSpecAPI; 007import com.fs.starfarer.api.combat.MutableShipStatsAPI; 008import com.fs.starfarer.api.combat.ShipAPI; 009import com.fs.starfarer.api.combat.ShipAPI.HullSize; 010import com.fs.starfarer.api.fleet.FleetMemberAPI; 011import com.fs.starfarer.api.ui.TooltipMakerAPI; 012 013public class WolfpackTactics { 014 015 public static float DAMAGE_TO_LARGER_BONUS = 20f; 016 public static float DAMAGE_TO_LARGER_BONUS_DEST = 10f; 017 public static float PEAK_TIME_BONUS = 50f; 018 public static float PEAK_TIME_BONUS_DEST = 25f; 019 020// public static float FLAGSHIP_SPEED_BONUS = 25f; 021// public static float FLAGSHIP_CP_BONUS = 100f; 022 023 public static boolean isFrigateAndOfficer(MutableShipStatsAPI stats) { 024 if (stats.getEntity() instanceof ShipAPI) { 025 ShipAPI ship = (ShipAPI) stats.getEntity(); 026 if (!ship.isFrigate()) return false; 027 return !ship.getCaptain().isDefault(); 028 } else { 029 FleetMemberAPI member = stats.getFleetMember(); 030 if (member == null) return false; 031 if (!member.isFrigate()) return false; 032 return !member.getCaptain().isDefault(); 033 } 034 } 035 036 public static boolean isDestroyerAndOfficer(MutableShipStatsAPI stats) { 037 if (stats.getEntity() instanceof ShipAPI) { 038 ShipAPI ship = (ShipAPI) stats.getEntity(); 039 if (!ship.isDestroyer()) return false; 040 return !ship.getCaptain().isDefault(); 041 } else { 042 FleetMemberAPI member = stats.getFleetMember(); 043 if (member == null) return false; 044 if (!member.isDestroyer()) return false; 045 return !member.getCaptain().isDefault(); 046 } 047 } 048 049// public static boolean isFrigateAndFlagship(MutableShipStatsAPI stats) { 050// if (stats.getEntity() instanceof ShipAPI) { 051// ShipAPI ship = (ShipAPI) stats.getEntity(); 052// if (!ship.isFrigate()) return false; 053// if (ship.getFleetMember() != null && 054// ship.getFleetMember().getFleetCommander() == ship.getCaptain()) { 055// return true; 056// } 057// return ship.getCaptain().isPlayer(); 058// } else { 059// FleetMemberAPI member = stats.getFleetMember(); 060// if (member == null) return false; 061// if (!member.isFrigate()) return false; 062// if (member.isFlagship()) { 063// return true; 064// } 065// return member.getCaptain().isPlayer(); 066// } 067// } 068// public static boolean isDestroyerAndFlagship(MutableShipStatsAPI stats) { 069// if (stats.getEntity() instanceof ShipAPI) { 070// ShipAPI ship = (ShipAPI) stats.getEntity(); 071// if (!ship.isDestroyer()) return false; 072// if (ship.getFleetMember() != null && 073// ship.getFleetMember().getFleetCommander() == ship.getCaptain()) { 074// return true; 075// } 076// return ship.getCaptain().isPlayer(); 077// } else { 078// FleetMemberAPI member = stats.getFleetMember(); 079// if (member == null) return false; 080// if (!member.isDestroyer()) return false; 081// if (member.isFlagship()) { 082// return true; 083// } 084// return member.getCaptain().isPlayer(); 085// } 086// } 087 088 public static class Level1A implements ShipSkillEffect { 089 public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) { 090 if (isFrigateAndOfficer(stats)) { 091 stats.getDamageToDestroyers().modifyPercent(id, DAMAGE_TO_LARGER_BONUS); 092 stats.getDamageToCruisers().modifyPercent(id, DAMAGE_TO_LARGER_BONUS); 093 stats.getDamageToCapital().modifyPercent(id, DAMAGE_TO_LARGER_BONUS); 094 095 stats.getPeakCRDuration().modifyPercent(id, PEAK_TIME_BONUS); 096 //stats.getDynamic().getMod(Stats.INDIVIDUAL_SHIP_RECOVERY_MOD).modifyFlat(id, 1000f); 097 } else if (isDestroyerAndOfficer(stats)) { 098 stats.getDamageToCruisers().modifyPercent(id, DAMAGE_TO_LARGER_BONUS_DEST); 099 stats.getDamageToCapital().modifyPercent(id, DAMAGE_TO_LARGER_BONUS_DEST); 100 101 stats.getPeakCRDuration().modifyPercent(id, PEAK_TIME_BONUS_DEST); 102 //stats.getDynamic().getMod(Stats.INDIVIDUAL_SHIP_RECOVERY_MOD).modifyFlat(id, 1000f); 103 } 104 } 105 106 public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) { 107 stats.getDamageToDestroyers().unmodifyPercent(id); 108 stats.getDamageToCruisers().unmodifyPercent(id); 109 stats.getDamageToCapital().unmodifyPercent(id); 110 111 stats.getPeakCRDuration().unmodifyPercent(id); 112 //stats.getDynamic().getMod(Stats.INDIVIDUAL_SHIP_RECOVERY_MOD).unmodify(id); 113 } 114 115 public String getEffectDescription(float level) { 116 //return "+" + (int)Math.round(DAMAGE_TO_LARGER_BONUS) + "% damage to ships larger than frigates"; 117 118 return "+" + (int)Math.round(DAMAGE_TO_LARGER_BONUS) + "% damage to ships larger than frigates if frigate, " + 119 "+" + (int)Math.round(DAMAGE_TO_LARGER_BONUS_DEST) + "% damage to capital ships and cruisers if destroyer\n" + 120 "+" + (int)(PEAK_TIME_BONUS) + "% seconds peak operating time if frigate, " + 121 "+" + (int)(PEAK_TIME_BONUS_DEST) + "% if destroyer"; 122// return "+" + (int)Math.round(DAMAGE_TO_LARGER_BONUS) + "% damage to ships larger than frigates\n" + 123// "+" + (int)(PEAK_TIME_BONUS) + " seconds peak operating time\n" + 124// "If lost in combat, ship is almost always recoverable"; 125 } 126 127 public String getEffectPerLevelDescription() { 128 return null; 129 } 130 131 public ScopeDescription getScopeDescription() { 132 return ScopeDescription.PILOTED_SHIP; 133 } 134 } 135 136 137// public static class Level1B extends BaseSkillEffectDescription implements ShipSkillEffect { 138// public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) { 139// if (isFrigateAndFlagship(stats)) { 140// stats.getDynamic().getMod(Stats.COMMAND_POINT_RATE_FLAT).modifyFlat(id, FLAGSHIP_CP_BONUS * 0.01f); 141// } else if (isDestroyerAndFlagship(stats)) { 142// stats.getZeroFluxSpeedBoost().modifyFlat(id, FLAGSHIP_SPEED_BONUS); 143// } 144// } 145// 146// public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) { 147// stats.getDynamic().getMod(Stats.COMMAND_POINT_RATE_FLAT).unmodify(id); 148// stats.getZeroFluxSpeedBoost().unmodifyFlat(id); 149// } 150// 151// public String getEffectDescription(float level) { 152// return null; 153// //return "\n+" + (int) DESTROYER_CP_BONUS + "% to command point recovery rate if flagship is a destroyer"; 154// } 155// 156// public void createCustomDescription(MutableCharacterStatsAPI stats, SkillSpecAPI skill, 157// TooltipMakerAPI info, float width) { 158// init(stats, skill); 159// 160// float opad = 10f; 161// Color c = Misc.getBasePlayerColor(); 162// info.addPara("Affects: %s", opad + 5f, Misc.getGrayColor(), c, "flagship"); 163// info.addSpacer(opad); 164// info.addPara("+%s to command point recovery rate if flagship is a frigate", 0f, hc, hc, 165// "" + (int) FLAGSHIP_CP_BONUS + "%"); 166// info.addPara("+%s to 0-flux speed boost if flagship is a destroyer", 0f, hc, hc, 167// "" + (int) FLAGSHIP_SPEED_BONUS + ""); 168// 169// //info.addSpacer(5f); 170// } 171// 172// public String getEffectPerLevelDescription() { 173// return null; 174// } 175// 176// public ScopeDescription getScopeDescription() { 177// return ScopeDescription.PILOTED_SHIP; 178// } 179// } 180 181 182 //public static class Level1C extends BaseSkillEffectDescription implements ShipSkillEffect, AfterShipCreationSkillEffect { 183 public static class Level1C extends BaseSkillEffectDescription implements AfterShipCreationSkillEffect { 184 public void applyEffectsAfterShipCreation(ShipAPI ship, String id) { 185// MutableShipStatsAPI stats = ship.getMutableStats(); 186// Global.getCombatEngine().getListenerManager().addListener(listener); 187// if (isDmoddedAndOfficer(stats)) { 188// ship.addListener(new DCDamageTakenMod(ship)); 189// 190// float dmods = DModManager.getNumDMods(ship.getVariant()); 191// if (dmods <= 0) return; 192// if (dmods > MAX_DMODS) dmods = MAX_DMODS; 193// 194// if (ship.getShield() == null) { 195// stats.getMinArmorFraction().modifyFlat(id, SHIELDLESS_ARMOR_BONUS_PER_DMOD * dmods); 196// } 197// } 198 } 199 200 public void unapplyEffectsAfterShipCreation(ShipAPI ship, String id) { 201// ship.removeListenerOfClass(DCDamageTakenMod.class); 202// 203// if (ship.getShield() == null) { 204// MutableShipStatsAPI stats = ship.getMutableStats(); 205// stats.getMinArmorFraction().unmodifyFlat(id); 206// } 207 } 208 209 210 public void createCustomDescription(MutableCharacterStatsAPI stats, SkillSpecAPI skill, 211 TooltipMakerAPI info, float width) { 212// init(stats, skill); 213 214// info.addPara("%s chance per d-mod* to have incoming hull damage reduced by %s", 0f, hc, hc, 215// "" + (int)AVOID_DAMAGE_CHANCE_PER_DMOD + "%", 216// "" + (int)Math.round((1f - AVOID_DAMAGE_DAMAGE_MULT) * 100f) + "%" 217// ); 218// info.addPara("%s crew lost due to hull damage in combat per d-mod*", 0f, hc, hc, 219// "-" + (int)CREW_LOSS_REDUCTION_PER_DMOD + "%" 220// ); 221// info.addPara("%s maximum combat readiness per d-mod*", 0f, hc, hc, 222// "+" + (int)CR_PER_DMOD + "%" 223// ); 224// 225// info.addSpacer(5f); 226// info.addPara("%s minimum armor value** for damage reduction per d-mod for unshielded ships", 0f, hc, hc, 227// "+" + (int)Math.round(SHIELDLESS_ARMOR_BONUS_PER_DMOD * 100f) + "%" 228// ); 229// 230 } 231 232 public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) { 233 } 234 235 public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) { 236 } 237 } 238 239 /* 240 public static class WolfpackExtraDamageMod implements DamageDealtModifier, AdvanceableListener { 241 protected int owner; 242 public WolfpackExtraDamageMod(int owner) { 243 this.owner = owner; 244 } 245 246 protected boolean addDamage = false; 247 protected boolean addDamageAlly = false; 248 public void advance(float amount) { 249 CombatFleetManagerAPI cfm = Global.getCombatEngine().getFleetManager(owner); 250 for (DeployedFleetMemberAPI dfm : cfm.getDeployedCopyDFM()) { 251 FleetMemberAPI member = dfm.getMember(); 252 if (member == null) continue; 253 PersonAPI commander = member.getFleetCommanderForStats(); 254 if (commander == null) continue; 255 256 ShipAPI ship = cfm.getShipFor(commander); 257 258 } 259 } 260 261 public String modifyDamageDealt(Object param, CombatEntityAPI target, DamageAPI damage, Vector2f point, boolean shieldHit) { 262 return null; 263 } 264 265 public String modifyDamageTaken(Object param, 266 CombatEntityAPI target, DamageAPI damage, 267 Vector2f point, boolean shieldHit) { 268 MutableShipStatsAPI stats = ship.getMutableStats(); 269 stats.getHullDamageTakenMult().unmodifyMult(DAMAGE_MOD_ID); 270 271 if (shieldHit) return null; 272 273 float chance = stats.getDynamic().getMod(AVOID_HULL_DAMAGE_CHANCE).computeEffective(0f); 274 if (Math.random() >= chance) { 275 return null; 276 } 277 278 stats.getHullDamageTakenMult().modifyMult(DAMAGE_MOD_ID, AVOID_DAMAGE_DAMAGE_MULT); 279 280 return null; 281 } 282 } 283 */ 284 285 286}