001package com.fs.starfarer.api.impl.campaign.skills; 002 003import java.awt.Color; 004 005import com.fs.starfarer.api.Global; 006import com.fs.starfarer.api.characters.CharacterStatsSkillEffect; 007import com.fs.starfarer.api.characters.DescriptionSkillEffect; 008import com.fs.starfarer.api.characters.MutableCharacterStatsAPI; 009import com.fs.starfarer.api.characters.MutableCharacterStatsAPI.SkillLevelAPI; 010import com.fs.starfarer.api.characters.PersonAPI; 011import com.fs.starfarer.api.characters.ShipSkillEffect; 012import com.fs.starfarer.api.characters.SkillSpecAPI; 013import com.fs.starfarer.api.combat.MutableShipStatsAPI; 014import com.fs.starfarer.api.combat.ShipAPI; 015import com.fs.starfarer.api.combat.ShipAPI.HullSize; 016import com.fs.starfarer.api.fleet.FleetMemberAPI; 017import com.fs.starfarer.api.impl.campaign.ids.Stats; 018import com.fs.starfarer.api.ui.TooltipMakerAPI; 019import com.fs.starfarer.api.util.Misc; 020 021public class CyberneticAugmentation { 022 023 public static float MAX_ELITE_SKILLS_BONUS = 1; 024 public static float ECCM_BONUS = 5; 025 026 public static float BONUS_PER_ELITE_SKILL = 1f; 027 028 public static boolean isOfficer(MutableShipStatsAPI stats) { 029 if (stats.getEntity() instanceof ShipAPI) { 030 ShipAPI ship = (ShipAPI) stats.getEntity(); 031 if (ship.getCaptain().isAICore()) return false; 032 return !ship.getCaptain().isDefault(); 033 } else { 034 FleetMemberAPI member = stats.getFleetMember(); 035 if (member == null) return false; 036 if (member.getCaptain().isAICore()) return false; 037 return !member.getCaptain().isDefault(); 038 } 039 } 040 041 public static boolean isFlagship(MutableShipStatsAPI stats) { 042 if (stats.getEntity() instanceof ShipAPI) { 043 ShipAPI ship = (ShipAPI) stats.getEntity(); 044 if (ship.getFleetMember() != null && 045 ship.getFleetMember().getFleetCommander() == ship.getCaptain()) { 046 return true; 047 } 048 return ship.getCaptain().isPlayer(); 049 } else { 050 FleetMemberAPI member = stats.getFleetMember(); 051 if (member == null) return false; 052 if (member.isFlagship()) { 053 return true; 054 } 055 return member.getCaptain().isPlayer(); 056 } 057 } 058 059 public static float getNumEliteSkillsOfFleetCommander(MutableShipStatsAPI stats) { 060 FleetMemberAPI member = stats.getFleetMember(); 061 if (member == null && stats.getEntity() instanceof ShipAPI) { 062 ShipAPI ship = (ShipAPI) stats.getEntity(); 063 member = ship.getFleetMember(); 064 } 065 066 if (member == null) return 0f; 067 PersonAPI person = member.getFleetCommanderForStats(); 068 if (person == null) person = member.getFleetCommander(); 069 if (person == null) return 0f; 070 071 MutableCharacterStatsAPI fcStats = person.getStats(); 072 if (fcStats == null) return 0f; 073 return getNumEliteSkills(fcStats); 074 } 075 076 public static float getNumEliteSkills(MutableCharacterStatsAPI stats) { 077 float count = 0f; 078 for (SkillLevelAPI sl : stats.getSkillsCopy()) { 079 if (sl.getLevel() >= 2f && sl.getSkill().isElite()) { 080 count++; 081 } 082 } 083 return count; 084 } 085 086 public static class Level0 implements DescriptionSkillEffect { 087 public String getString() { 088 int base = (int)Global.getSettings().getInt("officerMaxEliteSkills"); 089 return "\n*The base maximum number of elite skills per officer is " + base + "."; 090 } 091 public Color[] getHighlightColors() { 092 Color h = Misc.getDarkHighlightColor(); 093 return new Color[] {h}; 094 } 095 public String[] getHighlights() { 096 int base = (int)Global.getSettings().getInt("officerMaxEliteSkills"); 097 return new String [] {"" + base}; 098 } 099 public Color getTextColor() { 100 return null; 101 } 102 } 103 104 public static class Level1 implements CharacterStatsSkillEffect { 105 106 public void apply(MutableCharacterStatsAPI stats, String id, float level) { 107 stats.getDynamic().getMod(Stats.OFFICER_MAX_ELITE_SKILLS_MOD).modifyFlat(id, MAX_ELITE_SKILLS_BONUS); 108 } 109 110 public void unapply(MutableCharacterStatsAPI stats, String id) { 111 stats.getDynamic().getMod(Stats.OFFICER_MAX_ELITE_SKILLS_MOD).unmodify(id); 112 } 113 114 public String getEffectDescription(float level) { 115 return "+" + (int) MAX_ELITE_SKILLS_BONUS + " to maximum number of elite skills* for officers under your command"; 116 } 117 118 public String getEffectPerLevelDescription() { 119 return null; 120 } 121 122 public ScopeDescription getScopeDescription() { 123 return ScopeDescription.NONE; 124 } 125 } 126 127 public static class Level2 extends BaseSkillEffectDescription implements ShipSkillEffect { 128 public void createCustomDescription(MutableCharacterStatsAPI stats, SkillSpecAPI skill, 129 TooltipMakerAPI info, float width) { 130 init(stats, skill); 131 float opad = 10f; 132 Color c = Misc.getBasePlayerColor(); 133 //info.addPara("Affects: %s", opad + 5f, Misc.getGrayColor(), c, "fleet"); 134 info.addPara("Affects: %s", opad + 5f, Misc.getGrayColor(), c, "all ships with officers, including flagship"); 135 info.addSpacer(opad); 136 137// info.addPara("Negates up to %s of the weapon range penalty for superior enemy Electronic Warfare", 0f, hc, hc, 138// "" + (int) ECCM_BONUS + "%"); 139 info.addPara("Reduces the weapon range penalty due to superior enemy Electronic Warfare by up to %s percentage points", 0f, hc, hc, 140 "" + (int) ECCM_BONUS + ""); 141 } 142 143 public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) { 144 if (isOfficer(stats)) { 145 stats.getDynamic().getMod(Stats.ELECTRONIC_WARFARE_PENALTY_MOD).modifyFlat(id, -ECCM_BONUS); 146 } 147 } 148 149 public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) { 150 stats.getDynamic().getMod(Stats.ELECTRONIC_WARFARE_PENALTY_MOD).unmodifyFlat(id); 151 } 152 } 153 154 public static class Level3 extends BaseSkillEffectDescription implements ShipSkillEffect { 155 public void createCustomDescription(MutableCharacterStatsAPI stats, SkillSpecAPI skill, 156 TooltipMakerAPI info, float width) { 157 init(stats, skill); 158 float opad = 10f; 159 Color c = Misc.getBasePlayerColor(); 160 //info.addPara("Affects: %s", opad + 5f, Misc.getGrayColor(), c, "fleet"); 161 info.addPara("Affects: %s", opad + 5f, Misc.getGrayColor(), c, "all ships with officers (but not AI cores), including flagship"); 162 info.addSpacer(opad); 163 164 165 float count = getNumEliteSkills(stats); 166 float bonus = count * BONUS_PER_ELITE_SKILL; 167 168 info.addPara("%s damage dealt and %s damage taken (%s for each elite skill you have)", 0f, hc, hc, 169 "+" + (int) Math.round(bonus) + "%", 170 "-" + (int) Math.round(bonus) + "%", 171 "" + (int) Math.round(BONUS_PER_ELITE_SKILL) + "%" 172 ); 173 info.addPara("The damage-dealt bonus is doubled for the flagship", hc, 0f); 174// info.addPara("%s damage taken (%s per your elite skill), doubled for flagship", 0f, hc, hc, 175// "-" + (int) Math.round(bonus) + "%", 176// "" + (int) Math.round(BONUS_PER_ELITE_SKILL) + "%" 177// ); 178 } 179 180 public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) { 181 if (isOfficer(stats)) { 182 float count = getNumEliteSkillsOfFleetCommander(stats); 183 float bonusDealt = count * BONUS_PER_ELITE_SKILL; 184 float bonusTaken = count * BONUS_PER_ELITE_SKILL; 185 if (isFlagship(stats)) { 186 bonusDealt *= 2f; 187 //bonusTaken *= 2f; 188 } 189 190 stats.getArmorDamageTakenMult().modifyMult(id, 1f - bonusTaken / 100f); 191 stats.getHullDamageTakenMult().modifyMult(id, 1f - bonusTaken / 100f); 192 stats.getShieldDamageTakenMult().modifyMult(id, 1f - bonusTaken / 100f); 193 194 stats.getBallisticWeaponDamageMult().modifyPercent(id, bonusDealt); 195 stats.getEnergyWeaponDamageMult().modifyPercent(id, bonusDealt); 196 stats.getMissileWeaponDamageMult().modifyPercent(id, bonusDealt); 197 } 198 } 199 200 public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) { 201 stats.getArmorDamageTakenMult().unmodifyMult(id); 202 stats.getHullDamageTakenMult().unmodifyMult(id); 203 stats.getShieldDamageTakenMult().unmodifyMult(id); 204 205 stats.getBallisticWeaponDamageMult().unmodify(id); 206 stats.getEnergyWeaponDamageMult().unmodify(id); 207 stats.getMissileWeaponDamageMult().unmodify(id); 208 } 209 } 210} 211 212 213 214