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