Merging Source v1.7.2: actor changes

This commit is contained in:
Evan Debenham
2014-10-20 23:51:15 -04:00
parent 724338b57f
commit 4a49763309
30 changed files with 980 additions and 682 deletions
@@ -130,10 +130,12 @@ public abstract class Actor implements Bundlable {
public static void freeCell( int pos ) { public static void freeCell( int pos ) {
chars[pos] = null; chars[pos] = null;
} }
protected static void next() { /*protected*/public void next() {
current = null; if (current == this) {
} current = null;
}
}
public static void process() { public static void process() {
@@ -167,6 +169,14 @@ public abstract class Actor implements Bundlable {
} }
if (current != null) { if (current != null) {
if (current instanceof Char && ((Char)current).sprite.isMoving) {
// If it's character's turn to act, but its sprite
// is moving, wait till the movement is over
current = null;
break;
}
doNext = current.act(); doNext = current.act();
if (doNext && !Dungeon.hero.isAlive()) { if (doNext && !Dungeon.hero.isAlive()) {
doNext = false; doNext = false;
@@ -17,6 +17,7 @@
*/ */
package com.shatteredpixel.shatteredpixeldungeon.actors; package com.shatteredpixel.shatteredpixeldungeon.actors;
import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.*; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.*;
@@ -120,9 +121,9 @@ public abstract class Char extends Actor {
GLog.i( TXT_HIT, name, enemy.name ); GLog.i( TXT_HIT, name, enemy.name );
} }
// Refactoring needed! // FIXME
int dr = this instanceof Hero && ((Hero)this).usingRanged && ((Hero)this).subClass == HeroSubClass.SNIPER ? int dr = this instanceof Hero && ((Hero)this).rangedWeapon != null && ((Hero)this).subClass ==
0 : Random.IntRange( 0, enemy.dr() ); HeroSubClass.SNIPER ? 0 : Random.IntRange( 0, enemy.dr() );
int dmg = damageRoll(); int dmg = damageRoll();
int effectiveDamage = Math.max( dmg - dr, 0 );; int effectiveDamage = Math.max( dmg - dr, 0 );;
@@ -367,8 +368,12 @@ public abstract class Char extends Actor {
} else if (buff instanceof Bleeding) { } else if (buff instanceof Bleeding) {
sprite.showStatus( CharSprite.NEGATIVE, "bleeding" ); sprite.showStatus( CharSprite.NEGATIVE, "bleeding" );
} else if (buff instanceof Sleep) { } else if (buff instanceof Vertigo) {
sprite.showStatus( CharSprite.NEGATIVE, "dizzy" );
} else if (buff instanceof Sleep) {
sprite.idle(); sprite.idle();
} }
@@ -441,6 +446,19 @@ public abstract class Char extends Actor {
} }
public void move( int step ) { public void move( int step ) {
if (buff( Vertigo.class ) != null) {
ArrayList<Integer> candidates = new ArrayList<Integer>();
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 (Dungeon.level.map[pos] == Terrain.OPEN_DOOR) { if (Dungeon.level.map[pos] == Terrain.OPEN_DOOR) {
Door.leave( pos ); Door.leave( pos );
} }
@@ -0,0 +1,52 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* 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 <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.actors.blobs;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vertigo;
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
public class ConfusionGas extends Blob {
@Override
protected void evolve() {
super.evolve();
Char ch;
for (int i=0; i < LENGTH; i++) {
if (cur[i] > 0 && (ch = Actor.findChar( i )) != null) {
Buff.prolong( ch, Vertigo.class, Vertigo.duration( ch ) );
}
}
}
@Override
public void use( BlobEmitter emitter ) {
super.use( emitter );
emitter.pour( Speck.factory( Speck.CONFUSION, true ), 0.6f );
}
@Override
public String tileDesc() {
return "A cloud of confusion gas is swirling here.";
}
}
@@ -27,23 +27,24 @@ import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils; import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
import com.watabou.utils.Random;
public class ToxicGas extends Blob implements Hero.Doom { public class ToxicGas extends Blob implements Hero.Doom {
@Override @Override
protected void evolve() { protected void evolve() {
super.evolve(); super.evolve();
int levelDamage = 5 + Dungeon.depth * 5; int levelDamage = 5 + Dungeon.depth * 5;
Char ch; Char ch;
for (int i=0; i < LENGTH; i++) { for (int i=0; i < LENGTH; i++) {
if (cur[i] > 0 && (ch = Actor.findChar( i )) != null) { if (cur[i] > 0 && (ch = Actor.findChar( i )) != null) {
int damage = (ch.HT + levelDamage) / 40; int damage = (ch.HT + levelDamage) / 40;
if (damage < 1) { if (Random.Int( 40 ) < (ch.HT + levelDamage) % 40) {
damage = 1; damage++;
} }
ch.damage( damage, this ); ch.damage( damage, this );
} }
@@ -17,7 +17,7 @@
*/ */
package com.shatteredpixel.shatteredpixeldungeon.actors.buffs; package com.shatteredpixel.shatteredpixeldungeon.actors.buffs;
// Special kind of buff, that doesn't perform any kind actions //Special kind of buff, that doesn't perform any kind actions
public class FlavourBuff extends Buff { public class FlavourBuff extends Buff {
@Override @Override
@@ -41,7 +41,7 @@ public class MagicalSleep extends Buff {
GLog.i("You fall into a deep magical sleep."); GLog.i("You fall into a deep magical sleep.");
} }
else if (target instanceof Mob) else if (target instanceof Mob)
((Mob)target).state = Mob.State.SLEEPING; ((Mob)target).state = ((Mob)target).SLEEPEING;
target.paralysed = true; target.paralysed = true;
@@ -30,8 +30,6 @@ import com.watabou.utils.Bundle;
public class Poison extends Buff implements Hero.Doom { public class Poison extends Buff implements Hero.Doom {
public static final int DOT = 2;
protected float left; protected float left;
private static final String LEFT = "left"; private static final String LEFT = "left";
@@ -67,7 +65,7 @@ public class Poison extends Buff implements Hero.Doom {
public boolean act() { public boolean act() {
if (target.isAlive()) { if (target.isAlive()) {
target.damage( DOT, this ); target.damage( (int)(left / 3) + 1, this );
spend( TICK ); spend( TICK );
if ((left -= TICK) <= 0) { if ((left -= TICK) <= 0) {
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2012-2014 Oleg Dolya
*
* 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 <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.actors.buffs;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfElements.Resistance;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
public class Vertigo extends FlavourBuff {
public static final float DURATION = 10f;
@Override
public int icon() {
return BuffIndicator.VERTIGO;
}
@Override
public String toString() {
return "Vertigo";
}
public static float duration( Char ch ) {
Resistance r = ch.buff( Resistance.class );
return r != null ? r.durationFactor() * DURATION : DURATION;
}
}
@@ -117,18 +117,17 @@ public class Belongings implements Iterable<Item> {
return null; return null;
} }
public void countIronKeys() { public void countIronKeys() {
IronKey.curDepthQunatity = 0; IronKey.curDepthQuantity = 0;
for (Item item : backpack) { for (Item item : backpack) {
if (item instanceof IronKey && ((IronKey)item).depth == Dungeon.depth) { if (item instanceof IronKey && ((IronKey)item).depth == Dungeon.depth) {
IronKey.curDepthQunatity = item.quantity(); IronKey.curDepthQuantity++;
return; }
} }
} }
}
public void identify() { public void identify() {
for (Item item : this) { for (Item item : this) {
@@ -20,12 +20,16 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.hero;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
import com.shatteredpixel.shatteredpixeldungeon.Statistics; import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Drowsy; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Drowsy;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vertigo;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.NPC;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.CapeOfThorns; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.CapeOfThorns;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TalismanOfForesight; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TalismanOfForesight;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.*; import com.shatteredpixel.shatteredpixeldungeon.items.rings.*;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon;
import com.watabou.noosa.Camera; import com.watabou.noosa.Camera;
import com.watabou.noosa.Game; import com.watabou.noosa.Game;
import com.watabou.noosa.audio.Sample; import com.watabou.noosa.audio.Sample;
@@ -142,8 +146,8 @@ public class Hero extends Char {
private Item theKey; private Item theKey;
public boolean restoreHealth = false; public boolean restoreHealth = false;
public boolean usingRanged = false; public MissileWeapon rangedWeapon = null;
public Belongings belongings; public Belongings belongings;
public int STR; public int STR;
@@ -224,9 +228,6 @@ public class Hero extends Char {
} }
public static void preview( GamesInProgress.Info info, Bundle bundle ) { public static void preview( GamesInProgress.Info info, Bundle bundle ) {
// Refactoring needed!
Armor armor = (Armor)bundle.get( "armor" );
info.armor = armor == null ? 0 : armor.tier;
info.level = bundle.getInt( LEVEL ); info.level = bundle.getInt( LEVEL );
} }
@@ -242,30 +243,29 @@ public class Hero extends Char {
public int tier() { public int tier() {
return belongings.armor == null ? 0 : belongings.armor.tier; return belongings.armor == null ? 0 : belongings.armor.tier;
} }
public boolean shoot( Char enemy, Weapon wep ) { public boolean shoot( Char enemy, MissileWeapon wep ) {
// Ugly... rangedWeapon = wep;
usingRanged = true; boolean result = attack( enemy );
rangedWeapon = null;
KindOfWeapon curWep = belongings.weapon;
belongings.weapon = wep; return result;
}
boolean result = attack( enemy );
belongings.weapon = curWep;
usingRanged = false;
return result;
}
@Override @Override
public int attackSkill( Char target ) { public int attackSkill( Char target ) {
if (belongings.weapon != null) { float accuracy = 1;
return (int) (attackSkill * belongings.weapon.acuracyFactor(this)); if (rangedWeapon != null && Level.distance( pos, target.pos ) == 1) {
accuracy *= 0.5f;
}
KindOfWeapon wep = rangedWeapon != null ? rangedWeapon : belongings.weapon;
if (wep != null) {
return (int)(attackSkill * accuracy * wep.acuracyFactor( this ));
} else { } else {
return attackSkill; return (int)(attackSkill * accuracy);
} }
} }
@Override @Override
@@ -312,14 +312,15 @@ public class Hero extends Char {
@Override @Override
public int damageRoll() { public int damageRoll() {
KindOfWeapon wep = rangedWeapon != null ? rangedWeapon : belongings.weapon;
int dmg; int dmg;
int bonus = 0; int bonus = 0;
for (Buff buff : buffs( RingOfForce.Force.class )) { for (Buff buff : buffs( RingOfForce.Force.class )) {
bonus += ((RingOfForce.Force)buff).level; bonus += ((RingOfForce.Force)buff).level;
} }
if (belongings.weapon != null) { if (wep != null) {
dmg = belongings.weapon.damageRoll( this ) + bonus; dmg = wep.damageRoll( this ) + bonus;
} else { } else {
int bonusMax = 1 + (int)(bonus * (lvl/5f)); int bonusMax = 1 + (int)(bonus * (lvl/5f));
dmg = Random.NormalIntRange( 1+bonus, Math.max(1+bonus , STR()-9+bonusMax ) ); dmg = Random.NormalIntRange( 1+bonus, Math.max(1+bonus , STR()-9+bonusMax ) );
@@ -353,9 +354,10 @@ public class Hero extends Char {
} }
public float attackDelay() { public float attackDelay() {
if (belongings.weapon != null) { KindOfWeapon wep = rangedWeapon != null ? rangedWeapon : belongings.weapon;
if (wep != null) {
return belongings.weapon.speedFactor( this ); return wep.speedFactor( this );
} else { } else {
//Normally putting furor speed on unarmed attacks would be unnecessary //Normally putting furor speed on unarmed attacks would be unnecessary
@@ -408,6 +410,7 @@ public class Hero extends Char {
} }
ready(); ready();
return false;
} else { } else {
@@ -417,52 +420,52 @@ public class Hero extends Char {
if (curAction instanceof HeroAction.Move) { if (curAction instanceof HeroAction.Move) {
actMove( (HeroAction.Move)curAction ); return actMove( (HeroAction.Move)curAction );
} else } else
if (curAction instanceof HeroAction.Interact) { if (curAction instanceof HeroAction.Interact) {
actInteract( (HeroAction.Interact)curAction ); return actInteract( (HeroAction.Interact)curAction );
} else } else
if (curAction instanceof HeroAction.Buy) { if (curAction instanceof HeroAction.Buy) {
actBuy( (HeroAction.Buy)curAction ); return actBuy( (HeroAction.Buy)curAction );
}else }else
if (curAction instanceof HeroAction.PickUp) { if (curAction instanceof HeroAction.PickUp) {
actPickUp( (HeroAction.PickUp)curAction ); return actPickUp( (HeroAction.PickUp)curAction );
} else } else
if (curAction instanceof HeroAction.OpenChest) { if (curAction instanceof HeroAction.OpenChest) {
actOpenChest( (HeroAction.OpenChest)curAction ); return actOpenChest( (HeroAction.OpenChest)curAction );
} else } else
if (curAction instanceof HeroAction.Unlock) { if (curAction instanceof HeroAction.Unlock) {
actUnlock( (HeroAction.Unlock)curAction ); return actUnlock((HeroAction.Unlock) curAction);
} else } else
if (curAction instanceof HeroAction.Descend) { if (curAction instanceof HeroAction.Descend) {
actDescend( (HeroAction.Descend)curAction ); return actDescend( (HeroAction.Descend)curAction );
} else } else
if (curAction instanceof HeroAction.Ascend) { if (curAction instanceof HeroAction.Ascend) {
actAscend( (HeroAction.Ascend)curAction ); return actAscend( (HeroAction.Ascend)curAction );
} else } else
if (curAction instanceof HeroAction.Attack) { if (curAction instanceof HeroAction.Attack) {
actAttack( (HeroAction.Attack)curAction ); return actAttack( (HeroAction.Attack)curAction );
} else } else
if (curAction instanceof HeroAction.Cook) { if (curAction instanceof HeroAction.Cook) {
actCook( (HeroAction.Cook)curAction ); return actCook( (HeroAction.Cook)curAction );
} }
} }
@@ -495,40 +498,47 @@ public class Hero extends Char {
act(); act();
} }
private void actMove( HeroAction.Move action ) { private boolean actMove( HeroAction.Move action ) {
if (getCloser( action.dst )) { if (getCloser( action.dst )) {
return true;
} else { } else {
if (Dungeon.level.map[pos] == Terrain.SIGN) { if (Dungeon.level.map[pos] == Terrain.SIGN) {
GameScene.show( new WndMessage( Dungeon.tip() ) ); GameScene.show( new WndMessage( Dungeon.tip() ) );
} }
ready(); ready();
return false;
} }
} }
private void actInteract( HeroAction.Interact action ) { private boolean actInteract( HeroAction.Interact action ) {
Mob.NPC npc = action.npc; NPC npc = action.npc;
if (Level.adjacent( pos, npc.pos )) { if (Level.adjacent( pos, npc.pos )) {
ready(); ready();
sprite.turnTo( pos, npc.pos ); sprite.turnTo( pos, npc.pos );
npc.interact(); npc.interact();
return false;
} else { } else {
if (Level.fieldOfView[npc.pos] && getCloser( npc.pos )) { if (Level.fieldOfView[npc.pos] && getCloser( npc.pos )) {
return true;
} else { } else {
ready(); ready();
return false;
} }
} }
} }
private void actBuy( HeroAction.Buy action ) { private boolean actBuy( HeroAction.Buy action ) {
int dst = action.dst; int dst = action.dst;
if (pos == dst || Level.adjacent( pos, dst )) { if (pos == dst || Level.adjacent( pos, dst )) {
@@ -538,29 +548,38 @@ public class Hero extends Char {
if (heap != null && heap.type == Type.FOR_SALE && heap.size() == 1) { if (heap != null && heap.type == Type.FOR_SALE && heap.size() == 1) {
GameScene.show( new WndTradeItem( heap, true ) ); GameScene.show( new WndTradeItem( heap, true ) );
} }
return false;
} else if (getCloser( dst )) { } else if (getCloser( dst )) {
return true;
} else { } else {
ready(); ready();
return false;
} }
} }
private void actCook( HeroAction.Cook action ) { private boolean actCook( HeroAction.Cook action ) {
int dst = action.dst; int dst = action.dst;
if (Dungeon.visible[dst]) { if (Dungeon.visible[dst]) {
ready(); ready();
AlchemyPot.operate( this, dst ); AlchemyPot.operate( this, dst );
return false;
} else if (getCloser( dst )) { } else if (getCloser( dst )) {
return true;
} else { } else {
ready(); ready();
return false;
} }
} }
private void actPickUp( HeroAction.PickUp action ) { private boolean actPickUp( HeroAction.PickUp action ) {
int dst = action.dst; int dst = action.dst;
if (pos == dst) { if (pos == dst) {
@@ -597,16 +616,21 @@ public class Hero extends Char {
} }
} else { } else {
ready(); ready();
} }
} else if (getCloser( dst )) { return false;
} else { } else if (getCloser( dst )) {
ready();
return true;
} else {
ready();
return false;
} }
} }
private void actOpenChest( HeroAction.OpenChest action ) { private boolean actOpenChest( HeroAction.OpenChest action ) {
int dst = action.dst; int dst = action.dst;
if (Level.adjacent( pos, dst ) || pos == dst) { if (Level.adjacent( pos, dst ) || pos == dst) {
@@ -624,7 +648,7 @@ public class Hero extends Char {
if (theKey == null) { if (theKey == null) {
GLog.w( TXT_LOCKED_CHEST ); GLog.w( TXT_LOCKED_CHEST );
ready(); ready();
return; return false;
} }
} }
@@ -644,16 +668,21 @@ public class Hero extends Char {
} else { } else {
ready(); ready();
} }
} else if (getCloser( dst )) { return false;
} else { } else if (getCloser( dst )) {
ready();
} return true;
} else {
ready();
return false;
}
} }
private void actUnlock( HeroAction.Unlock action ) { private boolean actUnlock( HeroAction.Unlock action ) {
int doorCell = action.dst; int doorCell = action.dst;
if (Level.adjacent( pos, doorCell )) { if (Level.adjacent( pos, doorCell )) {
@@ -680,16 +709,21 @@ public class Hero extends Char {
} else { } else {
GLog.w( TXT_LOCKED_DOOR ); GLog.w( TXT_LOCKED_DOOR );
ready(); ready();
} }
} else if (getCloser( doorCell )) { return false;
} else { } else if (getCloser( doorCell )) {
ready();
} return true;
} else {
ready();
return false;
}
} }
private void actDescend( HeroAction.Descend action ) { private boolean actDescend( HeroAction.Descend action ) {
int stairs = action.dst; int stairs = action.dst;
if (pos == stairs && pos == Dungeon.level.exit) { if (pos == stairs && pos == Dungeon.level.exit) {
@@ -701,16 +735,21 @@ public class Hero extends Char {
} }
InterlevelScene.mode = InterlevelScene.Mode.DESCEND; InterlevelScene.mode = InterlevelScene.Mode.DESCEND;
Game.switchScene( InterlevelScene.class ); Game.switchScene( InterlevelScene.class );
} else if (getCloser( stairs )) { return false;
} else { } else if (getCloser( stairs )) {
ready();
} return true;
} else {
ready();
return false;
}
} }
private void actAscend( HeroAction.Ascend action ) { private boolean actAscend( HeroAction.Ascend action ) {
int stairs = action.dst; int stairs = action.dst;
if (pos == stairs && pos == Dungeon.level.entrance) { if (pos == stairs && pos == Dungeon.level.entrance) {
@@ -720,6 +759,7 @@ public class Hero extends Char {
GameScene.show( new WndMessage( TXT_LEAVE ) ); GameScene.show( new WndMessage( TXT_LEAVE ) );
ready(); ready();
} else { } else {
Dungeon.win( ResultDescriptions.WIN );
Dungeon.deleteGame( Dungeon.hero.heroClass, true ); Dungeon.deleteGame( Dungeon.hero.heroClass, true );
Game.switchScene( SurfaceScene.class ); Game.switchScene( SurfaceScene.class );
} }
@@ -735,33 +775,43 @@ public class Hero extends Char {
InterlevelScene.mode = InterlevelScene.Mode.ASCEND; InterlevelScene.mode = InterlevelScene.Mode.ASCEND;
Game.switchScene( InterlevelScene.class ); Game.switchScene( InterlevelScene.class );
} }
} else if (getCloser( stairs )) {
} else { return false;
ready();
} } else if (getCloser( stairs )) {
return true;
} else {
ready();
return false;
}
} }
private void actAttack( HeroAction.Attack action ) { private boolean actAttack( HeroAction.Attack action ) {
enemy = action.target; enemy = action.target;
if (Level.adjacent( pos, enemy.pos ) && enemy.isAlive() && !pacified) { if (Level.adjacent( pos, enemy.pos ) && enemy.isAlive() && !pacified) {
spend( attackDelay() ); spend( attackDelay() );
sprite.attack( enemy.pos ); sprite.attack( enemy.pos );
} else { return false;
if (Level.fieldOfView[enemy.pos] && getCloser( enemy.pos )) { } else {
} else { if (Level.fieldOfView[enemy.pos] && getCloser( enemy.pos )) {
ready();
} return true;
} } else {
ready();
return false;
}
}
} }
public void rest( boolean tillHealthy ) { public void rest( boolean tillHealthy ) {
@@ -774,20 +824,20 @@ public class Hero extends Char {
@Override @Override
public int attackProc( Char enemy, int damage ) { public int attackProc( Char enemy, int damage ) {
if (belongings.weapon != null) { KindOfWeapon wep = rangedWeapon != null ? rangedWeapon : belongings.weapon;
if (wep != null) {
KindOfWeapon weapon = belongings.weapon;
weapon.proc( this, enemy, damage ); wep.proc( this, enemy, damage );
switch (subClass) { switch (subClass) {
case GLADIATOR: case GLADIATOR:
if (weapon instanceof MeleeWeapon) { if (wep instanceof MeleeWeapon) {
damage += Buff.affect( this, Combo.class ).hit( enemy, damage ); damage += Buff.affect( this, Combo.class ).hit( enemy, damage );
} }
break; break;
case BATTLEMAGE: case BATTLEMAGE:
if (weapon instanceof Wand) { if (wep instanceof Wand) {
Wand wand = (Wand)weapon; Wand wand = (Wand)wep;
if (wand.curCharges < wand.maxCharges && damage > 0) { if (wand.curCharges < wand.maxCharges && damage > 0) {
wand.curCharges++; wand.curCharges++;
@@ -800,7 +850,7 @@ public class Hero extends Char {
damage += wand.curCharges; damage += wand.curCharges;
} }
case SNIPER: case SNIPER:
if (usingRanged) { if (rangedWeapon != null) {
Buff.prolong( enemy, SnipersMark.class, attackDelay() * 1.1f ); Buff.prolong( enemy, SnipersMark.class, attackDelay() * 1.1f );
} }
break; break;
@@ -859,7 +909,6 @@ public class Hero extends Char {
} }
private void checkVisibleMobs() { private void checkVisibleMobs() {
ArrayList<Mob> visible = new ArrayList<Mob>(); ArrayList<Mob> visible = new ArrayList<Mob>();
boolean newMob = false; boolean newMob = false;
@@ -886,7 +935,7 @@ public class Hero extends Char {
} }
public Mob visibleEnemy( int index ) { public Mob visibleEnemy( int index ) {
return visibleEnemies.get( index % visibleEnemies.size() ); return visibleEnemies.get(index % visibleEnemies.size());
} }
private boolean getCloser( final int target ) { private boolean getCloser( final int target ) {
@@ -925,9 +974,10 @@ public class Hero extends Char {
} }
if (step != -1) { if (step != -1) {
sprite.move( pos, step ); int oldPos = pos;
move( step ); move(step);
sprite.move(oldPos, pos);
spend( 1 / speed() ); spend( 1 / speed() );
return true; return true;
@@ -940,10 +990,10 @@ public class Hero extends Char {
} }
public void handle( int cell ) { public boolean handle( int cell ) {
if (cell == -1) { if (cell == -1) {
return; return false;
} }
Char ch; Char ch;
@@ -956,8 +1006,8 @@ public class Hero extends Char {
} else } else
if (Level.fieldOfView[cell] && (ch = Actor.findChar( cell )) instanceof Mob) { if (Level.fieldOfView[cell] && (ch = Actor.findChar( cell )) instanceof Mob) {
if (ch instanceof Mob.NPC) { if (ch instanceof NPC) {
curAction = new HeroAction.Interact( (Mob.NPC)ch ); curAction = new HeroAction.Interact( (NPC)ch );
} else { } else {
curAction = new HeroAction.Attack( ch ); curAction = new HeroAction.Attack( ch );
} }
@@ -996,7 +1046,7 @@ public class Hero extends Char {
} }
act(); return act();
} }
public void earnExp( int exp ) { public void earnExp( int exp ) {
@@ -1091,6 +1141,9 @@ public class Hero extends Char {
if (((RingOfMight.Might)buff).level > 0) { if (((RingOfMight.Might)buff).level > 0) {
HT += ((RingOfMight.Might) buff).level * 5; HT += ((RingOfMight.Might) buff).level * 5;
} }
} else if (buff instanceof Vertigo) {
GLog.w("Everything is spinning around you!");
interrupt();
} }
else if (buff instanceof Light) { else if (buff instanceof Light) {
@@ -1202,18 +1255,17 @@ public class Hero extends Char {
if (!flying) { if (!flying) {
if (Level.water[step]) { if (Level.water[pos]) {
Sample.INSTANCE.play( Assets.SND_WATER, 1, 1, Random.Float( 0.8f, 1.25f ) ); Sample.INSTANCE.play( Assets.SND_WATER, 1, 1, Random.Float( 0.8f, 1.25f ) );
} else { } else {
Sample.INSTANCE.play( Assets.SND_STEP ); Sample.INSTANCE.play( Assets.SND_STEP );
} }
Dungeon.level.press(step, this); Dungeon.level.press(pos, this);
} }
} }
@Override @Override
public void onMotionComplete() { public void onMotionComplete() {
Dungeon.observe(); Dungeon.observe();
search( false ); search( false );
@@ -1274,22 +1326,10 @@ public class Hero extends Char {
int positive = 0; int positive = 0;
int negative = 0; int negative = 0;
//holding onto this code for now as it may be useful in coding the Talisman of Foresight.
/*
for (Buff buff : buffs( RingOfDetection.Detection.class )) {
int bonus = ((RingOfDetection.Detection)buff).level;
if (bonus > positive) {
positive = bonus;
} else if (bonus < 0) {
negative += bonus;
}
}
*/
int distance = 1 + positive + negative; int distance = 1 + positive + negative;
float level = intentional ? (2 * awareness - awareness * awareness) : awareness; float level = intentional ? (2 * awareness - awareness * awareness) : awareness;
if (distance <= 0) { if (distance <= 0) {
level /= 2 - distance; level /= 2 - distance;
distance = 1; distance = 1;
} }
@@ -18,7 +18,7 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.hero; package com.shatteredpixel.shatteredpixeldungeon.actors.hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.NPC;
public class HeroAction { public class HeroAction {
@@ -50,8 +50,8 @@ public class HeroAction {
} }
public static class Interact extends HeroAction { public static class Interact extends HeroAction {
public Mob.NPC npc; public NPC npc;
public Interact( Mob.NPC npc ) { public Interact( NPC npc ) {
this.npc = npc; this.npc = npc;
} }
} }
@@ -77,101 +77,104 @@ public enum HeroClass {
"Huntresses gain more health from dewdrops.", "Huntresses gain more health from dewdrops.",
"Huntresses sense neighbouring monsters even if they are hidden behind obstacles." "Huntresses sense neighbouring monsters even if they are hidden behind obstacles."
}; };
public void initHero( Hero hero ) {
hero.heroClass = this;
switch (this) {
case WARRIOR:
initWarrior( hero );
break;
case MAGE:
initMage( hero );
break;
case ROGUE:
initRogue( hero );
break;
case HUNTRESS:
initHuntress( hero );
break;
}
hero.updateAwareness();
}
private static void initWarrior( Hero hero ) {
hero.STR = hero.STR + 1;
(hero.belongings.weapon = new ShortSword()).identify();
(hero.belongings.armor = new ClothArmor()).identify();
new Dart( 8 ).identify().collect();
new Food().identify().collect();
if (Badges.isUnlocked( Badges.Badge.MASTERY_WARRIOR )) {
new TomeOfMastery().collect();
}
Dungeon.quickslot = Dart.class;
new PotionOfStrength().setKnown();
}
private static void initMage( Hero hero ) {
(hero.belongings.weapon = new Knuckles()).identify();
(hero.belongings.armor = new ClothArmor()).identify();
new Food().identify().collect();
WandOfMagicMissile wand = new WandOfMagicMissile();
wand.identify().collect();
if (Badges.isUnlocked( Badges.Badge.MASTERY_MAGE )) {
new TomeOfMastery().collect();
}
Dungeon.quickslot = wand;
new ScrollOfIdentify().setKnown();
}
private static void initRogue( Hero hero ) {
(hero.belongings.weapon = new Dagger()).identify();
(hero.belongings.armor = new ClothArmor()).identify();
CloakOfShadows cloak = new CloakOfShadows();
hero.belongings.misc1 = cloak;
new Dart( 8 ).identify().collect();
new Food().identify().collect();
hero.belongings.misc1.activate( hero ); public void initHero( Hero hero ) {
if (Badges.isUnlocked( Badges.Badge.MASTERY_ROGUE )) { hero.heroClass = this;
new TomeOfMastery().collect();
} initCommon( hero );
Dungeon.quickslot = cloak; switch (this) {
case WARRIOR:
new ScrollOfMagicMapping().setKnown(); initWarrior( hero );
} break;
private static void initHuntress( Hero hero ) { case MAGE:
initMage( hero );
hero.HP = (hero.HT -= 5); break;
(hero.belongings.weapon = new Dagger()).identify(); case ROGUE:
(hero.belongings.armor = new ClothArmor()).identify(); initRogue( hero );
Boomerang boomerang = new Boomerang(); break;
boomerang.identify().collect();
new Food().identify().collect(); case HUNTRESS:
initHuntress( hero );
if (Badges.isUnlocked( Badges.Badge.MASTERY_HUNTRESS )) { break;
new TomeOfMastery().collect(); }
}
if (Badges.isUnlocked( masteryBadge() )) {
Dungeon.quickslot = boomerang; new TomeOfMastery().collect();
} }
hero.updateAwareness();
}
private static void initCommon( Hero hero ) {
(hero.belongings.armor = new ClothArmor()).identify();
new Food().identify().collect();
}
public Badges.Badge masteryBadge() {
switch (this) {
case WARRIOR:
return Badges.Badge.MASTERY_WARRIOR;
case MAGE:
return Badges.Badge.MASTERY_MAGE;
case ROGUE:
return Badges.Badge.MASTERY_ROGUE;
case HUNTRESS:
return Badges.Badge.MASTERY_HUNTRESS;
}
return null;
}
private static void initWarrior( Hero hero ) {
hero.STR = hero.STR + 1;
(hero.belongings.weapon = new ShortSword()).identify();
new Dart( 8 ).identify().collect();
Dungeon.quickslot = Dart.class;
new PotionOfStrength().setKnown();
}
private static void initMage( Hero hero ) {
(hero.belongings.weapon = new Knuckles()).identify();
WandOfMagicMissile wand = new WandOfMagicMissile();
wand.identify().collect();
Dungeon.quickslot = wand;
new ScrollOfIdentify().setKnown();
}
private static void initRogue( Hero hero ) {
(hero.belongings.weapon = new Dagger()).identify();
CloakOfShadows cloak = new CloakOfShadows();
hero.belongings.misc1 = cloak;
hero.belongings.misc1.activate( hero );
new Dart( 8 ).identify().collect();
Dungeon.quickslot = cloak;
new ScrollOfMagicMapping().setKnown();
}
private static void initHuntress( Hero hero ) {
hero.HP = (hero.HT -= 5);
(hero.belongings.weapon = new Dagger()).identify();
Boomerang boomerang = new Boomerang();
boomerang.identify().collect();
Dungeon.quickslot = boomerang;
}
public String title() { public String title() {
return title; return title;
@@ -26,7 +26,6 @@ public enum HeroSubClass {
GLADIATOR( "gladiator", GLADIATOR( "gladiator",
"A successful attack with a melee weapon allows the _Gladiator_ to start a combo, " + "A successful attack with a melee weapon allows the _Gladiator_ to start a combo, " +
"in which every next successful hit inflicts more damage." ), "in which every next successful hit inflicts more damage." ),
BERSERKER( "berserker", BERSERKER( "berserker",
"When severely wounded, the _Berserker_ enters a state of wild fury " + "When severely wounded, the _Berserker_ enters a state of wild fury " +
"significantly increasing his damage output." ), "significantly increasing his damage output." ),
@@ -34,14 +33,12 @@ public enum HeroSubClass {
WARLOCK( "warlock", WARLOCK( "warlock",
"After killing an enemy the _Warlock_ consumes its soul. " + "After killing an enemy the _Warlock_ consumes its soul. " +
"It heals his wounds and satisfies his hunger." ), "It heals his wounds and satisfies his hunger." ),
BATTLEMAGE( "battlemage", BATTLEMAGE( "battlemage",
"When fighting with a wand in his hands, the _Battlemage_ inflicts additional damage depending " + "When fighting with a wand in his hands, the _Battlemage_ inflicts additional damage depending " +
"on the current number of charges. Every successful hit restores 1 charge to this wand." ), "on the current number of charges. Every successful hit restores 1 charge to this wand." ),
ASSASSIN( "assassin", ASSASSIN( "assassin",
"When performing a surprise attack, the _Assassin_ inflicts additional damage to his target." ), "When performing a surprise attack, the _Assassin_ inflicts additional damage to his target." ),
FREERUNNER( "freerunner", FREERUNNER( "freerunner",
"The _Freerunner_ can move almost twice faster, than most of the monsters. When he " + "The _Freerunner_ can move almost twice faster, than most of the monsters. When he " +
"is running, the Freerunner is much harder to hit. For that he must be unencumbered and not starving." ), "is running, the Freerunner is much harder to hit. For that he must be unencumbered and not starving." ),
@@ -49,7 +46,6 @@ public enum HeroSubClass {
SNIPER( "sniper", SNIPER( "sniper",
"_Snipers_ are able to detect weak points in an enemy's armor, " + "_Snipers_ are able to detect weak points in an enemy's armor, " +
"effectively ignoring it when using a missile weapon." ), "effectively ignoring it when using a missile weapon." ),
WARDEN( "warden", WARDEN( "warden",
"Having a strong connection with forces of nature gives _Wardens_ an ability to gather dewdrops and " + "Having a strong connection with forces of nature gives _Wardens_ an ability to gather dewdrops and " +
"seeds from plants. Also trampling a high grass grants them a temporary armor buff." ); "seeds from plants. Also trampling a high grass grants them a temporary armor buff." );
@@ -246,7 +246,7 @@ public class King extends Mob {
EXP = 0; EXP = 0;
state = State.WANDERING; state = WANDERING;
} }
@Override @Override
@@ -20,6 +20,7 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
import java.util.HashSet; import java.util.HashSet;
import com.shatteredpixel.shatteredpixeldungeon.Badges; import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Challenges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics; import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
@@ -31,7 +32,6 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
import com.shatteredpixel.shatteredpixeldungeon.effects.Wound; import com.shatteredpixel.shatteredpixeldungeon.effects.Wound;
import com.shatteredpixel.shatteredpixeldungeon.items.Generator; import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfAccuracy; import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfAccuracy;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfWealth; import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfWealth;
@@ -48,15 +48,13 @@ public abstract class Mob extends Char {
protected static final String TXT_NOTICE1 = "?!"; protected static final String TXT_NOTICE1 = "?!";
protected static final String TXT_RAGE = "#$%^"; protected static final String TXT_RAGE = "#$%^";
protected static final String TXT_EXP = "%+dEXP"; protected static final String TXT_EXP = "%+dEXP";
public enum State { public AiState SLEEPEING = new Sleeping();
SLEEPING, public AiState HUNTING = new Hunting();
HUNTING, public AiState WANDERING = new Wandering();
WANDERING, public AiState FLEEING = new Fleeing();
FLEEING, public AiState PASSIVE = new Passive();
PASSIVE public AiState state = SLEEPEING;
}
public State state = State.SLEEPING;
public Class<? extends CharSprite> spriteClass; public Class<? extends CharSprite> spriteClass;
@@ -90,25 +88,41 @@ public abstract class Mob extends Char {
public void storeInBundle( Bundle bundle ) { public void storeInBundle( Bundle bundle ) {
super.storeInBundle( bundle ); super.storeInBundle( bundle );
bundle.put( STATE, state.toString() ); if (state == SLEEPEING) {
bundle.put( SEEN, enemySeen); bundle.put( STATE, Sleeping.TAG );
if (state != State.SLEEPING) { } else if (state == WANDERING) {
bundle.put( TARGET, target ); bundle.put( STATE, Wandering.TAG );
} } else if (state == HUNTING) {
bundle.put( STATE, Hunting.TAG );
} else if (state == FLEEING) {
bundle.put( STATE, Fleeing.TAG );
} else if (state == PASSIVE) {
bundle.put( STATE, Passive.TAG );
}
bundle.put( TARGET, target );
} }
@Override @Override
public void restoreFromBundle( Bundle bundle ) { public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle( bundle ); super.restoreFromBundle( bundle );
state = State.valueOf( bundle.getString( STATE ) ); String state = bundle.getString( STATE );
enemySeen = bundle.getBoolean( SEEN ); if (state.equals( Sleeping.TAG )) {
if (state != State.SLEEPING) { this.state = SLEEPEING;
target = bundle.getInt( TARGET ); } else if (state.equals( Wandering.TAG )) {
} this.state = WANDERING;
} } else if (state.equals( Hunting.TAG )) {
this.state = HUNTING;
} else if (state.equals( Fleeing.TAG )) {
this.state = FLEEING;
} else if (state.equals( Passive.TAG )) {
this.state = PASSIVE;
}
target = bundle.getInt( TARGET );
}
public CharSprite sprite() { public CharSprite sprite() {
CharSprite sprite = null; CharSprite sprite = null;
@@ -124,7 +138,7 @@ public abstract class Mob extends Char {
super.act(); super.act();
boolean alertedNow = alerted; boolean justAlerted = alerted;
alerted = false; alerted = false;
sprite.hideAlert(); sprite.hideAlert();
@@ -138,110 +152,8 @@ public abstract class Mob extends Char {
enemy = chooseEnemy(); enemy = chooseEnemy();
boolean enemyInFOV = enemy.isAlive() && Level.fieldOfView[enemy.pos] && enemy.invisible <= 0; boolean enemyInFOV = enemy.isAlive() && Level.fieldOfView[enemy.pos] && enemy.invisible <= 0;
int oldPos = pos;
switch (state) {
case SLEEPING:
if (enemyInFOV &&
Random.Int( distance( enemy ) + enemy.stealth() + (enemy.flying ? 2 : 0) ) == 0) {
enemySeen = true;
notice();
state = State.HUNTING;
target = enemy.pos;
spend( TIME_TO_WAKE_UP );
} else {
enemySeen = false;
spend( TICK );
}
return true;
case WANDERING:
if (enemyInFOV && (alertedNow || Random.Int( distance( enemy ) / 2 + enemy.stealth() ) == 0)) {
enemySeen = true;
notice();
state = State.HUNTING;
target = enemy.pos;
} else {
enemySeen = false;
if (target != -1 && getCloser( target )) {
spend( 1 / speed() );
return moveSprite( oldPos, pos );
} else {
target = Dungeon.level.randomDestination();
spend( TICK );
}
}
return true;
case HUNTING:
enemySeen = enemyInFOV;
if (enemyInFOV && canAttack( enemy )) {
return doAttack( enemy );
} else {
if (enemyInFOV) {
target = enemy.pos;
}
if (target != -1 && getCloser( target )) {
spend( 1 / speed() );
return moveSprite( oldPos, pos );
} else {
spend( TICK );
state = State.WANDERING;
target = Dungeon.level.randomDestination(); // <--------
return true;
}
}
case FLEEING:
enemySeen = enemyInFOV;
if (enemyInFOV) {
target = enemy.pos;
}
if (target != -1 && getFurther( target )) {
spend( 1 / speed() );
return moveSprite( oldPos, pos );
} else {
spend( TICK );
nowhereToRun();
return true;
}
case PASSIVE:
enemySeen = false;
spend( TICK );
return true;
}
return true;
return state.act( enemyInFOV, justAlerted );
} }
protected Char chooseEnemy() { protected Char chooseEnemy() {
@@ -271,15 +183,12 @@ public abstract class Mob extends Char {
return Dungeon.hero; return Dungeon.hero;
} }
protected void nowhereToRun() {
}
protected boolean moveSprite( int from, int to ) { protected boolean moveSprite( int from, int to ) {
if (sprite.isVisible() && (Dungeon.visible[from] || Dungeon.visible[to])) { if (sprite.isVisible() && (Dungeon.visible[from] || Dungeon.visible[to])) {
sprite.move( from, to ); sprite.move( from, to );
return false; return true;
} else { } else {
sprite.place( to ); sprite.place( to );
return true; return true;
@@ -293,11 +202,11 @@ public abstract class Mob extends Char {
if (sprite != null) { if (sprite != null) {
sprite.showStatus( CharSprite.NEGATIVE, TXT_RAGE ); sprite.showStatus( CharSprite.NEGATIVE, TXT_RAGE );
} }
state = State.HUNTING; state = HUNTING;
} else if (buff instanceof Terror) { } else if (buff instanceof Terror) {
state = State.FLEEING; state = FLEEING;
} else if (buff instanceof Sleep) { } else if (buff instanceof Sleep) {
state = State.SLEEPING; state = SLEEPEING;
this.sprite().showSleep(); this.sprite().showSleep();
postpone( Sleep.SWS ); postpone( Sleep.SWS );
} }
@@ -308,7 +217,7 @@ public abstract class Mob extends Char {
super.remove( buff ); super.remove( buff );
if (buff instanceof Terror) { if (buff instanceof Terror) {
sprite.showStatus( CharSprite.NEGATIVE, TXT_RAGE ); sprite.showStatus( CharSprite.NEGATIVE, TXT_RAGE );
state = State.HUNTING; state = HUNTING;
} }
} }
@@ -408,10 +317,10 @@ public abstract class Mob extends Char {
public void damage( int dmg, Object src ) { public void damage( int dmg, Object src ) {
Terror.recover( this ); Terror.recover( this );
if (state == State.SLEEPING) { if (state == SLEEPEING) {
state = State.WANDERING; state = WANDERING;
} }
alerted = true; alerted = true;
super.damage( dmg, src ); super.damage( dmg, src );
@@ -501,8 +410,8 @@ public abstract class Mob extends Char {
notice(); notice();
if (state != State.HUNTING) { if (state != HUNTING) {
state = State.WANDERING; state = WANDERING;
} }
target = cell; target = cell;
} }
@@ -518,32 +427,178 @@ public abstract class Mob extends Char {
public void yell( String str ) { public void yell( String str ) {
GLog.n( "%s: \"%s\" ", name, str ); GLog.n( "%s: \"%s\" ", name, str );
} }
public static abstract class NPC extends Mob { public interface AiState {
public boolean act( boolean enemyInFOV, boolean justAlerted );
{ public String status();
HP = HT = 1; }
EXP = 0;
private class Sleeping implements AiState {
hostile = false;
state = State.PASSIVE; public static final String TAG = "SLEEPING";
}
@Override
protected void throwItem() { public boolean act( boolean enemyInFOV, boolean justAlerted ) {
Heap heap = Dungeon.level.heaps.get( pos ); if (enemyInFOV && Random.Int( distance( enemy ) + enemy.stealth() + (enemy.flying ? 2 : 0) ) == 0) {
if (heap != null) {
int n; enemySeen = true;
do {
n = pos + Level.NEIGHBOURS8[Random.Int( 8 )]; notice();
} while (!Level.passable[n] && !Level.avoid[n]); state = HUNTING;
Dungeon.level.drop( heap.pickUp(), n ).sprite.drop( pos ); target = enemy.pos;
}
} if (Dungeon.isChallenged( Challenges.SWARM_INTELLIGENCE )) {
for (Mob mob : Dungeon.level.mobs) {
@Override if (mob != Mob.this) {
public void beckon( int cell ) { mob.beckon( target );
} }
}
abstract public void interact(); }
}
spend( TIME_TO_WAKE_UP );
} else {
enemySeen = false;
spend( TICK );
}
return true;
}
@Override
public String status() {
return String.format( "This %s is sleeping", name );
}
}
private class Wandering implements AiState {
public static final String TAG = "WANDERING";
@Override
public boolean act( boolean enemyInFOV, boolean justAlerted ) {
if (enemyInFOV && (justAlerted || Random.Int( distance( enemy ) / 2 + enemy.stealth() ) == 0)) {
enemySeen = true;
notice();
state = HUNTING;
target = enemy.pos;
} else {
enemySeen = false;
int oldPos = pos;
if (target != -1 && getCloser( target )) {
spend( 1 / speed() );
return moveSprite( oldPos, pos );
} else {
target = Dungeon.level.randomDestination();
spend( TICK );
}
}
return true;
}
@Override
public String status() {
return String.format( "This %s is wandering", name );
}
}
private class Hunting implements AiState {
public static final String TAG = "HUNTING";
@Override
public boolean act( boolean enemyInFOV, boolean justAlerted ) {
enemySeen = enemyInFOV;
if (enemyInFOV && canAttack( enemy )) {
return doAttack( enemy );
} else {
if (enemyInFOV) {
target = enemy.pos;
}
int oldPos = pos;
if (target != -1 && getCloser( target )) {
spend( 1 / speed() );
return moveSprite( oldPos, pos );
} else {
spend( TICK );
state = WANDERING;
target = Dungeon.level.randomDestination();
return true;
}
}
}
@Override
public String status() {
return String.format( "This %s is hunting", name );
}
}
protected class Fleeing implements AiState {
public static final String TAG = "FLEEING";
@Override
public boolean act( boolean enemyInFOV, boolean justAlerted ) {
enemySeen = enemyInFOV;
if (enemyInFOV) {
target = enemy.pos;
}
int oldPos = pos;
if (target != -1 && getFurther( target )) {
spend( 1 / speed() );
return moveSprite( oldPos, pos );
} else {
spend( TICK );
nowhereToRun();
return true;
}
}
protected void nowhereToRun() {
}
@Override
public String status() {
return String.format( "This %s is fleeing", name );
}
}
private class Passive implements AiState {
public static final String TAG = "PASSIVE";
@Override
public boolean act( boolean enemyInFOV, boolean justAlerted ) {
enemySeen = false;
spend( TICK );
return true;
}
@Override
public String status() {
return String.format( "This %s is passive", name );
}
}
} }
@@ -81,7 +81,7 @@ public class Scorpio extends Mob {
@Override @Override
protected boolean getCloser( int target ) { protected boolean getCloser( int target ) {
if (state == State.HUNTING) { if (state == HUNTING) {
return enemySeen && getFurther( target ); return enemySeen && getFurther( target );
} else { } else {
return super.getCloser( target ); return super.getCloser( target );
@@ -32,99 +32,105 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.SpinnerSprite;
import com.watabou.utils.Random; import com.watabou.utils.Random;
public class Spinner extends Mob { public class Spinner extends Mob {
{ {
name = "cave spinner"; name = "cave spinner";
spriteClass = SpinnerSprite.class; spriteClass = SpinnerSprite.class;
HP = HT = 50; HP = HT = 50;
defenseSkill = 14; defenseSkill = 14;
EXP = 9; EXP = 9;
maxLvl = 16; maxLvl = 16;
loot = new MysteryMeat(); loot = new MysteryMeat();
lootChance = 0.125f; lootChance = 0.125f;
}
FLEEING = new Fleeing();
@Override }
public int damageRoll() {
return Random.NormalIntRange( 12, 16 ); @Override
} public int damageRoll() {
return Random.NormalIntRange(12, 16);
@Override }
protected void nowhereToRun() {
if (buff( Terror.class ) == null) { @Override
state = State.HUNTING; public int attackSkill(Char target) {
} else { return 20;
super.nowhereToRun(); }
}
} @Override
public int dr() {
@Override return 6;
public int attackSkill( Char target ) { }
return 20;
} @Override
protected boolean act() {
@Override boolean result = super.act();
public int dr() {
return 6; if (state == FLEEING && buff(Terror.class) == null &&
} enemySeen && enemy.buff(Poison.class) == null) {
@Override state = HUNTING;
protected boolean act() { }
boolean result = super.act(); return result;
}
if (state == State.FLEEING && buff( Terror.class ) == null &&
enemySeen && enemy.buff( Poison.class ) == null) { @Override
public int attackProc(Char enemy, int damage) {
state = State.HUNTING; if (Random.Int(2) == 0) {
} Buff.affect(enemy, Poison.class).set(Random.Int(7, 9) * Poison.durationFactor(enemy));
return result; state = FLEEING;
} }
@Override return damage;
public int attackProc( Char enemy, int damage ) { }
if (Random.Int( 2 ) == 0) {
Buff.affect( enemy, Poison.class ).set( Random.Int( 5, 7 ) * Poison.durationFactor( enemy ) ); @Override
state = State.FLEEING; public void move(int step) {
} if (state == FLEEING) {
GameScene.add(Blob.seed(pos, Random.Int(5, 7), Web.class));
return damage; }
} super.move(step);
}
@Override
public void move( int step ) { @Override
if (state == State.FLEEING) { public String description() {
GameScene.add( Blob.seed( pos, Random.Int( 5, 7 ), Web.class ) ); return
} "These greenish furry cave spiders try to avoid direct combat, preferring to wait in the distance " +
super.move( step ); "while their victim, entangled in the spinner's excreted cobweb, slowly dies from their poisonous bite.";
} }
@Override private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>();
public String description() {
return static {
"These greenish furry cave spiders try to avoid direct combat, preferring to wait in the distance " + RESISTANCES.add(Poison.class);
"while their victim, entangled in the spinner's excreted cobweb, slowly dies from their poisonous bite."; }
}
@Override
private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>(); public HashSet<Class<?>> resistances() {
static { return RESISTANCES;
RESISTANCES.add( Poison.class ); }
}
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
@Override
public HashSet<Class<?>> resistances() { static {
return RESISTANCES; IMMUNITIES.add(Roots.class);
} }
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>(); @Override
static { public HashSet<Class<?>> immunities() {
IMMUNITIES.add( Roots.class ); return IMMUNITIES;
} }
@Override private class Fleeing extends Mob.Fleeing {
public HashSet<Class<?>> immunities() { @Override
return IMMUNITIES; protected void nowhereToRun() {
} if (buff(Terror.class) == null) {
state = HUNTING;
} else {
super.nowhereToRun();
}
}
}
} }
@@ -42,7 +42,7 @@ public class Statue extends Mob {
spriteClass = StatueSprite.class; spriteClass = StatueSprite.class;
EXP = 0; EXP = 0;
state = State.PASSIVE; state = PASSIVE;
} }
private Weapon weapon; private Weapon weapon;
@@ -106,8 +106,8 @@ public class Statue extends Mob {
@Override @Override
public void damage( int dmg, Object src ) { public void damage( int dmg, Object src ) {
if (state == State.PASSIVE) { if (state == PASSIVE) {
state = State.HUNTING; state = HUNTING;
} }
super.damage( dmg, src ); super.damage( dmg, src );
@@ -137,7 +137,7 @@ public class Statue extends Mob {
@Override @Override
public boolean reset() { public boolean reset() {
state = State.PASSIVE; state = PASSIVE;
return true; return true;
} }
@@ -91,7 +91,7 @@ public class Swarm extends Mob {
Swarm clone = split(); Swarm clone = split();
clone.HP = (HP - damage) / 2; clone.HP = (HP - damage) / 2;
clone.pos = Random.element( candidates ); clone.pos = Random.element( candidates );
clone.state = State.HUNTING; clone.state = clone.HUNTING;
if (Dungeon.level.map[clone.pos] == Terrain.DOOR) { if (Dungeon.level.map[clone.pos] == Terrain.DOOR) {
Door.enter( clone.pos ); Door.enter( clone.pos );
@@ -49,108 +49,112 @@ public class Thief extends Mob {
maxLvl = 10; maxLvl = 10;
loot = MasterThievesArmband.class; loot = MasterThievesArmband.class;
lootChance = 0.01f; lootChance = 0.01f;
}
private static final String ITEM = "item";
@Override
public void storeInBundle( Bundle bundle ) {
super.storeInBundle( bundle );
bundle.put( ITEM, item );
}
@Override
public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle( bundle );
item = (Item)bundle.get( ITEM );
}
@Override
public int damageRoll() {
return Random.NormalIntRange( 1, 7 );
}
@Override
protected float attackDelay() {
return 0.5f;
}
@Override
protected void nowhereToRun() {
if (buff( Terror.class ) == null) {
sprite.showStatus( CharSprite.NEGATIVE, TXT_RAGE );
state = State.HUNTING;
} else {
super.nowhereToRun();
}
}
@Override
public void die( Object cause ) {
super.die( cause ); FLEEING = new Fleeing();
}
if (item != null) {
Dungeon.level.drop( item, pos ).sprite.drop(); private static final String ITEM = "item";
}
} @Override
public void storeInBundle( Bundle bundle ) {
@Override super.storeInBundle( bundle );
public int attackSkill( Char target ) { bundle.put( ITEM, item );
return 12; }
}
@Override
@Override public void restoreFromBundle( Bundle bundle ) {
public int dr() { super.restoreFromBundle( bundle );
return 3; item = (Item)bundle.get( ITEM );
} }
@Override @Override
public int attackProc( Char enemy, int damage ) { public int damageRoll() {
if (item == null && enemy instanceof Hero && steal( (Hero)enemy )) { return Random.NormalIntRange( 1, 7 );
state = State.FLEEING; }
}
@Override
return damage; protected float attackDelay() {
} return 0.5f;
}
@Override
public int defenseProc(Char enemy, int damage) { @Override
if (state == State.FLEEING) { public void die( Object cause ) {
Dungeon.level.drop( new Gold(), pos ).sprite.drop();
} super.die( cause );
return damage; if (item != null) {
} Dungeon.level.drop( item, pos ).sprite.drop();
}
protected boolean steal( Hero hero ) { }
Item item = hero.belongings.randomUnequipped(); @Override
if (item != null) { public int attackSkill( Char target ) {
return 12;
GLog.w( TXT_STOLE, this.name, item.name() ); }
item.detachAll( hero.belongings.backpack ); @Override
this.item = item; public int dr() {
return 3;
return true; }
} else {
return false; @Override
} public int attackProc( Char enemy, int damage ) {
} if (item == null && enemy instanceof Hero && steal( (Hero)enemy )) {
state = FLEEING;
@Override }
public String description() {
String desc = return damage;
"Deeper levels of the dungeon have always been a hiding place for all kinds of criminals. " + }
"Not all of them could keep a clear mind during their extended periods so far from daylight. Long ago, " +
"these crazy thieves and bandits have forgotten who they are and why they steal."; @Override
public int defenseProc(Char enemy, int damage) {
if (item != null) { if (state == FLEEING) {
desc += String.format( TXT_CARRIES, Utils.capitalize( this.name ), item.name() ); Dungeon.level.drop( new Gold(), pos ).sprite.drop();
} }
return desc; return damage;
} }
protected boolean steal( Hero hero ) {
Item item = hero.belongings.randomUnequipped();
if (item != null) {
GLog.w( TXT_STOLE, this.name, item.name() );
item.detachAll( hero.belongings.backpack );
this.item = item;
return true;
} else {
return false;
}
}
@Override
public String description() {
String desc =
"Deeper levels of the dungeon have always been a hiding place for all kinds of criminals. " +
"Not all of them could keep a clear mind during their extended periods so far from daylight. Long ago, " +
"these crazy thieves and bandits have forgotten who they are and why they steal.";
if (item != null) {
desc += String.format( TXT_CARRIES, Utils.capitalize( this.name ), item.name() );
}
return desc;
}
private class Fleeing extends Mob.Fleeing {
@Override
protected void nowhereToRun() {
if (buff( Terror.class ) == null) {
sprite.showStatus( CharSprite.NEGATIVE, TXT_RAGE );
state = HUNTING;
} else {
super.nowhereToRun();
}
}
}
} }
@@ -86,7 +86,7 @@ public class Wraith extends Mob {
@Override @Override
public boolean reset() { public boolean reset() {
state = State.WANDERING; state = WANDERING;
return true; return true;
} }
@@ -112,7 +112,7 @@ public class Wraith extends Mob {
Wraith w = new Wraith(); Wraith w = new Wraith();
w.adjustStats( Dungeon.depth ); w.adjustStats( Dungeon.depth );
w.pos = pos; w.pos = pos;
w.state = State.HUNTING; w.state = w.HUNTING;
GameScene.add( w, SPAWN_DELAY ); GameScene.add( w, SPAWN_DELAY );
w.sprite.alpha( 0 ); w.sprite.alpha( 0 );
@@ -62,7 +62,7 @@ public class Yog extends Mob {
EXP = 50; EXP = 50;
state = State.PASSIVE; state = PASSIVE;
} }
private static final String TXT_DESC = private static final String TXT_DESC =
@@ -193,7 +193,7 @@ public class Yog extends Mob {
EXP = 0; EXP = 0;
state = State.WANDERING; state = WANDERING;
} }
public RottingFist() { public RottingFist() {
@@ -286,7 +286,7 @@ public class Yog extends Mob {
EXP = 0; EXP = 0;
state = State.WANDERING; state = WANDERING;
} }
public BurningFist() { public BurningFist() {
@@ -404,7 +404,7 @@ public class Yog extends Mob {
EXP = 0; EXP = 0;
state = State.HUNTING; state = HUNTING;
} }
@Override @Override
@@ -43,7 +43,7 @@ import com.shatteredpixel.shatteredpixeldungeon.windows.WndQuest;
import com.watabou.utils.Bundle; import com.watabou.utils.Bundle;
import com.watabou.utils.Random; import com.watabou.utils.Random;
public class Blacksmith extends Mob.NPC { public class Blacksmith extends NPC {
private static final String TXT_GOLD_1 = private static final String TXT_GOLD_1 =
"Hey human! Wanna be useful, eh? Take dis pickaxe and mine me some _dark gold ore_, _15 pieces_ should be enough. " + "Hey human! Wanna be useful, eh? Take dis pickaxe and mine me some _dark gold ore_, _15 pieces_ should be enough. " +
@@ -167,8 +167,8 @@ public class Blacksmith extends Mob.NPC {
if (item1 == item2) { if (item1 == item2) {
return "Select 2 different items, not the same item twice!"; return "Select 2 different items, not the same item twice!";
} }
if (!item1.isSimilar( item2 )) { if (item1.getClass() != item2.getClass()) {
return "Select 2 items of the same type!"; return "Select 2 items of the same type!";
} }
@@ -19,6 +19,7 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs;
import java.util.HashSet; import java.util.HashSet;
import com.shatteredpixel.shatteredpixeldungeon.Challenges;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Fire; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Fire;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.StenchGas; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.StenchGas;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
@@ -27,6 +28,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Crab; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Crab;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Gnoll; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Gnoll;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Rat; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Rat;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.ClothArmor;
import com.shatteredpixel.shatteredpixeldungeon.items.food.MysteryMeat; import com.shatteredpixel.shatteredpixeldungeon.items.food.MysteryMeat;
import com.shatteredpixel.shatteredpixeldungeon.items.quest.RatSkull; import com.shatteredpixel.shatteredpixeldungeon.items.quest.RatSkull;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand; import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
@@ -61,7 +63,7 @@ import com.shatteredpixel.shatteredpixeldungeon.windows.WndSadGhost;
import com.watabou.utils.Bundle; import com.watabou.utils.Bundle;
import com.watabou.utils.Random; import com.watabou.utils.Random;
public class Ghost extends Mob.NPC { public class Ghost extends NPC {
{ {
name = "sad ghost"; name = "sad ghost";
@@ -69,7 +71,7 @@ public class Ghost extends Mob.NPC {
flying = true; flying = true;
state = State.WANDERING; state = WANDERING;
} }
private static final String TXT_RAT1 = private static final String TXT_RAT1 =
@@ -195,7 +197,6 @@ public class Ghost extends Mob.NPC {
txt_quest = TXT_CRAB1; break; txt_quest = TXT_CRAB1; break;
} }
questBoss.state = Mob.State.WANDERING;
questBoss.pos = Dungeon.level.randomRespawnCell(); questBoss.pos = Dungeon.level.randomRespawnCell();
if (questBoss.pos != -1) { if (questBoss.pos != -1) {
@@ -353,6 +354,10 @@ public class Ghost extends Mob.NPC {
} }
} }
//TODO this is silly, why trap the player with bad armour? Just remove the button from the window.
if (Dungeon.isChallenged( Challenges.NO_ARMOR ))
armor = (Armor)new ClothArmor().degrade();
weapon.identify(); weapon.identify();
armor.identify(); armor.identify();
} }
@@ -386,6 +391,8 @@ public class Ghost extends Mob.NPC {
defenseSkill = 4; defenseSkill = 4;
EXP = 4; EXP = 4;
state = WANDERING;
} }
@Override @Override
@@ -445,6 +452,8 @@ public class Ghost extends Mob.NPC {
EXP = 5; EXP = 5;
state = WANDERING;
loot = Generator.random(CurareDart.class); loot = Generator.random(CurareDart.class);
lootChance = 1f; lootChance = 1f;
} }
@@ -489,7 +498,7 @@ public class Ghost extends Mob.NPC {
@Override @Override
protected boolean getCloser( int target ) { protected boolean getCloser( int target ) {
combo = 0; //if he's moving, he isn't attacking, reset combo. combo = 0; //if he's moving, he isn't attacking, reset combo.
if (state == State.HUNTING) { if (state == HUNTING) {
return enemySeen && getFurther( target ); return enemySeen && getFurther( target );
} else { } else {
return super.getCloser( target ); return super.getCloser( target );
@@ -573,6 +582,7 @@ public class Ghost extends Mob.NPC {
EXP = 6; EXP = 6;
state = WANDERING;
} }
private boolean moving = true; private boolean moving = true;
@@ -38,7 +38,7 @@ import com.shatteredpixel.shatteredpixeldungeon.windows.WndQuest;
import com.watabou.utils.Bundle; import com.watabou.utils.Bundle;
import com.watabou.utils.Random; import com.watabou.utils.Random;
public class Imp extends Mob.NPC { public class Imp extends NPC {
{ {
name = "ambitious imp"; name = "ambitious imp";
@@ -21,6 +21,8 @@ import java.util.HashSet;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
@@ -29,13 +31,13 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.MirrorSprite;
import com.watabou.utils.Bundle; import com.watabou.utils.Bundle;
import com.watabou.utils.Random; import com.watabou.utils.Random;
public class MirrorImage extends Mob.NPC { public class MirrorImage extends NPC {
{ {
name = "mirror image"; name = "mirror image";
spriteClass = MirrorSprite.class; spriteClass = MirrorSprite.class;
state = State.HUNTING; state = HUNTING;
enemy = DUMMY; enemy = DUMMY;
} }
@@ -134,5 +136,16 @@ public class MirrorImage extends Mob.NPC {
Dungeon.hero.spend( 1 / Dungeon.hero.speed() ); Dungeon.hero.spend( 1 / Dungeon.hero.speed() );
Dungeon.hero.busy(); Dungeon.hero.busy();
}
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
static {
IMMUNITIES.add( ToxicGas.class );
IMMUNITIES.add( Burning.class );
}
@Override
public HashSet<Class<?>> immunities() {
return IMMUNITIES;
} }
} }
@@ -0,0 +1,52 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* 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 <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.watabou.utils.Random;
public abstract class NPC extends Mob {
{
HP = HT = 1;
EXP = 0;
hostile = false;
state = PASSIVE;
}
protected void throwItem() {
Heap heap = Dungeon.level.heaps.get( pos );
if (heap != null) {
int n;
do {
n = pos + Level.NEIGHBOURS8[Random.Int( 8 )];
} while (!Level.passable[n] && !Level.avoid[n]);
Dungeon.level.drop( heap.pickUp(), n ).sprite.drop( pos );
}
}
@Override
public void beckon( int cell ) {
}
abstract public void interact();
}
@@ -24,13 +24,13 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.sprites.RatKingSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.RatKingSprite;
public class RatKing extends Mob.NPC { public class RatKing extends NPC {
{ {
name = "rat king"; name = "rat king";
spriteClass = RatKingSprite.class; spriteClass = RatKingSprite.class;
state = State.SLEEPING; state = SLEEPEING;
} }
@Override @Override
@@ -64,10 +64,10 @@ public class RatKing extends Mob.NPC {
@Override @Override
public void interact() { public void interact() {
sprite.turnTo( pos, Dungeon.hero.pos ); sprite.turnTo( pos, Dungeon.hero.pos );
if (state == State.SLEEPING) { if (state == SLEEPEING) {
notice(); notice();
yell( "I'm not sleeping!" ); yell( "I'm not sleeping!" );
state = State.WANDERING; state = WANDERING;
} else { } else {
yell( "What is it? I have no time for this nonsense. My kingdom won't rule itself!" ); yell( "What is it? I have no time for this nonsense. My kingdom won't rule itself!" );
} }
@@ -29,7 +29,7 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.ShopkeeperSprite;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag; import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndTradeItem; import com.shatteredpixel.shatteredpixeldungeon.windows.WndTradeItem;
public class Shopkeeper extends Mob.NPC { public class Shopkeeper extends NPC {
public static final String TXT_THIEF = "Thief, Thief!"; public static final String TXT_THIEF = "Thief, Thief!";
@@ -63,7 +63,7 @@ import com.shatteredpixel.shatteredpixeldungeon.windows.WndWandmaker;
import com.watabou.utils.Bundle; import com.watabou.utils.Bundle;
import com.watabou.utils.Random; import com.watabou.utils.Random;
public class Wandmaker extends Mob.NPC { public class Wandmaker extends NPC {
{ {
name = "old wandmaker"; name = "old wandmaker";