Starsector API
Loading...
Searching...
No Matches
ChiralFigmentStats.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.combat;
2
3import java.awt.Color;
4import java.util.HashMap;
5import java.util.List;
6import java.util.Map;
7
8import org.lwjgl.util.vector.Vector2f;
9
10import com.fs.starfarer.api.Global;
11import com.fs.starfarer.api.characters.PersonAPI;
12import com.fs.starfarer.api.combat.BaseEveryFrameCombatPlugin;
13import com.fs.starfarer.api.combat.CollisionClass;
14import com.fs.starfarer.api.combat.CombatEngineAPI;
15import com.fs.starfarer.api.combat.CombatEntityAPI;
16import com.fs.starfarer.api.combat.CombatFleetManagerAPI;
17import com.fs.starfarer.api.combat.MutableShipStatsAPI;
18import com.fs.starfarer.api.combat.ShipAPI;
19import com.fs.starfarer.api.combat.ShipCommand;
20import com.fs.starfarer.api.combat.listeners.ApplyDamageResultAPI;
21import com.fs.starfarer.api.combat.listeners.DamageListener;
22import com.fs.starfarer.api.impl.campaign.ids.Personalities;
23import com.fs.starfarer.api.impl.campaign.ids.Skills;
24import com.fs.starfarer.api.impl.hullmods.ShardSpawner;
25import com.fs.starfarer.api.input.InputEventAPI;
26import com.fs.starfarer.api.loading.FighterWingSpecAPI;
27import com.fs.starfarer.api.util.Misc;
28
30
31 public static Map<String, String> FIGMENTS = new HashMap<String, String>();
32 static {
33 FIGMENTS.put("shard_left_Attack", "shard_right_Attack");
34 FIGMENTS.put("shard_left_Attack2", "shard_right_Attack");
35 FIGMENTS.put("shard_right_Attack", "shard_left_Attack");
36 FIGMENTS.put("shard_left_Armorbreaker", "shard_right_Attack");
37 FIGMENTS.put("shard_left_Shieldbreaker", "shard_right_Shieldbreaker");
38 FIGMENTS.put("shard_right_Shieldbreaker", "shard_left_Shieldbreaker");
39 FIGMENTS.put("shard_left_Defense", "shard_right_Shock");
40 FIGMENTS.put("shard_right_Shock", "shard_left_Defense");
41 FIGMENTS.put("shard_left_Missile", "shard_right_Missile");
42 FIGMENTS.put("shard_right_Missile", "shard_left_Missile");
43 }
44
45 public static final Color JITTER_COLOR = ShardSpawner.JITTER_COLOR;
46 public static final Color JITTER_UNDER_COLOR = Misc.setAlpha(JITTER_COLOR, 155);
47
48
49 public static float DAMAGE_TAKEN_MULT = 1f;
50 public static float JITTER_PER_DAMAGE_DIVISOR = 100f;
51 public static float JITTER_PER_DAMAGE_DECAY_SECONDS = 1f;
52
53
54 public static float getSpawnAngle(ShipAPI ship) {
55 String variant = FIGMENTS.get(ship.getVariant().getHullVariantId());
56 if (ship.getVariant().getOriginalVariant() != null && variant == null) {
57 variant = FIGMENTS.get(ship.getVariant().getOriginalVariant());
58 }
59 if (variant != null && variant.contains("_left")) {
60 return 90f;
61 }
62 return -90f;
63 }
64
65 public void apply(MutableShipStatsAPI stats, String id, State state, float effectLevel) {
66 ShipAPI ship = null;
67 //boolean player = false;
68 if (stats.getEntity() instanceof ShipAPI) {
69 ship = (ShipAPI) stats.getEntity();
70 } else {
71 return;
72 }
73
74
75 float jitterLevel = effectLevel;
76 if (state == State.OUT) {
77 jitterLevel *= jitterLevel;
78 }
79 float maxRangeBonus = 25f;
80 float jitterRangeBonus = jitterLevel * maxRangeBonus;
81 if (state == State.OUT) {
82 }
83
84 ship.setJitterUnder(this, JITTER_UNDER_COLOR, jitterLevel, 11, 0f, 3f + jitterRangeBonus);
85 ship.setJitter(this, JITTER_COLOR, jitterLevel, 4, 0f, 0 + jitterRangeBonus);
86
87 if (state == State.IN) {
88 } else if (effectLevel >= 1) {
89 String variant = FIGMENTS.get(ship.getVariant().getHullVariantId());
90 if (ship.getVariant().getOriginalVariant() != null && variant == null) {
91 variant = FIGMENTS.get(ship.getVariant().getOriginalVariant());
92 }
93 if (variant != null) {
94 float angle = getSpawnAngle(ship);
95 float dist = ship.getCollisionRadius() * 1.25f;
96 Vector2f loc = Misc.getUnitVectorAtDegreeAngle(ship.getFacing() + angle);
97 loc.scale(dist);
98 Vector2f.add(loc, ship.getLocation(), loc);
99 if (isLocationClear(ship, loc, dist / 2f)) {
100 FigmentPlugin figment = new FigmentPlugin(variant, ship, 1f, 20f, loc);
101 Global.getCombatEngine().addPlugin(figment);
102 }
103 }
104 } else if (state == State.OUT ) {
105 }
106 }
107
108
109 public void unapply(MutableShipStatsAPI stats, String id) {
110 }
111
112
113 private boolean isLocationClear(ShipAPI ship, Vector2f loc, float minDist) {
114 for (ShipAPI other : Global.getCombatEngine().getShips()) {
115 if (other.isShuttlePod()) continue;
116 if (other.isFighter()) continue;
117 if (other == ship) continue;
118
119 Vector2f otherLoc = other.getShieldCenterEvenIfNoShield();
120 float otherR = other.getShieldRadiusEvenIfNoShield();
121
122
123 float dist = Misc.getDistance(loc, otherLoc);
124 float r = otherR;
125 if (dist < r + minDist) {
126 return false;
127 }
128 }
129 for (CombatEntityAPI other : Global.getCombatEngine().getAsteroids()) {
130 float dist = Misc.getDistance(loc, other.getLocation());
131 if (dist < other.getCollisionRadius() + minDist) {
132 return false;
133 }
134 }
135
136 return true;
137 }
138
139 public static class FigmentDamageListener implements DamageListener {
140 public FigmentPlugin plugin;
141 public FigmentDamageListener(FigmentPlugin plugin) {
142 this.plugin = plugin;
143 }
144
145 public void reportDamageApplied(Object source, CombatEntityAPI target, ApplyDamageResultAPI result) {
146 float totalDamage = result.getDamageToHull() + result.getDamageToShields() + result.getTotalDamageToArmor();
147 //plugin.recentHits += totalDamage / JITTER_PER_DAMAGE_DIVISOR;
148 float max = 1f;
149 if (result.isDps()) max = 0.1f;
150 plugin.recentHits += Math.min(max, totalDamage / 10f);
151 }
152 }
153 public static class FigmentPlugin extends BaseEveryFrameCombatPlugin {
154 float elapsed = 0f;
155 ShipAPI [] ships = null;
156 CollisionClass collisionClass;
157
158 String variantId;
159 ShipAPI source;
160 float fadeInTime;
161 Vector2f loc;
162 float dur;
163
164 boolean finishedFadingIn = false;
165
166 float recentHits = 0f;
167
168 public FigmentPlugin(String variantId, ShipAPI source, float fadeInTime, float dur, Vector2f loc) {
169 this.variantId = variantId;
170 this.source = source;
171 this.fadeInTime = fadeInTime;
172 this.dur = dur;
173 this.loc = loc;
174 }
175
176
177 @Override
178 public void advance(float amount, List<InputEventAPI> events) {
179 if (Global.getCombatEngine().isPaused()) return;
180
181 elapsed += amount;
182
183 CombatEngineAPI engine = Global.getCombatEngine();
184
185 if (ships == null) {
186 float facing = source.getFacing() + 15f * ((float) Math.random() - 0.5f);
187 CombatFleetManagerAPI fleetManager = engine.getFleetManager(source.getOriginalOwner());
188 boolean wasSuppressed = fleetManager.isSuppressDeploymentMessages();
189 fleetManager.setSuppressDeploymentMessages(true);
190 if (variantId.endsWith("_wing")) {
191 FighterWingSpecAPI spec = Global.getSettings().getFighterWingSpec(variantId);
192 ships = new ShipAPI[spec.getNumFighters()];
193 PersonAPI captain = Global.getSettings().createPerson();
194 captain.setPersonality(Personalities.RECKLESS); // doesn't matter for fighters
195 captain.getStats().setSkillLevel(Skills.POINT_DEFENSE, 2);
196 captain.getStats().setSkillLevel(Skills.GUNNERY_IMPLANTS, 2);
197 captain.getStats().setSkillLevel(Skills.IMPACT_MITIGATION, 2);
198 ShipAPI leader = engine.getFleetManager(source.getOriginalOwner()).spawnShipOrWing(variantId, loc, facing, 0f, captain);
199 for (int i = 0; i < ships.length; i++) {
200 ships[i] = leader.getWing().getWingMembers().get(i);
201 ships[i].getLocation().set(loc);
202 }
203 collisionClass = ships[0].getCollisionClass();
204 } else {
205 ships = new ShipAPI[1];
206 ships[0] = engine.getFleetManager(source.getOriginalOwner()).spawnShipOrWing(variantId, loc, facing, 0f, source.getOriginalCaptain());
207 }
208 fleetManager.setSuppressDeploymentMessages(wasSuppressed);
209 collisionClass = ships[0].getCollisionClass();
210 }
211
212
213 float progress = elapsed / fadeInTime;
214
215 float maxAlpha = 0.67f;
216 if (progress <= 1f) {
217 for (int i = 0; i < ships.length; i++) {
218 ShipAPI ship = ships[i];
219 ship.setAlphaMult(progress * maxAlpha);
220
221 if (progress < 0.5f) {
222 ship.blockCommandForOneFrame(ShipCommand.ACCELERATE);
223 ship.blockCommandForOneFrame(ShipCommand.TURN_LEFT);
224 ship.blockCommandForOneFrame(ShipCommand.TURN_RIGHT);
225 ship.blockCommandForOneFrame(ShipCommand.STRAFE_LEFT);
226 ship.blockCommandForOneFrame(ShipCommand.STRAFE_RIGHT);
227 }
228
229 ship.blockCommandForOneFrame(ShipCommand.USE_SYSTEM);
230 ship.blockCommandForOneFrame(ShipCommand.TOGGLE_SHIELD_OR_PHASE_CLOAK);
231 ship.blockCommandForOneFrame(ShipCommand.FIRE);
232 ship.blockCommandForOneFrame(ShipCommand.PULL_BACK_FIGHTERS);
233 ship.blockCommandForOneFrame(ShipCommand.VENT_FLUX);
234 ship.setHoldFireOneFrame(true);
235 ship.setHoldFire(true);
236
237
238 ship.setCollisionClass(CollisionClass.NONE);
239 ship.getMutableStats().getHullDamageTakenMult().modifyMult("FigmentInvuln", 0f);
240 if (progress < 0.5f) {
241 ship.getVelocity().set(source.getVelocity());
242 } else if (progress > 0.75f){
243 ship.setCollisionClass(collisionClass);
244 ship.getMutableStats().getHullDamageTakenMult().unmodifyMult("FigmentInvuln");
245 }
246
247 float jitterLevel = progress;
248// if (jitterLevel < 0.5f) {
249// jitterLevel *= 2f;
250// } else {
251// jitterLevel = (1f - jitterLevel) * 2f;
252// }
253
254 float jitterRange = 1f - progress * 0.5f;
255 float maxRangeBonus = 50f;
256 maxRangeBonus -= 30f * progress;
257 float jitterRangeBonus = jitterRange * maxRangeBonus;
258 Color c = JITTER_COLOR;
259 float num = 18f * (1f - progress * progress) + 7f;
260
261 ship.setJitter(this, c, jitterLevel, (int)Math.round(num), 0f, jitterRangeBonus);
262 }
263 }
264
265 if (elapsed > fadeInTime && !finishedFadingIn) {
266 for (int i = 0; i < ships.length; i++) {
267 ShipAPI ship = ships[i];
268 ship.setAlphaMult(maxAlpha);
269 ship.setHoldFire(false);
270 ship.setCollisionClass(collisionClass);
271 ship.getMutableStats().getHullDamageTakenMult().unmodifyMult("FigmentInvuln");
272
274 ship.getMutableStats().getHullDamageTakenMult().modifyMult("FigmentExtraDamage", DAMAGE_TAKEN_MULT);
275 ship.getMutableStats().getShieldDamageTakenMult().modifyMult("FigmentExtraDamage", DAMAGE_TAKEN_MULT);
276 ship.getMutableStats().getArmorDamageTakenMult().modifyMult("FigmentExtraDamage", DAMAGE_TAKEN_MULT);
277
278 ship.addListener(new FigmentDamageListener(this));
279 }
280 finishedFadingIn = true;
281 }
282
283 if (elapsed > fadeInTime) {
284 for (int i = 0; i < ships.length; i++) {
285 ShipAPI ship = ships[i];
286
287 if (!ship.isAlive() || !engine.isInPlay(ship)) {
288 engine.removePlugin(this);
289 return;
290 }
291
292 ship.setAlphaMult(maxAlpha);
293 ship.blockCommandForOneFrame(ShipCommand.USE_SYSTEM);
294 ship.blockCommandForOneFrame(ShipCommand.TOGGLE_SHIELD_OR_PHASE_CLOAK);
295
296
297 //float minus = recentHits * amount / JITTER_PER_DAMAGE_DECAY_SECONDS;
298 float minus = recentHits * amount * 2f;
299 minus += 0.1f * amount;
300 recentHits -= minus;
301 if (recentHits < 0) recentHits = 0;
302 if (recentHits > 5f) recentHits = 5f;
303
304 float jitterLevel = 1f;
305 float jitterRange = 0.5f;
306 float maxRangeBonus = 50f;
307 maxRangeBonus = 20f;
308 maxRangeBonus += recentHits * 40f;
309 float jitterRangeBonus = jitterRange * maxRangeBonus;
310 Color c = JITTER_COLOR;
311
312 float numCopies = 7f;
313 numCopies += recentHits * 2f;
314
315 ship.setJitter(this, c, jitterLevel, (int) Math.round(numCopies), 0f, jitterRangeBonus);
316 }
317 }
318
319 if (elapsed > dur) {
320 // destroy ship here?
321 //engine.removePlugin(this);
322 }
323 }
324 }
325
326}
327
328
329
330
331
332
333
334
static CombatEngineAPI getCombatEngine()
Definition Global.java:63
void apply(MutableShipStatsAPI stats, String id, State state, float effectLevel)
void unapply(MutableShipStatsAPI stats, String id)