001package com.fs.starfarer.api.impl.combat; 002 003import java.util.List; 004 005import java.awt.Color; 006 007import com.fs.starfarer.api.Global; 008import com.fs.starfarer.api.combat.BaseEveryFrameCombatPlugin; 009import com.fs.starfarer.api.combat.EveryFrameCombatPlugin; 010import com.fs.starfarer.api.combat.MutableShipStatsAPI; 011import com.fs.starfarer.api.combat.ShipAPI; 012import com.fs.starfarer.api.combat.ShipAPI.HullSize; 013import com.fs.starfarer.api.combat.ShipSystemAPI; 014import com.fs.starfarer.api.combat.ShipSystemAPI.SystemState; 015import com.fs.starfarer.api.combat.ShipwideAIFlags.AIFlags; 016import com.fs.starfarer.api.input.InputEventAPI; 017import com.fs.starfarer.api.util.Misc; 018 019public class EntropyAmplifierStats extends BaseShipSystemScript { 020 public static Object KEY_SHIP = new Object(); 021 public static Object KEY_TARGET = new Object(); 022 023 public static float DAM_MULT = 1.5f; 024 protected static float RANGE = 1500f; 025 026 public static Color TEXT_COLOR = new Color(255,55,55,255); 027 028 public static Color JITTER_COLOR = new Color(255,50,50,75); 029 public static Color JITTER_UNDER_COLOR = new Color(255,100,100,155); 030 031 032 public static class TargetData { 033 public ShipAPI ship; 034 public ShipAPI target; 035 public EveryFrameCombatPlugin targetEffectPlugin; 036 public float currDamMult; 037 public float elaspedAfterInState; 038 public TargetData(ShipAPI ship, ShipAPI target) { 039 this.ship = ship; 040 this.target = target; 041 } 042 } 043 044 045 public void apply(MutableShipStatsAPI stats, final String id, State state, float effectLevel) { 046 ShipAPI ship = null; 047 if (stats.getEntity() instanceof ShipAPI) { 048 ship = (ShipAPI) stats.getEntity(); 049 } else { 050 return; 051 } 052 053 final String targetDataKey = ship.getId() + "_entropy_target_data"; 054 055 Object targetDataObj = Global.getCombatEngine().getCustomData().get(targetDataKey); 056 if (state == State.IN && targetDataObj == null) { 057 ShipAPI target = findTarget(ship); 058 Global.getCombatEngine().getCustomData().put(targetDataKey, new TargetData(ship, target)); 059 if (target != null) { 060 if (target.getFluxTracker().showFloaty() || 061 ship == Global.getCombatEngine().getPlayerShip() || 062 target == Global.getCombatEngine().getPlayerShip()) { 063 target.getFluxTracker().showOverloadFloatyIfNeeded("Amplified Entropy!", TEXT_COLOR, 4f, true); 064 } 065 } 066 } else if (state == State.IDLE && targetDataObj != null) { 067 Global.getCombatEngine().getCustomData().remove(targetDataKey); 068 ((TargetData)targetDataObj).currDamMult = 1f; 069 targetDataObj = null; 070 } 071 if (targetDataObj == null || ((TargetData) targetDataObj).target == null) return; 072 073 final TargetData targetData = (TargetData) targetDataObj; 074 targetData.currDamMult = 1f + (DAM_MULT - 1f) * effectLevel; 075 //System.out.println("targetData.currDamMult: " + targetData.currDamMult); 076 if (targetData.targetEffectPlugin == null) { 077 targetData.targetEffectPlugin = new BaseEveryFrameCombatPlugin() { 078 @Override 079 public void advance(float amount, List<InputEventAPI> events) { 080 if (Global.getCombatEngine().isPaused()) return; 081 if (targetData.target == Global.getCombatEngine().getPlayerShip()) { 082 Global.getCombatEngine().maintainStatusForPlayerShip(KEY_TARGET, 083 targetData.ship.getSystem().getSpecAPI().getIconSpriteName(), 084 targetData.ship.getSystem().getDisplayName(), 085 "" + (int)((targetData.currDamMult - 1f) * 100f) + "% more damage taken", true); 086 } 087 088 if (targetData.currDamMult <= 1f || !targetData.ship.isAlive()) { 089 targetData.target.getMutableStats().getHullDamageTakenMult().unmodify(id); 090 targetData.target.getMutableStats().getArmorDamageTakenMult().unmodify(id); 091 targetData.target.getMutableStats().getShieldDamageTakenMult().unmodify(id); 092 targetData.target.getMutableStats().getEmpDamageTakenMult().unmodify(id); 093 Global.getCombatEngine().removePlugin(targetData.targetEffectPlugin); 094 } else { 095 targetData.target.getMutableStats().getHullDamageTakenMult().modifyMult(id, targetData.currDamMult); 096 targetData.target.getMutableStats().getArmorDamageTakenMult().modifyMult(id, targetData.currDamMult); 097 targetData.target.getMutableStats().getShieldDamageTakenMult().modifyMult(id, targetData.currDamMult); 098 targetData.target.getMutableStats().getEmpDamageTakenMult().modifyMult(id, targetData.currDamMult); 099 } 100 } 101 }; 102 Global.getCombatEngine().addPlugin(targetData.targetEffectPlugin); 103 } 104 105 106 if (effectLevel > 0) { 107 if (state != State.IN) { 108 targetData.elaspedAfterInState += Global.getCombatEngine().getElapsedInLastFrame(); 109 } 110 float shipJitterLevel = 0; 111 if (state == State.IN) { 112 shipJitterLevel = effectLevel; 113 } else { 114 float durOut = 0.5f; 115 shipJitterLevel = Math.max(0, durOut - targetData.elaspedAfterInState) / durOut; 116 } 117 float targetJitterLevel = effectLevel; 118 119 float maxRangeBonus = 50f; 120 float jitterRangeBonus = shipJitterLevel * maxRangeBonus; 121 122 Color color = JITTER_COLOR; 123 if (shipJitterLevel > 0) { 124 //ship.setJitterUnder(KEY_SHIP, JITTER_UNDER_COLOR, shipJitterLevel, 21, 0f, 3f + jitterRangeBonus); 125 ship.setJitter(KEY_SHIP, color, shipJitterLevel, 4, 0f, 0 + jitterRangeBonus * 1f); 126 } 127 128 if (targetJitterLevel > 0) { 129 //target.setJitterUnder(KEY_TARGET, JITTER_UNDER_COLOR, targetJitterLevel, 5, 0f, 15f); 130 targetData.target.setJitter(KEY_TARGET, color, targetJitterLevel, 3, 0f, 5f); 131 } 132 } 133 } 134 135 136 public void unapply(MutableShipStatsAPI stats, String id) { 137 138 } 139 140 protected ShipAPI findTarget(ShipAPI ship) { 141 float range = getMaxRange(ship); 142 boolean player = ship == Global.getCombatEngine().getPlayerShip(); 143 ShipAPI target = ship.getShipTarget(); 144 145 if (ship.getShipAI() != null && ship.getAIFlags().hasFlag(AIFlags.TARGET_FOR_SHIP_SYSTEM)){ 146 target = (ShipAPI) ship.getAIFlags().getCustom(AIFlags.TARGET_FOR_SHIP_SYSTEM); 147 } 148 149 if (target != null) { 150 float dist = Misc.getDistance(ship.getLocation(), target.getLocation()); 151 float radSum = ship.getCollisionRadius() + target.getCollisionRadius(); 152 if (dist > range + radSum) target = null; 153 } else { 154 if (target == null || target.getOwner() == ship.getOwner()) { 155 if (player) { 156 target = Misc.findClosestShipEnemyOf(ship, ship.getMouseTarget(), HullSize.FRIGATE, range, true); 157 } else { 158 Object test = ship.getAIFlags().getCustom(AIFlags.MANEUVER_TARGET); 159 if (test instanceof ShipAPI) { 160 target = (ShipAPI) test; 161 float dist = Misc.getDistance(ship.getLocation(), target.getLocation()); 162 float radSum = ship.getCollisionRadius() + target.getCollisionRadius(); 163 if (dist > range + radSum || target.isFighter()) target = null; 164 } 165 } 166 } 167 } 168 169 if (target != null && target.isFighter()) target = null; 170 if (target == null) { 171 target = Misc.findClosestShipEnemyOf(ship, ship.getLocation(), HullSize.FRIGATE, range, true); 172 } 173 174 return target; 175 } 176 177 178 public static float getMaxRange(ShipAPI ship) { 179 return ship.getMutableStats().getSystemRangeBonus().computeEffective(RANGE); 180 } 181 182 183 public StatusData getStatusData(int index, State state, float effectLevel) { 184 if (effectLevel > 0) { 185 if (index == 0) { 186 float damMult = 1f + (DAM_MULT - 1f) * effectLevel; 187 return new StatusData("" + (int)((damMult - 1f) * 100f) + "% more damage to target", false); 188 } 189 } 190 return null; 191 } 192 193 194 @Override 195 public String getInfoText(ShipSystemAPI system, ShipAPI ship) { 196 if (system.isOutOfAmmo()) return null; 197 if (system.getState() != SystemState.IDLE) return null; 198 199 ShipAPI target = findTarget(ship); 200 if (target != null && target != ship) { 201 return "READY"; 202 } 203 if ((target == null) && ship.getShipTarget() != null) { 204 return "OUT OF RANGE"; 205 } 206 return "NO TARGET"; 207 } 208 209 210 @Override 211 public boolean isUsable(ShipSystemAPI system, ShipAPI ship) { 212 //if (true) return true; 213 ShipAPI target = findTarget(ship); 214 return target != null && target != ship; 215 } 216 217} 218 219 220 221 222 223 224 225