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}