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