001package com.fs.starfarer.api.impl.combat.dweller;
002
003import java.util.ArrayList;
004import java.util.List;
005
006import java.awt.Color;
007
008import org.lwjgl.opengl.GL11;
009import org.lwjgl.opengl.GL14;
010import org.lwjgl.util.vector.Vector2f;
011
012import com.fs.starfarer.api.Global;
013import com.fs.starfarer.api.combat.CombatEngineAPI;
014import com.fs.starfarer.api.combat.CombatEngineLayers;
015import com.fs.starfarer.api.combat.CombatEntityAPI;
016import com.fs.starfarer.api.combat.DamagingProjectileAPI;
017import com.fs.starfarer.api.combat.ShipAPI;
018import com.fs.starfarer.api.combat.ViewportAPI;
019import com.fs.starfarer.api.combat.listeners.ApplyDamageResultAPI;
020import com.fs.starfarer.api.impl.combat.CryofluxTransducerEffect;
021import com.fs.starfarer.api.impl.combat.RiftLanceEffect;
022import com.fs.starfarer.api.util.IntervalUtil;
023import com.fs.starfarer.api.util.Misc;
024
025public class PseudoparticleJetEffect extends CryofluxTransducerEffect {
026        
027        public static float PARTICLE_SCALE_MULT = 0.7f;
028        
029        protected IntervalUtil interval = new IntervalUtil(0.075f, 0.125f);
030        protected List<ParticleData> negativeParticles = new ArrayList<>();
031        
032        public PseudoparticleJetEffect() {
033                super();
034        }
035
036        public PseudoparticleJetEffect(DamagingProjectileAPI projectile, DamagingProjectileAPI prev) {
037                super(projectile, prev);
038                
039                int num = 2;
040                num = 1;
041                for (int i = 0; i < num; i++) {
042                        negativeParticles.add(new ParticleData(proj, this));
043                }
044                
045                //PARTICLE_SCALE_MULT = 0.7f;
046                
047                float size = proj.getProjectileSpec().getWidth() * 0.6f;
048                
049                for (ParticleData p : negativeParticles) {
050                        p.sprite = Global.getSettings().getSprite(super.getParticleSpriteCat(), super.getParticleSpriteKey());
051                        float i = Misc.random.nextInt(4);
052                        float j = Misc.random.nextInt(4);
053                        p.sprite.setTexWidth(0.25f);
054                        p.sprite.setTexHeight(0.25f);
055                        p.sprite.setTexX(i * 0.25f);
056                        p.sprite.setTexY(j * 0.25f);
057                        
058                        p.scale = 2f + (float) Math.random();
059                        p.scale *= 1.5f; // 1 particle instead of 2
060                        p.scale *= PARTICLE_SCALE_MULT;
061                        p.scaleIncreaseRate *= 1f + (float) Math.random();
062                        
063                        Vector2f v = Misc.getUnitVectorAtDegreeAngle((float) Math.random() * 360f);
064                        v.scale(size + size * (float) Math.random() * 0.5f);
065                        v.scale(0.67f * p.scale);
066                        p.vel.set(v);
067                        //Vector2f.add(vel, v, v);
068                        
069//                      p.fader.setDuration(0.25f, 0.75f);
070//                      p.fader.setBounceDown(true);
071                        
072//                      float f = index / Math.max(1f, (negativeParticles.size() - 1));
073//                      Vector2f dir = Misc.getUnitVectorAtDegreeAngle(proj.getFacing() + 180f);
074//                      dir.scale(length * f);
075//                      Vector2f.add(p.offset, dir, p.offset);
076                        
077                        //p.offset = Misc.getPointWithinRadius(p.offset, width * 0.5f);
078                        p.offset = Misc.getPointWithinRadiusUniform(p.offset, size * 0.1f * p.scale, Misc.random);
079                        
080                        float offsetAngle = Misc.getAngleInDegrees(p.vel) + 180f;
081                        offsetAngle += 90f * ((float) Math.random() - 0.5f);
082                        p.offset = Misc.getUnitVectorAtDegreeAngle(offsetAngle);
083                        p.offset.scale(size * 1f * p.scale);
084                        
085                        //p.scale *= 1.5f;
086                        p.scale *= 0.7f;
087                        
088                        // don't apply scale increase to negative particles or they cover up too much
089                        p.scaleIncreaseRate /= getParticleScaleIncreaseRateMult();
090                        
091                        //p.scale = 0.25f + 0.75f * (1 - f);
092                }
093        }
094        
095        protected PseudoparticleJetEffect createTrail(DamagingProjectileAPI projectile, DamagingProjectileAPI prev) {
096                return new PseudoparticleJetEffect(projectile, prev);
097        }
098        
099        
100        public void advance(float amount) {
101                super.advance(amount);
102                
103                if (Global.getCombatEngine().isPaused()) return;
104                
105                for (ParticleData p : negativeParticles) {
106                        p.advance(amount);
107                }
108        }
109        
110        
111        @Override
112        public void render(CombatEngineLayers layer, ViewportAPI viewport) {
113                super.render(layer, viewport);
114                //if (true) return;
115                float x = entity.getLocation().x;
116                float y = entity.getLocation().y;
117        
118                
119                Color color = RiftLanceEffect.getColorForDarkening(proj.getProjectileSpec().getFringeColor());
120                color = Misc.setAlpha(color, 100);
121                
122                float b = proj.getBrightness();
123                b *= viewport.getAlphaMult();
124                
125                GL14.glBlendEquation(GL14.GL_FUNC_REVERSE_SUBTRACT);
126                
127                for (ParticleData p : negativeParticles) {
128                        float size = proj.getProjectileSpec().getWidth() * 0.6f;
129                        size *= p.scale;
130                        
131                        float alphaMult = 1f;
132                        Vector2f offset = p.offset;
133                        float diff = Misc.getAngleDiff(baseFacing, proj.getFacing());
134                        if (Math.abs(diff) > 0.1f) {
135                                offset = Misc.rotateAroundOrigin(offset, diff);
136                        }
137                        Vector2f loc = new Vector2f(x + offset.x, y + offset.y);
138                        
139                        p.sprite.setBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
140                        p.sprite.setAngle(p.angle);
141                        p.sprite.setSize(size, size);
142                        p.sprite.setAlphaMult(b * alphaMult * p.fader.getBrightness());
143                        p.sprite.setColor(color);
144                        p.sprite.renderAtCenter(loc.x, loc.y);
145                }
146                
147                GL14.glBlendEquation(GL14.GL_FUNC_ADD);
148        }
149        
150        
151        
152        public void onHit(DamagingProjectileAPI projectile, CombatEntityAPI target, Vector2f point, boolean shieldHit, ApplyDamageResultAPI damageResult, CombatEngineAPI engine) {
153                super.onHit(projectile, target, point, shieldHit, damageResult, engine);
154                
155                Color c = RiftLanceEffect.getColorForDarkening(projectile.getProjectileSpec().getFringeColor());
156                c = Misc.setAlpha(c, 100);
157                float baseDuration = 1f;
158                float baseSize = projectile.getProjectileSpec().getLength() * 0.5f;
159                float size = baseSize * 1.5f;
160                float sizeMult = Misc.getHitGlowSize(100f, projectile.getDamage().getBaseDamage(), damageResult) / 100f;
161                size *= sizeMult;
162                
163                size *= 1.5f;
164                
165                float extraDur = 0f;
166                
167                point = Misc.getPointWithinRadiusUniform(point, baseSize * 0.75f, Misc.random);
168                float dur = baseDuration + baseDuration * (float) Math.random();
169                dur += extraDur;
170                float nSize = size;
171                Vector2f pt = point;
172                
173                Vector2f vel = new Vector2f();
174                if (target instanceof ShipAPI) {
175                        vel.set(target.getVelocity());
176                }
177                
178                Vector2f v = Misc.getUnitVectorAtDegreeAngle((float) Math.random() * 360f);
179                v.scale(nSize + nSize * (float) Math.random() * 0.5f);
180                v.scale(0.5f);
181                Vector2f.add(vel, v, v);
182                
183                float maxSpeed = nSize * 1.5f * 0.2f; 
184                float minSpeed = nSize * 1f * 0.2f; 
185                float overMin = v.length() - minSpeed;
186                if (overMin > 0) {
187                        float durMult = 1f - overMin / (maxSpeed - minSpeed);
188                        if (durMult < 0.1f) durMult = 0.1f;
189                        dur *= 0.5f + 0.5f * durMult;
190                }
191                
192                engine.addNegativeNebulaParticle(pt, v, nSize * 1f, 2f,
193                                                                                0.25f / dur, 0f, dur, c);
194        }
195        
196
197        protected String getParticleSpriteCat() {
198                return "dweller";
199        }
200        protected String getParticleSpriteKey() {
201                return "dweller_pieces";
202        }
203        protected float getParticleScale() {
204                return 2.5f * PARTICLE_SCALE_MULT;
205        }
206        protected float getParticleScaleIncreaseRateMult() {
207                return 1.5f;
208        }
209        protected int getNumParticles() {
210                return 2;
211        }
212        public Color getParticleColor() {
213                Color color = proj.getProjectileSpec().getFringeColor();
214                color = Misc.setAlpha(color, 75);
215                return color;
216        }
217
218        protected String getLoopId() {
219                return "pseudoparticle_jet_loop";
220        }
221        protected float getThresholdDist() {
222                //return 50f;
223                return super.getThresholdDist();
224        }
225        
226        protected void playImpactSound(ApplyDamageResultAPI damageResult, Vector2f point, Vector2f vel) {
227                Misc.playSound(damageResult, point, vel,
228                                "pseudoparticle_jet_hit_shield_light",
229                                "pseudoparticle_jet_hit_shield_solid",
230                                "pseudoparticle_jet_hit_shield_heavy",
231                                "pseudoparticle_jet_hit_light",
232                                "pseudoparticle_jet_hit_solid",
233                                "pseudoparticle_jet_hit_heavy");
234        }
235}