001package com.fs.starfarer.api.impl.combat.threat;
002
003import java.awt.Color;
004
005import com.fs.starfarer.api.combat.MutableShipStatsAPI;
006import com.fs.starfarer.api.combat.ShipAPI;
007import com.fs.starfarer.api.combat.ShipwideAIFlags.AIFlags;
008import com.fs.starfarer.api.combat.WeaponAPI;
009import com.fs.starfarer.api.combat.WeaponAPI.AIHints;
010import com.fs.starfarer.api.combat.WeaponGroupAPI;
011import com.fs.starfarer.api.combat.listeners.WeaponRangeModifier;
012import com.fs.starfarer.api.impl.campaign.ids.Stats;
013import com.fs.starfarer.api.impl.campaign.ids.Tags;
014import com.fs.starfarer.api.util.Misc;
015
016public class FragmentVolleySystemScript extends BaseEnergyLashActivatedSystem implements WeaponRangeModifier {
017        
018        //public static float FRAGMENT_RANGE_PERCENT = 100;
019        public static float FRAGMENT_RANGE_MULT = 2;
020        public static float MAX_VOLLEY_RANGE = 3000f;
021        
022        public static float FRAGMENT_REGEN_RATE_MULT = 10f;
023        
024        public void applyImpl(ShipAPI ship, MutableShipStatsAPI stats, String id, State state, float effectLevel) {
025                if (effectLevel <= 0f) {
026                        stats.getDynamic().getStat(Stats.FRAGMENT_SWARM_RESPAWN_RATE_MULT).unmodifyMult(id);
027                        return;
028                }
029                
030                stats.getDynamic().getStat(Stats.FRAGMENT_SWARM_RESPAWN_RATE_MULT).modifyMult(id, 
031                                                                1f + (FRAGMENT_REGEN_RATE_MULT - 1f) * effectLevel);
032                
033                Color glowColor = Misc.setAlpha(VoltaicDischargeOnFireEffect.EMP_FRINGE_COLOR, 50);
034                for (WeaponGroupAPI g : ship.getWeaponGroupsCopy()) {
035                        for (WeaponAPI w : g.getWeaponsCopy()) {
036                                if (w.hasAIHint(AIHints.PD)) continue;
037                                if (w.hasAIHint(AIHints.NO_MANUAL_FIRE)) continue;
038                                
039                                if (w.getSpec().hasTag(Tags.FRAGMENT)) {
040                                        w.setGlowAmount(effectLevel, glowColor);
041                                }
042                        }
043                }
044                
045                setStandardJitter(ship, state, effectLevel);
046                
047                if (state == State.OUT) {
048                        ship.removeListenerOfClass(FragmentVolleySystemScript.class);
049                        return;
050                }
051                if (state != State.ACTIVE) {
052                        return;
053                }
054                
055                if (!ship.hasListenerOfClass(FragmentVolleySystemScript.class)) {
056                        ship.addListener(this);
057                }
058                        
059                for (WeaponGroupAPI g : ship.getWeaponGroupsCopy()) {
060                        for (WeaponAPI w : g.getWeaponsCopy()) {
061                                if (w.hasAIHint(AIHints.NO_MANUAL_FIRE)) continue;
062                                
063                                if (!w.hasAIHint(AIHints.PD) && w.getSpec().hasTag(Tags.FRAGMENT)) {
064                                        if (w.getCooldownRemaining() > 1f) {
065                                                w.setRemainingCooldownTo(1f);
066                                        }
067                                        if (w.usesAmmo()) {
068                                                w.setAmmo(w.getMaxAmmo());
069                                        }
070                                        w.setForceFireOneFrame(true);
071                                } else {
072                                        w.setForceNoFireOneFrame(true);
073                                }
074                        }
075                }
076                
077                Object test = ship.getAIFlags().getCustom(AIFlags.MANEUVER_TARGET);
078                if (test instanceof ShipAPI) {
079                        ShipAPI target = (ShipAPI) test;
080                        ship.setShipTarget(target);
081                }
082        }
083        
084        
085        public StatusData getStatusData(int index, State state, float effectLevel) {
086                if (effectLevel <= 0f) return null;
087                if (index == 0) {
088                        return new StatusData("firing fragments", false);
089                } else if (index == 1) {
090                        return new StatusData("" + (int)FRAGMENT_RANGE_MULT + "x fragment range", false);
091                }
092                return null;
093        }
094
095        @Override
096        public float getCurrentUsefulnessLevel(ShipAPI overseer, ShipAPI ship) {
097                if (ship.getSystem().isActive() || ship.getSystem().isChargedown() ||
098                                ship.getSystem().isChargeup() || ship.getSystem().isCoolingDown()) {
099                        return 0f;
100                }
101                
102                Object test = ship.getAIFlags().getCustom(AIFlags.MANEUVER_TARGET);
103                if (test instanceof ShipAPI) {
104                        ShipAPI target = (ShipAPI) test;
105                        
106                        float dist = Misc.getDistance(ship.getLocation(), target.getLocation());
107                        dist -= ship.getCollisionRadius() + target.getCollisionRadius();
108                        
109                        float range = getMinFragmentWeaponRange(ship) * FRAGMENT_RANGE_MULT;
110                        if (dist < range * 0.8f && dist < MAX_VOLLEY_RANGE) {
111                                float distToOverseer = Misc.getDistance(ship.getLocation(), overseer.getLocation());
112                                distToOverseer -= ship.getCollisionRadius() + overseer.getCollisionRadius();
113                                float overseerDistFactor = 0f;
114                                if (distToOverseer < 1000f) {
115                                        float min = 500f;
116                                        overseerDistFactor = (1f - Math.max(0f, distToOverseer - min) / (1000f - min)) * 0.25f;
117                                }
118                                return Math.min(1f, 0.5f + Math.min(0.5f, ship.getFluxLevel() * 1f) + overseerDistFactor);
119                        }
120                }
121                
122                return 0f;
123        }
124        
125        
126        public static float getMinFragmentWeaponRange(ShipAPI ship) {
127                float min = Float.MAX_VALUE;
128                boolean found = false;
129                for (WeaponAPI w : ship.getAllWeapons()) {
130                        if (w.isDecorative()) continue;
131                        if (!w.hasAIHint(AIHints.PD) &&
132                                        !w.hasAIHint(AIHints.NO_MANUAL_FIRE) &&
133                                        w.getSpec().hasTag(Tags.FRAGMENT)) {
134                                min = Math.min(min, w.getRange());
135                                found = true;
136                        }
137                }
138                if (!found) min = 0;
139                
140                return min;
141        }
142
143        @Override
144        public float getWeaponRangePercentMod(ShipAPI ship, WeaponAPI weapon) {
145                return 0;
146        }
147
148        @Override
149        public float getWeaponRangeMultMod(ShipAPI ship, WeaponAPI weapon) {
150                if (!weapon.hasAIHint(AIHints.PD) && 
151                                !weapon.hasAIHint(AIHints.NO_MANUAL_FIRE) &&
152                                weapon.getSpec().hasTag(Tags.FRAGMENT)) {
153                        return FRAGMENT_RANGE_MULT;
154                }
155                return 1f;
156        }
157
158        @Override
159        public float getWeaponRangeFlatMod(ShipAPI ship, WeaponAPI weapon) {
160                return 0;
161        }
162        
163}
164
165
166
167
168
169
170
171