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