Ahh, I see. Fixed.
The fix sure got ugly... problem was that dpsDuration is being reset every frame (by the beam), while a fast-time ship's beam effect plugin might run several times per frame. Normally dpsDuration would be something like 0, 0, 0, 0, 0.1, 0, 0, etc (beams doing damage at 0.1 second intervals), but for a fast-time ship it'd do a bunch of the .1 frames in a row. Which would be fine, except the beam is also running 3x faster, sort of mimicking ship-time in engine-time, to ensure it does the right amount of damage, i.e. based on ship-time.
Can't fix it by advancing beams in ship-time due to the order of calls being important. And advancing beams multiple times in fast-time - instead of once in engine-time, but with a ship-time multiplier - would get pretty involved too, on the engine side - that's the "right" fix, and doable, but would take a while to make sure it was right. Hence this abomination. Sigh.
In conclusion, messing with time messes with my mind.
Spoiler
public class TachyonLanceEffect implements BeamEffectPlugin {
private IntervalUtil fireInterval = new IntervalUtil(0.2f, 0.3f);
private boolean wasZero = true;
public void advance(float amount, CombatEngineAPI engine, BeamAPI beam) {
CombatEntityAPI target = beam.getDamageTarget();
if (target instanceof ShipAPI && beam.getBrightness() >= 1f) {
float dur = beam.getDamage().getDpsDuration();
// needed because when the ship is in fast-time, dpsDuration will not be reset every frame as it should be
if (!wasZero) dur = 0;
wasZero = beam.getDamage().getDpsDuration() <= 0;
fireInterval.advance(dur);
if (fireInterval.intervalElapsed()) {
ShipAPI ship = (ShipAPI) target;
boolean hitShield = target.getShield() != null && target.getShield().isWithinArc(beam.getTo());
float pierceChance = ((ShipAPI)target).getHardFluxLevel() - 0.1f;
pierceChance *= ship.getMutableStats().getDynamic().getValue(Stats.SHIELD_PIERCED_MULT);
boolean piercedShield = hitShield && (float) Math.random() < pierceChance;
//piercedShield = true;
if (!hitShield || piercedShield) {
Vector2f dir = Vector2f.sub(beam.getTo(), beam.getFrom(), new Vector2f());
if (dir.lengthSquared() > 0) dir.normalise();
dir.scale(50f);
Vector2f point = Vector2f.sub(beam.getTo(), dir, new Vector2f());
float emp = beam.getWeapon().getDamage().getFluxComponent() * 0.5f;
float dam = beam.getWeapon().getDamage().getDamage() * 0.25f;
engine.spawnEmpArcPierceShields(
beam.getSource(), point, beam.getDamageTarget(), beam.getDamageTarget(),
DamageType.ENERGY,
dam, // damage
emp, // emp
100000f, // max range
"tachyon_lance_emp_impact",
beam.getWidth() + 5f,
beam.getFringeColor(),
beam.getCoreColor()
);
}
}
}
}
}
Edit: and, I almost forgot to undo one of the Scarab's slots being large to test this. That would be a really fun one to completely forget about and make the next release with.