001package com.fs.starfarer.api.impl.combat; 002 003import java.util.Iterator; 004 005import java.awt.Color; 006 007import org.lwjgl.util.vector.Vector2f; 008 009import com.fs.starfarer.api.Global; 010import com.fs.starfarer.api.combat.CollisionClass; 011import com.fs.starfarer.api.combat.CombatEngineAPI; 012import com.fs.starfarer.api.combat.CombatEntityAPI; 013import com.fs.starfarer.api.combat.DamageType; 014import com.fs.starfarer.api.combat.DamagingProjectileAPI; 015import com.fs.starfarer.api.combat.EmpArcEntityAPI; 016import com.fs.starfarer.api.combat.MissileAPI; 017import com.fs.starfarer.api.combat.OnFireEffectPlugin; 018import com.fs.starfarer.api.combat.ShipAPI; 019import com.fs.starfarer.api.combat.WeaponAPI; 020import com.fs.starfarer.api.combat.WeaponAPI.AIHints; 021import com.fs.starfarer.api.impl.campaign.ids.Stats; 022import com.fs.starfarer.api.util.Misc; 023 024/** 025 */ 026public class ShockRepeaterOnFireEffect implements OnFireEffectPlugin { 027 028 public static float ARC = 30f; 029 030 public void onFire(DamagingProjectileAPI projectile, WeaponAPI weapon, CombatEngineAPI engine) { 031 //ARC = 30f; 032 float emp = projectile.getEmpAmount(); 033 float dam = projectile.getDamageAmount(); 034 035 CombatEntityAPI target = findTarget(projectile, weapon, engine); 036 float thickness = 20f; 037 float coreWidthMult = 0.67f; 038 Color color = weapon.getSpec().getGlowColor(); 039 if (target != null) { 040 EmpArcEntityAPI arc = engine.spawnEmpArc(projectile.getSource(), projectile.getLocation(), weapon.getShip(), 041 target, 042 DamageType.ENERGY, 043 dam, 044 emp, // emp 045 100000f, // max range 046 "shock_repeater_emp_impact", 047 thickness, // thickness 048 color, 049 new Color(255,255,255,255) 050 ); 051 arc.setCoreWidthOverride(thickness * coreWidthMult); 052 arc.setSingleFlickerMode(); 053 } else { 054 Vector2f from = new Vector2f(projectile.getLocation()); 055 Vector2f to = pickNoTargetDest(projectile, weapon, engine); 056 EmpArcEntityAPI arc = engine.spawnEmpArcVisual(from, weapon.getShip(), to, weapon.getShip(), thickness, color, Color.white); 057 arc.setCoreWidthOverride(thickness * coreWidthMult); 058 arc.setSingleFlickerMode(); 059 //Global.getSoundPlayer().playSound("shock_repeater_emp_impact", 1f, 1f, to, new Vector2f()); 060 } 061 } 062 063 public Vector2f pickNoTargetDest(DamagingProjectileAPI projectile, WeaponAPI weapon, CombatEngineAPI engine) { 064 float spread = 50f; 065 float range = weapon.getRange() - spread; 066 Vector2f from = projectile.getLocation(); 067 Vector2f dir = Misc.getUnitVectorAtDegreeAngle(weapon.getCurrAngle()); 068 dir.scale(range); 069 Vector2f.add(from, dir, dir); 070 dir = Misc.getPointWithinRadius(dir, spread); 071 return dir; 072 } 073 074 public CombatEntityAPI findTarget(DamagingProjectileAPI projectile, WeaponAPI weapon, CombatEngineAPI engine) { 075 float range = weapon.getRange(); 076 Vector2f from = projectile.getLocation(); 077 078 Iterator<Object> iter = Global.getCombatEngine().getAllObjectGrid().getCheckIterator(from, 079 range * 2f, range * 2f); 080 int owner = weapon.getShip().getOwner(); 081 CombatEntityAPI best = null; 082 float minScore = Float.MAX_VALUE; 083 084 ShipAPI ship = weapon.getShip(); 085 boolean ignoreFlares = ship != null && ship.getMutableStats().getDynamic().getValue(Stats.PD_IGNORES_FLARES, 0) >= 1; 086 ignoreFlares |= weapon.hasAIHint(AIHints.IGNORES_FLARES); 087 088 while (iter.hasNext()) { 089 Object o = iter.next(); 090 if (!(o instanceof MissileAPI) && 091 //!(o instanceof CombatAsteroidAPI) && 092 !(o instanceof ShipAPI)) continue; 093 CombatEntityAPI other = (CombatEntityAPI) o; 094 if (other.getOwner() == owner) continue; 095 096 if (other instanceof ShipAPI) { 097 ShipAPI otherShip = (ShipAPI) other; 098 if (otherShip.isHulk()) continue; 099 //if (!otherShip.isAlive()) continue; 100 if (otherShip.isPhased()) continue; 101 if (!otherShip.isTargetable()) continue; 102 } 103 104 if (other.getCollisionClass() == CollisionClass.NONE) continue; 105 106 if (ignoreFlares && other instanceof MissileAPI) { 107 MissileAPI missile = (MissileAPI) other; 108 if (missile.isFlare()) continue; 109 } 110 111 float radius = Misc.getTargetingRadius(from, other, false); 112 float dist = Misc.getDistance(from, other.getLocation()) - radius; 113 if (dist > range) continue; 114 115 if (!Misc.isInArc(weapon.getCurrAngle(), ARC, from, other.getLocation())) continue; 116 117 //float angleTo = Misc.getAngleInDegrees(from, other.getLocation()); 118 //float score = Misc.getAngleDiff(weapon.getCurrAngle(), angleTo); 119 float score = dist; 120 121 if (score < minScore) { 122 minScore = score; 123 best = other; 124 } 125 } 126 return best; 127 } 128 129}