diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/actors/Actor.java b/src/com/shatteredpixel/shatteredpixeldungeon/actors/Actor.java index ed73834b8..4f1c38736 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/actors/Actor.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/actors/Actor.java @@ -20,6 +20,8 @@ package com.shatteredpixel.shatteredpixeldungeon.actors; import java.util.Arrays; import java.util.HashSet; +import android.util.SparseArray; + import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.Statistics; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob; @@ -35,7 +37,9 @@ public abstract class Actor implements Bundlable { public static final float TICK = 1f; private float time; - + + private int id = 0; + protected abstract boolean act(); protected void spend( float time ) { @@ -59,25 +63,44 @@ public abstract class Actor implements Bundlable { protected void onAdd() {} protected void onRemove() {} - - private static final String TIME = "time"; - + + private static final String TIME = "time"; + private static final String ID = "id"; + @Override public void storeInBundle( Bundle bundle ) { bundle.put( TIME, time ); + bundle.put( ID, id ); } - + @Override public void restoreFromBundle( Bundle bundle ) { time = bundle.getFloat( TIME ); + id = bundle.getInt( ID ); } - + + public int id() { + if (id > 0) { + return id; + } else { + int max = 0; + for (Actor a : all) { + if (a.id > max) { + max = a.id; + } + } + return (id = max + 1); + } + } + // ********************** // *** Static members *** private static HashSet all = new HashSet(); private static Actor current; - + + private static SparseArray ids = new SparseArray(); + private static float now = 0; private static Char[] chars = new Char[Level.LENGTH]; @@ -88,6 +111,8 @@ public abstract class Actor implements Bundlable { Arrays.fill( chars, null ); all.clear(); + + ids.clear(); } public static void fixTime() { @@ -202,9 +227,13 @@ public abstract class Actor implements Bundlable { if (all.contains( actor )) { return; } - + + if (actor.id > 0) { + ids.put( actor.id, actor ); + } + all.add( actor ); - actor.time += time; // (+=) => (=) ? + actor.time += time; actor.onAdd(); if (actor instanceof Char) { @@ -222,13 +251,21 @@ public abstract class Actor implements Bundlable { if (actor != null) { all.remove( actor ); actor.onRemove(); + + if (actor.id > 0) { + ids.remove( actor.id ); + } } } public static Char findChar( int pos ) { return chars[pos]; } - + + public static Actor findById( int id ) { + return ids.get( id ); + } + public static HashSet all() { return all; } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java b/src/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java index a702b2621..2a96148d5 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java @@ -35,11 +35,12 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; import com.shatteredpixel.shatteredpixeldungeon.utils.Utils; import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.Camera; import com.watabou.utils.Bundlable; import com.watabou.utils.Bundle; +import com.watabou.utils.GameMath; import com.watabou.utils.Random; -import java.util.ArrayList; import java.util.HashSet; public abstract class Char extends Actor { @@ -65,7 +66,6 @@ public abstract class Char extends Actor { protected float baseSpeed = 1; public boolean paralysed = false; - public boolean pacified = false; public boolean rooted = false; public boolean flying = false; public int invisible = 0; @@ -127,10 +127,24 @@ public abstract class Char extends Actor { HeroSubClass.SNIPER ? 0 : Random.IntRange( 0, enemy.dr() ); int dmg = damageRoll(); - int effectiveDamage = Math.max( dmg - dr, 0 );; + int effectiveDamage = Math.max( dmg - dr, 0 ); effectiveDamage = attackProc( enemy, effectiveDamage ); effectiveDamage = enemy.defenseProc( this, effectiveDamage ); + + //game screen shakes for large amounts of damage dealt to/by the player. + //TODO: make sure this isn't distracting + float shake = 0f; + if (enemy == Dungeon.hero) { + shake = Math.max(effectiveDamage / (enemy.HT / 4), + (float) Math.pow(effectiveDamage / (enemy.HP / 2), 2)); + } else if (this == Dungeon.hero && effectiveDamage >= enemy.HP) { + shake = (float) Math.pow(effectiveDamage / (enemy.HT / 2), 2); + } + + if (shake > 1f) + Camera.main.shake( GameMath.gate( 1, shake, 5), 0.3f ); + enemy.damage( effectiveDamage, this ); if (visibleFight) { @@ -141,7 +155,7 @@ public abstract class Char extends Actor { buff(FireImbue.class).proc(enemy); if (buff(EarthImbue.class) != null) buff(EarthImbue.class).proc(enemy); - + enemy.sprite.bloodBurstA( sprite.center(), effectiveDamage ); enemy.sprite.flash(); @@ -149,10 +163,11 @@ public abstract class Char extends Actor { if (enemy == Dungeon.hero) { if (Dungeon.hero.killerGlyph != null) { - - Dungeon.fail( Utils.format( ResultDescriptions.GLYPH, Dungeon.hero.killerGlyph.name(), Dungeon.depth ) ); - GLog.n( TXT_KILL, Dungeon.hero.killerGlyph.name() ); - + + // FIXME + // Dungeon.fail( Utils.format( ResultDescriptions.GLYPH, Dungeon.hero.killerGlyph.name(), Dungeon.depth ) ); + // GLog.n( TXT_KILL, Dungeon.hero.killerGlyph.name() ); + } else { if ( this instanceof Yog ) { Dungeon.fail( Utils.format( ResultDescriptions.NAMED, name) ); @@ -183,7 +198,7 @@ public abstract class Char extends Actor { GLog.i( TXT_SMB_MISSED, enemy.name, defense, name ); } - Sample.INSTANCE.play( Assets.SND_MISS ); + Sample.INSTANCE.play(Assets.SND_MISS); } return false; @@ -325,8 +340,17 @@ public abstract class Char extends Actor { } return null; } - - + + public boolean isCharmedBy( Char ch ) { + int chID = ch.id(); + for (Buff b : buffs) { + if (b instanceof Charm && ((Charm)b).object == chID) { + return true; + } + } + return false; + } + public void add( Buff buff ) { buffs.add( buff ); @@ -450,17 +474,11 @@ public abstract class Char extends Actor { public void move( int step ) { - if (buff( Vertigo.class ) != null) { - ArrayList candidates = new ArrayList(); - for (int dir : Level.NEIGHBOURS8) { - int p = pos + dir; - if ((Level.passable[p] || Level.avoid[p]) && Actor.findChar( p ) == null) { - candidates.add( p ); - } - } - - step = Random.element( candidates ); - } + if (Level.adjacent( step, pos ) && buff( Vertigo.class ) != null) { + step = pos + Level.NEIGHBOURS8[Random.Int( 8 )]; + if (!(Level.passable[step] || Level.avoid[step]) || Actor.findChar( step ) != null) + return; + } if (Dungeon.level.map[pos] == Terrain.OPEN_DOOR) { Door.leave( pos );