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}