1package com.fs.starfarer.api.impl.combat.threat;
3import java.util.LinkedHashSet;
8import org.lwjgl.util.vector.Vector2f;
10import com.fs.starfarer.api.Global;
11import com.fs.starfarer.api.combat.CombatEngineAPI;
12import com.fs.starfarer.api.combat.CombatEntityAPI;
13import com.fs.starfarer.api.combat.DamageType;
14import com.fs.starfarer.api.combat.DamagingProjectileAPI;
15import com.fs.starfarer.api.combat.EmpArcEntityAPI;
16import com.fs.starfarer.api.combat.EmpArcEntityAPI.EmpArcParams;
17import com.fs.starfarer.api.combat.EveryFrameWeaponEffectPlugin;
18import com.fs.starfarer.api.combat.GuidedMissileAI;
19import com.fs.starfarer.api.combat.MissileAPI;
20import com.fs.starfarer.api.combat.OnFireEffectPlugin;
21import com.fs.starfarer.api.combat.ShipAPI;
22import com.fs.starfarer.api.combat.WeaponAPI;
23import com.fs.starfarer.api.combat.WeaponAPI.AIHints;
24import com.fs.starfarer.api.impl.combat.threat.RoilingSwarmEffect.RoilingSwarmParams;
25import com.fs.starfarer.api.impl.combat.threat.RoilingSwarmEffect.SwarmMember;
26import com.fs.starfarer.api.util.Misc;
27import com.fs.starfarer.api.util.WeightedRandomPicker;
31 public static enum FragmentBehaviorOnImpact {
51 if (
ship ==
null)
return;
56 boolean disable = active < required;
88 if (fragment ==
null) {
101 boolean setFacing =
false;
111 if (!setFacing && fragment.vel.length() > 0.1f) {
116 RoilingSwarmParams params =
new RoilingSwarmParams();
117 params.despawnSound =
null;
119 params.baseMembersToMaintain = 0;
120 params.removeMembersAboveMaintainLevel =
false;
121 params.keepProxBasedScaleForAllMembers =
true;
122 params.initialMembers = 0;
133 boolean exploded =
false;
134 Set<SwarmMember> stopped =
new LinkedHashSet<>();
136 boolean inited =
false;
138 public void advance(
float amount) {
139 super.advance(amount);
144 origMembers = members.size();
147 if (origMembers > 0 && members.size() > 1 && missile2.
getMaxHitpoints() > 0) {
149 float hpPerMember = max / origMembers;
151 int loseMembers = (int) (hpLost / hpPerMember);
152 int num = members.size();
153 int alreadyLost = origMembers - num;
154 for (SwarmMember p : members) {
155 if (p.fader.isFadingOut()) {
159 int lose = loseMembers - alreadyLost;
161 despawnMembers(lose,
false);
172 if (behavior != FragmentBehaviorOnImpact.KEEP_GOING) {
177 for (SwarmMember p : members) {
178 if (p == fragment || stopped.contains(p)) {
186 if (target instanceof
ShipAPI) {
200 Vector2f toP = Vector2f.sub(p.loc, fragment.loc,
new Vector2f());
201 hit = Vector2f.dot(toP, fragment.vel) > 0;
204 p.vel.set(
new Vector2f());
205 if (behavior == FragmentBehaviorOnImpact.STOP_AND_FLASH) {
225 params.minDespawnTime = 0.5f;
226 params.maxDespawnTime = 1f;
227 params.minFadeoutTime = 0.5f;
228 params.maxFadeoutTime = 1f;
229 setForceDespawn(
true);
250 if (fragment.flash !=
null) {
251 fragment.flash =
null;
253 fragment.flashNext =
null;
267 add += transfer - (missileSwarm.
members.size() - 1);
276 hpLoss *= 1 + transfer;
305 params.flashFringeColor =
new Color(255,50,50,255);
306 params.flashCoreColor = Color.white;
307 params.flashRadius = 60f;
308 params.flashCoreRadiusMult = 0.75f;
335 SwarmMember best =
null;
336 float maxDist = -Float.MAX_VALUE;
345 if (dist > maxDist && dist < range) {
355 SwarmMember best =
null;
356 float maxVelDiff = 0f;
365 if (velDiff > maxVelDiff && dist < range) {
374 SwarmMember best =
null;
375 float minDist = Float.MAX_VALUE;
383 if (dist > range)
continue;
385 if (dist < minDist) {
423 return FragmentBehaviorOnImpact.STOP_AND_FLASH;
464 EmpArcParams params =
new EmpArcParams();
465 params.segmentLengthMult = 4f;
467 params.glowSizeMult = 0.5f;
468 params.brightSpotFadeFraction = 0.33f;
469 params.brightSpotFullFraction = 0.5f;
470 params.movementDurMax = 0.2f;
471 params.flickerRateMult = 0.5f;
474 float minBright = 100f;
475 if (dist * params.brightSpotFullFraction < minBright) {
476 params.brightSpotFullFraction = minBright / Math.max(minBright, dist);
479 float thickness = 20f;
static SoundPlayerAPI getSoundPlayer()
DamagingProjectileAPI projectile
int getNumFragmentsToFire()
void advance(float amount, CombatEngineAPI engine, WeaponAPI weapon)
void swarmAdvance(float amount, MissileAPI missile, RoilingSwarmEffect swarm)
void reportFragmentHit(MissileAPI missile, SwarmMember p, RoilingSwarmEffect swarm, CombatEntityAPI target)
float getRangeForNearbyFragments()
boolean removeFragmentsWhenMissileLosesHitpoints()
SwarmMember pickPrimaryFragment()
boolean addNewMembersIfNotEnoughToTransfer()
String getExplosionSoundId()
boolean makePrimaryFragmentGlow()
boolean explodeOnFizzling()
boolean shouldPickVelocityMatchingPrimaryFragment()
FragmentBehaviorOnImpact getOtherFragmentBehaviorOnImpact()
SwarmMember pickOuterFragmentWithinRangeClosestTo(float range, Vector2f otherLoc)
float getHPLossPerTransferredMember()
SwarmMember pickVelocityMatchingFragmentWithinRange(float range)
Color getEMPFringeColor()
float getRangeFromSourceToPickFragments()
SwarmMember pickOuterFragmentWithinRange(float range)
BaseFragmentMissileEffect()
int getNumOtherMembersToAdd()
void configureMissileSwarmParams(RoilingSwarmParams params)
void swarmCreated(MissileAPI missile, RoilingSwarmEffect missileSwarm, RoilingSwarmEffect sourceSwarm)
RoilingSwarmEffect sourceSwarm
void onFire(DamagingProjectileAPI projectile, WeaponAPI weapon, CombatEngineAPI engine)
boolean shouldMakeMissileFaceTargetOnSpawnIfAny()
int getNumOtherMembersToTransfer()
int getNumActiveMembers()
void removeMember(SwarmMember sm)
RoilingSwarmParams params
CombatEntityAPI attachedTo
void transferMembersTo(RoilingSwarmEffect other, float fraction)
List< SwarmMember > members
WeightedRandomPicker< SwarmMember > getPicker(boolean preferNonFlashing, boolean preferNonPicked, Vector2f towards)
static RoilingSwarmEffect getSwarmFor(CombatEntityAPI entity)
CombatEntityAPI getAttachedTo()
void setBounceDown(boolean bounceDown)
void setBrightness(float brightness)
static float getDistance(SectorEntityToken from, SectorEntityToken to)
static float getTargetingRadius(Vector2f from, CombatEntityAPI target, boolean considerShield)
static float getAngleInDegrees(Vector2f v)
SoundAPI playSound(String id, float pitch, float volume, Vector2f loc, Vector2f vel)
EmpArcEntityAPI spawnEmpArcVisual(Vector2f from, CombatEntityAPI fromAnchor, Vector2f to, CombatEntityAPI toAnchor, float thickness, Color fringe, Color core)
void applyDamage(CombatEntityAPI entity, Vector2f point, float damageAmount, DamageType damageType, float empAmount, boolean bypassShields, boolean dealsSoftFlux, Object source, boolean playSound)
void removeEntity(CombatEntityAPI entity)
boolean isMissileAlive(MissileAPI missile)
float getCollisionRadius()
boolean isPointInBounds(Vector2f p)
BoundsAPI getExactBounds()
void setFacing(float facing)
CombatEntityAPI getDamageTarget()
void setSingleFlickerMode()
void setUpdateFromOffsetEveryFrame(boolean updateFromOffsetEveryFrame)
CombatEntityAPI getTarget()
float getCurrentBaseAlpha()
void setEmpResistance(int empResistance)
void setStart(Vector2f start)
DamagingProjectileAPI explode()
boolean isWithinArc(Vector2f point)
float getShieldRadiusEvenIfNoShield()
void setSpawnDebris(boolean spawnDebris)
void setHitpoints(float value)
Vector2f getShieldCenterEvenIfNoShield()
void setForceDisabled(boolean forceDisabled)
boolean hasAIHint(AIHints hint)
Vector2f getFirePoint(int barrel)
default void showNoFragmentSwarmWarning(WeaponAPI w, ShipAPI ship)