001package com.fs.starfarer.api.impl.hullmods;
002
003import java.util.Iterator;
004
005import com.fs.starfarer.api.Global;
006import com.fs.starfarer.api.combat.BaseHullMod;
007import com.fs.starfarer.api.combat.CombatEngineAPI;
008import com.fs.starfarer.api.combat.MutableShipStatsAPI;
009import com.fs.starfarer.api.combat.ShipAPI;
010import com.fs.starfarer.api.combat.ShipAPI.HullSize;
011import com.fs.starfarer.api.util.IntervalUtil;
012import com.fs.starfarer.api.util.Misc;
013
014public class EscortPackage extends BaseHullMod {
015
016        public static float MANEUVER_BONUS = 25f;
017        public static float SPEED_BONUS = 10f;
018        public static float RANGE_BONUS = 20f;
019        public static float SHIELD_BONUS = 10f;
020        
021        public static float EFFECT_RANGE = 700f;
022        public static float EFFECT_FADE = 500f;
023        
024        public static Object STATUS_KEY = new Object();
025        
026
027        public String getDescriptionParam(int index, HullSize hullSize) {
028                if (index == 0) return "1000";
029                if (index == 1) return "" + (int)Math.round(MANEUVER_BONUS) + "%";
030                if (index == 2) return "" + (int)Math.round(SPEED_BONUS) + "%";
031                if (index == 3) return "" + (int)Math.round(RANGE_BONUS) + "%";
032                if (index == 4) return "doubled";
033                return null;
034        }
035        
036        public String getSModDescriptionParam(int index, HullSize hullSize) {
037                if (index == 0) return "" + (int)Math.round(SHIELD_BONUS) + "%";
038                return null;
039        }
040
041
042        @Override
043        public boolean isApplicableToShip(ShipAPI ship) {
044                return getUnapplicableReason(ship) == null;
045        }
046
047        @Override
048        public String getUnapplicableReason(ShipAPI ship) {
049                if (ship != null && ship.isFrigate()) {
050                        return "Can not be installed on frigates";
051                }
052                if (ship != null && ship.isCapital()) {
053                        return "Can not be installed on capital ships";
054                }
055                return super.getUnapplicableReason(ship);
056        }
057
058        
059        public static String EP_DATA_KEY = "core_escort_package_data_key";
060        public static class EscortPackageData {
061                IntervalUtil interval = new IntervalUtil(0.9f, 1.1f);
062                float mag = 0;
063        }
064        
065        public void applyEPEffect(ShipAPI ship, ShipAPI other, float mag) {
066                String id = "escort_package_bonus" + ship.getId();
067                MutableShipStatsAPI stats = ship.getMutableStats();
068                
069                if (mag > 0) {
070                        boolean sMod = isSMod(ship);
071                        
072                        float maneuver = MANEUVER_BONUS * mag;
073                        stats.getAcceleration().modifyPercent(id, maneuver);
074                        stats.getDeceleration().modifyPercent(id, maneuver);
075                        stats.getTurnAcceleration().modifyPercent(id, maneuver * 2f);
076                        stats.getMaxTurnRate().modifyPercent(id, maneuver);
077                        
078                        float speed = SPEED_BONUS * mag;
079                        stats.getMaxSpeed().modifyPercent(id, speed);
080                        
081                        float range = RANGE_BONUS * mag;
082                        stats.getBallisticWeaponRangeBonus().modifyPercent(id, range);
083                        stats.getEnergyWeaponRangeBonus().modifyPercent(id, range);
084                        
085                        if (sMod && ship.isDestroyer()) {
086                                float shields = SHIELD_BONUS * mag;
087                                stats.getShieldDamageTakenMult().modifyMult(id, 1f - shields / 100f);
088                        }
089                } else {
090                        stats.getAcceleration().unmodify(id);
091                        stats.getDeceleration().unmodify(id);
092                        stats.getTurnAcceleration().unmodify(id);
093                        stats.getMaxTurnRate().unmodify(id);
094                        
095                        stats.getMaxSpeed().unmodify(id);
096                        
097                        stats.getBallisticWeaponRangeBonus().unmodify(id);
098                        stats.getEnergyWeaponRangeBonus().unmodify(id);
099                        
100                        stats.getShieldDamageTakenMult().unmodify(id);
101                }
102                
103        }
104        
105        @Override
106        public void advanceInCombat(ShipAPI ship, float amount) {
107                super.advanceInCombat(ship, amount);
108
109                if (!ship.isAlive()) return;
110                if (amount <= 0f) return;
111                
112                CombatEngineAPI engine = Global.getCombatEngine();
113                
114                String key = EP_DATA_KEY + "_" + ship.getId();
115                EscortPackageData data = (EscortPackageData) engine.getCustomData().get(key);
116                if (data == null) {
117                        data = new EscortPackageData();
118                        engine.getCustomData().put(key, data);
119                }
120
121                boolean playerShip = ship == Global.getCombatEngine().getPlayerShip();
122                
123                data.interval.advance(amount * 4f);
124                if (data.interval.intervalElapsed() || playerShip) {
125                        float checkSize = EFFECT_RANGE + EFFECT_FADE + ship.getCollisionRadius() + 300f;
126                        checkSize *= 2f;
127                        
128                        Iterator<Object> iter = Global.getCombatEngine().getShipGrid().getCheckIterator(
129                                                                                        ship.getLocation(), checkSize, checkSize);
130                        
131                        ShipAPI best = null;
132                        float bestMag = 0f;
133                        while (iter.hasNext()) {
134                                Object next = iter.next();
135                                if (!(next instanceof ShipAPI)) continue;
136                                
137                                ShipAPI other = (ShipAPI) next;
138                                
139                                if (ship == other) continue;
140                                if (other.getOwner() != ship.getOwner()) continue;
141                                if (other.isHulk()) continue;
142                                
143                                if (other.getHullSize().ordinal() <= ship.getHullSize().ordinal()) continue;
144                                
145                                float radSum = ship.getShieldRadiusEvenIfNoShield() + other.getShieldRadiusEvenIfNoShield();
146                                radSum *= 0.75f;
147                                float dist = Misc.getDistance(ship.getShieldCenterEvenIfNoShield(), other.getShieldCenterEvenIfNoShield());
148                                dist -= radSum;
149                                
150                                float mag = 0f;
151                                if (dist < EFFECT_RANGE) {
152                                        mag = 1f;
153                                } else if (dist < EFFECT_RANGE + EFFECT_FADE) {
154                                        mag = 1f - (dist - EFFECT_RANGE) / EFFECT_FADE;
155                                }
156                                
157                                if (ship.isDestroyer() && other.isCapital()) {
158                                        mag *= 2f;
159                                }
160                                
161                                if (mag > bestMag) {
162                                        best = other;
163                                        bestMag = mag;
164                                }
165                        }
166                        
167                        //if (best != null && bestMag > 0) {
168                                applyEPEffect(ship, best, bestMag);
169                        //}
170                        
171                        data.mag = bestMag;
172                }
173                
174                if (playerShip) {
175                        if (data.mag > 0.005f) {
176                                String icon = Global.getSettings().getSpriteName("ui", "icon_tactical_escort_package");
177                                String percent = "" + (int) Math.round(data.mag * 100f) + "%";
178                                Global.getCombatEngine().maintainStatusForPlayerShip(
179                                                STATUS_KEY, icon, "Escort package", percent + " telemetry quality", false);
180                        } else {
181                                String icon = Global.getSettings().getSpriteName("ui", "icon_tactical_escort_package");
182                                Global.getCombatEngine().maintainStatusForPlayerShip(
183                                                STATUS_KEY, icon, "Escort package", "no connection", true);
184                        }
185                }
186                
187        }
188        
189}
190
191
192
193
194
195
196
197
198
199
200
201
202
203