v0.6.2: overhauled enemy AI behaviour with respect to alignment
This commit is contained in:
parent
ddaa763a86
commit
925d737d93
|
@ -77,6 +77,14 @@ public abstract class Char extends Actor {
|
||||||
public boolean flying = false;
|
public boolean flying = false;
|
||||||
public int invisible = 0;
|
public int invisible = 0;
|
||||||
|
|
||||||
|
//these are relative to the hero
|
||||||
|
public enum Alignment{
|
||||||
|
ENEMY,
|
||||||
|
NEUTRAL,
|
||||||
|
ALLY
|
||||||
|
}
|
||||||
|
public Alignment alignment;
|
||||||
|
|
||||||
public int viewDistance = 8;
|
public int viewDistance = 8;
|
||||||
|
|
||||||
protected boolean[] fieldOfView = null;
|
protected boolean[] fieldOfView = null;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
package com.shatteredpixel.shatteredpixeldungeon.actors.buffs;
|
package com.shatteredpixel.shatteredpixeldungeon.actors.buffs;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||||
|
@ -32,7 +33,17 @@ public class Corruption extends Buff {
|
||||||
}
|
}
|
||||||
|
|
||||||
private float buildToDamage = 0f;
|
private float buildToDamage = 0f;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean attachTo(Char target) {
|
||||||
|
if (super.attachTo(target)){
|
||||||
|
target.alignment = Char.Alignment.ALLY;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean act() {
|
public boolean act() {
|
||||||
buildToDamage += target.HT/200f;
|
buildToDamage += target.HT/200f;
|
||||||
|
|
|
@ -131,6 +131,8 @@ public class Hero extends Char {
|
||||||
|
|
||||||
{
|
{
|
||||||
actPriority = 0; //acts at priority 0, baseline for the rest of behaviour.
|
actPriority = 0; //acts at priority 0, baseline for the rest of behaviour.
|
||||||
|
|
||||||
|
alignment = Alignment.ALLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final int MAX_LEVEL = 30;
|
public static final int MAX_LEVEL = 30;
|
||||||
|
@ -988,7 +990,7 @@ public class Hero extends Char {
|
||||||
|
|
||||||
Mob target = null;
|
Mob target = null;
|
||||||
for (Mob m : Dungeon.level.mobs) {
|
for (Mob m : Dungeon.level.mobs) {
|
||||||
if (fieldOfView[ m.pos ] && m.hostile) {
|
if (fieldOfView[ m.pos ] && m.alignment == Alignment.ENEMY) {
|
||||||
visible.add(m);
|
visible.add(m);
|
||||||
if (!visibleEnemies.contains( m )) {
|
if (!visibleEnemies.contains( m )) {
|
||||||
newMob = true;
|
newMob = true;
|
||||||
|
|
|
@ -127,9 +127,13 @@ public class Bee extends Mob {
|
||||||
|
|
||||||
//find all mobs near the pot
|
//find all mobs near the pot
|
||||||
HashSet<Char> enemies = new HashSet<>();
|
HashSet<Char> enemies = new HashSet<>();
|
||||||
for (Mob mob : Dungeon.level.mobs)
|
for (Mob mob : Dungeon.level.mobs) {
|
||||||
if (!(mob instanceof Bee) && Dungeon.level.distance(mob.pos, potPos) <= 3 && (mob.hostile || mob.ally))
|
if (!(mob instanceof Bee)
|
||||||
|
&& Dungeon.level.distance(mob.pos, potPos) <= 3
|
||||||
|
&& mob.alignment != Alignment.NEUTRAL) {
|
||||||
enemies.add(mob);
|
enemies.add(mob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//pick one, if there are none, check if the hero is near the pot, go for them, otherwise go for nothing.
|
//pick one, if there are none, check if the hero is near the pot, go for them, otherwise go for nothing.
|
||||||
if (enemies.size() > 0) return Random.element(enemies);
|
if (enemies.size() > 0) return Random.element(enemies);
|
||||||
|
|
|
@ -62,6 +62,8 @@ public abstract class Mob extends Char {
|
||||||
{
|
{
|
||||||
name = Messages.get(this, "name");
|
name = Messages.get(this, "name");
|
||||||
actPriority = 2; //hero gets priority over mobs.
|
actPriority = 2; //hero gets priority over mobs.
|
||||||
|
|
||||||
|
alignment = Alignment.ENEMY;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String TXT_DIED = "You hear something died in the distance";
|
private static final String TXT_DIED = "You hear something died in the distance";
|
||||||
|
@ -92,9 +94,6 @@ public abstract class Mob extends Char {
|
||||||
|
|
||||||
protected static final float TIME_TO_WAKE_UP = 1f;
|
protected static final float TIME_TO_WAKE_UP = 1f;
|
||||||
|
|
||||||
public boolean hostile = true;
|
|
||||||
public boolean ally = false;
|
|
||||||
|
|
||||||
private static final String STATE = "state";
|
private static final String STATE = "state";
|
||||||
private static final String SEEN = "seen";
|
private static final String SEEN = "seen";
|
||||||
private static final String TARGET = "target";
|
private static final String TARGET = "target";
|
||||||
|
@ -194,8 +193,8 @@ public abstract class Mob extends Char {
|
||||||
//we have no enemy, or the current one is dead
|
//we have no enemy, or the current one is dead
|
||||||
if ( enemy == null || !enemy.isAlive() || state == WANDERING)
|
if ( enemy == null || !enemy.isAlive() || state == WANDERING)
|
||||||
newEnemy = true;
|
newEnemy = true;
|
||||||
//We are corrupted, and current enemy is either the hero or another corrupted character.
|
//We are an ally, and current enemy is another ally.
|
||||||
else if (buff(Corruption.class) != null && (enemy == Dungeon.hero || enemy.buff(Corruption.class) != null))
|
else if (alignment == Alignment.ALLY && enemy.alignment == Alignment.ALLY)
|
||||||
newEnemy = true;
|
newEnemy = true;
|
||||||
//We are amoked and current enemy is the hero
|
//We are amoked and current enemy is the hero
|
||||||
else if (buff( Amok.class ) != null && enemy == Dungeon.hero)
|
else if (buff( Amok.class ) != null && enemy == Dungeon.hero)
|
||||||
|
@ -205,47 +204,55 @@ public abstract class Mob extends Char {
|
||||||
|
|
||||||
HashSet<Char> enemies = new HashSet<>();
|
HashSet<Char> enemies = new HashSet<>();
|
||||||
|
|
||||||
//if the mob is corrupted...
|
|
||||||
if ( buff(Corruption.class) != null) {
|
|
||||||
|
|
||||||
//look for enemy mobs to attack, which are also not corrupted
|
|
||||||
for (Mob mob : Dungeon.level.mobs)
|
|
||||||
if (mob != this && fieldOfView[mob.pos] && mob.hostile && mob.buff(Corruption.class) == null)
|
|
||||||
enemies.add(mob);
|
|
||||||
if (enemies.size() > 0) return Random.element(enemies);
|
|
||||||
|
|
||||||
//otherwise go for nothing
|
|
||||||
return null;
|
|
||||||
|
|
||||||
//if the mob is amoked...
|
//if the mob is amoked...
|
||||||
} else if ( buff(Amok.class) != null) {
|
if ( buff(Amok.class) != null) {
|
||||||
|
|
||||||
//try to find an enemy mob to attack first.
|
//try to find an enemy mob to attack first.
|
||||||
for (Mob mob : Dungeon.level.mobs)
|
for (Mob mob : Dungeon.level.mobs)
|
||||||
if (mob != this && fieldOfView[mob.pos] && mob.hostile)
|
if (mob.alignment == Alignment.ENEMY && mob != this && fieldOfView[mob.pos])
|
||||||
enemies.add(mob);
|
enemies.add(mob);
|
||||||
if (enemies.size() > 0) return Random.element(enemies);
|
|
||||||
|
|
||||||
//try to find ally mobs to attack second.
|
|
||||||
for (Mob mob : Dungeon.level.mobs)
|
|
||||||
if (mob != this && fieldOfView[mob.pos] && mob.ally)
|
|
||||||
enemies.add(mob);
|
|
||||||
if (enemies.size() > 0) return Random.element(enemies);
|
|
||||||
|
|
||||||
//if there is nothing, go for the hero
|
|
||||||
else return Dungeon.hero;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
//try to find ally mobs to attack.
|
|
||||||
for (Mob mob : Dungeon.level.mobs)
|
|
||||||
if (mob != this && fieldOfView[mob.pos] && mob.ally)
|
|
||||||
enemies.add(mob);
|
|
||||||
|
|
||||||
//and add the hero to the list of targets.
|
|
||||||
enemies.add(Dungeon.hero);
|
|
||||||
|
|
||||||
//go after the closest enemy, preferring the hero if two are equidistant
|
if (enemies.isEmpty()) {
|
||||||
|
//try to find ally mobs to attack second.
|
||||||
|
for (Mob mob : Dungeon.level.mobs)
|
||||||
|
if (mob.alignment == Alignment.ALLY && mob != this && fieldOfView[mob.pos])
|
||||||
|
enemies.add(mob);
|
||||||
|
|
||||||
|
if (enemies.isEmpty()) {
|
||||||
|
//try to find the hero third
|
||||||
|
if (fieldOfView[Dungeon.hero.pos]) {
|
||||||
|
enemies.add(Dungeon.hero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if the mob is an ally...
|
||||||
|
} else if ( alignment == Alignment.ALLY ) {
|
||||||
|
//look for hostile mobs that are not passive to attack
|
||||||
|
for (Mob mob : Dungeon.level.mobs)
|
||||||
|
if (mob.alignment == Alignment.ENEMY
|
||||||
|
&& fieldOfView[mob.pos]
|
||||||
|
&& mob.state != mob.PASSIVE)
|
||||||
|
enemies.add(mob);
|
||||||
|
|
||||||
|
//if the mob is an enemy...
|
||||||
|
} else if (alignment == Alignment.ENEMY) {
|
||||||
|
//look for ally mobs to attack
|
||||||
|
for (Mob mob : Dungeon.level.mobs)
|
||||||
|
if (mob.alignment == Alignment.ALLY && fieldOfView[mob.pos])
|
||||||
|
enemies.add(mob);
|
||||||
|
|
||||||
|
//and look for the hero
|
||||||
|
if (fieldOfView[Dungeon.hero.pos]) {
|
||||||
|
enemies.add(Dungeon.hero);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//neutral character in particular do not choose enemies.
|
||||||
|
if (enemies.isEmpty()){
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
//go after the closest potential enemy, preferring the hero if two are equidistant
|
||||||
Char closest = null;
|
Char closest = null;
|
||||||
for (Char curr : enemies){
|
for (Char curr : enemies){
|
||||||
if (closest == null
|
if (closest == null
|
||||||
|
@ -255,7 +262,6 @@ public abstract class Mob extends Char {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return closest;
|
return closest;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else
|
} else
|
||||||
|
@ -538,7 +544,7 @@ public abstract class Mob extends Char {
|
||||||
|
|
||||||
if (Dungeon.hero.isAlive()) {
|
if (Dungeon.hero.isAlive()) {
|
||||||
|
|
||||||
if (hostile) {
|
if (alignment == Alignment.ENEMY) {
|
||||||
Statistics.enemiesSlain++;
|
Statistics.enemiesSlain++;
|
||||||
Badges.validateMonstersSlain();
|
Badges.validateMonstersSlain();
|
||||||
Statistics.qualifiedForNoKilling = false;
|
Statistics.qualifiedForNoKilling = false;
|
||||||
|
@ -566,7 +572,7 @@ public abstract class Mob extends Char {
|
||||||
Dungeon.level.drop( loot , pos ).sprite.drop();
|
Dungeon.level.drop( loot , pos ).sprite.drop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hostile && Dungeon.hero.lvl <= maxLvl + 2){
|
if (alignment == Alignment.ENEMY && Dungeon.hero.lvl <= maxLvl + 2){
|
||||||
int rolls = 1;
|
int rolls = 1;
|
||||||
if (properties.contains(Property.BOSS)) rolls = 15;
|
if (properties.contains(Property.BOSS)) rolls = 15;
|
||||||
else if (properties.contains(Property.MINIBOSS)) rolls = 5;
|
else if (properties.contains(Property.MINIBOSS)) rolls = 5;
|
||||||
|
@ -723,18 +729,20 @@ public abstract class Mob extends Char {
|
||||||
|
|
||||||
if (enemyInFOV) {
|
if (enemyInFOV) {
|
||||||
target = enemy.pos;
|
target = enemy.pos;
|
||||||
|
} else if (enemy == null) {
|
||||||
|
state = WANDERING;
|
||||||
|
target = Dungeon.level.randomDestination();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int oldPos = pos;
|
int oldPos = pos;
|
||||||
if (target != -1 && getCloser( target )) {
|
if (target != -1 && getCloser( target )) {
|
||||||
|
|
||||||
spend( 1 / speed() );
|
spend( 1 / speed() );
|
||||||
return moveSprite( oldPos, pos );
|
return moveSprite( oldPos, pos );
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
spend( TICK );
|
spend( TICK );
|
||||||
|
|
||||||
if (!enemyInFOV) {
|
if (!enemyInFOV) {
|
||||||
sprite.showLost();
|
sprite.showLost();
|
||||||
state = WANDERING;
|
state = WANDERING;
|
||||||
|
|
|
@ -27,18 +27,16 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.VenomGas;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.VenomGas;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
|
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.sprites.CharSprite;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.MirrorSprite;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.MirrorSprite;
|
||||||
import com.watabou.utils.Bundle;
|
import com.watabou.utils.Bundle;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
public class MirrorImage extends NPC {
|
public class MirrorImage extends NPC {
|
||||||
|
|
||||||
{
|
{
|
||||||
spriteClass = MirrorSprite.class;
|
spriteClass = MirrorSprite.class;
|
||||||
|
|
||||||
|
alignment = Alignment.ALLY;
|
||||||
state = HUNTING;
|
state = HUNTING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,32 +91,6 @@ public class MirrorImage extends NPC {
|
||||||
return damage;
|
return damage;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Char chooseEnemy() {
|
|
||||||
|
|
||||||
if (enemy == null || !enemy.isAlive()) {
|
|
||||||
HashSet<Mob> enemies = new HashSet<>();
|
|
||||||
for (Mob mob : Dungeon.level.mobs) {
|
|
||||||
if (mob.hostile
|
|
||||||
&& fieldOfView[mob.pos]
|
|
||||||
&& mob.state != mob.PASSIVE) {
|
|
||||||
enemies.add(mob);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//go for closest enemy
|
|
||||||
Char closest = null;
|
|
||||||
for (Char curr : enemies){
|
|
||||||
if (closest == null
|
|
||||||
|| Dungeon.level.distance(pos, curr.pos) < Dungeon.level.distance(pos, closest.pos)){
|
|
||||||
closest = curr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return closest;
|
|
||||||
}
|
|
||||||
|
|
||||||
return enemy;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharSprite sprite() {
|
public CharSprite sprite() {
|
||||||
CharSprite s = super.sprite();
|
CharSprite s = super.sprite();
|
||||||
|
|
|
@ -33,7 +33,7 @@ public abstract class NPC extends Mob {
|
||||||
HP = HT = 1;
|
HP = HT = 1;
|
||||||
EXP = 0;
|
EXP = 0;
|
||||||
|
|
||||||
hostile = false;
|
alignment = Alignment.NEUTRAL;
|
||||||
state = PASSIVE;
|
state = PASSIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -378,13 +378,11 @@ public class DriedRose extends Artifact {
|
||||||
|
|
||||||
flying = true;
|
flying = true;
|
||||||
|
|
||||||
ally = true;
|
alignment = Alignment.ALLY;
|
||||||
|
|
||||||
WANDERING = new Wandering();
|
WANDERING = new Wandering();
|
||||||
HUNTING = new Hunting();
|
|
||||||
|
|
||||||
state = WANDERING;
|
state = HUNTING;
|
||||||
enemy = null;
|
|
||||||
|
|
||||||
//after hero, but before mobs
|
//after hero, but before mobs
|
||||||
actPriority = 1;
|
actPriority = 1;
|
||||||
|
@ -470,11 +468,12 @@ public class DriedRose extends Artifact {
|
||||||
|| !enemy.isAlive()
|
|| !enemy.isAlive()
|
||||||
|| !Dungeon.level.mobs.contains(enemy)
|
|| !Dungeon.level.mobs.contains(enemy)
|
||||||
|| Dungeon.level.distance(enemy.pos, Dungeon.hero.pos) > 8
|
|| Dungeon.level.distance(enemy.pos, Dungeon.hero.pos) > 8
|
||||||
|
|| enemy.alignment != Alignment.ENEMY
|
||||||
|| state == WANDERING) {
|
|| state == WANDERING) {
|
||||||
|
|
||||||
HashSet<Mob> enemies = new HashSet<>();
|
HashSet<Mob> enemies = new HashSet<>();
|
||||||
for (Mob mob : Dungeon.level.mobs) {
|
for (Mob mob : Dungeon.level.mobs) {
|
||||||
if (mob.hostile
|
if (mob.alignment == Alignment.ENEMY
|
||||||
&& fieldOfView[mob.pos]
|
&& fieldOfView[mob.pos]
|
||||||
&& Dungeon.level.distance(mob.pos, Dungeon.hero.pos) <= 8
|
&& Dungeon.level.distance(mob.pos, Dungeon.hero.pos) <= 8
|
||||||
&& mob.state != mob.PASSIVE) {
|
&& mob.state != mob.PASSIVE) {
|
||||||
|
@ -676,12 +675,14 @@ public class DriedRose extends Artifact {
|
||||||
enemySeen = true;
|
enemySeen = true;
|
||||||
|
|
||||||
notice();
|
notice();
|
||||||
|
alerted = true;
|
||||||
state = HUNTING;
|
state = HUNTING;
|
||||||
target = enemy.pos;
|
target = enemy.pos;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
enemySeen = false;
|
enemySeen = false;
|
||||||
|
sprite.hideLost();
|
||||||
|
|
||||||
int oldPos = pos;
|
int oldPos = pos;
|
||||||
//always move towards the hero when wandering
|
//always move towards the hero when wandering
|
||||||
|
@ -701,40 +702,6 @@ public class DriedRose extends Artifact {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Hunting extends Mob.Hunting {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean act( boolean enemyInFOV, boolean justAlerted ) {
|
|
||||||
|
|
||||||
enemySeen = enemyInFOV;
|
|
||||||
if (enemyInFOV && !isCharmedBy( enemy ) && canAttack( enemy )) {
|
|
||||||
|
|
||||||
return doAttack( enemy );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (enemyInFOV) {
|
|
||||||
target = enemy.pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
int oldPos = pos;
|
|
||||||
if (enemyInFOV && getCloser( target )) {
|
|
||||||
|
|
||||||
spend( 1 / speed() );
|
|
||||||
return moveSprite( oldPos, pos );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
//don't lose a turn due to the transition, immediately act instead
|
|
||||||
state = WANDERING;
|
|
||||||
return state.act( false, justAlerted );
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//************************************************************************************
|
//************************************************************************************
|
||||||
//This is a bunch strings & string arrays, used in all of the sad ghost's voice lines.
|
//This is a bunch strings & string arrays, used in all of the sad ghost's voice lines.
|
||||||
|
|
|
@ -29,7 +29,6 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.LockedFloor;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.LockedFloor;
|
||||||
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.effects.MagicMissile;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation;
|
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation;
|
||||||
|
@ -118,7 +117,7 @@ public class LloydsBeacon extends Artifact {
|
||||||
|
|
||||||
for (int i = 0; i < PathFinder.NEIGHBOURS8.length; i++) {
|
for (int i = 0; i < PathFinder.NEIGHBOURS8.length; i++) {
|
||||||
Char ch = Actor.findChar(hero.pos + PathFinder.NEIGHBOURS8[i]);
|
Char ch = Actor.findChar(hero.pos + PathFinder.NEIGHBOURS8[i]);
|
||||||
if (ch != null && !(ch instanceof Mob && !((Mob) ch).hostile)) {
|
if (ch != null && ch.alignment == Char.Alignment.ENEMY) {
|
||||||
GLog.w( Messages.get(this, "creatures") );
|
GLog.w( Messages.get(this, "creatures") );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,12 +23,10 @@ package com.shatteredpixel.shatteredpixeldungeon.items.wands;
|
||||||
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Charm;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Charm;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Corruption;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Beam;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.Beam;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||||
|
@ -48,6 +46,7 @@ import com.shatteredpixel.shatteredpixeldungeon.plants.Plant;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||||
import com.watabou.noosa.audio.Sample;
|
import com.watabou.noosa.audio.Sample;
|
||||||
import com.watabou.utils.Bundle;
|
import com.watabou.utils.Bundle;
|
||||||
|
@ -83,8 +82,8 @@ public class WandOfTransfusion extends Wand {
|
||||||
|
|
||||||
processSoulMark(ch, chargesPerCast());
|
processSoulMark(ch, chargesPerCast());
|
||||||
|
|
||||||
//heals an ally, or charmed/corrupted enemy
|
//heals an ally, or a charmed enemy
|
||||||
if (((Mob) ch).ally || ch.buff(Charm.class) != null || ch.buff(Corruption.class) != null){
|
if (ch.alignment == Char.Alignment.ALLY || ch.buff(Charm.class) != null){
|
||||||
|
|
||||||
int missingHP = ch.HT - ch.HP;
|
int missingHP = ch.HT - ch.HP;
|
||||||
//heals 30%+3%*lvl missing HP.
|
//heals 30%+3%*lvl missing HP.
|
||||||
|
|
|
@ -227,7 +227,7 @@ public class CavesBossLevel extends Level {
|
||||||
|
|
||||||
for (Mob m : mobs){
|
for (Mob m : mobs){
|
||||||
//bring the first ally with you
|
//bring the first ally with you
|
||||||
if (m.ally){
|
if (m.alignment == Char.Alignment.ALLY){
|
||||||
m.pos = Dungeon.hero.pos + (Random.Int(2) == 0 ? +1 : -1);
|
m.pos = Dungeon.hero.pos + (Random.Int(2) == 0 ? +1 : -1);
|
||||||
m.sprite.place(m.pos);
|
m.sprite.place(m.pos);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -198,7 +198,7 @@ public class CityBossLevel extends Level {
|
||||||
|
|
||||||
for (Mob m : mobs){
|
for (Mob m : mobs){
|
||||||
//bring the first ally with you
|
//bring the first ally with you
|
||||||
if (m.ally){
|
if (m.alignment == Char.Alignment.ALLY){
|
||||||
m.pos = Dungeon.hero.pos + (Random.Int(2) == 0 ? +1 : -1);
|
m.pos = Dungeon.hero.pos + (Random.Int(2) == 0 ? +1 : -1);
|
||||||
m.sprite.place(m.pos);
|
m.sprite.place(m.pos);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -503,7 +503,7 @@ public abstract class Level implements Bundlable {
|
||||||
protected boolean act() {
|
protected boolean act() {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (Mob mob : mobs.toArray(new Mob[0])){
|
for (Mob mob : mobs.toArray(new Mob[0])){
|
||||||
if (mob.hostile) count++;
|
if (mob.alignment == Char.Alignment.ENEMY) count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count < nMobs()) {
|
if (count < nMobs()) {
|
||||||
|
|
|
@ -287,7 +287,7 @@ public class PrisonBossLevel extends Level {
|
||||||
|
|
||||||
for (Mob m : mobs){
|
for (Mob m : mobs){
|
||||||
//bring the first ally with you
|
//bring the first ally with you
|
||||||
if (m.ally){
|
if (m.alignment == Char.Alignment.ALLY){
|
||||||
m.pos = 5 + 25 * 32; //they should immediately walk out of the door
|
m.pos = 5 + 25 * 32; //they should immediately walk out of the door
|
||||||
m.sprite.place(m.pos);
|
m.sprite.place(m.pos);
|
||||||
break;
|
break;
|
||||||
|
@ -340,7 +340,7 @@ public class PrisonBossLevel extends Level {
|
||||||
|
|
||||||
//if any allies are left over, move them along the same way as the hero
|
//if any allies are left over, move them along the same way as the hero
|
||||||
for (Mob m : mobs){
|
for (Mob m : mobs){
|
||||||
if (m.ally) {
|
if (m.alignment == Char.Alignment.ALLY) {
|
||||||
m.pos += 9 + 3 * 32;
|
m.pos += 9 + 3 * 32;
|
||||||
m.sprite().place(m.pos);
|
m.sprite().place(m.pos);
|
||||||
}
|
}
|
||||||
|
@ -386,7 +386,7 @@ public class PrisonBossLevel extends Level {
|
||||||
//remove all mobs, but preserve allies
|
//remove all mobs, but preserve allies
|
||||||
ArrayList<Mob> allies = new ArrayList<>();
|
ArrayList<Mob> allies = new ArrayList<>();
|
||||||
for(Mob m : mobs.toArray(new Mob[0])){
|
for(Mob m : mobs.toArray(new Mob[0])){
|
||||||
if (m.ally){
|
if (m.alignment == Char.Alignment.ALLY){
|
||||||
allies.add(m);
|
allies.add(m);
|
||||||
mobs.remove(m);
|
mobs.remove(m);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user