From 545cda0bbaa3062a5e282d9db949fe7fbf5d03bd Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Thu, 4 Jul 2019 21:04:00 -0400 Subject: [PATCH] v0.7.4: initial implementation for wand of warding --- core/src/main/assets/wards.png | Bin 0 -> 279 bytes .../shatteredpixeldungeon/Assets.java | 1 + .../shatteredpixeldungeon/actors/Char.java | 4 + .../actors/hero/Hero.java | 2 +- .../effects/MagicMissile.java | 34 +- .../items/Generator.java | 11 +- .../items/wands/Wand.java | 24 +- .../items/wands/WandOfWarding.java | 329 ++++++++++++++++++ .../shatteredpixeldungeon/levels/Level.java | 17 + .../sprites/SpinnerSprite.java | 1 + .../sprites/WardSprite.java | 116 ++++++ 11 files changed, 519 insertions(+), 20 deletions(-) create mode 100644 core/src/main/assets/wards.png create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfWarding.java create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/WardSprite.java diff --git a/core/src/main/assets/wards.png b/core/src/main/assets/wards.png new file mode 100644 index 0000000000000000000000000000000000000000..f7614f01d315b4b41cb326507c97f1e069e60d47 GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^4nQox#0(^FcTU^|q<8{+LR^7#1H=C{I{yP0&I_^6 zlmzk_OM?7@862M7NCR?qdb&7)d@Lxn?&)|CU;8G!z~c9xT^Icp?fL5}aVYlt$1OG|lJ{5bXP^Bh z@9wj|8<#CEv12%u%C)P|a_6O5=9zA9cf>YpuM22BvsGk*O)INlmPcCB^vwwe&&-?2 bt!8gKTle--ofGOnPcV48`njxgN@xNA=N@l6 literal 0 HcmV?d00001 diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java index dfd603725..e468fe9a0 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java @@ -97,6 +97,7 @@ public class Assets { public static final String ROT_LASH = "rot_lasher.png"; public static final String ROT_HEART= "rot_heart.png"; public static final String GUARD = "guard.png"; + public static final String WARDS = "wards.png"; public static final String ITEMS = "items.png"; public static final String TERRAIN_FEATURES = "terrain_features.png"; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java index 0f4f95460..3cac043d6 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java @@ -131,6 +131,10 @@ public abstract class Char extends Actor { Dungeon.level.updateFieldOfView( this, fieldOfView ); return false; } + + public boolean canInteract( Hero h ){ + return Dungeon.level.adjacent( pos, h.pos ); + } //swaps places by default public boolean interact(){ 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 ded1fd802..a23c88aaa 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 @@ -630,7 +630,7 @@ public class Hero extends Char { Char ch = action.ch; - if (Dungeon.level.adjacent( pos, ch.pos )) { + if (ch.canInteract(this)) { ready(); sprite.turnTo( pos, ch.pos ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/MagicMissile.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/MagicMissile.java index 8d640fbd2..1219358da 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/MagicMissile.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/MagicMissile.java @@ -59,6 +59,7 @@ public class MagicMissile extends Emitter { public static final int SHADOW = 7; public static final int RAINBOW = 8; public static final int EARTH = 9; + public static final int WARD = 10; public static final int FIRE_CONE = 100; public static final int FOLIAGE_CONE = 101; @@ -138,6 +139,10 @@ public class MagicMissile extends Emitter { size( 4 ); pour( EarthParticle.FACTORY, 0.01f ); break; + case WARD: + size( 4 ); + pour( WardParticle.FACTORY, 0.01f ); + break; case FIRE_CONE: size( 10 ); @@ -416,26 +421,37 @@ public class MagicMissile extends Emitter { am = (1 - left / lifespan) / 2; } } - - public static class ColdParticle extends PixelParticle.Shrinking { + + public static class WardParticle extends PixelParticle.Shrinking { public static final Emitter.Factory FACTORY = new Factory() { @Override public void emit( Emitter emitter, int index, float x, float y ) { - ((ColdParticle)emitter.recycle( ColdParticle.class )).reset( x, y ); + ((WardParticle)emitter.recycle( WardParticle.class )).reset( x, y ); } @Override public boolean lightMode() { return true; - }; + } + }; + + public static final Emitter.Factory UP = new Factory() { + @Override + public void emit( Emitter emitter, int index, float x, float y ) { + ((WardParticle)emitter.recycle( WardParticle.class )).resetUp( x, y ); + } + @Override + public boolean lightMode() { + return true; + } }; - public ColdParticle() { + public WardParticle() { super(); lifespan = 0.6f; - color( 0x2244FF ); + color( 0x8822FF ); } public void reset( float x, float y ) { @@ -447,6 +463,12 @@ public class MagicMissile extends Emitter { left = lifespan; size = 8; } + + public void resetUp( float x, float y){ + reset(x, y); + + speed.set( Random.Float( -8, +8 ), Random.Float( -32, -48 ) ); + } @Override public void update() { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java index f0db8f4d2..fa01c6028 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java @@ -106,10 +106,12 @@ import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfDisintegration import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFireblast; import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFrost; import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfLightning; +import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfLivingEarth; import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfMagicMissile; import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfPrismaticLight; import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfRegrowth; import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfTransfusion; +import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfWarding; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.AssassinsBlade; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.BattleAxe; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Crossbow; @@ -296,8 +298,7 @@ public class Generator { StoneOfShock.class }; STONE.probs = new float[]{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - - //TODO: add last ones when implemented + WAND.classes = new Class[]{ WandOfMagicMissile.class, WandOfLightning.class, @@ -305,14 +306,14 @@ public class Generator { WandOfFireblast.class, WandOfCorrosion.class, WandOfBlastWave.class, - //WandOfLivingEarth.class, + WandOfLivingEarth.class, WandOfFrost.class, WandOfPrismaticLight.class, - //WandOfWarding.class, + WandOfWarding.class, WandOfTransfusion.class, WandOfCorruption.class, WandOfRegrowth.class }; - WAND.probs = new float[]{ 5, 4, 4, 4, 4, 3, /*3,*/ 3, 3, /*3,*/ 3, 3, 3 }; + WAND.probs = new float[]{ 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3 }; //see generator.randomWeapon WEAPON.classes = new Class[]{}; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java index 175fd1edd..5d18ee1cc 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java @@ -111,6 +111,21 @@ public abstract class Wand extends Item { public abstract void onHit( MagesStaff staff, Char attacker, Char defender, int damage); + public boolean tryToZap( Hero owner ){ + + if (owner.buff(MagicImmune.class) != null){ + GLog.w( Messages.get(this, "no_magic") ); + return false; + } + + if ( curCharges >= (cursed ? 1 : chargesPerCast())){ + return true; + } else { + GLog.w(Messages.get(this, "fizzles")); + return false; + } + } + @Override public boolean collect( Bag container ) { if (super.collect( container )) { @@ -411,9 +426,6 @@ public abstract class Wand extends Item { if (target == curUser.pos || cell == curUser.pos) { GLog.i( Messages.get(Wand.class, "self_target") ); return; - } else if (curUser.buff(MagicImmune.class) != null){ - GLog.w( Messages.get(Wand.class, "no_magic") ); - return; } curUser.sprite.zap(cell); @@ -424,7 +436,7 @@ public abstract class Wand extends Item { else QuickSlotButton.target(Actor.findChar(cell)); - if (curWand.curCharges >= (curWand.cursed ? 1 : curWand.chargesPerCast())) { + if (curWand.tryToZap(curUser)) { curUser.busy(); Invisibility.dispel(); @@ -452,10 +464,6 @@ public abstract class Wand extends Item { } curWand.cursedKnown = true; - } else { - - GLog.w( Messages.get(Wand.class, "fizzles") ); - } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfWarding.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfWarding.java new file mode 100644 index 000000000..0034ec26e --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfWarding.java @@ -0,0 +1,329 @@ +package com.shatteredpixel.shatteredpixeldungeon.items.wands; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.NPC; +import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile; +import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff; +import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica; +import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; +import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; +import com.shatteredpixel.shatteredpixeldungeon.sprites.WardSprite; +import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton; +import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; +import com.shatteredpixel.shatteredpixeldungeon.windows.WndOptions; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Callback; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; + +public class WandOfWarding extends Wand { + + { + collisionProperties = Ballistica.STOP_TARGET | Ballistica.STOP_TERRAIN; + + image = ItemSpriteSheet.WAND_WARDING; + } + + @Override + protected void onZap(Ballistica bolt) { + + int currentWardLevels = 0; + for (Char ch : Actor.chars()){ + if (ch instanceof Ward){ + currentWardLevels += ((Ward) ch).tier; + } + } + boolean canPlaceMore = currentWardLevels < level()+2; + + Char ch = Actor.findChar(bolt.collisionPos); + if (ch != null){ + if (ch instanceof Ward){ + if (canPlaceMore) { + ((Ward) ch).upgrade(level()); + } else { + if (((Ward) ch).tier <= 3){ + GLog.w("Your wand can't sustain any more wards."); + } else { + ((Ward) ch).wandHeal( level() ); + } + } + ch.sprite.emitter().burst(MagicMissile.WardParticle.UP, ((Ward) ch).tier); + } else { + GLog.w("There isn't room to place a ward here"); + } + } else if (canPlaceWard(bolt.collisionPos)){ + if (canPlaceMore) { + Ward ward = new Ward(); + ward.pos = bolt.collisionPos; + GameScene.add(ward, 1f); + ward.sprite.emitter().burst(MagicMissile.WardParticle.UP, ward.tier); + QuickSlotButton.target(ward); + } else { + GLog.w("Your wand can't sustain any more wards."); + } + } else { + GLog.w("There isn't room to place a ward here"); + } + } + + @Override + protected void fx(Ballistica bolt, Callback callback) { + MagicMissile.boltFromChar(curUser.sprite.parent, + MagicMissile.WARD, + curUser.sprite, + bolt.collisionPos, + callback); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + + @Override + public void onHit(MagesStaff staff, Char attacker, Char defender, int damage) { + //TODO + } + + @Override + public void staffFx(MagesStaff.StaffParticle particle) { + //TODO + super.staffFx(particle); + } + + public static boolean canPlaceWard(int pos){ + + int adjacentBlockedCells = 0; + int adjacentCellGroups = 0; + boolean prevOpen = openCell(pos + PathFinder.CIRCLE8[PathFinder.CIRCLE8.length-1]); + + for (int i : PathFinder.CIRCLE8){ + if (!openCell(pos + i)){ + adjacentBlockedCells++; + } + if (prevOpen != openCell(pos + i)){ + prevOpen = !prevOpen; + adjacentCellGroups++; + } + } + + switch (adjacentBlockedCells){ + case 0: case 1: + return true; + case 2: + return (openCell(pos + PathFinder.CIRCLE4[0]) || openCell( pos + PathFinder.CIRCLE4[2])) + && (openCell(pos + PathFinder.CIRCLE4[1]) || openCell( pos + PathFinder.CIRCLE4[3])); + case 3: + return adjacentCellGroups <= 2; + default: + return false; + } + + } + + private static boolean openCell(int pos){ + //a cell is considered blocked if it isn't passable or a ward is there + return Dungeon.level.passable[pos] && !(Actor.findChar(pos) instanceof Ward); + } + + public static class Ward extends NPC { + + private int tier = 1; + private int wandLevel = 1; + + private int totalZaps = 0; + + { + spriteClass = WardSprite.class; + + alignment = Alignment.ALLY; + + properties.add(Property.IMMOVABLE); + + viewDistance = 3; + state = WANDERING; + } + + public void upgrade( int wandLevel ){ + if (this.wandLevel < wandLevel){ + this.wandLevel = wandLevel; + } + + wandHeal(0); + + switch (tier){ + case 1: case 2: default: + break; //do nothing + case 3: + HP = HT = 30; + break; + case 4: + HT = 48; + HP = Math.round(48*(HP/30f)); + break; + case 5: + HT = 72; + HP = Math.round(72*(HP/48f)); + break; + } + + if (tier < 6){ + tier++; + viewDistance++; + updateSpriteState(); + } + } + + private void wandHeal( int wandLevel ){ + if (this.wandLevel < wandLevel){ + this.wandLevel = wandLevel; + } + + switch(tier){ + default: + break; + case 4: + HP = Math.min(HT, HP+6); + break; + case 5: + HP = Math.min(HT, HP+8); + break; + case 6: + HP = Math.min(HT, HP+12); + break; + } + } + + @Override + protected float attackDelay() { + switch (tier){ + case 1: case 2: default: + return 2f; + case 3: case 4: + return 1.5f; + case 5: case 6: + return 1f; + } + } + + @Override + protected boolean canAttack( Char enemy ) { + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + + @Override + protected boolean doAttack(Char enemy) { + boolean visible = fieldOfView[pos] || fieldOfView[enemy.pos]; + if (visible) { + sprite.zap( enemy.pos ); + } else { + zap(); + } + + return !visible; + } + + private void zap() { + spend( 1f ); + + //always hits + int dmg = Random.Int( 2 + wandLevel, 8 + 4*wandLevel ); + enemy.damage( dmg, WandOfWarding.class ); + + if (!enemy.isAlive() && enemy == Dungeon.hero) { + Dungeon.fail( getClass() ); + } + + totalZaps++; + switch(tier){ + default: + if (totalZaps >= tier){ + die(this); + } + break; + case 3: + if (totalZaps >= 4){ + die(this); + } + break; + case 4: + damage(6, this); + break; + case 5: + damage(8, this); + break; + case 6: + damage(9, this); + break; + } + } + + public void onZapComplete() { + zap(); + next(); + } + + @Override + protected boolean getCloser(int target) { + return false; + } + + @Override + protected boolean getFurther(int target) { + return false; + } + + @Override + public CharSprite sprite() { + WardSprite sprite = (WardSprite) super.sprite(); + sprite.updateTier(tier); + return sprite; + } + + @Override + public void updateSpriteState() { + super.updateSpriteState(); + ((WardSprite)sprite).updateTier(tier); + } + + @Override + public boolean canInteract(Hero h) { + return true; + } + + @Override + public boolean interact() { + GameScene.show(new WndOptions("test", "dismiss this ward?", "yes", "no"){ + @Override + protected void onSelect(int index) { + if (index == 0){ + die(null); + } + } + }); + return true; + } + + private static final String TIER = "tier"; + private static final String WAND_LEVEL = "wand_level"; + private static final String TOTAL_ZAPS = "total_zaps"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(TIER, tier); + bundle.put(WAND_LEVEL, wandLevel); + bundle.put(TOTAL_ZAPS, totalZaps); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + tier = bundle.getInt(TIER); + wandLevel = bundle.getInt(WAND_LEVEL); + totalZaps = bundle.getInt(TOTAL_ZAPS); + } + } +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java index 3367489c1..58278c3aa 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java @@ -57,6 +57,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfStrength; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade; import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfEnchantment; import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfIntuition; +import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfWarding; import com.shatteredpixel.shatteredpixeldungeon.levels.features.Chasm; import com.shatteredpixel.shatteredpixeldungeon.levels.features.Door; import com.shatteredpixel.shatteredpixeldungeon.levels.features.HighGrass; @@ -976,6 +977,22 @@ public abstract class Level implements Bundlable { fieldOfView[p+i] = true; } } + + for (Mob ward : mobs){ + if (ward instanceof WandOfWarding.Ward){ + if (ward.fieldOfView == null || ward.fieldOfView.length != length()){ + ward.fieldOfView = new boolean[length()]; + Dungeon.level.updateFieldOfView( ward, ward.fieldOfView ); + } + for (Mob m : mobs){ + if (ward.fieldOfView[m.pos] && !fieldOfView[m.pos] && + !Dungeon.hero.mindVisionEnemies.contains(m)){ + Dungeon.hero.mindVisionEnemies.add(m); + } + } + BArray.or(fieldOfView, ward.fieldOfView, fieldOfView); + } + } } if (c == Dungeon.hero) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/SpinnerSprite.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/SpinnerSprite.java index fdf7817b4..5d075928f 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/SpinnerSprite.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/SpinnerSprite.java @@ -54,6 +54,7 @@ public class SpinnerSprite extends MobSprite { @Override public void link(Char ch) { super.link(ch); + if (parent != null) parent.sendToBack(this); renderShadow = false; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/WardSprite.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/WardSprite.java new file mode 100644 index 000000000..7c6210b00 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/WardSprite.java @@ -0,0 +1,116 @@ +package com.shatteredpixel.shatteredpixeldungeon.sprites; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.effects.Beam; +import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile; +import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfWarding; +import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap; +import com.watabou.noosa.Game; +import com.watabou.noosa.tweeners.AlphaTweener; + +public class WardSprite extends MobSprite { + + private Animation tierIdles[] = new Animation[7]; + + public WardSprite(){ + super(); + + texture(Assets.WARDS); + + tierIdles[1] = new Animation( 1, true ); + tierIdles[1].frames(texture.uvRect(0, 0, 9, 10)); + + tierIdles[2] = new Animation( 1, true ); + tierIdles[2].frames(texture.uvRect(10, 0, 21, 12)); + + tierIdles[3] = new Animation( 1, true ); + tierIdles[3].frames(texture.uvRect(22, 0, 37, 16)); + + tierIdles[4] = new Animation( 1, true ); + tierIdles[4].frames(texture.uvRect(38, 0, 44, 13)); + + tierIdles[5] = new Animation( 1, true ); + tierIdles[5].frames(texture.uvRect(45, 0, 51, 15)); + + tierIdles[6] = new Animation( 1, true ); + tierIdles[6].frames(texture.uvRect(52, 0, 60, 15)); + + } + + @Override + public void zap( int pos ) { + idle(); + flash(); + emitter().burst(MagicMissile.WardParticle.UP, 2); + if (Actor.findChar(pos) != null){ + parent.add(new Beam.DeathRay(center(), Actor.findChar(pos).sprite.center())); + } else { + parent.add(new Beam.DeathRay(center(), DungeonTilemap.raisedTileCenterToWorld(pos))); + } + ((WandOfWarding.Ward)ch).onZapComplete(); + } + + @Override + public void die() { + super.die(); + //cancels die animation and fades out immediately + play(idle, true); + emitter().burst(MagicMissile.WardParticle.UP, 10); + parent.add( new AlphaTweener( this, 0, 2f ) { + @Override + protected void onComplete() { + WardSprite.this.killAndErase(); + parent.erase( this ); + } + } ); + } + + public void updateTier(int tier){ + + idle = tierIdles[tier]; + run = idle.clone(); + //zap = idle.clone(); + //attack = idle.clone(); + die = idle.clone(); + + //always render first + if (parent != null) { + parent.sendToBack(this); + } + + idle(); + + if (tier <= 3){ + shadowWidth = shadowHeight = 1f; + perspectiveRaise = (16 - height()) / 32f; //center of the cell + } else { + shadowWidth = 1.2f; + shadowHeight = 0.25f; + perspectiveRaise = 6 / 16f; //6 pixels + } + + if (ch != null) { + place(ch.pos); + } + } + + private float baseY; + + @Override + public void place(int cell) { + super.place(cell); + baseY = y; + } + + @Override + public void update() { + super.update(); + //if tier is greater than 3 + if (perspectiveRaise >= 6 / 16f){ + y = baseY + (float) Math.sin(Game.timeTotal); + shadowOffset = 0.25f - 0.8f*(float) Math.sin(Game.timeTotal); + } + } + +}