diff --git a/core/src/main/assets/burning_fist.png b/core/src/main/assets/burning_fist.png
deleted file mode 100644
index 5962f9c3c..000000000
Binary files a/core/src/main/assets/burning_fist.png and /dev/null differ
diff --git a/core/src/main/assets/rotting_fist.png b/core/src/main/assets/rotting_fist.png
deleted file mode 100644
index 4468677ca..000000000
Binary files a/core/src/main/assets/rotting_fist.png and /dev/null differ
diff --git a/core/src/main/assets/yog_fists.png b/core/src/main/assets/yog_fists.png
new file mode 100644
index 000000000..05af17b24
Binary files /dev/null and b/core/src/main/assets/yog_fists.png differ
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java
index efd2f7a26..27abe0945 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java
@@ -83,8 +83,7 @@ public class Assets {
public static final String EYE = "eye.png";
public static final String SUCCUBUS = "succubus.png";
public static final String SCORPIO = "scorpio.png";
- public static final String ROTTING = "rotting_fist.png";
- public static final String BURNING = "burning_fist.png";
+ public static final String FISTS = "yog_fists.png";
public static final String YOG = "yog.png";
public static final String LARVA = "larva.png";
public static final String GHOST = "ghost.png";
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Yog.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Yog.java
index 7f649132d..ef221510f 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Yog.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Yog.java
@@ -49,10 +49,9 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GrimTrap;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
-import com.shatteredpixel.shatteredpixeldungeon.sprites.BurningFistSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
+import com.shatteredpixel.shatteredpixeldungeon.sprites.FistSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.LarvaSprite;
-import com.shatteredpixel.shatteredpixeldungeon.sprites.RottingFistSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.YogSprite;
import com.shatteredpixel.shatteredpixeldungeon.ui.BossHealthBar;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
@@ -214,7 +213,7 @@ public class Yog extends Mob {
private static final int REGENERATION = 4;
{
- spriteClass = RottingFistSprite.class;
+ spriteClass = FistSprite.Rotting.class;
HP = HT = 300;
defenseSkill = 25;
@@ -286,7 +285,7 @@ public class Yog extends Mob {
public static class BurningFist extends Mob {
{
- spriteClass = BurningFistSprite.class;
+ spriteClass = FistSprite.Burning.class;
HP = HT = 200;
defenseSkill = 25;
@@ -322,37 +321,49 @@ public class Yog extends Mob {
//used so resistances can differentiate between melee and magical attacks
public static class DarkBolt{}
-
- @Override
- public boolean attack( Char enemy ) {
-
- if (!Dungeon.level.adjacent( pos, enemy.pos )) {
- spend( attackDelay() );
-
- if (hit( this, enemy, true )) {
-
- int dmg = damageRoll();
- enemy.damage( dmg, new DarkBolt() );
-
- enemy.sprite.bloodBurstA( sprite.center(), dmg );
- enemy.sprite.flash();
-
- if (!enemy.isAlive() && enemy == Dungeon.hero) {
- Dungeon.fail( getClass() );
- GLog.n( Messages.get(Char.class, "kill", name()) );
- }
- return true;
-
- } else {
-
- enemy.sprite.showStatus( CharSprite.NEUTRAL, enemy.defenseVerb() );
- return false;
- }
+
+ protected boolean doAttack( Char enemy ) {
+
+ if (Dungeon.level.adjacent( pos, enemy.pos )) {
+
+ return super.doAttack( enemy );
+
} else {
- return super.attack( enemy );
+
+ if (sprite != null && (sprite.visible || enemy.sprite.visible)) {
+ sprite.zap( enemy.pos );
+ return false;
+ } else {
+ zap();
+ return true;
+ }
}
}
-
+
+ private void zap() {
+ spend( 1f );
+
+ if (hit( this, enemy, true )) {
+
+ int dmg = damageRoll();
+ enemy.damage( dmg, new DarkBolt() );
+
+ if (!enemy.isAlive() && enemy == Dungeon.hero) {
+ Dungeon.fail( getClass() );
+ GLog.n( Messages.get(Char.class, "kill", name()) );
+ }
+
+ } else {
+
+ enemy.sprite.showStatus( CharSprite.NEUTRAL, enemy.defenseVerb() );
+ }
+ }
+
+ public void onZapComplete() {
+ zap();
+ next();
+ }
+
@Override
public boolean act() {
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/BurningFistSprite.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/BurningFistSprite.java
deleted file mode 100644
index 2383dc23a..000000000
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/BurningFistSprite.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Pixel Dungeon
- * Copyright (C) 2012-2015 Oleg Dolya
- *
- * Shattered Pixel Dungeon
- * Copyright (C) 2014-2019 Evan Debenham
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- */
-
-package com.shatteredpixel.shatteredpixeldungeon.sprites;
-
-import com.shatteredpixel.shatteredpixeldungeon.Assets;
-import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
-import com.watabou.noosa.TextureFilm;
-import com.watabou.noosa.audio.Sample;
-import com.watabou.utils.Callback;
-
-public class BurningFistSprite extends MobSprite {
-
- public BurningFistSprite() {
- super();
-
- texture( Assets.BURNING );
-
- TextureFilm frames = new TextureFilm( texture, 24, 17 );
-
- idle = new Animation( 2, true );
- idle.frames( frames, 0, 0, 1 );
-
- run = new Animation( 3, true );
- run.frames( frames, 0, 1 );
-
- attack = new Animation( 8, false );
- attack.frames( frames, 0, 5, 6 );
-
- die = new Animation( 10, false );
- die.frames( frames, 0, 2, 3, 4 );
-
- play( idle );
- }
-
- private int posToShoot;
-
- @Override
- public void attack( int cell ) {
- posToShoot = cell;
- super.attack( cell );
- }
-
- @Override
- public void onComplete( Animation anim ) {
- if (anim == attack) {
-
- Sample.INSTANCE.play( Assets.SND_ZAP );
- MagicMissile.boltFromChar( parent,
- MagicMissile.SHADOW,
- this,
- posToShoot,
- new Callback() {
- @Override
- public void call() {
- ch.onAttackComplete();
- }
- } );
-
- idle();
-
- } else {
- super.onComplete( anim );
- }
- }
-}
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/CharSprite.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/CharSprite.java
index 31d0aca9d..b4e44065a 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/CharSprite.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/CharSprite.java
@@ -273,10 +273,14 @@ public class CharSprite extends MovieClip implements Tweener.Listener, MovieClip
}
public void jump( int from, int to, Callback callback ) {
+ float distance = Dungeon.level.trueDistance( from, to );
+ jump( from, to, callback, distance * 2, distance * 0.1f );
+ }
+
+ public void jump( int from, int to, Callback callback, float height, float duration ) {
jumpCallback = callback;
- float distance = Dungeon.level.trueDistance( from, to );
- jumpTweener = new JumpTweener( this, worldToCamera( to ), distance * 2, distance * 0.1f );
+ jumpTweener = new JumpTweener( this, worldToCamera( to ), height, duration );
jumpTweener.listener = this;
parent.add( jumpTweener );
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/FistSprite.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/FistSprite.java
new file mode 100644
index 000000000..cc7bb07f2
--- /dev/null
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/FistSprite.java
@@ -0,0 +1,195 @@
+/*
+ * Pixel Dungeon
+ * Copyright (C) 2012-2015 Oleg Dolya
+ *
+ * Shattered Pixel Dungeon
+ * Copyright (C) 2014-2020 Evan Debenham
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ */
+
+package com.shatteredpixel.shatteredpixeldungeon.sprites;
+
+import com.shatteredpixel.shatteredpixeldungeon.Assets;
+import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
+import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Yog;
+import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
+import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlameParticle;
+import com.shatteredpixel.shatteredpixeldungeon.levels.SewerLevel;
+import com.watabou.noosa.Camera;
+import com.watabou.noosa.TextureFilm;
+import com.watabou.noosa.audio.Sample;
+import com.watabou.noosa.particles.Emitter;
+import com.watabou.utils.Callback;
+
+public abstract class FistSprite extends MobSprite {
+
+ private static final float SLAM_TIME = 0.33f;
+
+ protected int boltType;
+
+ protected abstract int texOffset();
+
+ private Emitter particles;
+ protected abstract Emitter createEmitter();
+
+ public FistSprite() {
+ super();
+
+ int c = texOffset();
+
+ texture( Assets.FISTS );
+
+ TextureFilm frames = new TextureFilm( texture, 24, 17 );
+
+ idle = new Animation( 2, true );
+ idle.frames( frames, c+0, c+0, c+1 );
+
+ run = new Animation( 3, true );
+ run.frames( frames, c+0, c+1 );
+
+ attack = new Animation( Math.round(1 / SLAM_TIME), false );
+ attack.frames( frames, c+0 );
+
+ zap = new Animation( 8, false );
+ zap.frames( frames, c+0, c+5, c+6 );
+
+ die = new Animation( 10, false );
+ die.frames( frames, c+0, c+2, c+3, c+4 );
+
+ play( idle );
+ }
+
+ @Override
+ public void link( Char ch ) {
+ super.link( ch );
+
+ if (particles == null) {
+ particles = createEmitter();
+ }
+ }
+
+ @Override
+ public void update() {
+ super.update();
+
+ if (particles != null){
+ particles.visible = visible;
+ }
+ }
+
+ @Override
+ public void die() {
+ super.die();
+ if (particles != null){
+ particles.on = false;
+ }
+ }
+
+ @Override
+ public void kill() {
+ super.kill();
+ if (particles != null){
+ particles.killAndErase();
+ }
+ }
+
+ @Override
+ public void attack( int cell ) {
+ super.attack( cell );
+
+ jump(ch.pos, ch.pos, null, 9, SLAM_TIME );
+ }
+
+ public void zap( int cell ) {
+
+ turnTo( ch.pos , cell );
+ play( zap );
+
+ MagicMissile.boltFromChar( parent,
+ boltType,
+ this,
+ cell,
+ new Callback() {
+ @Override
+ public void call() {
+ ((Yog.BurningFist)ch).onZapComplete();
+ }
+ } );
+ Sample.INSTANCE.play( Assets.SND_ZAP );
+ }
+
+ @Override
+ public void onComplete( Animation anim ) {
+ super.onComplete( anim );
+ if (anim == attack) {
+ Camera.main.shake( 4, 0.2f );
+ } else if (anim == zap) {
+ idle();
+ }
+ }
+
+ public static class Burning extends FistSprite {
+
+ {
+ boltType = MagicMissile.FIRE;
+ }
+
+ @Override
+ protected int texOffset() {
+ return 0;
+ }
+
+ @Override
+ protected Emitter createEmitter() {
+ Emitter emitter = emitter();
+ emitter.pour( FlameParticle.FACTORY, 0.06f );
+ return emitter;
+ }
+
+ @Override
+ public int blood() {
+ return 0xFFFFBB33;
+ }
+
+ }
+
+ ///
+
+ public static class Rotting extends FistSprite {
+
+ {
+ boltType = MagicMissile.TOXIC_VENT;
+ }
+
+ @Override
+ protected int texOffset() {
+ return 20;
+ }
+
+ @Override
+ protected Emitter createEmitter() {
+ Emitter emitter = emitter();
+ //emitter.pour( SewerLevel.WaterParticle.FACTORY, 0.06f );
+ return emitter;
+ }
+
+ @Override
+ public int blood() {
+ return 0xFFFFBB33;
+ }
+
+ }
+
+}
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/RottingFistSprite.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/RottingFistSprite.java
deleted file mode 100644
index 6a206e5da..000000000
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/RottingFistSprite.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Pixel Dungeon
- * Copyright (C) 2012-2015 Oleg Dolya
- *
- * Shattered Pixel Dungeon
- * Copyright (C) 2014-2019 Evan Debenham
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- */
-
-package com.shatteredpixel.shatteredpixeldungeon.sprites;
-
-import com.shatteredpixel.shatteredpixeldungeon.Assets;
-import com.watabou.noosa.Camera;
-import com.watabou.noosa.TextureFilm;
-
-public class RottingFistSprite extends MobSprite {
-
- private static final float FALL_SPEED = 64;
-
- public RottingFistSprite() {
- super();
-
- texture( Assets.ROTTING );
-
- TextureFilm frames = new TextureFilm( texture, 24, 17 );
-
- idle = new Animation( 2, true );
- idle.frames( frames, 0, 0, 1 );
-
- run = new Animation( 3, true );
- run.frames( frames, 0, 1 );
-
- attack = new Animation( 2, false );
- attack.frames( frames, 0 );
-
- die = new Animation( 10, false );
- die.frames( frames, 0, 2, 3, 4 );
-
- play( idle );
- }
-
- @Override
- public void attack( int cell ) {
- super.attack( cell );
-
- speed.set( 0, -FALL_SPEED );
- acc.set( 0, FALL_SPEED * 4 );
- }
-
- @Override
- public void onComplete( Animation anim ) {
- super.onComplete( anim );
- if (anim == attack) {
- speed.set( 0 );
- acc.set( 0 );
- place( ch.pos );
-
- Camera.main.shake( 4, 0.2f );
- }
- }
-}