001package com.fs.starfarer.api.impl.combat.dweller;
002
003import org.lwjgl.util.vector.Vector2f;
004
005import com.fs.starfarer.api.Global;
006import com.fs.starfarer.api.combat.CombatEngineAPI;
007import com.fs.starfarer.api.combat.ShipAIPlugin;
008import com.fs.starfarer.api.combat.ShipAPI;
009import com.fs.starfarer.api.combat.ShipCommand;
010import com.fs.starfarer.api.combat.ShipSystemAIScript;
011import com.fs.starfarer.api.combat.ShipSystemAPI;
012import com.fs.starfarer.api.combat.ShipwideAIFlags;
013import com.fs.starfarer.api.combat.ShipwideAIFlags.AIFlags;
014import com.fs.starfarer.api.util.IntervalUtil;
015import com.fs.starfarer.api.util.Misc;
016
017
018public class DarkenedGazeSystemAI implements ShipSystemAIScript {
019
020        protected ShipAPI ship;
021        protected CombatEngineAPI engine;
022        protected ShipwideAIFlags flags;
023        protected ShipSystemAPI system;
024        protected DarkenedGazeSystemScript script;
025        protected float systemFluxPerSecond;
026        
027        protected IntervalUtil tracker = new IntervalUtil(0.75f, 1.25f);
028        
029        public void init(ShipAPI ship, ShipSystemAPI system, ShipwideAIFlags flags, CombatEngineAPI engine) {
030                this.ship = ship;
031                this.flags = flags;
032                this.engine = engine;
033                this.system = system;
034                
035                script = (DarkenedGazeSystemScript)system.getScript();
036                
037                systemFluxPerSecond = system.getFluxPerSecond();
038        }
039        
040        protected ShipAPI targetOverride = null;
041        
042        public void advance(float amount, Vector2f missileDangerDir, Vector2f collisionDangerDir, ShipAPI target) {
043                tracker.advance(amount);
044                
045                //boolean toggle = system.getSpec().isToggle();
046                
047                if (system.isActive()) {
048                        if (ship.getAI() instanceof ShipAIPlugin) {
049                                ShipAIPlugin b = (ShipAIPlugin) ship.getAI();
050                                b.setTargetOverride(targetOverride); // needs to be set every frame
051                        }
052                } else {
053                        targetOverride = null;
054                }
055                
056                if (tracker.intervalElapsed()) {
057                        
058                        if (system.getCooldownRemaining() > 0) return;
059                        if (system.isOutOfAmmo()) return;
060                        if (ship.getFluxTracker().isOverloadedOrVenting()) return;
061                        
062                        if (target != null) {
063                                if (target.isHulk() || !target.isAlive()) {
064                                        target = null;
065                                }
066                        }
067                        
068                        float activeTimeRemaining = (ship.getMaxFlux() - ship.getCurrFlux()) / Math.max(1f, systemFluxPerSecond);
069                        
070                        boolean missilesInOpenArc = false;
071                        // too easy to shut it down with missiles
072                        if (missileDangerDir != null && false) {
073                                missilesInOpenArc = Misc.isInArc(ship.getFacing(), DarkenedGazeSystemScript.SHIELD_OPENING, 
074                                                                        Misc.getAngleInDegrees(missileDangerDir));
075                        }
076                        
077                        boolean inRange = false;
078                        boolean inArc = false;
079                        boolean isFarFromArc = false;
080                        if (target != null) {
081                                float range = Misc.getDistance(ship.getLocation(), target.getLocation()) - 
082                                                          Misc.getTargetingRadius(ship.getLocation(), target, false);
083                                inRange = range < script.getRange();
084                                inArc = Misc.isInArc(ship.getFacing(), 5f, 
085                                                Misc.getAngleInDegrees(ship.getLocation(), target.getLocation()));
086                                if (!inArc) {
087                                        isFarFromArc = !Misc.isInArc(ship.getFacing(), Math.max(30f, 60f - range * 0.05f), 
088                                                        Misc.getAngleInDegrees(ship.getLocation(), target.getLocation()));
089                                }
090                        }
091                        
092                        Vector2f to = Misc.getUnitVectorAtDegreeAngle(ship.getFacing());
093                        to.scale(script.getRange());
094                        Vector2f.add(ship.getLocation(), to, to);
095                        boolean ffDanger = false;
096                        if (script.isFFAConcern() ) {
097                                ffDanger = Global.getSettings().getFriendlyFireDanger(ship, null, 
098                                                                ship.getLocation(), to, Float.MAX_VALUE, 3f, script.getRange()) > 0.1f;
099                        } else {
100                                // pretend FF concern, so it doesn't fire right through friendlies but can clip them without
101                                // worrying too much about it
102                                ffDanger = Global.getSettings().getFriendlyFireDanger(ship, null, 
103                                                ship.getLocation(), to, Float.MAX_VALUE, 3f, script.getRange()) > 0.5f;
104                        }
105                        if (system.isActive()) {
106                                flags.setFlag(AIFlags.DO_NOT_VENT);
107                                
108                                if (target == null || !inRange || isFarFromArc || missilesInOpenArc || ffDanger) {
109                                        giveCommand();
110                                        return;
111                                }
112                                
113                                if (activeTimeRemaining < 3f) {
114                                        giveCommand();
115                                        return;
116                                }
117                                
118                                return;
119                        }
120                        
121                        float minFireTime = system.getSpecAPI().getIn() + 6f;
122                        float fluxLevel = ship.getFluxLevel();
123                        
124                        if (fluxLevel > 0.9f || activeTimeRemaining < minFireTime) {
125                                return;
126                        }
127                        
128                        if (inRange && inArc && !missilesInOpenArc && !ffDanger) {
129                                giveCommand();
130                                targetOverride = target;
131                        }
132                }
133        }
134
135        
136        public void giveCommand() {
137                ship.giveCommand(ShipCommand.USE_SYSTEM, null, 0);
138        }
139
140}
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162