001package com.fs.starfarer.api.impl.combat.dweller;
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.BeamEffectPlugin;
010import com.fs.starfarer.api.combat.CollisionClass;
011import com.fs.starfarer.api.combat.CombatEngineAPI;
012import com.fs.starfarer.api.combat.DamageType;
013import com.fs.starfarer.api.combat.DamagingProjectileAPI;
014import com.fs.starfarer.api.combat.EmpArcEntityAPI;
015import com.fs.starfarer.api.combat.EmpArcEntityAPI.EmpArcParams;
016import com.fs.starfarer.api.combat.ShipAPI;
017import com.fs.starfarer.api.impl.combat.NegativeExplosionVisual.NEParams;
018import com.fs.starfarer.api.impl.combat.RiftCascadeMineExplosion;
019import com.fs.starfarer.api.loading.DamagingExplosionSpec;
020import com.fs.starfarer.api.util.IntervalUtil;
021import com.fs.starfarer.api.util.Misc;
022
023public class AbyssalGlareEffect implements BeamEffectPlugin {
024
025        public static float RIFT_DAMAGE = 200f; // happens approximately every 1.25 seconds; ~160 dps per beam
026        public static float DAMAGE_MULT_NORMAL_WEAPON = 0.5f;
027        
028        protected IntervalUtil fireInterval = new IntervalUtil(0.2f, 0.3f);
029        protected boolean hadDamageTargetPrev = false;
030        protected boolean lengthChangedPrev = false;
031        protected float sinceRiftSpawn = 0f;
032        protected Vector2f prevTo = null;
033        protected Vector2f prevFrom = null;
034        
035        public AbyssalGlareEffect() {
036                fireInterval.randomize();
037        }
038        
039        public void advance(float amount, CombatEngineAPI engine, BeamAPI beam) {
040                //if (true) return;
041
042                if (beam.getSource() == null || beam.getWeapon() == null) return;
043                
044                boolean normalWeaponMode = !beam.getSource().hasTag(DarkenedGazeSystemScript.DARKENED_GAZE_SYSTEM_TAG);
045                //normalWeaponMode = true;
046                boolean primary = beam.getWeapon().getCustom() == DarkenedGazeSystemScript.DARKENED_GAZE_PRIMARY_WEAPON_TAG;
047                if (normalWeaponMode) primary = true;
048                
049                sinceRiftSpawn += amount;
050                
051                float maxRange = beam.getWeapon().getRange();
052                Vector2f from = beam.getFrom();
053                Vector2f to = beam.getRayEndPrevFrame();
054                Vector2f to2 = beam.getTo();
055                float dist = Misc.getDistance(from, to);
056                float dist2 = Misc.getDistance(from, to2);
057                if (dist2 < dist) {
058                        to = to2;
059                        dist = dist2;
060                }
061                
062//              if (beam.getDamageTarget() instanceof ShipAPI) {
063//                      ((ShipAPI)beam.getDamageTarget()).setSkipNextDamagedExplosion(true);
064//              }
065                
066                boolean hasDamageTarget = beam.getDamageTarget() != null;
067                boolean lengthChanged = prevTo == null || 
068                                                Math.abs(Misc.getDistance(prevFrom, prevTo) - Misc.getDistance(from, to)) > 2f;
069                
070                boolean forceRiftSpawn = (hasDamageTarget && !hadDamageTargetPrev) ||
071                                                (!lengthChanged && lengthChangedPrev);
072                if (!primary) forceRiftSpawn = false;
073                
074                lengthChangedPrev = lengthChanged;
075                hadDamageTargetPrev = hasDamageTarget;
076                prevFrom = new Vector2f(from);
077                prevTo = new Vector2f(to);
078                
079//              forceRiftSpawn = false;
080//              if (forceRiftSpawn) {
081//                      System.out.println("efwfwefwe");
082//              }
083                fireInterval.advance(amount);
084                if (fireInterval.intervalElapsed() || forceRiftSpawn) {
085                        
086                        if (beam.getDamageTarget() == null && dist < maxRange * 0.9f) {
087                                return;
088                        }
089                        if (beam.getBrightness() < 1) {
090                                return;
091                        }
092                        
093                        
094                        Color color = RiftLightningEffect.RIFT_LIGHTNING_COLOR;
095                        
096                        boolean spawnedExplosion = false;
097                        float maxTimeWithoutExplosion = 1f;
098                        if (normalWeaponMode) {
099                                maxTimeWithoutExplosion = 0.5f;
100                        }
101                        if ((float) Math.random() > 0.8f || forceRiftSpawn || (primary && sinceRiftSpawn > maxTimeWithoutExplosion)) {
102                                DamagingProjectileAPI explosion = engine.spawnDamagingExplosion(
103                                                                createExplosionSpec(normalWeaponMode ? DAMAGE_MULT_NORMAL_WEAPON : 1f),
104                                                                beam.getSource(), to);
105                                //explosion.addDamagedAlready(target);
106                                //color = new Color(255,75,75,255);
107                                
108                                float distFactor = 0f;
109                                if (dist > 500f) {
110                                        distFactor = (dist - 500f) / 1500f;
111                                        if (distFactor < 0f) distFactor = 0f;
112                                        if (distFactor > 1f) distFactor = 1f;
113                                }
114                                
115                                float sizeAdd = 5f * distFactor;
116                                float baseSize = 15f;
117                                if (normalWeaponMode) {
118                                        baseSize *= 0.5f;
119                                        sizeAdd = 0f; // beam is not getting wider at end, so don't increase explosion size
120                                }
121                                
122                                NEParams p = RiftCascadeMineExplosion.createStandardRiftParams(
123                                                                                        color, baseSize + sizeAdd);
124                                //p.hitGlowSizeMult = 0.5f;
125                                p.noiseMult = 6f;
126                                p.thickness = 25f;
127                                p.fadeOut = 0.5f;
128                                p.spawnHitGlowAt = 1f;
129                                p.additiveBlend = true;
130                                p.blackColor = Color.white;
131                                p.underglow = null;
132                                p.withNegativeParticles = false;
133                                p.withHitGlow = false;
134                                p.fadeIn = 0f;
135                                //p.numRiftsToSpawn = 1;
136                                
137                                RiftCascadeMineExplosion.spawnStandardRift(explosion, p);
138                                
139                                spawnedExplosion = true;
140                                sinceRiftSpawn = 0f;
141                        }
142                        
143                        if (dist > 100f && ((float) Math.random() > 0.5f || (normalWeaponMode && spawnedExplosion))) {
144                        //if (dist > 100f && spawnedExplosion) {
145                                EmpArcParams params = new EmpArcParams();
146                                params.segmentLengthMult = 8f;
147                                params.zigZagReductionFactor = 0.15f;
148                                params.fadeOutDist = 50f;
149                                params.minFadeOutMult = 10f;
150        //                      params.flickerRateMult = 0.7f;
151                                params.flickerRateMult = 0.3f;
152        //                      params.flickerRateMult = 0.05f;
153        //                      params.glowSizeMult = 3f;
154                                
155                                float fraction = Math.min(0.33f, 300f / dist);
156                                params.brightSpotFullFraction = fraction;
157                                params.brightSpotFadeFraction = fraction;
158                                
159                                float arcSpeed = RiftLightningEffect.RIFT_LIGHTNING_SPEED;
160                                params.movementDurOverride = Math.max(0.05f, dist / arcSpeed);
161                                
162                                ShipAPI ship = beam.getSource();
163                                //Color color = weapon.getSpec().getGlowColor();
164                                EmpArcEntityAPI arc = (EmpArcEntityAPI)engine.spawnEmpArcVisual(from, ship, to, ship,
165                                                80f, // thickness
166                                                color,
167                                                new Color(255,255,255,255),
168                                                params
169                                                );
170                                arc.setCoreWidthOverride(40f);
171                                
172                                arc.setRenderGlowAtStart(false);
173                                arc.setFadedOutAtStart(true);
174                                arc.setSingleFlickerMode(true);
175                                
176                                Vector2f pt = Vector2f.add(from, to, new Vector2f());
177                                pt.scale(0.5f);
178                                
179                                Global.getSoundPlayer().playSound("abyssal_glare_lightning", 1f, 1f, pt, new Vector2f());
180                        }
181                        
182                }
183                
184                if (normalWeaponMode) {
185                        Vector2f pt = Vector2f.add(from, to, new Vector2f());
186                        pt.scale(0.5f);
187                        Global.getSoundPlayer().playLoop("abyssal_glare_loop", 
188                                                                                         beam.getSource(), 1f, beam.getBrightness(),
189                                                                                         pt, beam.getSource().getVelocity());
190                } else if (primary) {
191                        Vector2f pt = Vector2f.add(from, to, new Vector2f());
192                        pt.scale(0.5f);
193                        Global.getSoundPlayer().playLoop("darkened_gaze_loop", 
194                                         beam.getSource(), 1f, beam.getBrightness(),
195                                         pt, beam.getSource().getVelocity());
196                }
197        }
198        
199
200
201        public DamagingExplosionSpec createExplosionSpec(float damageMult) {
202                float damage = RIFT_DAMAGE * damageMult;
203                DamagingExplosionSpec spec = new DamagingExplosionSpec(
204                                0.1f, // duration
205                                75f, // radius
206                                50f, // coreRadius
207                                damage, // maxDamage
208                                damage / 2f, // minDamage
209                                CollisionClass.PROJECTILE_FF, // collisionClass
210                                CollisionClass.PROJECTILE_FIGHTER, // collisionClassByFighter
211                                3f, // particleSizeMin
212                                3f, // particleSizeRange
213                                0.5f, // particleDuration
214                                0, // particleCount
215                                new Color(255,255,255,0), // particleColor
216                                new Color(255,100,100,0)  // explosionColor
217                                );
218
219                spec.setDamageType(DamageType.ENERGY);
220                spec.setUseDetailedExplosion(false);
221                spec.setSoundSetId("abyssal_glare_explosion");
222                spec.setSoundVolume(damageMult);
223                return spec;            
224        }
225        
226}
227
228