From 3c4cb08cd281f27fc81c3d57a28d7104b98eb8f6 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Wed, 16 Sep 2020 16:05:58 -0400 Subject: [PATCH] v0.9.0: improved logic for ripper demon leaping --- .../actors/mobs/RipperDemon.java | 67 ++++++++++++------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/RipperDemon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/RipperDemon.java index af302a796..e567b37b6 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/RipperDemon.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/RipperDemon.java @@ -135,39 +135,56 @@ public class RipperDemon extends Mob { public boolean act( boolean enemyInFOV, boolean justAlerted ) { if (leapPos != -1){ + + leapCooldown = Random.NormalIntRange(2, 4); + Ballistica b = new Ballistica(pos, leapPos, Ballistica.STOP_TARGET | Ballistica.STOP_SOLID); + + //check if leap pos is not obstructed by terrain + if (b.collisionPos != leapPos){ + leapPos = -1; + return true; + } + + final Char leapVictim = Actor.findChar(leapPos); + final int endPos; + + //ensure there is somewhere to land after leaping + if (leapVictim != null){ + int bouncepos = -1; + for (int i : PathFinder.NEIGHBOURS8){ + if ((bouncepos == -1 || Dungeon.level.trueDistance(pos, leapPos+i) < Dungeon.level.trueDistance(pos, bouncepos)) + && Actor.findChar(leapPos+i) == null && Dungeon.level.passable[leapPos+i]){ + bouncepos = leapPos+i; + } + } + if (bouncepos == -1) { + leapPos = -1; + return true; + } else { + endPos = bouncepos; + } + } else { + endPos = leapPos; + } + //do leap - sprite.visible = Dungeon.level.heroFOV[pos] || Dungeon.level.heroFOV[leapPos]; + sprite.visible = Dungeon.level.heroFOV[pos] || Dungeon.level.heroFOV[leapPos] || Dungeon.level.heroFOV[endPos]; sprite.jump(pos, leapPos, new Callback() { @Override public void call() { - Char ch = Actor.findChar(leapPos); - if (ch != null){ - if (alignment != ch.alignment){ - Buff.affect(ch, Bleeding.class).set(0.75f*damageRoll()); - ch.sprite.flash(); - Sample.INSTANCE.play(Assets.Sounds.HIT); - } - //bounce to a random safe pos(if possible) - int bouncepos = -1; - for (int i : PathFinder.NEIGHBOURS8){ - if ((bouncepos == -1 || Dungeon.level.trueDistance(pos, leapPos+i) < Dungeon.level.trueDistance(pos, bouncepos)) - && Actor.findChar(leapPos+i) == null && Dungeon.level.passable[leapPos+i]){ - bouncepos = leapPos+i; - } - } - if (bouncepos != -1) { - pos = bouncepos; - Actor.addDelayed(new Pushing(RipperDemon.this, leapPos, bouncepos), -1); - } else { - pos = leapPos; - } - } else { - pos = leapPos; + if (leapVictim != null && alignment != leapVictim.alignment){ + Buff.affect(leapVictim, Bleeding.class).set(0.75f*damageRoll()); + leapVictim.sprite.flash(); + Sample.INSTANCE.play(Assets.Sounds.HIT); } + if (endPos != leapPos){ + Actor.addDelayed(new Pushing(RipperDemon.this, leapPos, endPos), -1); + } + + pos = endPos; leapPos = -1; - leapCooldown = Random.NormalIntRange(2, 4); sprite.idle(); Dungeon.level.occupyCell(RipperDemon.this); next();