001package com.fs.starfarer.api.impl.combat; 002 003import java.util.List; 004 005import java.awt.Color; 006 007import org.lwjgl.util.vector.Vector2f; 008 009import com.fs.starfarer.api.Global; 010import com.fs.starfarer.api.combat.BaseEveryFrameCombatPlugin; 011import com.fs.starfarer.api.combat.CombatEngineAPI; 012import com.fs.starfarer.api.combat.MissileAPI; 013import com.fs.starfarer.api.combat.ShipAPI; 014import com.fs.starfarer.api.input.InputEventAPI; 015import com.fs.starfarer.api.util.IntervalUtil; 016import com.fs.starfarer.api.util.Misc; 017 018public class RiftTrailEffect extends BaseEveryFrameCombatPlugin { 019 020 protected IntervalUtil interval = new IntervalUtil(0.1f, 0.3f); 021 022 protected MissileAPI missile; 023 protected ShipAPI ship; 024 protected String loopId; 025 026 027 public RiftTrailEffect(MissileAPI missile, String loopId) { 028 this.missile = missile; 029 this.loopId = loopId; 030 } 031 032 public RiftTrailEffect(ShipAPI ship, String loopId) { 033 this.ship = ship; 034 this.loopId = loopId; 035 } 036 037 @Override 038 public void advance(float amount, List<InputEventAPI> events) { 039 if (Global.getCombatEngine().isPaused()) return; 040 041 if (missile != null) { 042 if (loopId != null) { 043 Global.getSoundPlayer().playLoop(loopId, missile, 1f, missile.getBrightness(), 044 missile.getLocation(), missile.getVelocity()); 045 } 046 047 interval.advance(amount); 048 if (interval.intervalElapsed()) { 049 addParticles(); 050 } 051 052 if (missile.isExpired() || missile.didDamage() || !Global.getCombatEngine().isEntityInPlay(missile)) { 053 Global.getCombatEngine().removePlugin(this); 054 } 055 } else if (ship != null) { 056 if (loopId != null) { 057 Global.getSoundPlayer().playLoop(loopId, ship, 1f, 1f, 058 ship.getLocation(), ship.getVelocity()); 059 } 060 061 interval.advance(amount); 062 if (interval.intervalElapsed()) { 063 addParticles(); 064 } 065 066 if (ship.isExpired() || !Global.getCombatEngine().isShipAlive(ship)) { 067 Global.getCombatEngine().removePlugin(this); 068 } 069 } 070 } 071 072 protected Color getUndercolor() { 073 return RiftCascadeEffect.EXPLOSION_UNDERCOLOR; 074 } 075 protected Color getDarkeningColor() { 076 return RiftLanceEffect.getColorForDarkening(RiftCascadeEffect.STANDARD_RIFT_COLOR); 077 } 078 protected float getBaseParticleDuration() { 079 return 4f; 080 } 081 082 protected float getBaseParticleSize() { 083 if (missile != null) return missile.getSpec().getGlowRadius() * 0.5f; 084 return ship.getCollisionRadius(); 085 } 086 protected float getCurrentBaseAlpha() { 087 if (missile != null) return missile.getCurrentBaseAlpha(); 088 return 1f; 089 } 090 protected Vector2f getEntityLocation() { 091 if (missile != null) return missile.getLocation(); 092 return ship.getLocation(); 093 } 094 protected Vector2f getEntityVelocity() { 095 if (missile != null) return missile.getVelocity(); 096 return ship.getVelocity(); 097 } 098 099 public void addParticles() { 100 CombatEngineAPI engine = Global.getCombatEngine(); 101 Color c = getDarkeningColor(); 102 // subtracting the standard color looks better, makes the red a bit purplish 103 // inverting red to substract doesn't look as good for the trails 104// MissileSpecAPI spec = missile.getSpec(); 105// c = spec.getExplosionColor(); 106 107 Color undercolor = getUndercolor(); 108 109 float b = getCurrentBaseAlpha(); 110 c = Misc.scaleAlpha(c, b); 111 undercolor = Misc.scaleAlpha(undercolor, b); 112 113 float baseDuration = getBaseParticleDuration(); 114 float size = 30f; 115 size = getBaseParticleSize(); 116 117 Vector2f point = new Vector2f(getEntityLocation()); 118 Vector2f pointOffset = new Vector2f(getEntityVelocity()); 119 pointOffset.scale(0.1f); 120 Vector2f.add(point, pointOffset, point); 121 122 Vector2f vel = new Vector2f(); 123 124 for (int i = 0; i < 1; i++) { 125 float dur = baseDuration + baseDuration * (float) Math.random(); 126 //float nSize = size * (1f + 0.0f * (float) Math.random()); 127 //float nSize = size * (0.75f + 0.5f * (float) Math.random()); 128 float nSize = size; 129 Vector2f pt = Misc.getPointWithinRadius(point, nSize * 0.5f); 130 Vector2f v = Misc.getUnitVectorAtDegreeAngle((float) Math.random() * 360f); 131 v.scale(nSize + nSize * (float) Math.random() * 0.5f); 132 v.scale(0.2f); 133 Vector2f.add(vel, v, v); 134 135 float maxSpeed = nSize * 1.5f * 0.2f; 136 float minSpeed = nSize * 1f * 0.2f; 137 float overMin = v.length() - minSpeed; 138 if (overMin > 0) { 139 float durMult = 1f - overMin / (maxSpeed - minSpeed); 140 if (durMult < 0.1f) durMult = 0.1f; 141 dur *= 0.5f + 0.5f * durMult; 142 } 143 engine.addNegativeNebulaParticle(pt, v, nSize * 1f, 2f, 144 0.5f, 0f, dur, c); 145 } 146 147 float dur = baseDuration; 148 float rampUp = 0f; 149 rampUp = 0.5f; 150 c = undercolor; 151 for (int i = 0; i < 2; i++) { 152 Vector2f loc = new Vector2f(point); 153 loc = Misc.getPointWithinRadius(loc, size * 1f); 154 float s = size * 3f * (0.5f + (float) Math.random() * 0.5f); 155 engine.addNebulaParticle(loc, vel, s, 1.5f, rampUp, 0f, dur, c); 156 } 157 } 158 159}