001package com.fs.starfarer.api.impl.combat;
002
003import java.awt.Color;
004
005import org.lwjgl.util.vector.Vector2f;
006
007import com.fs.starfarer.api.Global;
008import com.fs.starfarer.api.combat.BeamAPI;
009import com.fs.starfarer.api.combat.BeamEffectPluginWithReset;
010import com.fs.starfarer.api.combat.CombatEngineAPI;
011import com.fs.starfarer.api.combat.CombatEntityAPI;
012import com.fs.starfarer.api.combat.MissileAPI;
013import com.fs.starfarer.api.combat.ShipAPI;
014import com.fs.starfarer.api.combat.WeaponAPI.WeaponType;
015import com.fs.starfarer.api.util.Misc;
016
017public class NSLanceEffectSavedCopy implements BeamEffectPluginWithReset {
018
019        public static float MIN_SPAWN_DIST = 200f;
020        public static float DIST_PER_SPAWN = 150;
021        public static float NUM_SPAWNS = 5;
022        public static float SPAWN_INTERVAL = 0.1f;
023        
024        //private IntervalUtil fireInterval = new IntervalUtil(0.25f, 1.75f);
025
026        protected Vector2f arcFrom = null;
027        protected Vector2f prevMineLoc = null;
028        
029        protected boolean done = false;
030        protected float spawned = 0;
031        protected int numToSpawn = 0;
032        protected float untilNextSpawn = 0;
033        protected float spawnDir = 0;
034        protected boolean canSpawn = false;
035        public void reset() {
036                done = false;
037                spawned = 0;
038                untilNextSpawn = 0;
039                arcFrom = null;
040                prevMineLoc = null;
041                numToSpawn = 0;
042                spawnDir = 0;
043        }
044        
045        public void advance(float amount, CombatEngineAPI engine, BeamAPI beam) {
046                if (done) return;
047                
048                //if (beam.getBrightness() < 1f) return;
049                
050                if (numToSpawn <= 0 && beam.getDamageTarget() != null) {
051                        float range = beam.getWeapon().getRange();
052                        float length = beam.getLengthPrevFrame();
053                        //float perSpawn = range / NUM_SPAWNS;
054                        float perSpawn = DIST_PER_SPAWN;
055                        
056                        numToSpawn = (int) ((range - length) / perSpawn) + 1;
057                        //numToSpawn = 5;
058                        numToSpawn = 1;
059                        untilNextSpawn = 0f;
060                }
061                numToSpawn = 5;
062                
063                if (beam.getBrightness() >= 1f) {
064                        canSpawn = true;
065                }
066                //untilNextSpawn = 0f;
067                
068                untilNextSpawn -= amount;
069                if (untilNextSpawn > 0) return;
070                //if (!canSpawn || beam.getBrightness() >= 1f) return;
071                
072//              NUM_SPAWNS = 15f;
073//              SPAWN_INTERVAL = 0.03f;
074                float range = beam.getWeapon().getRange();
075                float length = beam.getLengthPrevFrame();
076                float perSpawn = (range - MIN_SPAWN_DIST) / Math.max(1, (NUM_SPAWNS - 1));
077                //float perSpawn = range / NUM_SPAWNS;
078                //float perSpawn = DIST_PER_SPAWN;
079                float rangeToSpawnAt = MIN_SPAWN_DIST + spawned * perSpawn;
080                if (numToSpawn == 1) {
081                        rangeToSpawnAt = range;
082                }
083                
084                ShipAPI ship = beam.getSource();
085                
086                boolean spawnedMine = false;
087                if (length > rangeToSpawnAt - 10f) {
088                        float angle = Misc.getAngleInDegrees(beam.getFrom(), beam.getRayEndPrevFrame());
089                        Vector2f loc = Misc.getUnitVectorAtDegreeAngle(angle);
090                        loc.scale(rangeToSpawnAt);
091                        Vector2f.add(loc, beam.getFrom(), loc);
092                        
093                        spawnMine(ship, loc);
094                        spawnedMine = true;
095                } else if (beam.getDamageTarget() != null) {
096                        Vector2f arcTo = getNextArcLoc(engine, beam, perSpawn);
097                        float thickness = beam.getWidth();
098                        engine.spawnEmpArcVisual(arcFrom, null, arcTo, null, thickness, beam.getFringeColor(), Color.white);
099//                      engine.spawnEmpArcVisual(arcFrom, null, arcTo, null, thickness, beam.getFringeColor(), beam.getCoreColor());
100//                      engine.spawnEmpArcVisual(arcFrom, null, arcTo, null, thickness, beam.getFringeColor(), beam.getCoreColor());
101//                      engine.spawnEmpArcVisual(arcFrom, null, arcTo, null, thickness, beam.getFringeColor(), beam.getCoreColor());
102//                      engine.spawnEmpArcVisual(arcFrom, null, arcTo, null, thickness, beam.getFringeColor(), beam.getCoreColor());
103                        spawnMine(ship, arcTo);
104                        spawnedMine = true;
105                        arcFrom = arcTo;
106                }
107
108                untilNextSpawn = SPAWN_INTERVAL;
109                if (spawnedMine) {
110                        spawned++;
111                        if (spawned >= numToSpawn) {
112                                done = true;
113                        }
114                }
115        }
116        
117        public Vector2f getNextArcLoc(CombatEngineAPI engine, BeamAPI beam, float perSpawn) {
118                CombatEntityAPI target = beam.getDamageTarget();
119                
120                if (arcFrom == null) {
121                        arcFrom = new Vector2f(beam.getRayEndPrevFrame());
122//                      Vector2f loc = Misc.getUnitVectorAtDegreeAngle(beamAngle);
123//                      loc.scale(beam.getLengthPrevFrame());
124//                      //loc.scale(200f);
125//                      Vector2f.add(loc, beam.getFrom(), loc);
126//                      arcFrom = loc;
127                        
128                        float beamAngle = Misc.getAngleInDegrees(beam.getFrom(), beam.getRayEndPrevFrame());
129                        float beamSourceToTarget = Misc.getAngleInDegrees(beam.getFrom(), target.getLocation());
130                        
131                        // this is the direction we'll rotate - from the target's center - so that it's spawning mines around the side
132                        // closer to the beam's straight line
133                        spawnDir = Misc.getClosestTurnDirection(beamAngle, beamSourceToTarget);
134                        
135                        boolean computeNextLoc = false;
136                        if (prevMineLoc != null && false) {
137                                float dist = Misc.getDistance(arcFrom, prevMineLoc);
138                                if (dist < perSpawn) {
139                                        perSpawn -= dist;
140                                        computeNextLoc = true;
141                                }
142                        }
143                        if (!computeNextLoc) {
144                                return arcFrom;
145                        }
146                }
147                
148//              target = Global.getCombatEngine().getPlayerShip();
149//              target.getLocation().y += 750f;
150                
151                Vector2f targetLoc = target.getLocation();
152                float targetRadius = target.getCollisionRadius();
153                
154//              if (target instanceof ShipAPI) {
155//                      ShipAPI ship = (ShipAPI) target;
156//                      targetLoc = ship.getShieldCenterEvenIfNoShield();
157//                      targetRadius = ship.getShieldRadiusEvenIfNoShield();
158//              }
159                
160                boolean hitShield = target.getShield() != null && target.getShield().isWithinArc(beam.getRayEndPrevFrame());
161                
162//              float beamAngle = Misc.getAngleInDegrees(beam.getFrom(), beam.getRayEndPrevFrame());
163//              float beamSourceToTarget = Misc.getAngleInDegrees(beam.getFrom(), targetLoc);
164//              
165//              // this is the direction we'll rotate - from the target's center - so that it's spawning mines around the side
166//              // closer to the beam's straight line
167//              float dir = Misc.getClosestTurnDirection(beamAngle, beamSourceToTarget);
168                
169                float prevAngle = Misc.getAngleInDegrees(targetLoc, arcFrom);
170                float anglePerSegment = 360f * perSpawn / (3.14f * 2f * targetRadius);
171                if (anglePerSegment > 90f) anglePerSegment = 90f;
172                float angle = prevAngle + anglePerSegment * spawnDir;
173                
174                
175                Vector2f arcTo = Misc.getUnitVectorAtDegreeAngle(angle);
176                arcTo.scale(targetRadius);
177                Vector2f.add(targetLoc, arcTo, arcTo);
178                
179                float actualRadius = Global.getSettings().getTargetingRadius(arcTo, target, hitShield);
180                if (!hitShield) {
181                        //actualRadius *= 1f + 0.1f * (float) Math.random();
182                        actualRadius += 30f + 50f * (float) Math.random();
183                } else {
184                        actualRadius += 30f + 50f * (float) Math.random();
185                }
186                
187//              float angleDiff = Misc.getAngleDiff(beamSourceToTarget + 180f, angle);
188//              if (angleDiff > 150f) {
189//                      actualRadius += perSpawn * (180f - angleDiff) / 30f;
190//              }
191                
192                
193                arcTo = Misc.getUnitVectorAtDegreeAngle(angle);
194                arcTo.scale(actualRadius);
195                Vector2f.add(targetLoc, arcTo, arcTo);
196                
197                
198//              target.getLocation().y -= 750f;
199                
200                return arcTo;
201        }
202        
203        public void spawnMine(ShipAPI source, Vector2f mineLoc) {
204                CombatEngineAPI engine = Global.getCombatEngine();
205                
206                
207                //Vector2f currLoc = mineLoc;
208                MissileAPI mine = (MissileAPI) engine.spawnProjectile(source, null, 
209                                                                                                                          "nslance_minelayer", 
210                                                                                                                          mineLoc, 
211                                                                                                                          (float) Math.random() * 360f, null);
212                if (source != null) {
213                        Global.getCombatEngine().applyDamageModifiersToSpawnedProjectileWithNullWeapon(
214                                                                                        source, WeaponType.MISSILE, false, mine.getDamage());
215//                      float extraDamageMult = source.getMutableStats().getMissileWeaponDamageMult().getModifiedValue();
216//                      mine.getDamage().setMultiplier(mine.getDamage().getMultiplier() * extraDamageMult);
217                }
218                
219                
220                float fadeInTime = 0.05f;
221                mine.getVelocity().scale(0);
222                mine.fadeOutThenIn(fadeInTime);
223                
224                //Global.getCombatEngine().addPlugin(createMissileJitterPlugin(mine, fadeInTime));
225                
226                //mine.setFlightTime((float) Math.random());
227                float liveTime = 0f;
228                //liveTime = 0.01f;
229                mine.setFlightTime(mine.getMaxFlightTime() - liveTime);
230                mine.addDamagedAlready(source);
231                
232                prevMineLoc = mineLoc;
233        }
234
235}
236
237
238
239
240