From aa32a58dbd90e33311568a500d0a83eef812ce7b Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Fri, 10 Oct 2025 14:04:23 -0400 Subject: [PATCH] v3.3.0: movement and glyph improvements: - hero move speed is now calculated based on destination tile - added particles when glyphs affect movespeed --- .../com/watabou/noosa/particles/Emitter.java | 12 ++++++--- .../assets/messages/items/items.properties | 2 +- .../actors/hero/Hero.java | 6 ++--- .../shatteredpixeldungeon/effects/Speck.java | 25 +++++++++++++++++++ .../items/armor/curses/Bulk.java | 4 +++ .../items/armor/glyphs/Flow.java | 6 +++++ .../items/armor/glyphs/Swiftness.java | 10 ++++++-- 7 files changed, 55 insertions(+), 10 deletions(-) diff --git a/SPD-classes/src/main/java/com/watabou/noosa/particles/Emitter.java b/SPD-classes/src/main/java/com/watabou/noosa/particles/Emitter.java index 6cc3e846e..65af2edee 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/particles/Emitter.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/particles/Emitter.java @@ -88,16 +88,20 @@ public class Emitter extends Group { } public void start( Factory factory, float interval, int quantity ) { + //by default the delay is random, up to the interval + startDelayed( factory, interval, quantity, Random.Float(interval)); + } + public void startDelayed( Factory factory, float interval, int quantity, float delay ) { this.factory = factory; this.lightMode = factory.lightMode(); - + this.interval = interval; this.quantity = quantity; - + count = 0; - time = Random.Float( interval ); - + time = interval - delay; + on = true; started = true; } diff --git a/core/src/main/assets/messages/items/items.properties b/core/src/main/assets/messages/items/items.properties index a0e56bcab..c3e9ea9b2 100644 --- a/core/src/main/assets/messages/items/items.properties +++ b/core/src/main/assets/messages/items/items.properties @@ -3,7 +3,7 @@ items.armor.curses.antientropy.name=%s of anti-entropy items.armor.curses.antientropy.desc=The Anti-entropy curse works against the forces of the universe, pulling energy into the wearer and away from their surroundings. This briefly sets the wearer on fire, but freezes everything around them! items.armor.curses.bulk.name=%s of bulk -items.armor.curses.bulk.desc=Armor of bulk looks larger and more imposing, but doesn't actually have enhanced defense. Even worse, the added size makes moving through doorways very difficult. +items.armor.curses.bulk.desc=Armor of bulk looks larger and more imposing, but doesn't actually have enhanced defense. Even worse, the added size makes moving into doorways very difficult. items.armor.curses.corrosion.name=%s of corrosion items.armor.curses.corrosion.desc=Armor of corrosion is capable of bursting with corrosive fluid, coating everything in the area with sticky acidic ooze. diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java index 69a21a180..fe20c8479 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java @@ -1812,14 +1812,14 @@ public class Hero extends Char { if (step != -1) { - float delay = 1 / speed(); + float delay = 1; if (buff(GreaterHaste.class) != null){ delay = 0; } if (Dungeon.level.pit[step] && !Dungeon.level.solid[step] - && (!flying || buff(Levitation.class) != null && buff(Levitation.class).detachesWithinDelay(delay))){ + && (!flying || buff(Levitation.class) != null && buff(Levitation.class).detachesWithinDelay(delay / speed()))){ if (!Chasm.jumpConfirmed){ Chasm.heroJump(this); interrupt(); @@ -1843,7 +1843,7 @@ public class Hero extends Char { sprite.move(pos, step); move(step); - spend( delay ); + spend( delay / speed() ); search(false); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/Speck.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/Speck.java index 9131c6e0d..8b9671be0 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/Speck.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/Speck.java @@ -70,6 +70,8 @@ public class Speck extends Image { public static final int STORM = 117; public static final int INFERNO = 118; public static final int BLIZZARD = 119; + public static final int YELLOW_LIGHT= 120; + public static final int BLUE_LIGHT = 121; private static final int SIZE = 7; @@ -115,6 +117,8 @@ public class Speck extends Image { switch (type) { case DISCOVER: case RED_LIGHT: + case YELLOW_LIGHT: + case BLUE_LIGHT: frame( film.get( LIGHT ) ); break; case EVOKE: @@ -204,11 +208,30 @@ public class Speck extends Image { case RED_LIGHT: tint(0xFFCC0000); + angle = Random.Float( 360 ); + angularSpeed = 90; + lifespan = 1f; + break; + case LIGHT: angle = Random.Float( 360 ); angularSpeed = 90; lifespan = 1f; break; + + case YELLOW_LIGHT: + tint(0xFFDDDD00); + angle = Random.Float( 360 ); + angularSpeed = 90; + lifespan = 1f; + break; + + case BLUE_LIGHT: + tint(0xFF00CCFF); + angle = Random.Float( 360 ); + angularSpeed = 90; + lifespan = 1f; + break; case DISCOVER: angle = Random.Float( 360 ); @@ -420,6 +443,8 @@ public class Speck extends Image { break; case RED_LIGHT: + case YELLOW_LIGHT: + case BLUE_LIGHT: case LIGHT: am = scale.set( p < 0.2f ? p * 5f : (1 - p) * 1.25f ).x; break; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/curses/Bulk.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/curses/Bulk.java index b0ef7fdea..7246fdacc 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/curses/Bulk.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/curses/Bulk.java @@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.items.armor.curses; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle; import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite; @@ -43,6 +44,9 @@ public class Bulk extends Armor.Glyph { (Dungeon.level.map[owner.pos] != Terrain.DOOR && Dungeon.level.map[owner.pos] != Terrain.OPEN_DOOR )) { return 1; } else { + if (owner.sprite != null){ + owner.sprite.emitter().startDelayed(ShadowParticle.UP, 0.02f, 5, 0.05f); + } return 1/3f * genericProcChanceMultiplier(owner); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/glyphs/Flow.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/glyphs/Flow.java index 1a7ca6d53..88b20b944 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/glyphs/Flow.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/glyphs/Flow.java @@ -23,8 +23,10 @@ package com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite; +import com.watabou.utils.Random; public class Flow extends Armor.Glyph { @@ -40,6 +42,10 @@ public class Flow extends Armor.Glyph { if (level == -1 || !Dungeon.level.water[owner.pos]){ return 1; } else { + if (owner.sprite != null){ + int particles = 2 + (int) Random.Float(1+level/2f); + owner.sprite.emitter().startDelayed(Speck.factory(Speck.BLUE_LIGHT), 0.02f, particles, 0.05f); + } return (2f + 0.5f*level) * genericProcChanceMultiplier(owner); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/glyphs/Swiftness.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/glyphs/Swiftness.java index 27c1f3069..5ba2b8fbd 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/glyphs/Swiftness.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/glyphs/Swiftness.java @@ -24,9 +24,11 @@ package com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite; import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; public class Swiftness extends Armor.Glyph { @@ -44,7 +46,7 @@ public class Swiftness extends Armor.Glyph { } boolean enemyNear = false; - //for each enemy, check if they are adjacent, or within 2 tiles and an adjacent cell is open + //for each enemy, check if they are adjacent, or within 2 tiles and an adjacent cell is open or a door for (Char ch : Actor.chars()){ if ( Dungeon.level.distance(ch.pos, owner.pos) <= 2 && owner.alignment != ch.alignment && ch.alignment != Char.Alignment.NEUTRAL){ if (Dungeon.level.adjacent(ch.pos, owner.pos)){ @@ -52,7 +54,7 @@ public class Swiftness extends Armor.Glyph { break; } else { for (int i : PathFinder.NEIGHBOURS8){ - if (Dungeon.level.adjacent(owner.pos+i, ch.pos) && !Dungeon.level.solid[owner.pos+i]){ + if (Dungeon.level.adjacent(owner.pos+i, ch.pos) && (!Dungeon.level.solid[owner.pos+i] || Dungeon.level.passable[owner.pos+i])){ enemyNear = true; break; } @@ -63,6 +65,10 @@ public class Swiftness extends Armor.Glyph { if (enemyNear){ return 1; } else { + if (owner.sprite != null){ + int particles = 1 + (int)Random.Float(1+level/5f); + owner.sprite.emitter().startDelayed(Speck.factory(Speck.YELLOW_LIGHT), 0.02f, particles, 0.05f); + } return (1.2f + 0.04f * level) * genericProcChanceMultiplier(owner); } }