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