Advertisement
Guest User

Untitled

a guest
Mar 26th, 2017
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 25.13 KB | None | 0 0
  1. package data.scripts.plugins;
  2.  
  3. import com.fs.starfarer.api.Global;
  4. import com.fs.starfarer.api.combat.BaseEveryFrameCombatPlugin;
  5. import com.fs.starfarer.api.combat.CollisionClass;
  6. import com.fs.starfarer.api.combat.CombatEngineAPI;
  7. import com.fs.starfarer.api.combat.CombatEntityAPI;
  8. import com.fs.starfarer.api.combat.DamagingProjectileAPI;
  9. import com.fs.starfarer.api.combat.ShieldAPI;
  10. import com.fs.starfarer.api.combat.ShipAPI;
  11. import com.fs.starfarer.api.combat.ViewportAPI;
  12. import com.fs.starfarer.api.graphics.SpriteAPI;
  13. import com.fs.starfarer.api.input.InputEventAPI;
  14. import data.scripts.utils.exigency_Twig;
  15. import java.awt.Color;
  16. import java.util.ArrayList;
  17. import java.util.HashMap;
  18. import java.util.Iterator;
  19. import java.util.LinkedHashMap;
  20. import java.util.List;
  21. import java.util.Map;
  22. import org.lazywizard.lazylib.CollisionUtils;
  23. import org.lazywizard.lazylib.MathUtils;
  24. import org.lazywizard.lazylib.VectorUtils;
  25. import org.lazywizard.lazylib.combat.CombatUtils;
  26. import org.lwjgl.util.vector.Vector2f;
  27.  
  28. public class exigency_ShieldBypass extends BaseEveryFrameCombatPlugin {
  29.  
  30. private static final String DATA_KEY = "exigency_ShieldBypass";
  31.  
  32. // Projectile ID (String), bypass effect data (ProjData)
  33. private static final Map<String, ProjData> PROJ_DATA = new HashMap<>(5);
  34.  
  35. public static void init() {
  36. // Add all projectiles that should pierce shields here
  37. PROJ_DATA.put("exigency_rr_shot",
  38. new ProjData("exigency_shieldpierce", // Shield pierce sound
  39. 2f, // Shield pierce sound pitch
  40. new Color(50, 150, 255), // Shield pierce sprite color
  41. "exigency_shieldpierce", // Shield pierce enter sound
  42. 2f, // Shield pierce enter sound pitch
  43. "exigency_rr_hit", // Hit sound
  44. 0.9f, // Hit sound pitch
  45. 175f, // Hit force
  46. 100f, // Explosion size
  47. 1.5f, // Explosion duration
  48. new Color(255, 165, 130, 150), // Explosion color
  49. 200f, // Hit particle size,
  50. ParticleType.HIT, // Hit particle type (HIT, SMOKE, SMOOTH)
  51. 1f, // Hit particle duration
  52. 1f, // Hit particle alpha mod
  53. new Color(250, 150, 200, 140), // Hit particle color
  54. 51.0f, // Shield pierce sprite size
  55. 0.5f, // Shield pierce sprite opacity
  56. 2f, // Shield pierce sprite jitter
  57. Global.getSettings().getSprite("misc", "CIGEN_piercerGlow"))); // Shield pierce sprite
  58.  
  59. PROJ_DATA.put("exigency_super_cigen_shot",
  60. new ProjData("exigency_shieldpierce", // Shield pierce sound
  61. 1.5f, // Shield pierce sound pitch
  62. new Color(100, 125, 255), // Shield pierce sprite color
  63. "exigency_shieldpierce", // Shield pierce enter sound
  64. 1.5f, // Shield pierce enter sound pitch
  65. "exigency_super_cigen_hit", // Hit sound
  66. 0.85f, // Hit sound pitch
  67. 350f, // Hit force
  68. 150f, // Explosion size
  69. 1.5f, // Explosion duration
  70. new Color(255, 185, 150, 150), // Explosion color
  71. 250f, // Hit particle size,
  72. ParticleType.HIT, // Hit particle type (HIT, SMOKE, SMOOTH)
  73. 1f, // Hit particle duration
  74. 1f, // Hit particle alpha mod
  75. new Color(250, 200, 150, 140), // Hit particle color
  76. 60.0f, // Shield pierce sprite size
  77. 0.6f, // Shield pierce sprite opacity
  78. 2.5f, // Shield pierce sprite jitter
  79. Global.getSettings().getSprite("misc", "CIGEN_piercerGlow"))); // Shield pierce sprite
  80.  
  81. PROJ_DATA.put("exigency_cigenrepeater_shot",
  82. new ProjData("exigency_shieldpierce_small", // Shield pierce sound
  83. 3f, // Shield pierce sound pitch
  84. new Color(50, 150, 255), // Shield pierce sprite color
  85. "exigency_shieldpierce_small", // Shield pierce enter sound
  86. 3f, // Shield pierce enter sound pitch
  87. "exigency_cigenrepeaterhit", // Hit sound
  88. 0.9f, // Hit sound pitch
  89. 0f, // Hit force
  90. 0.1f, // Explosion size
  91. 0.2f, // Explosion duration
  92. new Color(255, 165, 130, 10), // Explosion color
  93. 70f, // Hit particle size,
  94. ParticleType.HIT, // Hit particle type (HIT, SMOKE, SMOOTH)
  95. 0.1f, // Hit particle duration
  96. 1f, // Hit particle alpha mod
  97. new Color(250, 150, 200, 30), // Hit particle color
  98. 17f, // Shield pierce sprite size
  99. 0.5f, // Shield pierce sprite opacity
  100. 1f, // Shield pierce sprite jitter
  101. Global.getSettings().getSprite("misc", "CIGEN_piercerGlow"))); // Shield pierce sprite
  102.  
  103. PROJ_DATA.put("exigency_cigenautocannon_shot",
  104. new ProjData("exigency_shieldpierce_medium", // Shield pierce sound
  105. 2.5f, // Shield pierce sound pitch
  106. new Color(50, 150, 255), // Shield pierce sprite color
  107. "exigency_shieldpierce_medium", // Shield pierce enter sound
  108. 2.5f, // Shield pierce enter sound pitch
  109. "exigency_cigenautocannonhit", // Hit sound
  110. 0.9f, // Hit sound pitch
  111. 0f, // Hit force
  112. 0.3f, // Explosion size
  113. 0.35f, // Explosion duration
  114. new Color(255, 165, 130, 15), // Explosion color
  115. 75f, // Hit particle size,
  116. ParticleType.HIT, // Hit particle type (HIT, SMOKE, SMOOTH)
  117. 0.15f, // Hit particle duration
  118. 1f, // Hit particle alpha mod
  119. new Color(250, 150, 200, 50), // Hit particle color
  120. 21f, // Shield pierce sprite size
  121. 0.5f, // Shield pierce sprite opacity
  122. 1.25f, // Shield pierce sprite jitter
  123. Global.getSettings().getSprite("misc", "CIGEN_piercerGlow"))); // Shield pierce sprite
  124.  
  125. PROJ_DATA.put("exigency_cigen_sabot_shot",
  126. new ProjData("exigency_shieldpierce_medium", // Shield pierce sound
  127. 2.5f, // Shield pierce sound pitch
  128. new Color(50, 150, 255), // Shield pierce sprite color
  129. "exigency_shieldpierce_medium", // Shield pierce enter sound
  130. 2.5f, // Shield pierce enter sound pitch
  131. "exigency_cigenMirvhit", // Hit sound
  132. 0.8f, // Hit sound pitch
  133. 10f, // Hit force
  134. 25f, // Explosion size
  135. 0.7f, // Explosion duration
  136. new Color(255, 165, 130, 15), // Explosion color
  137. 100f, // Hit particle size,
  138. ParticleType.HIT, // Hit particle type (HIT, SMOKE, SMOOTH)
  139. 0.5f, // Hit particle duration
  140. 1f, // Hit particle alpha mod
  141. new Color(250, 150, 200, 55), // Hit particle color
  142. 34f, // Shield pierce sprite size
  143. 0.5f, // Shield pierce sprite opacity
  144. 1.25f, // Shield pierce sprite jitter
  145. Global.getSettings().getSprite("misc", "CIGEN_piercerGlow"))); // Shield pierce sprite
  146. }
  147. private CombatEngineAPI engine;
  148.  
  149. @Override
  150. public void advance(float amount, List<InputEventAPI> events) {
  151. if (engine == null) {
  152. return;
  153. }
  154.  
  155. if (engine.isPaused()) {
  156. return;
  157. }
  158.  
  159. final LocalData localData = (LocalData) engine.getCustomData().get(DATA_KEY);
  160. final Map<DamagingProjectileAPI, ProjInfo> projectileData = localData.projectileData;
  161.  
  162. String spec;
  163. ProjData data;
  164.  
  165. List<DamagingProjectileAPI> activeProjectiles = engine.getProjectiles();
  166. int projectilesSize = activeProjectiles.size();
  167. for (int i = 0; i < projectilesSize; i++) {
  168. DamagingProjectileAPI proj = activeProjectiles.get(i);
  169. spec = proj.getProjectileSpecId();
  170. if (proj.getProjectileSpecId() == null ||
  171. proj.didDamage() ||
  172. proj.isFading()) {
  173. continue;
  174. }
  175.  
  176. // Is this projectile shield piercing?
  177. if (PROJ_DATA.containsKey(spec)) {
  178. if (!projectileData.containsKey(proj)) {
  179. projectileData.put(proj, new ProjInfo());
  180. }
  181. }
  182. }
  183.  
  184. if (!projectileData.isEmpty()) {
  185. Iterator<Map.Entry<DamagingProjectileAPI, ProjInfo>> iter = projectileData.entrySet().iterator();
  186. while (iter.hasNext()) {
  187. Map.Entry<DamagingProjectileAPI, ProjInfo> entry = iter.next();
  188. DamagingProjectileAPI proj = entry.getKey();
  189.  
  190. if (proj.didDamage() || !engine.isEntityInPlay(proj)) {
  191. iter.remove();
  192. continue;
  193. }
  194.  
  195. ProjInfo info = entry.getValue();
  196. spec = proj.getProjectileSpecId();
  197. data = PROJ_DATA.get(spec);
  198.  
  199. // We'll do collision checks manually
  200. proj.setCollisionClass(CollisionClass.NONE);
  201.  
  202. // Find nearby ships and asteroids
  203. List<CombatEntityAPI> toCheck = new ArrayList<>(100);
  204. toCheck.addAll(CombatUtils.getShipsWithinRange(proj.getLocation(), proj.getCollisionRadius() + 5f));
  205. toCheck.addAll(CombatUtils.getAsteroidsWithinRange(proj.getLocation(), proj.getCollisionRadius() + 5f));
  206.  
  207. // Don't include the ship that fired this projectile!
  208. toCheck.remove(proj.getSource());
  209.  
  210. int checkSize = toCheck.size();
  211. for (int j = 0; j < checkSize; j++) {
  212. CombatEntityAPI entity = toCheck.get(j);
  213. // Check for an active phase cloak/shield
  214. if (entity instanceof ShipAPI) {
  215. ShipAPI ship = (ShipAPI) entity;
  216.  
  217. // Pass right through a cloaked ship
  218. if (ship.getCollisionClass() == CollisionClass.NONE) {
  219. continue;
  220. }
  221.  
  222. // Ignore friendly fighters
  223. if ((ship.isFighter() || ship.isDrone()) &&
  224. ship.isAlive() &&
  225. !ship.getEngineController().isFlamedOut() &&
  226. ship.getOwner() == proj.getOwner()) {
  227. continue;
  228. }
  229.  
  230. // Play sound when passing through a shield
  231. ShieldAPI shield = ship.getShield();
  232. if (shield != null &&
  233. shield.isOn() &&
  234. shield.isWithinArc(proj.getLocation()) &&
  235. MathUtils.isWithinRange(proj.getLocation(), shield.getLocation(), shield.getRadius())) {
  236. Global.getSoundPlayer().playLoop(data.shieldPierceSound, proj, data.shieldPierceSoundPitch,
  237. 1f, proj.getLocation(), proj.getVelocity());
  238.  
  239. /* Started piercing */
  240. if (info.pierceTarget == null) {
  241. Vector2f collisionPoint = VectorUtils.getDirectionalVector(
  242. ship.getShield().getLocation(),
  243. proj.getLocation());
  244. collisionPoint.scale(ship.getShield().getRadius());
  245. Vector2f.add(collisionPoint, ship.getShield().getLocation(), collisionPoint);
  246.  
  247. engine.addSmoothParticle(collisionPoint, entity.getVelocity(), data.pierceSize,
  248. data.particleAlpha, data.particleDuration,
  249. data.shieldPierceColor);
  250. int particleCount = 1 + (int) (Math.sqrt(data.pierceSize) * 2f);
  251. for (int n = 0; n < particleCount; n++) {
  252. Vector2f particleVel = new Vector2f(50f + proj.getVelocity().length() / 3f, 0f);
  253. VectorUtils.rotate(particleVel,
  254. MathUtils.getRandomNumberInRange(proj.getFacing() - 75f,
  255. proj.getFacing() + 75f),
  256. particleVel);
  257. particleVel.scale(MathUtils.getRandomNumberInRange(0.25f, 1f));
  258. engine.addHitParticle(collisionPoint, particleVel, (float) Math.sqrt(
  259. data.particleSize) * 0.75f, data.particleAlpha,
  260. data.particleDuration *
  261. MathUtils.getRandomNumberInRange(0.33f, 1f),
  262. data.shieldPierceColor);
  263. }
  264. Global.getSoundPlayer().playSound(data.shieldPierceEnterSound,
  265. data.shieldPierceEnterSoundPitch, 1f, collisionPoint,
  266. entity.getVelocity());
  267. info.pierceTarget = ship;
  268. }
  269. } else {
  270. /* No longer piercing */
  271. info.pierceTarget = null;
  272. }
  273. }
  274.  
  275. /* Check for hull collisions */
  276. Vector2f prevLoc = new Vector2f(proj.getVelocity());
  277. prevLoc.scale(-amount);
  278. Vector2f.add(prevLoc, proj.getLocation(), prevLoc);
  279. Vector2f collisionPoint;
  280. if (entity.getExactBounds() == null) {
  281. collisionPoint = proj.getLocation();
  282. } else {
  283. collisionPoint = CollisionUtils.getCollisionPoint(prevLoc, proj.getLocation(), entity);
  284. }
  285. if (collisionPoint == null) {
  286. if (CollisionUtils.isPointWithinBounds(proj.getLocation(), entity)) {
  287. collisionPoint = proj.getLocation();
  288. }
  289. }
  290.  
  291. if (collisionPoint != null) {
  292. // Apply damage and destroy the projectile
  293. if (entity instanceof ShipAPI) {
  294. CombatUtils.applyForce(exigency_Twig.getRoot((ShipAPI) entity), proj.getVelocity(),
  295. data.hitForce);
  296. } else {
  297. CombatUtils.applyForce(entity, proj.getVelocity(), data.hitForce);
  298. }
  299. engine.applyDamage(entity, collisionPoint, proj.getDamageAmount(), proj.getDamageType(),
  300. proj.getEmpAmount(), true, true, proj.getSource());
  301. engine.spawnExplosion(collisionPoint, entity.getVelocity(), data.explosionColor,
  302. data.explosionSize,
  303. data.explosionDuration);
  304. engine.spawnExplosion(MathUtils.getRandomPointOnCircumference(collisionPoint,
  305. data.explosionSize / 4f),
  306. entity.getVelocity(), data.explosionColor, data.explosionSize / 3f,
  307. data.explosionDuration / 2f);
  308. switch (data.particleType) {
  309. case HIT:
  310. engine.addHitParticle(collisionPoint, entity.getVelocity(), data.particleSize,
  311. data.particleAlpha, data.particleDuration, data.particleColor);
  312. break;
  313. case SMOOTH:
  314. engine.addSmoothParticle(collisionPoint, entity.getVelocity(), data.particleSize,
  315. data.particleAlpha, data.particleDuration, data.particleColor);
  316. break;
  317. default:
  318. engine.addSmokeParticle(collisionPoint, entity.getVelocity(), data.particleSize,
  319. data.particleAlpha, data.particleDuration, data.particleColor);
  320. }
  321. Global.getSoundPlayer().playSound(data.hitSound, data.hitSoundPitch, 1f, collisionPoint,
  322. entity.getVelocity());
  323. engine.removeEntity(proj);
  324. }
  325. }
  326. }
  327. }
  328. }
  329.  
  330. @Override
  331. public void init(CombatEngineAPI engine) {
  332. this.engine = engine;
  333. Global.getCombatEngine().getCustomData().put(DATA_KEY, new LocalData());
  334. }
  335.  
  336. @Override
  337. public void renderInWorldCoords(ViewportAPI viewport) {
  338. if (engine == null) {
  339. return;
  340. }
  341.  
  342. String spec;
  343. ProjData data;
  344.  
  345. // Scan all shots on the map for shield piercing projectiles
  346. List<DamagingProjectileAPI> projectiles = engine.getProjectiles();
  347. int size = projectiles.size();
  348. for (int i = 0; i < size; i++) {
  349. DamagingProjectileAPI proj = projectiles.get(i);
  350. spec = proj.getProjectileSpecId();
  351.  
  352. // Is this projectile shield piercing?
  353. if (!PROJ_DATA.containsKey(spec)) {
  354. continue;
  355. }
  356.  
  357. data = PROJ_DATA.get(spec);
  358.  
  359. // Find nearby ships and asteroids
  360. List<ShipAPI> toCheck = new ArrayList<>(100);
  361. toCheck.addAll(CombatUtils.getShipsWithinRange(proj.getLocation(), proj.getCollisionRadius() + 5f));
  362. // Don't include the ship that fired this projectile!
  363. toCheck.remove(proj.getSource());
  364. int checkSize = toCheck.size();
  365. for (int j = 0; j < checkSize; j++) {
  366. ShipAPI ship = toCheck.get(j);
  367. // Pass right through a cloaked ship
  368. if (ship.getCollisionClass() == CollisionClass.NONE) {
  369. continue;
  370. }
  371.  
  372. // Ignore friendly fighters
  373. if ((ship.isFighter() || ship.isDrone()) &&
  374. ship.isAlive() &&
  375. !ship.getEngineController().isFlamedOut() &&
  376. ship.getOwner() == proj.getOwner()) {
  377. continue;
  378. }
  379.  
  380. // Show effects when passing through a shield
  381. ShieldAPI shield = ship.getShield();
  382. if (shield != null &&
  383. shield.isOn() &&
  384. shield.isWithinArc(proj.getLocation()) &&
  385. MathUtils.isWithinRange(proj.getLocation(), shield.getLocation(), shield.getRadius())) {
  386. data.pierceSprite.setAlphaMult(data.pierceOpacity);
  387. data.pierceSprite.setAdditiveBlend();
  388. data.pierceSprite.setAngle(proj.getFacing() - 90);
  389. data.pierceSprite.setColor(data.shieldPierceColor);
  390. float pierceSize = data.pierceSize + MathUtils.getRandomNumberInRange(-1f, 1f) * data.pierceJitter;
  391. data.pierceSprite.setSize(pierceSize / 2f, pierceSize);
  392. float pierceX = proj.getLocation().x + MathUtils.getRandomNumberInRange(-1f, 1f) * data.pierceJitter;
  393. float pierceY = proj.getLocation().y + MathUtils.getRandomNumberInRange(-1f, 1f) * data.pierceJitter;
  394. data.pierceSprite.renderAtCenter(pierceX, pierceY);
  395. }
  396. }
  397. }
  398. }
  399.  
  400. private static enum ParticleType {
  401.  
  402. HIT,
  403. SMOOTH,
  404. SMOKE
  405. }
  406.  
  407. private static final class LocalData {
  408.  
  409. final Map<DamagingProjectileAPI, ProjInfo> projectileData = new LinkedHashMap<>(100);
  410. }
  411.  
  412. private static final class ProjData {
  413.  
  414. final Color explosionColor;
  415. final float explosionDuration;
  416. final float explosionSize;
  417. final float hitForce;
  418. final String hitSound;
  419. final float hitSoundPitch;
  420. final float particleAlpha;
  421. final Color particleColor;
  422. final float particleDuration;
  423. final float particleSize;
  424. final ParticleType particleType;
  425. final float pierceJitter;
  426. final float pierceOpacity;
  427. final float pierceSize;
  428. final SpriteAPI pierceSprite;
  429. final Color shieldPierceColor;
  430. final String shieldPierceEnterSound;
  431. final float shieldPierceEnterSoundPitch;
  432. final String shieldPierceSound;
  433. final float shieldPierceSoundPitch;
  434.  
  435. private ProjData(String shieldPierceSound, float shieldPierceSoundPitch, Color shieldPierceColor,
  436. String shieldPierceEnterSound, float shieldPierceEnterSoundPitch, String hitSound,
  437. float hitSoundPitch, float hitForce, float explosionSize, float explosionDuration,
  438. Color explosionColor, float particleSize,
  439. ParticleType particleType, float particleDuration, float particleAlpha,
  440. Color particleColor, float pierceSize, float pierceOpacity, float pierceJitter,
  441. SpriteAPI pierceSprite) {
  442. this.shieldPierceSound = shieldPierceSound;
  443. this.shieldPierceSoundPitch = shieldPierceSoundPitch;
  444. this.shieldPierceColor = shieldPierceColor;
  445. this.shieldPierceEnterSound = shieldPierceEnterSound;
  446. this.shieldPierceEnterSoundPitch = shieldPierceEnterSoundPitch;
  447. this.pierceSize = pierceSize;
  448. this.pierceJitter = pierceJitter;
  449. this.pierceOpacity = pierceOpacity;
  450. this.hitSound = hitSound;
  451. this.hitSoundPitch = hitSoundPitch;
  452. this.hitForce = hitForce;
  453. this.particleSize = particleSize;
  454. this.particleType = particleType;
  455. this.particleDuration = particleDuration;
  456. this.particleAlpha = particleAlpha;
  457. this.particleColor = particleColor;
  458. this.explosionSize = explosionSize;
  459. this.explosionDuration = explosionDuration;
  460. this.explosionColor = explosionColor;
  461. this.pierceSprite = pierceSprite;
  462. }
  463. }
  464.  
  465. private static final class ProjInfo {
  466.  
  467. CombatEntityAPI pierceTarget = null;
  468. }
  469. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement