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 ); - } - } -}