diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/Designs.java b/LobbySystem/src/de/steamwar/lobby/particle/design/Designs.java index 69b3ca5e..ede7e6b5 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/design/Designs.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/Designs.java @@ -112,7 +112,14 @@ public class Designs { public ParticleElement build(ParameterValues values, ParticleElement particle) { WingShape shape = values.get(WING_SHAPE); return new Wing(particle, values.get(WING_SIZE), shape.design(values.get(WING_DETAIL)), - values.get(WING_COLORING) == WingColoring.ALONG_WING, values.get(WING_SPARKLE), values.get(WING_MOTION)); + values.get(WING_COLORING) == WingColoring.ALONG_WING, values.get(WING_SPARKLE), values.get(WING_MOTION), + values.get(EntryParameters.TOUCH) == Touches.JUMP_WINGS); + } + + // The wing beat touch makes these wings beat instead of drawing wings of its own + @Override + public boolean absorbsTouch(Touch touch) { + return touch == Touches.JUMP_WINGS; } @Override @@ -133,11 +140,12 @@ public class Designs { @Override public void adjust(Parameter changed, ParameterValues values) { - if (changed != WING_MOTION) return; + if (changed != WING_MOTION && changed != EntryParameters.TOUCH) return; + boolean moving = values.get(WING_MOTION) != Wing.Motion.NONE || values.get(EntryParameters.TOUCH) == Touches.JUMP_WINGS; int interval = values.get(EntryParameters.INTERVAL); - if (values.get(WING_MOTION) != Wing.Motion.NONE && interval > MOVING_WING_INTERVAL) { + if (moving && interval > MOVING_WING_INTERVAL) { values.set(EntryParameters.INTERVAL, MOVING_WING_INTERVAL); - } else if (values.get(WING_MOTION) == Wing.Motion.NONE && interval == MOVING_WING_INTERVAL) { + } else if (!moving && interval == MOVING_WING_INTERVAL) { values.set(EntryParameters.INTERVAL, STILL_WING_INTERVAL); } } diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleDesign.java b/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleDesign.java index ac0b175a..4d834e86 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleDesign.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleDesign.java @@ -73,7 +73,12 @@ public abstract class ParticleDesign { } - // Called after a design setting changed, to adjust others that depend on it + // Whether the design shows the touch itself instead of the touch drawing its own particles + public boolean absorbsTouch(Touch touch) { + return false; + } + + // Called after a setting changed, to adjust others that depend on it public void adjust(Parameter changed, ParameterValues values) { } diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/Touches.java b/LobbySystem/src/de/steamwar/lobby/particle/design/Touches.java index f00e7844..0123c800 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/design/Touches.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/Touches.java @@ -39,13 +39,16 @@ public class Touches { public final Touch NONE = new Touch("none", Material.GRAY_DYE, 0, () -> ParticleRequirement.NO_REQUIRMENT, () -> null); + // On a Wings entry the entry's own wings beat; on others it draws dragon breath wings for the beat + public final Touch JUMP_WINGS = new Touch("jump_wings", Material.DRAGON_BREATH, 2, Unlocks.WARGEAR_SEASON_2022, + () -> new Delayed(new Wing(new SimpleParticle(Particle.DRAGON_BREATH, 0, 0, 0, 0, 1), 0.15, WingDesign.COMPLEX, false, 100, Wing.Motion.JUMP_BEAT), 2)); + private final List ALL = List.of( NONE, // Bursts on jumping, landing or sneaking new Touch("jump_cloud", Material.SNOWBALL, 1, Unlocks.AIRSHIP_PLACEMENT, () -> new EventBurst(EventBurst.Trigger.JUMP, new SimpleParticle(Particle.CLOUD, 0.3F, 0.05F, 0.3F, 0.02, 12))), - new Touch("jump_wings", Material.DRAGON_BREATH, 2, Unlocks.WARGEAR_SEASON_2022, - () -> new Delayed(new Wing(new SimpleParticle(Particle.DRAGON_BREATH, 0, 0, 0, 0, 1), 0.15, WingDesign.COMPLEX, false, 100, Wing.Motion.JUMP_BEAT), 2)), + JUMP_WINGS, new Touch("landing_splash", Material.PRISMARINE_SHARD, 1, Unlocks.UNDERWATER_PLACEMENT, () -> new EventBurst(EventBurst.Trigger.LAND, 1, new Ring(new SimpleParticle(Particle.SPLASH, 0, 0, 0, 0, 3), 1, 16))), new Touch("crash_landing", Material.FEATHER, 1, Unlocks.ABSTURZ_PLACEMENT, diff --git a/LobbySystem/src/de/steamwar/lobby/particle/elements/Wing.java b/LobbySystem/src/de/steamwar/lobby/particle/elements/Wing.java index 6f8ab05f..1f1fd578 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/elements/Wing.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/elements/Wing.java @@ -51,6 +51,8 @@ public class Wing extends DelegatingParticleElement { // Share of the points shown each tick, in percent; below 100 the wing twinkles private int density = 100; private Motion motion = Motion.NONE; + // An extra beat after each jump on top of the motion + private boolean beatOnJump; private double widest; public Wing(ParticleElement particleElement, double size, WingDesign wingDesign) { @@ -69,6 +71,11 @@ public class Wing extends DelegatingParticleElement { } } + public Wing(ParticleElement particleElement, double size, WingDesign wingDesign, boolean colorAlongWing, int density, Motion motion, boolean beatOnJump) { + this(particleElement, size, wingDesign, colorAlongWing, density, motion); + this.beatOnJump = beatOnJump; + } + @Override public void tick(ParticleTickData particleTickData) { if (motion == Motion.JUMP_BEAT && BodyMotion.ticksSinceJump(particleTickData.getPlayer()) > JUMP_BEAT_TICKS) { @@ -108,14 +115,23 @@ public class Wing extends DelegatingParticleElement { private double openDegrees(ParticleTickData particleTickData, double ticks) { double speed = Math.min(1, BodyMotion.speed(particleTickData.getPlayer()) / FULL_OPEN_SPEED); double open = IDLE_OPEN_DEGREES + (MOVING_OPEN_DEGREES - IDLE_OPEN_DEGREES) * speed; + if (beatOnJump) { + open += jumpBeat(particleTickData); + } return switch (motion) { case FLAP_SLOW -> open + FLAP_DEGREES * Math.sin(2 * Math.PI * ticks / 20); case FLAP_FAST -> open + FLAP_DEGREES * Math.sin(2 * Math.PI * ticks / 10); - case JUMP_BEAT -> open + FLAP_DEGREES * Math.sin(Math.PI * BodyMotion.ticksSinceJump(particleTickData.getPlayer()) / JUMP_BEAT_TICKS); + case JUMP_BEAT -> open + jumpBeat(particleTickData); default -> open; }; } + // One swing back and forth during the ticks after a jump + private double jumpBeat(ParticleTickData particleTickData) { + long sinceJump = BodyMotion.ticksSinceJump(particleTickData.getPlayer()); + return sinceJump > JUMP_BEAT_TICKS ? 0 : FLAP_DEGREES * Math.sin(Math.PI * sinceJump / JUMP_BEAT_TICKS); + } + // Full wings never draw a random number, so presets keep their exact look private boolean hidden() { return density < 100 && RANDOM.nextInt(100) >= density; diff --git a/LobbySystem/src/de/steamwar/lobby/particle/slot/ParticleEntry.java b/LobbySystem/src/de/steamwar/lobby/particle/slot/ParticleEntry.java index bd64690e..66d2ca57 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/slot/ParticleEntry.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/slot/ParticleEntry.java @@ -171,6 +171,9 @@ public class ParticleEntry { // The entry's touch with its placement and visibility, or null; touches ignore conditions and timing public ParticleElement buildTouch() { + if (design.absorbsTouch(values.get(TOUCH))) { + return null; + } ParticleElement touch = values.get(TOUCH).element().get(); if (touch == null) { return null; @@ -206,7 +209,8 @@ public class ParticleEntry { // Particle positions spawned per tick, used for the slot budget public double cost() { double perTick = design.usesEntryParticle() ? (double) design.points(values) * amount() : design.points(values); - return perTick / values.get(INTERVAL) + values.get(TOUCH).points(); + int touchPoints = design.absorbsTouch(values.get(TOUCH)) ? 0 : values.get(TOUCH).points(); + return perTick / values.get(INTERVAL) + touchPoints; } public JsonObject toJson() {