diff --git a/LobbySystem/src/de/steamwar/lobby/LobbySystem.properties b/LobbySystem/src/de/steamwar/lobby/LobbySystem.properties index e60bb545..b69d53b6 100644 --- a/LobbySystem/src/de/steamwar/lobby/LobbySystem.properties +++ b/LobbySystem/src/de/steamwar/lobby/LobbySystem.properties @@ -116,6 +116,7 @@ PARTICLE_SLOT_COST = §7Particles per tick§8: §e{0}§8/§7{1} PARTICLE_ENTRY_EDITOR = §0{0} PARTICLE_ENTRY_DESIGN = §7Design§8: {0} PARTICLE_ENTRY_PARTICLE = §7Particle§8: {0} +PARTICLE_ENTRY_TOUCH = §7Touch§8: {0} PARTICLE_ENTRY_LOCKED = §cDesign locked, not shown PARTICLE_ENTRY_COST = §7Particles per tick§8: §e{0} PARTICLE_ENTRY_COST_SHARE = §7This entry§8: §e{0} @@ -137,6 +138,7 @@ PARTICLE_DESIGN_WING = §fWings PARTICLE_DESIGN_CLOUD = §fCloud PARTICLE_PARAM_PARTICLE = §fParticle +PARTICLE_PARAM_TOUCH = §fTouch PARTICLE_PARAM_COUNT = §fAmount PARTICLE_PARAM_SPREAD_X = §fSpread X PARTICLE_PARAM_SPREAD_Y = §fSpread Y @@ -198,6 +200,27 @@ PARTICLE_CHOICE_IMAGE_SWORD = §fSword PARTICLE_CHOICE_IMAGE_BAT = §fBat PARTICLE_CHOICE_IMAGE_BUTTERFLY = §fButterfly PARTICLE_CHOICE_IMAGE_FAIRY = §fFairy +PARTICLE_CHOICE_IMAGE_MWGL = §fMiniWarGear League +PARTICLE_CHOICE_IMAGE_SW = §fSteamWar +PARTICLE_CHOICE_IMAGE_WGS = §fWarGear Season +PARTICLE_CHOICE_IMAGE_SWORD_CROSSED = §fCrossed Swords +PARTICLE_CHOICE_TOUCH_NONE = §7None +PARTICLE_CHOICE_TOUCH_JUMP_CLOUD = §fCloud puff on jumping +PARTICLE_CHOICE_TOUCH_JUMP_WINGS = §5Wing beat on jumping +PARTICLE_CHOICE_TOUCH_LANDING_SPLASH = §bSplash on landing +PARTICLE_CHOICE_TOUCH_CRASH_LANDING = §cCrash landing +PARTICLE_CHOICE_TOUCH_LAVA_LANDING = §6Lava on landing +PARTICLE_CHOICE_TOUCH_OBSIDIAN_LANDING = §5Obsidian tears on landing +PARTICLE_CHOICE_TOUCH_GLYPH_BURST = §dGlyph burst on sneaking +PARTICLE_CHOICE_TOUCH_WET_FOOTPRINTS = §bWet footprints +PARTICLE_CHOICE_TOUCH_CLOUD_FOOTPRINTS = §fCloud footprints +PARTICLE_CHOICE_TOUCH_BLOSSOM_FOOTPRINTS = §aBlossom footprints +PARTICLE_CHOICE_TOUCH_WATER_LINK = §bWater link to others with it +PARTICLE_CHOICE_TOUCH_BUBBLE_LINK = §3Bubble link to others with it +PARTICLE_CHOICE_TOUCH_GLYPH_PULL = §dGlyphs while standing still +PARTICLE_CHOICE_TOUCH_STILL_SHIMMER = §3Shimmer while standing still +PARTICLE_CHOICE_TOUCH_HEARTBEAT = §cHeartbeat while standing still +PARTICLE_CHOICE_TOUCH_DECEMBER_SNOW = §fSnow in December PARTICLE_CHOICE_COLORING_OVER_TIME = §fChange over time PARTICLE_CHOICE_COLORING_ALONG_WING = §fFrom the back to the tips PARTICLE_CHOICE_MOTION_NONE = §fNone @@ -373,21 +396,11 @@ PARTICLE_TEAM_PULSE_LOGO = §fPulse Logo PARTICLE_TEAM_PULSE_HEART_BEAT = §cHeart Beat PARTICLE_EVENT_ENCHANTING = §cEnchantment -PARTICLE_EVENT_CLOUD = §fClouds -PARTICLE_EVENT_SMOKE = §7Smoke -PARTICLE_EVENT_WATER = §bWater -PARTICLE_EVENT_LAVA = §cLava -PARTICLE_EVENT_WINGS = §fWings PARTICLE_EVENT_RAIN_CLOUD = §fRandom Raincloud -PARTICLE_EVENT_WGS = §fWGS -PARTICLE_EVENT_WARGEARCLASH = §fClash -PARTICLE_EGG_HUNT_EASY = §aGreenery PARTICLE_EGG_HUNT_MEDIUM = §eHide and Seek PARTICLE_EGG_HUNT_HARD = §cOrbit -PARTICLE_EGG_HUNT_EXTREME = §5Purple rain PARTICLE_EGG_HUNT_ADVANCED = §5Lift off -PARTICLE_EGG_HUNT_HALF = §fThe hunt is on JUMP_AND_RUN_PROGRESS = §e{0}§8/§f{1} §c{2} §7{3} JUMP_AND_RUN_CANCEL = {0} diff --git a/LobbySystem/src/de/steamwar/lobby/LobbySystem_de.properties b/LobbySystem/src/de/steamwar/lobby/LobbySystem_de.properties index d87f72f0..6130a069 100644 --- a/LobbySystem/src/de/steamwar/lobby/LobbySystem_de.properties +++ b/LobbySystem/src/de/steamwar/lobby/LobbySystem_de.properties @@ -116,6 +116,7 @@ PARTICLE_SLOT_COST = §7Partikel pro Tick§8: §e{0}§8/§7{1} PARTICLE_ENTRY_EDITOR = §0{0} PARTICLE_ENTRY_DESIGN = §7Design§8: {0} PARTICLE_ENTRY_PARTICLE = §7Partikel§8: {0} +PARTICLE_ENTRY_TOUCH = §7Akzent§8: {0} PARTICLE_ENTRY_LOCKED = §cDesign gesperrt, wird nicht angezeigt PARTICLE_ENTRY_COST = §7Partikel pro Tick§8: §e{0} PARTICLE_ENTRY_COST_SHARE = §7Dieser Eintrag§8: §e{0} @@ -137,6 +138,7 @@ PARTICLE_DESIGN_WING = §fFlügel PARTICLE_DESIGN_CLOUD = §fWolke PARTICLE_PARAM_PARTICLE = §fPartikel +PARTICLE_PARAM_TOUCH = §fAkzent PARTICLE_PARAM_COUNT = §fAnzahl PARTICLE_PARAM_SPREAD_X = §fStreuung X PARTICLE_PARAM_SPREAD_Y = §fStreuung Y @@ -198,6 +200,27 @@ PARTICLE_CHOICE_IMAGE_SWORD = §fSchwert PARTICLE_CHOICE_IMAGE_BAT = §fFledermaus PARTICLE_CHOICE_IMAGE_BUTTERFLY = §fSchmetterling PARTICLE_CHOICE_IMAGE_FAIRY = §fFee +PARTICLE_CHOICE_IMAGE_MWGL = §fMiniWarGear Liga +PARTICLE_CHOICE_IMAGE_SW = §fSteamWar +PARTICLE_CHOICE_IMAGE_WGS = §fWarGear Saison +PARTICLE_CHOICE_IMAGE_SWORD_CROSSED = §fGekreuzte Schwerter +PARTICLE_CHOICE_TOUCH_NONE = §7Keiner +PARTICLE_CHOICE_TOUCH_JUMP_CLOUD = §fWolke beim Springen +PARTICLE_CHOICE_TOUCH_JUMP_WINGS = §5Flügelschlag beim Springen +PARTICLE_CHOICE_TOUCH_LANDING_SPLASH = §bSpritzer beim Landen +PARTICLE_CHOICE_TOUCH_CRASH_LANDING = §cBruchlandung +PARTICLE_CHOICE_TOUCH_LAVA_LANDING = §6Lava beim Landen +PARTICLE_CHOICE_TOUCH_OBSIDIAN_LANDING = §5Obsidiantränen beim Landen +PARTICLE_CHOICE_TOUCH_GLYPH_BURST = §dGlyphen beim Schleichen +PARTICLE_CHOICE_TOUCH_WET_FOOTPRINTS = §bNasse Fußspuren +PARTICLE_CHOICE_TOUCH_CLOUD_FOOTPRINTS = §fWolkenfußspuren +PARTICLE_CHOICE_TOUCH_BLOSSOM_FOOTPRINTS = §aBlütenfußspuren +PARTICLE_CHOICE_TOUCH_WATER_LINK = §bWasserband zu anderen damit +PARTICLE_CHOICE_TOUCH_BUBBLE_LINK = §3Blasenband zu anderen damit +PARTICLE_CHOICE_TOUCH_GLYPH_PULL = §dGlyphen im Stillstand +PARTICLE_CHOICE_TOUCH_STILL_SHIMMER = §3Schimmer im Stillstand +PARTICLE_CHOICE_TOUCH_HEARTBEAT = §cHerzschlag im Stillstand +PARTICLE_CHOICE_TOUCH_DECEMBER_SNOW = §fSchnee im Dezember PARTICLE_CHOICE_COLORING_OVER_TIME = §fWechseln mit der Zeit PARTICLE_CHOICE_COLORING_ALONG_WING = §fVom Rücken zu den Spitzen PARTICLE_CHOICE_MOTION_NONE = §fKeine @@ -362,21 +385,11 @@ PARTICLE_PLAYER_10697_AURA = §7Rauchgranate PARTICLE_TEAM_PULSE_HEART_BEAT = §cHerzschlag PARTICLE_EVENT_ENCHANTING = §cVerzaubert -PARTICLE_EVENT_CLOUD = §fWolken -PARTICLE_EVENT_SMOKE = §7Rauch -PARTICLE_EVENT_WATER = §bWasser -PARTICLE_EVENT_LAVA = §cLava -PARTICLE_EVENT_WINGS = §fFlügel PARTICLE_EVENT_RAIN_CLOUD = §fRegenwolke -PARTICLE_EVENT_WGS = §fWGS -PARTICLE_EVENT_WARGEARCLASH = §fClash -PARTICLE_EGG_HUNT_EASY = §aGrünplfanzen PARTICLE_EGG_HUNT_MEDIUM = §eVersteckspiel PARTICLE_EGG_HUNT_HARD = §cOrbit -PARTICLE_EGG_HUNT_EXTREME = §5Lila regen PARTICLE_EGG_HUNT_ADVANCED = §5Abheben -PARTICLE_EGG_HUNT_HALF = §fDie Jagd ist eröffnet JUMP_AND_RUN_FINISHED = §aBeendet in {0} mit {1} Fails JUMP_AND_RUN_PERSONAL_BEST = §aNice! Du hast deinen Rekord um {0} verbessert! diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/Designs.java b/LobbySystem/src/de/steamwar/lobby/particle/design/Designs.java index 9b3b6a66..69b3ca5e 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/design/Designs.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/Designs.java @@ -75,10 +75,10 @@ public class Designs { new ChoiceParameter.Choice<>("butterfly", WingShape.drawn(DrawnWings.BUTTERFLY, Material.PINK_PETALS), false), new ChoiceParameter.Choice<>("fairy", WingShape.drawn(DrawnWings.FAIRY, Material.ALLAY_SPAWN_EGG), false), // Tournament wing images, unlocked by the placement that earns their reward - new ChoiceParameter.Choice<>("mwgl", WingShape.image(WingDesign.MWGL, Material.IRON_SWORD), false, () -> RewardDesigns.EVENT_PLACEMENT_MINI_WARGEAR_LIGA.getRequirement()), - new ChoiceParameter.Choice<>("sw", WingShape.image(WingDesign.SW, Material.CYAN_CARPET), false, () -> RewardDesigns.EVENT_PLACEMENT_UNDERWATER_MWG.getRequirement()), - new ChoiceParameter.Choice<>("wgs", WingShape.image(WingDesign.WGS, Material.DIAMOND_HELMET), false, () -> RewardDesigns.EVENT_PLACEMENT_WARGEAR_SEASON_2022.getRequirement()), - new ChoiceParameter.Choice<>("sword_crossed", WingShape.image(WingDesign.SWORD_CROSSED, Material.GOLDEN_SWORD), false, () -> RewardDesigns.EVENT_PLACEMENT_WARGEAR_CLASH.getRequirement()), + new ChoiceParameter.Choice<>("mwgl", WingShape.image(WingDesign.MWGL, Material.IRON_SWORD), false, Unlocks.MINI_WARGEAR_LIGA_PLACEMENT), + new ChoiceParameter.Choice<>("sw", WingShape.image(WingDesign.SW, Material.CYAN_CARPET), false, Unlocks.UNDERWATER_MWG_PLACEMENT), + new ChoiceParameter.Choice<>("wgs", WingShape.image(WingDesign.WGS, Material.DIAMOND_HELMET), false, Unlocks.WARGEAR_SEASON_2022_PLACEMENT), + new ChoiceParameter.Choice<>("sword_crossed", WingShape.image(WingDesign.SWORD_CROSSED, Material.GOLDEN_SWORD), false, Unlocks.WARGEAR_CLASH_PLACEMENT), new ChoiceParameter.Choice<>("eclipse", WingShape.image(WingDesign.ECLIPSE), true), new ChoiceParameter.Choice<>("pl", WingShape.image(WingDesign.PL), true), new ChoiceParameter.Choice<>("plompa_easter", WingShape.image(WingDesign.PlompaEasterWings), true), diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/EntryParameters.java b/LobbySystem/src/de/steamwar/lobby/particle/design/EntryParameters.java index 29ba76e0..b3c757dc 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/design/EntryParameters.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/EntryParameters.java @@ -204,8 +204,10 @@ public class EntryParameters { public final ChoiceParameter SNEAK = ChoiceParameter.ofEnum("sneak", "PARTICLE_PARAM_SNEAK", Sneak.ANY); public final ChoiceParameter VISIBILITY = ChoiceParameter.ofEnum("visibility", "PARTICLE_PARAM_VISIBILITY", Visibility.EVERYONE); + public final ChoiceParameter TOUCH = new ChoiceParameter<>("touch", "PARTICLE_PARAM_TOUCH", Touches.NONE, Touches.choices()); + public final List> ALL = List.of( - PARTICLE, COUNT, SPREAD_X, SPREAD_Y, SPREAD_Z, SPEED, COLORS, BLOCK, + TOUCH, PARTICLE, COUNT, SPREAD_X, SPREAD_Y, SPREAD_Z, SPEED, COLORS, BLOCK, TRAIL_DURATION, TRAIL_TARGET_X, TRAIL_TARGET_Y, TRAIL_TARGET_Z, OFFSET_X, OFFSET_Y, OFFSET_Z, PLACEMENT, INTERVAL, TICK_MODE, MOVEMENT, GLIDING, GROUND, SNEAK, VISIBILITY diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/FixedDesign.java b/LobbySystem/src/de/steamwar/lobby/particle/design/FixedDesign.java index 8e8f552d..48d9e49b 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/design/FixedDesign.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/FixedDesign.java @@ -32,8 +32,6 @@ public class FixedDesign extends ParticleDesign { private final int points; private final Consumer defaults; private final Supplier shape; - private Supplier touch; - private int touchPoints; public FixedDesign(String id, Material icon, String nameKey, ParticleRequirement requirement, int points, Consumer defaults, Supplier shape) { super(id, icon, nameKey, DesignVisibility.REWARD, requirement); @@ -47,21 +45,9 @@ public class FixedDesign extends ParticleDesign { return shape.get(); } - // Adds the reward's unique touch; its points count towards the slot budget - public FixedDesign withTouch(int touchPoints, Supplier touch) { - this.touchPoints = touchPoints; - this.touch = touch; - return this; - } - - @Override - public ParticleElement touch() { - return touch == null ? null : touch.get(); - } - @Override public int points(ParameterValues values) { - return points + touchPoints; + return points; } @Override diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleDesign.java b/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleDesign.java index 1c74f090..ac0b175a 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleDesign.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleDesign.java @@ -72,11 +72,6 @@ public abstract class ParticleDesign { return false; } - // An extra the builder cannot make, shown next to the design's look and checked every tick so it never misses - // a jump or landing; null for designs without one - public ParticleElement touch() { - return null; - } // Called after a design 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/ParticleType.java b/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleType.java index de64fe61..dc9e6826 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleType.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleType.java @@ -185,7 +185,7 @@ public enum ParticleType { public ParticleRequirement getRequirement() { return switch (this) { case CHERRY_LEAVES, PALE_OAK_LEAVES, TINTED_LEAVES -> ParticleRequirement.SERVER_TEAM; - case CAMPFIRE_COSY_SMOKE -> RewardDesigns.EVENT_PARTICIPATION_HELLS_BELLS.getRequirement(); + case CAMPFIRE_COSY_SMOKE -> Unlocks.HELLS_BELLS.get(); default -> ParticleRequirement.NO_REQUIRMENT; }; } diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/RewardDesigns.java b/LobbySystem/src/de/steamwar/lobby/particle/design/RewardDesigns.java index 4f73de22..b689a917 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/design/RewardDesigns.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/RewardDesigns.java @@ -19,107 +19,26 @@ package de.steamwar.lobby.particle.design; -import de.steamwar.lobby.particle.Gradient; import de.steamwar.lobby.particle.ParticleElement; import de.steamwar.lobby.particle.ParticleRequirement; -import de.steamwar.lobby.particle.WingDesign; import de.steamwar.lobby.particle.elements.*; -import de.steamwar.lobby.particle.elements.custom.HearthBeat; -import de.steamwar.lobby.particle.elements.custom.NonMoving; -import de.steamwar.lobby.particle.elements.custom.PulseShimmer; -import de.steamwar.lobby.particle.elements.touch.*; import lombok.experimental.UtilityClass; import org.bukkit.Material; import org.bukkit.Particle; import org.bukkit.entity.Player; import org.bukkit.util.Vector; -import java.time.Month; import java.util.List; import java.util.function.Consumer; import static de.steamwar.lobby.particle.design.EntryParameters.*; -// Designs earned in tournaments, events and the Easter egg hunt. Rewards whose look the basic designs can build get a -// touch the builder cannot make: bursts on jumping, landing or sneaking, footprints, a link to team-mates, a seasonal -// extra, a preset-only shape or aimed glyphs. +// Reward designs the builder cannot make. Other rewards unlock ingredients instead: wing images, particles and touches. @UtilityClass public class RewardDesigns { - private final Consumer MOVE = values -> { - }; private final Consumer ALWAYS = values -> values.set(TICK_MODE, TickMode.ALWAYS); - private final Consumer WINGS = values -> values - .set(TICK_MODE, TickMode.ALWAYS) - .set(INTERVAL, 20) - .set(GLIDING, Gliding.NOT_GLIDING); - public final ParticleDesign EVENT_PLACEMENT_WARGEAR_SEASON = new FixedDesign("event_placement_wargear_season", Material.ENCHANTING_TABLE, "PARTICLE_EVENT_ENCHANTING", - ParticleRequirement.eventPlacement(22, 12, 285, 54), 5, MOVE, - () -> new Cloud(new Circle(new LocationMutator(new SimpleParticle(Particle.ENCHANT, 0, 0, 0, 0.01), 0, 1.1, 0)))) - .withTouch(3, () -> new NonMoving(new Glyphs(Glyphs.Path.INTO_PLAYER, 3, 1.5))); - public final ParticleDesign EVENT_PLACEMENT_AIRSHIP = new FixedDesign("event_placement_airship", Material.SNOWBALL, "PARTICLE_EVENT_CLOUD", - ParticleRequirement.eventPlacement(26, 205, 9, 54, 120, 292), 5, MOVE, - () -> new Circle(new LocationMutator(new SimpleParticle(Particle.CLOUD, 0, 0, 0, 0.01), 0, 2.2, 0))) - .withTouch(1, () -> new EventBurst(EventBurst.Trigger.JUMP, new SimpleParticle(Particle.CLOUD, 0.3F, 0.05F, 0.3F, 0.02, 12))); - public final ParticleDesign EVENT_PLACEMENT_HELLS_BELLS = new FixedDesign("event_placement_hells_bells", Material.TNT_MINECART, "PARTICLE_EVENT_SMOKE", - ParticleRequirement.eventPlacement(28, 205, 9, 11), 5, MOVE, - () -> new Cloud(new Circle(new LocationMutator(new SimpleParticle(Particle.CAMPFIRE_COSY_SMOKE, 0, 0, 0, 0.01), 0, 2.2, 0)))); - public final ParticleDesign EVENT_PLACEMENT_UNDERWATER = new FixedDesign("event_placement_underwater", Material.PRISMARINE_SHARD, "PARTICLE_EVENT_WATER", - ParticleRequirement.eventPlacement(31, 9, 210, 520), 5, MOVE, - () -> new Cloud(new SimpleParticle(Particle.DRIPPING_WATER))) - .withTouch(1, () -> new EventBurst(EventBurst.Trigger.LAND, 1, new Ring(new SimpleParticle(Particle.SPLASH, 0, 0, 0, 0, 3), 1, 16))); - public final ParticleDesign EVENT_PLACEMENT_ADVENT_WAR_SHIP = new FixedDesign("event_placement_advent_war_ship", Material.PRISMARINE_CRYSTALS, "PARTICLE_EVENT_WATER", - ParticleRequirement.eventPlacement(32, 9, 205, 210), 10, ALWAYS, - () -> new LocationMutator(new Circle(new Group(new SimpleParticle(Particle.DRIPPING_WATER), new SimpleParticle(Particle.UNDERWATER, 0.2F, 0.2F, 0.2F, 0.01))), 0, 1.1, 0)) - .withTouch(4, () -> new Footprints(new SimpleParticle(Particle.FISHING, 0.05F, 0, 0.05F, 0, 1), 40)); - public final ParticleDesign EVENT_PLACEMENT_MINI_WARGEAR_LIGA = wings("event_placement_mini_wargear_liga", Material.IRON_SWORD, "PARTICLE_EVENT_WINGS", - ParticleRequirement.eventPlacement(33, 9, 34, 205), Particle.UNDERWATER, 0.15, WingDesign.MWGL); - public final ParticleDesign EVENT_PLACEMENT_ABSTURZ = wings("event_placement_absturz", Material.FEATHER, "PARTICLE_EVENT_WINGS", - ParticleRequirement.eventPlacement(34, 210, 205, 527, 286), Particle.CRIT, 0.15, WingDesign.SIMPLE) - .withTouch(1, () -> new EventBurst(EventBurst.Trigger.LAND, 3, new Group(new SimpleParticle(Particle.EXPLOSION, 0, 0, 0, 0, 1), - new Ring(new SimpleParticle(Particle.CRIT, 0, 0.1F, 0, 0.1, 2), 1.2, 16)))); - public final ParticleDesign EVENT_PLACEMENT_UNDERWATER_MWG = wings("event_placement_underwater_mwg", Material.CYAN_CARPET, "PARTICLE_EVENT_RAIN_CLOUD", - ParticleRequirement.eventPlacement(35, 9, 210), Particle.CRIT, 0.15, WingDesign.SW); - public final ParticleDesign EVENT_PLACEMENT_WARGEAR_SEASON_2022 = wings("event_placement_wargear_season_2022", Material.DIAMOND_HELMET, "PARTICLE_EVENT_WGS", - ParticleRequirement.eventPlacement(37, 285, 210, 122), Particle.FIREWORK, 0.15, WingDesign.WGS); - public final ParticleDesign EVENT_PLACEMENT_WARGEAR_CLASH = wings("event_placement_wargear_clash", Material.GOLDEN_SWORD, "PARTICLE_EVENT_WARGEARCLASH", - ParticleRequirement.eventPlacement(38, 210, 158, 167, 286), Particle.CRIT, 0.1, WingDesign.SWORD_CROSSED); - - // For taking part in any event - public final ParticleDesign EVENT_PARTICIPATION_WATER = new FixedDesign("event_participation_water", Material.WATER_BUCKET, "PARTICLE_EVENT_WATER", - ParticleRequirement.EVENT_PARTICIPATION, 5, ALWAYS, - () -> new Circle(new LocationMutator(new SimpleParticle(Particle.DRIPPING_WATER), 0, 1.1, 0))) - .withTouch(5, () -> new TeamLink("event_participation_water", new SimpleParticle(Particle.DRIPPING_WATER, 0, 0, 0, 0, 1))); - public final ParticleDesign EVENT_PARTICIPATION_LAVA = new FixedDesign("event_participation_lava", Material.LAVA_BUCKET, "PARTICLE_EVENT_LAVA", - ParticleRequirement.EVENT_PARTICIPATION, 5, ALWAYS, - () -> new Circle(new LocationMutator(new SimpleParticle(Particle.DRIPPING_LAVA), 0, 1.1, 0))) - .withTouch(1, () -> new EventBurst(EventBurst.Trigger.LAND, 1, new Group(new SimpleParticle(Particle.LAVA, 0.2F, 0, 0.2F, 0, 4), - new SimpleParticle(Particle.SMOKE, 0.2F, 0.1F, 0.2F, 0.02, 6)))); - - public final ParticleDesign EVENT_PARTICIPATION_WARGEAR_SEASON = new FixedDesign("event_participation_wargear_season", Material.BOOK, "PARTICLE_EVENT_ENCHANTING", - ParticleRequirement.eventParticipation(22), 5, MOVE, - () -> new SimpleParticle(Particle.ENCHANT)) - .withTouch(1, () -> new EventBurst(EventBurst.Trigger.SNEAK, new Glyphs(Glyphs.Path.OUT_OF_PLAYER, 16, 1.5))); - public final ParticleDesign EVENT_PARTICIPATION_AIRSHIP = new FixedDesign("event_participation_airship", Material.SNOW_BLOCK, "PARTICLE_EVENT_CLOUD", - ParticleRequirement.eventParticipation(26), 5, MOVE, - () -> new SimpleParticle(Particle.CLOUD)) - .withTouch(4, () -> new Footprints(new SimpleParticle(Particle.CLOUD, 0.05F, 0, 0.05F, 0, 1), 40)); - public final ParticleDesign EVENT_PARTICIPATION_HELLS_BELLS = new FixedDesign("event_participation_hells_bells", Material.TNT, "PARTICLE_EVENT_SMOKE", - ParticleRequirement.eventParticipation(28), 5, MOVE, - () -> new Circle(new SimpleParticle(Particle.CAMPFIRE_COSY_SMOKE, 0, 0, 0, 0.01))); - public final ParticleDesign EVENT_PARTICIPATION_UNDERWATER = new FixedDesign("event_participation_underwater", Material.PRISMARINE_BRICKS, "PARTICLE_EVENT_WATER", - ParticleRequirement.eventParticipation(31), 5, MOVE, - () -> new SimpleParticle(Particle.DRIPPING_WATER)) - .withTouch(5, () -> new TeamLink("event_participation_underwater", new SimpleParticle(Particle.DRIPPING_WATER, 0, 0, 0, 0, 1))); - public final ParticleDesign EVENT_PARTICIPATION_ADVENT_WAR_SHIP = new FixedDesign("event_participation_advent_war_ship", Material.PRISMARINE_WALL, "PARTICLE_EVENT_WATER", - ParticleRequirement.eventParticipation(32), 10, MOVE, - () -> new Group(new SimpleParticle(Particle.DRIPPING_WATER), new SimpleParticle(Particle.UNDERWATER, 0.2F, 0.2F, 0.2F, 0.01))) - .withTouch(2, () -> new Seasonal(Month.DECEMBER, new LocationMutator(new SimpleParticle(Particle.SNOWFLAKE, 1.2F, 0.3F, 1.2F, 0.01, 2), 0, 2.4, 0))); - public final ParticleDesign EVENT_PARTICIPATION_MINI_WARGEAR_LIGA = new FixedDesign("event_participation_mini_wargear_liga", Material.PRISMARINE_SLAB, "PARTICLE_EVENT_WATER", - ParticleRequirement.eventParticipation(33), 5, MOVE, - () -> new Circle(new SimpleParticle(Particle.UNDERWATER, 0, 0, 0, 0))) - .withTouch(3, () -> new NonMoving(new PulseShimmer(new SimpleParticle(Particle.UNDERWATER, 0, 0, 0, 0, 1), 80, 2))); public final ParticleDesign EVENT_PARTICIPATION_UNDERWATER_MWG = new FixedDesign("event_participation_underwater_mwg", Material.BLUE_CARPET, "PARTICLE_EVENT_RAIN_CLOUD", ParticleRequirement.eventParticipation(35), 15, ALWAYS, () -> new RandomParticle( @@ -136,25 +55,12 @@ public class RewardDesigns { rainCloud(null, Particle.SNOWFLAKE, 5), rainCloud(null, Particle.TOTEM_OF_UNDYING, 2) )); - public final ParticleDesign EVENT_PARTICIPATION_WARGEAR_SEASON_2022 = wings("event_participation_wargear_season_2022", Material.DIAMOND_SWORD, "PARTICLE_EVENT_WINGS", - ParticleRequirement.eventParticipation(37), Particle.DRAGON_BREATH, 0.15, WingDesign.COMPLEX) - .withTouch(2, () -> 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)); - - public final ParticleDesign EGG_HUNT_EASY = new FixedDesign("egg_hunt_easy", Material.LIME_CONCRETE_POWDER, "PARTICLE_EGG_HUNT_EASY", - ParticleRequirement.EGG_HUNT_EASY, 1, ALWAYS, - () -> new LocationMutator(new SimpleParticle(Particle.FALLING_SPORE_BLOSSOM, 0.5F, 0.1f, 0.5F, 1, 1), 0, 2.2, 0)) - .withTouch(4, () -> new Footprints(new SimpleParticle(Particle.SPORE_BLOSSOM_AIR, 0.05F, 0, 0.05F, 0, 1), 40)); public final ParticleDesign EGG_HUNT_MEDIUM = new FixedDesign("egg_hunt_medium", Material.YELLOW_CONCRETE_POWDER, "PARTICLE_EGG_HUNT_MEDIUM", ParticleRequirement.EGG_HUNT_MEDIUM, 5, ALWAYS.andThen(values -> values.set(GROUND, Ground.ON_GROUND).set(SNEAK, Sneak.SNEAKING)), () -> new SimpleParticle(Particle.GLOW_SQUID_INK, 0.4F, 0.9F, 0.4F, 0.01)); public final ParticleDesign EGG_HUNT_HARD = new FixedDesign("egg_hunt_hard", Material.RED_CONCRETE_POWDER, "PARTICLE_EGG_HUNT_HARD", ParticleRequirement.EGG_HUNT_HARD, 2, ALWAYS, () -> new LocationMutator(new Circle(new DoubleCircle(new DustParticle(Particle.DUST, 0, 0, 0, 0.01, 1, null), new DustParticle(Particle.DUST, 0, 0, 0, 0.01, 1, null)), 0.8, 0.5), 0, 0.5, 0)); - public final ParticleDesign EGG_HUNT_EXTREME = new FixedDesign("egg_hunt_extreme", Material.PURPLE_CONCRETE_POWDER, "PARTICLE_EGG_HUNT_EXTREME", - ParticleRequirement.EGG_HUNT_EXTREME, 1, ALWAYS, - () -> new LocationMutator(new SimpleParticle(Particle.FALLING_OBSIDIAN_TEAR, 0.5F, 0.1F, 0.5F, 1, 1), 0, 2.2, 0)) - .withTouch(1, () -> new EventBurst(EventBurst.Trigger.LAND, 1, new Group(new Ring(new SimpleParticle(Particle.WITCH, 0, 0.05F, 0, 0, 2), 1, 16), - new SimpleParticle(Particle.LANDING_OBSIDIAN_TEAR, 0.4F, 0, 0.4F, 0, 6)))); public final ParticleDesign EGG_HUNT_ADVANCED = new FixedDesign("egg_hunt_advanced", Material.BLACK_CONCRETE_POWDER, "PARTICLE_EGG_HUNT_ADVANCED", ParticleRequirement.EGG_HUNT_ADVANCED, 2, ALWAYS.andThen(values -> values.set(SNEAK, Sneak.SNEAKING)), () -> new LocationMutator(new Group( @@ -165,19 +71,6 @@ public class RewardDesigns { player.setVelocity(player.getVelocity().add(new Vector(0, 0.1, 0))); } ), 0, -0.2, 0)); - // Hearts above the head while sneaking on the ground, a heart cloud ring while in the air - public final ParticleDesign EGG_HUNT_HALF = new FixedDesign("egg_hunt_half", Material.EGG, "PARTICLE_EGG_HUNT_HALF", - ParticleRequirement.EGG_HUNT_FOUND_HALF, 5, ALWAYS, - () -> new Group( - new Sneaking(new Floor(new LocationMutator(new SimpleParticle(Particle.HEART, 0, 0, 0, 0.01), 0, 1.7, 0))), - new NonFloor(new NonFlying(new LocationMutator(new Cloud(new Circle(new SimpleParticle(Particle.HEART, 0, 0, 0, 0.01))), 0, 0.5, 0))) - )) - .withTouch(1, () -> new NonMoving(new HearthBeat(new DustParticle(Particle.DUST, 0, 0, 0, 0, 1, new Gradient(java.awt.Color.RED)), 80))); - - private FixedDesign wings(String id, Material icon, String nameKey, ParticleRequirement requirement, Particle particle, double size, WingDesign wingDesign) { - return new FixedDesign(id, icon, nameKey, requirement, wingDesign.getVectors().length, WINGS, - () -> new Wing(new SimpleParticle(particle, 0, 0, 0, 0, 1), size, wingDesign)); - } // A cloud above the head that drips the given particle; rain is an optional second particle inside the cloud private ParticleElement rainCloud(Particle rain, Particle drip, int dripCount) { @@ -188,15 +81,6 @@ public class RewardDesigns { } public List all() { - return List.of( - EVENT_PLACEMENT_WARGEAR_SEASON, EVENT_PLACEMENT_AIRSHIP, EVENT_PLACEMENT_HELLS_BELLS, EVENT_PLACEMENT_UNDERWATER, - EVENT_PLACEMENT_ADVENT_WAR_SHIP, EVENT_PLACEMENT_MINI_WARGEAR_LIGA, EVENT_PLACEMENT_ABSTURZ, EVENT_PLACEMENT_UNDERWATER_MWG, - EVENT_PLACEMENT_WARGEAR_SEASON_2022, EVENT_PLACEMENT_WARGEAR_CLASH, - EVENT_PARTICIPATION_WATER, EVENT_PARTICIPATION_LAVA, - EVENT_PARTICIPATION_WARGEAR_SEASON, EVENT_PARTICIPATION_AIRSHIP, EVENT_PARTICIPATION_HELLS_BELLS, EVENT_PARTICIPATION_UNDERWATER, - EVENT_PARTICIPATION_ADVENT_WAR_SHIP, EVENT_PARTICIPATION_MINI_WARGEAR_LIGA, EVENT_PARTICIPATION_UNDERWATER_MWG, - EVENT_PARTICIPATION_WARGEAR_SEASON_2022, - EGG_HUNT_EASY, EGG_HUNT_MEDIUM, EGG_HUNT_HARD, EGG_HUNT_EXTREME, EGG_HUNT_ADVANCED, EGG_HUNT_HALF - ); + return List.of(EVENT_PARTICIPATION_UNDERWATER_MWG, EGG_HUNT_MEDIUM, EGG_HUNT_HARD, EGG_HUNT_ADVANCED); } } diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/Touch.java b/LobbySystem/src/de/steamwar/lobby/particle/design/Touch.java new file mode 100644 index 00000000..d5584b91 --- /dev/null +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/Touch.java @@ -0,0 +1,30 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2026 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package de.steamwar.lobby.particle.design; + +import de.steamwar.lobby.particle.ParticleElement; +import de.steamwar.lobby.particle.ParticleRequirement; +import org.bukkit.Material; + +import java.util.function.Supplier; + +// An extra effect an entry can carry next to its design, unlocked by a reward. Touches run every tick, independent +// of the entry's conditions and timing, so their points count fully towards the slot budget. +public record Touch(String id, Material icon, int points, Supplier requirement, Supplier element) { +} diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/Touches.java b/LobbySystem/src/de/steamwar/lobby/particle/design/Touches.java new file mode 100644 index 00000000..f00e7844 --- /dev/null +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/Touches.java @@ -0,0 +1,89 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2026 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package de.steamwar.lobby.particle.design; + +import de.steamwar.lobby.particle.Gradient; +import de.steamwar.lobby.particle.ParticleRequirement; +import de.steamwar.lobby.particle.WingDesign; +import de.steamwar.lobby.particle.elements.*; +import de.steamwar.lobby.particle.elements.custom.HearthBeat; +import de.steamwar.lobby.particle.elements.custom.NonMoving; +import de.steamwar.lobby.particle.elements.custom.PulseShimmer; +import de.steamwar.lobby.particle.elements.touch.*; +import lombok.experimental.UtilityClass; +import org.bukkit.Material; +import org.bukkit.Particle; + +import java.time.Month; +import java.util.List; + +// The touches of the entries' touch setting, each unlocked by the event or egg hunt reward that used to carry it +@UtilityClass +public class Touches { + + public final Touch NONE = new Touch("none", Material.GRAY_DYE, 0, () -> ParticleRequirement.NO_REQUIRMENT, () -> null); + + 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)), + 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, + () -> new EventBurst(EventBurst.Trigger.LAND, 3, new Group(new SimpleParticle(Particle.EXPLOSION, 0, 0, 0, 0, 1), + new Ring(new SimpleParticle(Particle.CRIT, 0, 0.1F, 0, 0.1, 2), 1.2, 16)))), + new Touch("lava_landing", Material.LAVA_BUCKET, 1, Unlocks.ANY_EVENT, + () -> new EventBurst(EventBurst.Trigger.LAND, 1, new Group(new SimpleParticle(Particle.LAVA, 0.2F, 0, 0.2F, 0, 4), + new SimpleParticle(Particle.SMOKE, 0.2F, 0.1F, 0.2F, 0.02, 6)))), + new Touch("obsidian_landing", Material.CRYING_OBSIDIAN, 1, Unlocks.EGG_HUNT_EXTREME, + () -> new EventBurst(EventBurst.Trigger.LAND, 1, new Group(new Ring(new SimpleParticle(Particle.WITCH, 0, 0.05F, 0, 0, 2), 1, 16), + new SimpleParticle(Particle.LANDING_OBSIDIAN_TEAR, 0.4F, 0, 0.4F, 0, 6)))), + new Touch("glyph_burst", Material.BOOK, 1, Unlocks.WARGEAR_SEASON, + () -> new EventBurst(EventBurst.Trigger.SNEAK, new Glyphs(Glyphs.Path.OUT_OF_PLAYER, 16, 1.5))), + // Footprints + new Touch("wet_footprints", Material.PRISMARINE_CRYSTALS, 4, Unlocks.ADVENT_WAR_SHIP_PLACEMENT, + () -> new Footprints(new SimpleParticle(Particle.FISHING, 0.05F, 0, 0.05F, 0, 1), 40)), + new Touch("cloud_footprints", Material.SNOW_BLOCK, 4, Unlocks.AIRSHIP, + () -> new Footprints(new SimpleParticle(Particle.CLOUD, 0.05F, 0, 0.05F, 0, 1), 40)), + new Touch("blossom_footprints", Material.SPORE_BLOSSOM, 4, Unlocks.EGG_HUNT_EASY, + () -> new Footprints(new SimpleParticle(Particle.SPORE_BLOSSOM_AIR, 0.05F, 0, 0.05F, 0, 1), 40)), + // Lines to nearby players with the same touch + new Touch("water_link", Material.WATER_BUCKET, 5, Unlocks.ANY_EVENT, + () -> new TeamLink("water_link", new SimpleParticle(Particle.DRIPPING_WATER, 0, 0, 0, 0, 1))), + new Touch("bubble_link", Material.PRISMARINE_BRICKS, 5, Unlocks.UNDERWATER, + () -> new TeamLink("bubble_link", new SimpleParticle(Particle.BUBBLE_POP, 0, 0, 0, 0, 1))), + // While standing still + new Touch("glyph_pull", Material.ENCHANTING_TABLE, 3, Unlocks.WARGEAR_SEASON_PLACEMENT, + () -> new NonMoving(new Glyphs(Glyphs.Path.INTO_PLAYER, 3, 1.5))), + new Touch("still_shimmer", Material.PRISMARINE_SLAB, 3, Unlocks.MINI_WARGEAR_LIGA, + () -> new NonMoving(new PulseShimmer(new SimpleParticle(Particle.UNDERWATER, 0, 0, 0, 0, 1), 80, 2))), + new Touch("heartbeat", Material.POPPY, 1, Unlocks.EGG_HUNT_HALF, + () -> new NonMoving(new HearthBeat(new DustParticle(Particle.DUST, 0, 0, 0, 0, 1, new Gradient(java.awt.Color.RED)), 80))), + // Seasonal + new Touch("december_snow", Material.POWDER_SNOW_BUCKET, 2, Unlocks.ADVENT_WAR_SHIP, + () -> new Seasonal(Month.DECEMBER, new LocationMutator(new SimpleParticle(Particle.SNOWFLAKE, 1.2F, 0.3F, 1.2F, 0.01, 2), 0, 2.4, 0))) + ); + + public List> choices() { + return ALL.stream().map(touch -> new ChoiceParameter.Choice<>(touch.id(), touch, false, touch.requirement())).toList(); + } +} diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/Unlocks.java b/LobbySystem/src/de/steamwar/lobby/particle/design/Unlocks.java new file mode 100644 index 00000000..c11dc7a8 --- /dev/null +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/Unlocks.java @@ -0,0 +1,65 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2026 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package de.steamwar.lobby.particle.design; + +import de.steamwar.lobby.particle.ParticleRequirement; +import lombok.experimental.UtilityClass; + +import java.util.function.Supplier; + +// Requirements of the reward ingredients: wing images, particles and touches. Each is created on first use, as event +// requirements look up the event's name. +@UtilityClass +public class Unlocks { + + public final Supplier WARGEAR_SEASON_PLACEMENT = lazy(() -> ParticleRequirement.eventPlacement(22, 12, 285, 54)); + public final Supplier AIRSHIP_PLACEMENT = lazy(() -> ParticleRequirement.eventPlacement(26, 205, 9, 54, 120, 292)); + public final Supplier UNDERWATER_PLACEMENT = lazy(() -> ParticleRequirement.eventPlacement(31, 9, 210, 520)); + public final Supplier ADVENT_WAR_SHIP_PLACEMENT = lazy(() -> ParticleRequirement.eventPlacement(32, 9, 205, 210)); + public final Supplier MINI_WARGEAR_LIGA_PLACEMENT = lazy(() -> ParticleRequirement.eventPlacement(33, 9, 34, 205)); + public final Supplier ABSTURZ_PLACEMENT = lazy(() -> ParticleRequirement.eventPlacement(34, 210, 205, 527, 286)); + public final Supplier UNDERWATER_MWG_PLACEMENT = lazy(() -> ParticleRequirement.eventPlacement(35, 9, 210)); + public final Supplier WARGEAR_SEASON_2022_PLACEMENT = lazy(() -> ParticleRequirement.eventPlacement(37, 285, 210, 122)); + public final Supplier WARGEAR_CLASH_PLACEMENT = lazy(() -> ParticleRequirement.eventPlacement(38, 210, 158, 167, 286)); + + public final Supplier ANY_EVENT = () -> ParticleRequirement.EVENT_PARTICIPATION; + public final Supplier WARGEAR_SEASON = lazy(() -> ParticleRequirement.eventParticipation(22)); + public final Supplier AIRSHIP = lazy(() -> ParticleRequirement.eventParticipation(26)); + public final Supplier HELLS_BELLS = lazy(() -> ParticleRequirement.eventParticipation(28)); + public final Supplier UNDERWATER = lazy(() -> ParticleRequirement.eventParticipation(31)); + public final Supplier ADVENT_WAR_SHIP = lazy(() -> ParticleRequirement.eventParticipation(32)); + public final Supplier MINI_WARGEAR_LIGA = lazy(() -> ParticleRequirement.eventParticipation(33)); + public final Supplier WARGEAR_SEASON_2022 = lazy(() -> ParticleRequirement.eventParticipation(37)); + + public final Supplier EGG_HUNT_EASY = () -> ParticleRequirement.EGG_HUNT_EASY; + public final Supplier EGG_HUNT_EXTREME = () -> ParticleRequirement.EGG_HUNT_EXTREME; + public final Supplier EGG_HUNT_HALF = () -> ParticleRequirement.EGG_HUNT_FOUND_HALF; + + private Supplier lazy(Supplier create) { + return new Supplier<>() { + private ParticleRequirement requirement; + + @Override + public ParticleRequirement get() { + if (requirement == null) requirement = create.get(); + return requirement; + } + }; + } +} diff --git a/LobbySystem/src/de/steamwar/lobby/particle/gui/EntryEditor.java b/LobbySystem/src/de/steamwar/lobby/particle/gui/EntryEditor.java index 772e25e3..a7139dd8 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/gui/EntryEditor.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/gui/EntryEditor.java @@ -119,21 +119,24 @@ class EntryEditor { inventory.setItem(ROW_DESIGN * 9 + FIRST_SETTING, new SWItem(design.getIcon(), designName(design, player), List.of(msg("PARTICLE_VALUE_CLICK", player)), false, clickType -> Pickers.design(player, design, picked -> changeDesign(context, picked), context::reopen))); + inventory.setItem(ROW_DESIGN * 9 + FIRST_SETTING + 1, parameterItem(context, TOUCH)); if (design.usesEntryParticle()) { - inventory.setItem(ROW_DESIGN * 9 + FIRST_SETTING + 1, parameterItem(context, PARTICLE)); + inventory.setItem(ROW_DESIGN * 9 + FIRST_SETTING + 2, parameterItem(context, PARTICLE)); ParticleType type = entry.getValues().get(PARTICLE); if (type.usesColors()) { - inventory.setItem(ROW_DESIGN * 9 + FIRST_SETTING + 2, parameterItem(context, COLORS)); + inventory.setItem(ROW_DESIGN * 9 + FIRST_SETTING + 3, parameterItem(context, COLORS)); } else if (type.usesBlock()) { - inventory.setItem(ROW_DESIGN * 9 + FIRST_SETTING + 2, parameterItem(context, BLOCK)); + inventory.setItem(ROW_DESIGN * 9 + FIRST_SETTING + 3, parameterItem(context, BLOCK)); } + // The trail target follows the particle; its duration goes to the end of the particle row + List> particleRow = new ArrayList<>(design.replacesAmount(entry.getValues()) ? List.of(SPEED, SPREAD_X, SPREAD_Y, SPREAD_Z) : List.of(COUNT, SPEED, SPREAD_X, SPREAD_Y, SPREAD_Z)); if (type.isTrail()) { - List> trail = List.of(TRAIL_DURATION, TRAIL_TARGET_X, TRAIL_TARGET_Y, TRAIL_TARGET_Z); - for (int i = 0; i < trail.size(); i++) { - inventory.setItem(ROW_DESIGN * 9 + FIRST_SETTING + 3 + i, parameterItem(context, trail.get(i))); + List> target = List.of(TRAIL_TARGET_X, TRAIL_TARGET_Y, TRAIL_TARGET_Z); + for (int i = 0; i < target.size(); i++) { + inventory.setItem(ROW_DESIGN * 9 + FIRST_SETTING + 4 + i, parameterItem(context, target.get(i))); } + particleRow.add(TRAIL_DURATION); } - List> particleRow = design.replacesAmount(entry.getValues()) ? List.of(SPEED, SPREAD_X, SPREAD_Y, SPREAD_Z) : List.of(COUNT, SPEED, SPREAD_X, SPREAD_Y, SPREAD_Z); row(inventory, context, ROW_PARTICLE, particleRow); } else { inventory.setItem(ROW_PARTICLE * 9 + FIRST_SETTING, new SWItem(Material.STRUCTURE_VOID, msg("PARTICLE_FIXED_LOOK", player), clickType -> { @@ -187,6 +190,7 @@ class EntryEditor { if (parameter == COLORS) icon = Material.RED_DYE; if (parameter == BLOCK) icon = (Material) value; if (value instanceof WingShape shape) icon = shape.getIcon(); + if (value instanceof Touch touch) icon = touch.icon(); return new SWItem(icon, name(parameter.getNameKey(), player), lore, false, clickType -> { if (parameter instanceof BooleanParameter toggle) { @@ -254,6 +258,7 @@ class EntryEditor { private Material choiceIcon(Object value) { if (value instanceof ParticleType type) return type.getIcon(); if (value instanceof WingShape shape) return shape.getIcon(); + if (value instanceof Touch touch) return touch.icon(); if (value instanceof Material material) return material; return Material.LEVER; } diff --git a/LobbySystem/src/de/steamwar/lobby/particle/gui/ParticleGuiText.java b/LobbySystem/src/de/steamwar/lobby/particle/gui/ParticleGuiText.java index efbdc2af..cddfaefe 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/gui/ParticleGuiText.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/gui/ParticleGuiText.java @@ -120,6 +120,9 @@ class ParticleGuiText { if (entry.getDesign().usesEntryParticle()) { lore.add(msg("PARTICLE_ENTRY_PARTICLE", player, particleName(values.get(PARTICLE), player))); } + if (values.get(TOUCH) != Touches.NONE) { + lore.add(msg("PARTICLE_ENTRY_TOUCH", player, choiceName(TOUCH, values.get(TOUCH), player))); + } lore.add("§8- " + choiceName(TICK_MODE, values.get(TICK_MODE), player)); addCondition(lore, MOVEMENT, values.get(MOVEMENT), Movement.ANY, player); addCondition(lore, GLIDING, values.get(GLIDING), Gliding.ANY, player); diff --git a/LobbySystem/src/de/steamwar/lobby/particle/slot/ParticleEntry.java b/LobbySystem/src/de/steamwar/lobby/particle/slot/ParticleEntry.java index 478ac1a3..bd64690e 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/slot/ParticleEntry.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/slot/ParticleEntry.java @@ -169,9 +169,9 @@ public class ParticleEntry { return new LocationMutator(element, offsetX, offsetY, offsetZ); } - // The design's touch with the entry's placement and visibility, or null; touches ignore conditions and timing + // The entry's touch with its placement and visibility, or null; touches ignore conditions and timing public ParticleElement buildTouch() { - ParticleElement touch = design.touch(); + ParticleElement touch = values.get(TOUCH).element().get(); if (touch == null) { return null; } @@ -181,12 +181,15 @@ public class ParticleEntry { return new Always(values.get(VISIBILITY).wrap(touch)); } - // Shown only when the design, its chosen options and, for designs that use it, the particle type are unlocked + // Shown only when the design, its chosen options, the touch and, for designs that use it, the particle type are unlocked @SuppressWarnings("unchecked") public boolean isUnlocked(UnlockContext context) { if (!design.getRequirement().test(context)) { return false; } + if (!TOUCH.requirement(values.get(TOUCH)).test(context)) { + return false; + } for (Parameter parameter : design.getParameters()) { if (parameter instanceof ChoiceParameter choice && !((ChoiceParameter) choice).requirement(values.get(choice)).test(context)) { return false; @@ -203,7 +206,7 @@ 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); + return perTick / values.get(INTERVAL) + values.get(TOUCH).points(); } public JsonObject toJson() {