001package com.fs.starfarer.api.impl.combat.threat; 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.CombatEngineAPI; 009import com.fs.starfarer.api.combat.CombatEntityAPI; 010import com.fs.starfarer.api.combat.DamageAPI; 011import com.fs.starfarer.api.combat.DamagingProjectileAPI; 012import com.fs.starfarer.api.combat.MissileAPI; 013import com.fs.starfarer.api.combat.OnHitEffectPlugin; 014import com.fs.starfarer.api.combat.ShipAPI; 015import com.fs.starfarer.api.combat.WeaponAPI; 016import com.fs.starfarer.api.combat.listeners.ApplyDamageResultAPI; 017import com.fs.starfarer.api.combat.listeners.DamageDealtModifier; 018import com.fs.starfarer.api.impl.combat.DisintegratorEffect; 019import com.fs.starfarer.api.impl.combat.threat.RoilingSwarmEffect.RoilingSwarmParams; 020import com.fs.starfarer.api.impl.combat.threat.RoilingSwarmEffect.SwarmMember; 021import com.fs.starfarer.api.util.Misc; 022 023public class DevouringSwarmMissileEffect extends BaseFragmentMissileEffect implements OnHitEffectPlugin { 024 025 public static String DISMANTLING_SWARM = "dismantling_swarm"; 026 027 public static int NUM_TICKS = 11; // about 10 seconds (duration of damage over time effect) 028 029 public static class DismantlingFragmentBaseDamageNegator implements DamageDealtModifier { 030 @Override 031 public String modifyDamageDealt(Object param, CombatEntityAPI target, DamageAPI damage, Vector2f point, 032 boolean shieldHit) { 033 if (shieldHit) { 034 return null; 035 } 036 if (param instanceof MissileAPI) { 037 MissileAPI missile = (MissileAPI) param; 038 RoilingSwarmEffect swarm = RoilingSwarmEffect.getSwarmFor(missile); 039 if (swarm != null && swarm.params.tags.contains(DISMANTLING_SWARM)) { 040 damage.getModifier().modifyMult(DISMANTLING_SWARM, 0f); 041 return DISMANTLING_SWARM; 042 } 043 } 044 return null; 045 } 046 } 047 048 049 050 public void onFire(DamagingProjectileAPI projectile, WeaponAPI weapon, CombatEngineAPI engine) { 051 super.onFire(projectile, weapon, engine); 052 if (weapon.getShip() != null && 053 !weapon.getShip().hasListenerOfClass(DismantlingFragmentBaseDamageNegator.class)) { 054 weapon.getShip().addListener(new DismantlingFragmentBaseDamageNegator()); 055 } 056 } 057 058 protected void configureMissileSwarmParams(RoilingSwarmParams params) { 059// params.flashFringeColor = new Color(183,65,13,255); 060// params.flashCoreColor = Color.white; 061// params.flashRadius = 40f; 062// params.flashCoreRadiusMult = 0.75f; 063 064 params.tags.add(DISMANTLING_SWARM); 065 066// params.flashFringeColor = new Color(183,65,13,80); 067// params.flashCoreColor = new Color(183,65,13,127); 068 params.flashFringeColor = new Color(130,165,50,50); 069 params.flashCoreColor = new Color(130,165,50,127); 070 //params.flashCoreColor = new Color(50,165,50,127); 071 072// params.flashFringeColor = new Color(100,165,100,127); 073// params.flashCoreColor = Color.white; 074 075 076 //params.flashCoreColor = new Color(183,65,13,127); 077 params.flashCoreRadiusMult = 0f; 078 params.renderFlashOnSameLayer = true; 079 params.flashRadius = 40f; 080 params.preFlashDelay = 0.5f * (float) Math.random(); 081 082 params.flashFrequency = 40f; 083 params.flashProbability = 1f; 084 } 085 086 protected int getNumOtherMembersToTransfer() { 087 return 5; 088 //return 0; 089 } 090 091 @Override 092 protected int getNumOtherMembersToAdd() { 093 return 0; 094 //return 5; 095 } 096 097 protected int getEMPResistance() { 098 return 1; 099 } 100 101 protected boolean explodeOnFizzling() { 102 return false; 103 } 104 105 @Override 106 protected FragmentBehaviorOnImpact getOtherFragmentBehaviorOnImpact() { 107 return FragmentBehaviorOnImpact.STOP_AND_FADE; 108 } 109 110 protected void reportFragmentHit(MissileAPI missile, SwarmMember p, RoilingSwarmEffect swarm, CombatEntityAPI target) { 111 CombatEngineAPI engine = Global.getCombatEngine(); 112 Color color = swarm.params.flashFringeColor; 113 color = Misc.setAlpha(color, 255); 114 float size = swarm.params.flashRadius * 2f; 115 engine.addHitParticle(p.loc, new Vector2f(), size, 0.5f, color); 116 engine.addHitParticle(p.loc, new Vector2f(), size * 0.25f, 1f, Color.white); 117 } 118 119 @Override 120 public void onHit(DamagingProjectileAPI projectile, CombatEntityAPI target, Vector2f point, boolean shieldHit, 121 ApplyDamageResultAPI damageResult, CombatEngineAPI engine) { 122 if (shieldHit) return; 123 if (projectile.getDamageAmount() <= 0f) return; 124 //if (projectile.isFading()) return; 125 if (!(target instanceof ShipAPI)) return; 126 127 ShipAPI source = projectile.getSource(); 128 RoilingSwarmEffect sourceSwarm = RoilingSwarmEffect.getSwarmFor(source); 129 130 Vector2f offset = Vector2f.sub(point, target.getLocation(), new Vector2f()); 131 offset = Misc.rotateAroundOrigin(offset, -target.getFacing()); 132 DisintegratorEffect effect = new DisintegratorEffect(projectile, (ShipAPI) target, offset) { 133 protected float getTotalDamage() { 134 return projectile.getDamageAmount(); 135 } 136 protected int getNumTicks() { 137 return NUM_TICKS; 138 } 139 protected boolean canDamageHull() { 140 return true; 141 } 142 protected int getNumParticlesPerTick() { 143 return 5; 144 } 145 protected String getSoundLoopId() { 146 return "devouring_swarm_loop"; 147 } 148 protected void addParticle() { 149 ParticleData p = new ParticleData(25f, 3f + (float) Math.random() * 2f, 1f); 150 p.color = new Color(125,100,200,25); 151// p.color = RiftLanceEffect.getColorForDarkening(VoltaicDischargeOnFireEffect.EMP_FRINGE_COLOR); 152// p.color = Misc.setAlpha(p.color, 25); 153 particles.add(p); 154 p.offset = Misc.getPointWithinRadius(p.offset, 10f); 155 } 156 protected void damageDealt(Vector2f loc, float hullDamage, float armorDamage) { 157 if (sourceSwarm == null || source == null || !source.isAlive()) return; 158 if (source.isFighter()) return; 159 160 if ((float) Math.random() < 0.25f) return; 161 if (hullDamage > 0 || armorDamage > 0) { 162 SwarmMember p = sourceSwarm.addMember(); 163 p.loc.set(loc); 164 p.fader.setDurationIn(0.3f); 165 } 166 } 167 }; 168 CombatEntityAPI e = engine.addLayeredRenderingPlugin(effect); 169 e.getLocation().set(projectile.getLocation()); 170 171 if (projectile instanceof MissileAPI) { 172 MissileAPI missile = (MissileAPI) projectile; 173 missile.setDidDamage(true); 174 Global.getSoundPlayer().playSound("devouring_swarm_hit_ship", 1f, 1f, point, 175 missile.getVelocity()); 176 } 177 } 178 179 protected boolean withEMPArc() { 180 return super.withEMPArc(); 181 } 182 183 protected Color getEMPFringeColor() { 184 Color c = weapon.getSpec().getGlowColor(); 185 c = Misc.scaleColorOnly(c, 0.5f); 186 return c; 187 //return super.getEMPFringeColor(); 188 } 189 190 protected Color getEMPCoreColor() { 191 Color c = Color.white; 192 c = Misc.scaleColorOnly(c, 0.5f); 193 return c; 194 //return super.getEMPCoreColor(); 195 } 196 197// protected String getExplosionSoundId() { 198// return "devastator_explosion"; 199// } 200 201} 202 203 204 205 206 207 208 209