1package com.fs.starfarer.api.impl.campaign;
4import java.util.ArrayList;
5import java.util.LinkedHashSet;
8import org.lwjgl.util.vector.Vector2f;
10import com.fs.starfarer.api.Global;
11import com.fs.starfarer.api.campaign.CampaignEngineLayers;
12import com.fs.starfarer.api.campaign.CampaignFleetAPI;
13import com.fs.starfarer.api.campaign.LocationAPI;
14import com.fs.starfarer.api.campaign.SectorEntityToken;
15import com.fs.starfarer.api.combat.ViewportAPI;
16import com.fs.starfarer.api.fleet.FleetMemberAPI;
17import com.fs.starfarer.api.graphics.SpriteAPI;
18import com.fs.starfarer.api.impl.campaign.ids.Stats;
19import com.fs.starfarer.api.impl.campaign.terrain.HyperspaceTerrainPlugin;
20import com.fs.starfarer.api.impl.campaign.terrain.ShoveFleetScript;
21import com.fs.starfarer.api.util.Misc;
22import com.fs.starfarer.api.util.WeightedRandomPicker;
26 public static enum ExplosionFleetDamage {
33 public static class ExplosionParams {
35 public ExplosionFleetDamage damage = ExplosionFleetDamage.NONE;
37 public float durationMult = 1f;
40 public ExplosionParams(Color color,
LocationAPI where, Vector2f loc,
float radius,
float durationMult) {
45 this.durationMult = durationMult;
50 public static class ParticleData {
51 public Vector2f offset =
new Vector2f();
52 public Vector2f vel =
new Vector2f();
53 public float scale = 1f;
54 public float scaleDelta = 1f;
55 public float turnDir = 1f;
56 public float angle = 1f;
61 public float swImpact = 1f;
68 public ParticleData(Color color,
float size,
float maxDur,
float endScale) {
74 angle = (float) Math.random() * 360f;
77 scaleDelta = (endScale - 1f) / maxDur;
80 turnDir = Math.signum((
float) Math.random() - 0.5f) * 10f * (float) Math.random();
85 public void setVelocity(
float direction,
float minSpeed,
float maxSpeed) {
87 vel.scale(minSpeed + (maxSpeed - minSpeed) * (
float) Math.random());
90 public void setOffset(
float direction,
float minDist,
float maxDist) {
92 offset.scale(minDist + (maxDist - minDist) * (
float) Math.random());
95 public void advance(
float amount) {
96 scale += scaleDelta * amount;
97 if (scale < 0) scale = 0f;
99 offset.x += vel.x * amount;
100 offset.y += vel.y * amount;
102 angle += turnDir * amount;
107 public float getBrightness() {
108 float b = 1f - (elapsed / maxDur);
117 protected List<ParticleData>
particles =
new ArrayList<ParticleData>();
131 super.init(
entity, pluginParams);
134 params = (ExplosionParams) pluginParams;
141 float baseSize = params.radius * 0.08f;
144 float fullArea = (float) (Math.PI *
params.radius *
params.radius);
145 float particleArea = (float) (Math.PI * baseSize * baseSize);
147 int count = (int) Math.round(fullArea / particleArea * 1f);
150 durMult =
params.durationMult;
153 for (
int i = 0; i < count; i++) {
154 float size = baseSize * (1f + (float) Math.random());
156 Color randomColor =
new Color(
Misc.
random.nextInt(256),
159 adjustedColor =
params.color;
160 ParticleData data =
new ParticleData(adjustedColor, size,
161 (0.25f + (
float) Math.random()) * 2f * durMult, 3f);
163 float r = (float) Math.random();
164 float dist = params.radius * 0.2f * (0.1f + r * 0.9f);
165 float dir = (float) Math.random() * 360f;
166 data.setOffset(dir, dist, dist);
172 data.swImpact = (float) Math.random();
173 if (i > count / 2) data.swImpact = 1;
178 Vector2f loc =
new Vector2f(
params.loc);
179 loc.x -= params.radius * 0.01f;
180 loc.y += params.radius * 0.01f;
184 loc =
new Vector2f(
params.loc);
210 Object readResolve() {
217 for (ParticleData p :
new ArrayList<ParticleData>(
particles)) {
219 if (p.elapsed >= p.maxDur) {
235 float dist = p.offset.length();
245 float speed = p.vel.length();
246 float dot = Vector2f.dot(p.offset, p.vel);
248 if (speed > threshold) {
249 impact *= threshold / speed;
255 impact *= p.swImpact;
259 p.vel.x += accel.x * amount;
260 p.vel.y += accel.y * amount;
269 if (
params !=
null) extra = params.radius * 3;
277 if (alphaMult <= 0)
return;
294 Vector2f loc =
new Vector2f(x + p.offset.x, y + p.offset.y);
312 if (
params.damage ==
null ||
params.damage == ExplosionFleetDamage.NONE) {
316 float shockwaveDist = 0f;
318 shockwaveDist = Math.max(shockwaveDist, p.offset.length());
322 String
id = fleet.getId();
325 if (dist < shockwaveDist) {
326 float damageMult = 1f - (dist /
params.radius);
327 if (damageMult > 1f) damageMult = 1f;
328 if (damageMult < 0.1f) damageMult = 0.1f;
341 if (members.isEmpty())
return;
343 float totalValue = 0;
345 totalValue += member.getStats().getSuppliesToRecover().getModifiedValue();
347 if (totalValue <= 0)
return;
350 float damageFraction = 0f;
355 damageFraction = 0.1f;
358 damageFraction = 0.3f;
361 damageFraction = 0.6f;
364 damageFraction = 0.9f;
368 damageFraction *= damageMult;
376 float volumeMult = 0.5f + 0.5f * damageFraction;
386 if (member.isFrigate()) w *= 0.1f;
387 if (member.isDestroyer()) w *= 0.2f;
388 if (member.isCruiser()) w *= 0.5f;
389 picker.
add(member, w);
392 int numStrikes = picker.
getItems().size();
394 for (
int i = 0; i < numStrikes; i++) {
396 if (member ==
null)
return;
401 if (suppliesPerDep <= 0 || crPerDep <= 0)
return;
402 float suppliesPer100CR = suppliesPerDep * 1f / Math.max(0.01f, crPerDep);
405 float strikeSupplies = (250f + suppliesPer100CR) * 0.5f * damageFraction;
408 float strikeDamage = strikeSupplies / suppliesPer100CR * (0.75f + (float) Math.random() * 0.5f);
413 strikeDamage *= resistance;
419 if (strikeDamage > 0) {
421 float crDamage = Math.min(currCR, strikeDamage);
425 "Damaged by explosion");
430 int numHits = (int) (strikeDamage / 0.1f);
431 if (numHits < 1) numHits = 1;
432 for (
int j = 0; j < numHits; j++) {
static SettingsAPI getSettings()
static SoundPlayerAPI getSoundPlayer()
static SectorAPI getSector()
float computeEffective(float baseValue)
List< ParticleData > particles
void render(CampaignEngineLayers layer, ViewportAPI viewport)
LinkedHashSet< String > damagedAlready
void init(SectorEntityToken entity, Object pluginParams)
void applyDamageToFleets()
transient SpriteAPI sprite
void advance(float amount)
void applyDamageToFleet(CampaignFleetAPI fleet, float damageMult)
static final String CORONA_EFFECT_MULT
static float STORM_STRIKE_SOUND_RANGE
static float STORM_MAX_STRIKE_DAMAGE
static Vector2f getUnitVectorAtDegreeAngle(float degrees)
static Color getNegativeHighlightColor()
static final Vector2f ZERO
static float getDistance(SectorEntityToken from, SectorEntityToken to)
static Color interpolateColor(Color from, Color to, float progress)
static float getAngleInDegrees(Vector2f v)
void setWeight(int index, float weight)
SpriteAPI getSprite(String filename)
SoundAPI playSound(String id, float pitch, float volume, Vector2f loc, Vector2f vel)
FleetDataAPI getFleetData()
boolean isInCurrentLocation()
void addMessage(String text)
List< FleetMemberAPI > getMembersListCopy()
void addHitParticle(Vector2f loc, Vector2f vel, float size, float brightness, float duration, Color color)
boolean isCurrentLocation()
List< CampaignFleetAPI > getFleets()
CampaignFleetAPI getPlayerFleet()
CampaignUIAPI getCampaignUI()
LocationAPI getContainingLocation()
float getSensorContactFaderBrightness()
void setExpired(boolean expired)
void addScript(EveryFrameScript script)
float getSensorFaderBrightness()
StatBonus getArmorBonus()
DynamicStatsAPI getDynamic()
MutableStat getSuppliesToRecover()
FleetMemberStatusAPI getStatus()
RepairTrackerAPI getRepairTracker()
ShipHullSpecAPI getHullSpec()
MutableShipStatsAPI getStats()
void applyDamage(float hitStrength)
void setHullFraction(float fraction)
void applyCREvent(float crChange, String description)
void setSize(float width, float height)
void setTexWidth(float texWidth)
void setAngle(float angle)
void renderAtCenter(float x, float y)
void setColor(Color color)
void setAlphaMult(float alphaMult)
void setTexHeight(float texHeight)
float getValue(String id)