v2.5.0: adjusted logic for landmarks, now get added based on hero action

This commit is contained in:
Evan Debenham
2024-06-27 13:07:36 -04:00
parent b770732b06
commit aa7b645645
19 changed files with 125 additions and 75 deletions
@@ -30,6 +30,11 @@ public class Alchemy extends Blob {
protected int pos; protected int pos;
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.ALCHEMY;
}
@Override @Override
protected void evolve() { protected void evolve() {
int cell; int cell;
@@ -40,9 +45,6 @@ public class Alchemy extends Blob {
off[cell] = cur[cell]; off[cell] = cur[cell];
volume += off[cell]; volume += off[cell];
if (off[cell] > 0 && Dungeon.level.visited[cell]){
Notes.add( Notes.Landmark.ALCHEMY );
}
} }
} }
} }
@@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.blobs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter; import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.watabou.utils.Bundle; import com.watabou.utils.Bundle;
import com.watabou.utils.Rect; import com.watabou.utils.Rect;
@@ -223,6 +224,12 @@ public class Blob extends Actor {
//do nothing by default, only some blobs affect flags //do nothing by default, only some blobs affect flags
} }
//some blobs have an associated landmark entry, which is added when the hero sees them
//blobs may also remove this landmark in some cases, such as when they expire or are consumed
public Notes.Landmark landmark(){
return null;
}
public String tileDesc() { public String tileDesc() {
return null; return null;
} }
@@ -34,6 +34,11 @@ import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
public class Foliage extends Blob { public class Foliage extends Blob {
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.GARDEN;
}
@Override @Override
protected void evolve() { protected void evolve() {
@@ -70,10 +75,6 @@ public class Foliage extends Blob {
s.prolong(); s.prolong();
} }
} }
if (seen) {
Notes.add( Notes.Landmark.GARDEN );
}
} }
@Override @Override
@@ -64,6 +64,11 @@ public class SacrificialFire extends Blob {
private Item prize; private Item prize;
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.SACRIFICIAL_FIRE;
}
@Override @Override
protected void evolve() { protected void evolve() {
int cell; int cell;
@@ -87,8 +92,6 @@ public class SacrificialFire extends Blob {
if (off[cell] > 0 && Dungeon.level.visited[cell]) { if (off[cell] > 0 && Dungeon.level.visited[cell]) {
Notes.add( Notes.Landmark.SACRIFICIAL_FIRE);
if (Dungeon.level.mobCount() == 0 if (Dungeon.level.mobCount() == 0
&& bonusSpawns > 0) { && bonusSpawns > 0) {
if (Dungeon.level.spawnMob(4)) { if (Dungeon.level.spawnMob(4)) {
@@ -187,7 +190,7 @@ public class SacrificialFire extends Blob {
GLog.w( Messages.get(SacrificialFire.class, "worthy")); GLog.w( Messages.get(SacrificialFire.class, "worthy"));
} else { } else {
clear(firePos); clear(firePos);
Notes.remove(Notes.Landmark.SACRIFICIAL_FIRE); if (volume <= 0) Notes.remove( landmark() );
for (int i : PathFinder.NEIGHBOURS9){ for (int i : PathFinder.NEIGHBOURS9){
CellEmitter.get(firePos+i).burst( SacrificialParticle.FACTORY, 20 ); CellEmitter.get(firePos+i).burst( SacrificialParticle.FACTORY, 20 );
@@ -88,7 +88,7 @@ public class WaterOfAwareness extends WellWater {
} }
@Override @Override
protected Landmark record() { public Landmark landmark() {
return Landmark.WELL_OF_AWARENESS; return Landmark.WELL_OF_AWARENESS;
} }
@@ -91,7 +91,7 @@ public class WaterOfHealth extends WellWater {
} }
@Override @Override
protected Landmark record() { public Landmark landmark() {
return Landmark.WELL_OF_HEALTH; return Landmark.WELL_OF_HEALTH;
} }
@@ -44,17 +44,9 @@ public abstract class WellWater extends Blob {
if (Dungeon.level.insideMap(cell)) { if (Dungeon.level.insideMap(cell)) {
off[cell] = cur[cell]; off[cell] = cur[cell];
volume += off[cell]; volume += off[cell];
if (off[cell] > 0 && Dungeon.level.visited[cell]) {
seen = true;
}
} }
} }
} }
if (seen){
Notes.add(record());
} else {
Notes.remove(record());
}
} }
protected boolean affect( int pos ) { protected boolean affect( int pos ) {
@@ -63,7 +55,8 @@ public abstract class WellWater extends Blob {
if (pos == Dungeon.hero.pos && affectHero( Dungeon.hero )) { if (pos == Dungeon.hero.pos && affectHero( Dungeon.hero )) {
cur[pos] = 0; clear(pos);
if (volume <= 0 && landmark() != null) Notes.remove(landmark());
return true; return true;
} else if ((heap = Dungeon.level.heaps.get( pos )) != null) { } else if ((heap = Dungeon.level.heaps.get( pos )) != null) {
@@ -85,7 +78,8 @@ public abstract class WellWater extends Blob {
} }
heap.sprite.link(); heap.sprite.link();
cur[pos] = 0; clear(pos);
if (volume <= 0 && landmark() != null) Notes.remove(landmark());
return true; return true;
@@ -112,8 +106,6 @@ public abstract class WellWater extends Blob {
protected abstract Item affectItem( Item item, int pos ); protected abstract Item affectItem( Item item, int pos );
protected abstract Notes.Landmark record();
public static void affectCell( int cell ) { public static void affectCell( int cell ) {
Class<?>[] waters = {WaterOfHealth.class, WaterOfAwareness.class}; Class<?>[] waters = {WaterOfHealth.class, WaterOfAwareness.class};
@@ -31,6 +31,7 @@ import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics; import com.shatteredpixel.shatteredpixeldungeon.Statistics;
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.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.SacrificialFire; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.SacrificialFire;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.AdrenalineSurge; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.AdrenalineSurge;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.AnkhInvulnerability; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.AnkhInvulnerability;
@@ -1518,6 +1519,10 @@ public class Hero extends Char {
Mob target = null; Mob target = null;
for (Mob m : Dungeon.level.mobs.toArray(new Mob[0])) { for (Mob m : Dungeon.level.mobs.toArray(new Mob[0])) {
if (fieldOfView[ m.pos ] && m.landmark() != null){
Notes.add(m.landmark());
}
if (fieldOfView[ m.pos ] && m.alignment == Alignment.ENEMY) { if (fieldOfView[ m.pos ] && m.alignment == Alignment.ENEMY) {
visible.add(m); visible.add(m);
if (!visibleEnemies.contains( m )) { if (!visibleEnemies.contains( m )) {
@@ -1558,6 +1563,26 @@ public class Hero extends Char {
} }
visibleEnemies = visible; visibleEnemies = visible;
//we also scan for blob landmarks here
for (Blob b : Dungeon.level.blobs.values().toArray(new Blob[0])){
if (b.volume > 0 && b.landmark() != null && !Notes.contains(b.landmark())){
int cell;
boolean found = false;
//if a single cell within the blob is visible, we add the landmark
for (int i=b.area.top; i < b.area.bottom; i++) {
for (int j = b.area.left; j < b.area.right; j++) {
cell = j + i* Dungeon.level.width();
if (fieldOfView[cell] && b.cur[cell] > 0) {
Notes.add( b.landmark() );
found = true;
break;
}
}
if (found) break;
}
}
}
} }
public int visibleEnemies() { public int visibleEnemies() {
@@ -87,10 +87,6 @@ public class DemonSpawner extends Mob {
spawnRecorded = true; spawnRecorded = true;
} }
if (Dungeon.level.visited[pos]){
Notes.add( Notes.Landmark.DEMON_SPAWNER );
}
if (Dungeon.hero.buff(AscensionChallenge.class) != null && spawnCooldown > 20){ if (Dungeon.hero.buff(AscensionChallenge.class) != null && spawnCooldown > 20){
spawnCooldown = 20; spawnCooldown = 20;
} }
@@ -145,11 +141,16 @@ public class DemonSpawner extends Mob {
super.damage(dmg, src); super.damage(dmg, src);
} }
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.DEMON_SPAWNER;
}
@Override @Override
public void die(Object cause) { public void die(Object cause) {
if (spawnRecorded){ if (spawnRecorded){
Statistics.spawnersAlive--; Statistics.spawnersAlive--;
Notes.remove(Notes.Landmark.DEMON_SPAWNER); Notes.remove(landmark());
} }
GLog.h(Messages.get(this, "on_death")); GLog.h(Messages.get(this, "on_death"));
super.die(cause); super.die(cause);
@@ -73,6 +73,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Lucky;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.darts.Dart; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.darts.Dart;
import com.shatteredpixel.shatteredpixeldungeon.journal.Bestiary; import com.shatteredpixel.shatteredpixeldungeon.journal.Bestiary;
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Chasm; import com.shatteredpixel.shatteredpixeldungeon.levels.features.Chasm;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
@@ -990,6 +991,12 @@ public abstract class Mob extends Char {
GLog.n( "%s: \"%s\" ", Messages.titleCase(name()), str ); GLog.n( "%s: \"%s\" ", Messages.titleCase(name()), str );
} }
//some mobs have an associated landmark entry, which is added when the hero sees them
//mobs may also remove this landmark in some cases, such as when a quest is complete or they die
public Notes.Landmark landmark(){
return null;
}
public interface AiState { public interface AiState {
boolean act( boolean enemyInFOV, boolean justAlerted ); boolean act( boolean enemyInFOV, boolean justAlerted );
} }
@@ -84,14 +84,6 @@ public class Statue extends Mob {
weapon = (Weapon)bundle.get( WEAPON ); weapon = (Weapon)bundle.get( WEAPON );
} }
@Override
protected boolean act() {
if (levelGenStatue && Dungeon.level.visited[pos]) {
Notes.add( Notes.Landmark.STATUE );
}
return super.act();
}
@Override @Override
public int damageRoll() { public int damageRoll() {
return weapon.damageRoll(this); return weapon.damageRoll(this);
@@ -161,10 +153,15 @@ public class Statue extends Mob {
super.die( cause ); super.die( cause );
} }
@Override
public Notes.Landmark landmark() {
return levelGenStatue ? Notes.Landmark.STATUE : null;
}
@Override @Override
public void destroy() { public void destroy() {
if (levelGenStatue) { if (landmark() != null) {
Notes.remove( Notes.Landmark.STATUE ); Notes.remove( landmark() );
} }
super.destroy(); super.destroy();
} }
@@ -58,15 +58,19 @@ public class Blacksmith extends NPC {
properties.add(Property.IMMOVABLE); properties.add(Property.IMMOVABLE);
} }
@Override
public Notes.Landmark landmark() {
return (!Quest.completed() || Quest.rewardsAvailable()) ? Notes.Landmark.TROLL : null;
}
@Override @Override
protected boolean act() { protected boolean act() {
if (Dungeon.hero.buff(AscensionChallenge.class) != null){ if (Dungeon.hero.buff(AscensionChallenge.class) != null){
die(null); die(null);
Notes.remove( Notes.Landmark.TROLL ); Notes.remove( landmark() );
return true; return true;
} } else if (!Quest.rewardsAvailable() && Quest.completed()){
if (Dungeon.level.visited[pos] && !Quest.started()){ Notes.remove( landmark() );
Notes.add( Notes.Landmark.TROLL );
} }
return super.act(); return super.act();
} }
@@ -121,7 +125,6 @@ public class Blacksmith extends NPC {
Quest.given = true; Quest.given = true;
Quest.completed = false; Quest.completed = false;
Notes.add( Notes.Landmark.TROLL );
Item pick = Quest.pickaxe != null ? Quest.pickaxe : new Pickaxe(); Item pick = Quest.pickaxe != null ? Quest.pickaxe : new Pickaxe();
if (pick.doPickUp( Dungeon.hero )) { if (pick.doPickUp( Dungeon.hero )) {
GLog.i( Messages.capitalize(Messages.get(Dungeon.hero, "you_now_have", pick.name()) )); GLog.i( Messages.capitalize(Messages.get(Dungeon.hero, "you_now_have", pick.name()) ));
@@ -81,15 +81,18 @@ public class Ghost extends NPC {
} }
} }
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.GHOST;
}
@Override @Override
protected boolean act() { protected boolean act() {
if (Dungeon.hero.buff(AscensionChallenge.class) != null){ if (Dungeon.hero.buff(AscensionChallenge.class) != null){
die(null); die(null);
Notes.remove( landmark() );
return true; return true;
} }
if (Dungeon.level.heroFOV[pos] && !Quest.completed()){
Notes.add( Notes.Landmark.GHOST );
}
return super.act(); return super.act();
} }
@@ -184,7 +187,6 @@ public class Ghost extends NPC {
if (questBoss.pos != -1) { if (questBoss.pos != -1) {
GameScene.add(questBoss); GameScene.add(questBoss);
Quest.given = true; Quest.given = true;
Notes.add( Notes.Landmark.GHOST );
Game.runOnRenderThread(new Callback() { Game.runOnRenderThread(new Callback() {
@Override @Override
public void call() { public void call() {
@@ -55,6 +55,11 @@ public class Imp extends NPC {
private boolean seenBefore = false; private boolean seenBefore = false;
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.IMP;
}
@Override @Override
protected boolean act() { protected boolean act() {
if (Dungeon.hero.buff(AscensionChallenge.class) != null){ if (Dungeon.hero.buff(AscensionChallenge.class) != null){
@@ -62,7 +67,6 @@ public class Imp extends NPC {
return true; return true;
} }
if (!Quest.given && Dungeon.level.visited[pos]) { if (!Quest.given && Dungeon.level.visited[pos]) {
Notes.add( Notes.Landmark.IMP );
if (!seenBefore && Dungeon.level.heroFOV[pos]) { if (!seenBefore && Dungeon.level.heroFOV[pos]) {
yell(Messages.get(this, "hey", Messages.titleCase(Dungeon.hero.name()))); yell(Messages.get(this, "hey", Messages.titleCase(Dungeon.hero.name())));
seenBefore = true; seenBefore = true;
@@ -123,7 +127,6 @@ public class Imp extends NPC {
tell( Quest.alternative ? Messages.get(this, "monks_1") : Messages.get(this, "golems_1") ); tell( Quest.alternative ? Messages.get(this, "monks_1") : Messages.get(this, "golems_1") );
Quest.given = true; Quest.given = true;
Quest.completed = false; Quest.completed = false;
Notes.add( Notes.Landmark.IMP );
} }
return true; return true;
@@ -85,6 +85,11 @@ public class RatKing extends NPC {
} }
} }
@Override
public Notes.Landmark landmark() {
return Dungeon.depth == 5 ? Notes.Landmark.RAT_KING : null;
}
@Override @Override
protected boolean act() { protected boolean act() {
if (Dungeon.depth < 5){ if (Dungeon.depth < 5){
@@ -101,10 +106,6 @@ public class RatKing extends NPC {
} else { } else {
target = Dungeon.level.entrance(); target = Dungeon.level.entrance();
} }
} else {
if (Dungeon.level.heroFOV[pos]){
Notes.add(Notes.Landmark.RAT_KING);
}
} }
return super.act(); return super.act();
} }
@@ -70,11 +70,12 @@ public class Shopkeeper extends NPC {
private int turnsSinceHarmed = -1; private int turnsSinceHarmed = -1;
@Override @Override
protected boolean act() { public Notes.Landmark landmark() {
return Notes.Landmark.SHOP;
}
if (Dungeon.level.visited[pos]){ @Override
Notes.add(Notes.Landmark.SHOP); protected boolean act() {
}
if (turnsSinceHarmed >= 0){ if (turnsSinceHarmed >= 0){
turnsSinceHarmed ++; turnsSinceHarmed ++;
@@ -148,7 +149,7 @@ public class Shopkeeper extends NPC {
public void flee() { public void flee() {
destroy(); destroy();
Notes.remove(Notes.Landmark.SHOP); Notes.remove( landmark() );
if (sprite != null) { if (sprite != null) {
sprite.killAndErase(); sprite.killAndErase();
@@ -66,15 +66,17 @@ public class Wandmaker extends NPC {
properties.add(Property.IMMOVABLE); properties.add(Property.IMMOVABLE);
} }
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.WANDMAKER;
}
@Override @Override
protected boolean act() { protected boolean act() {
if (Dungeon.hero.buff(AscensionChallenge.class) != null){ if (Dungeon.hero.buff(AscensionChallenge.class) != null){
die(null); die(null);
return true; return true;
} }
if (Dungeon.level.visited[pos] && Quest.wand1 != null){
Notes.add( Notes.Landmark.WANDMAKER );
}
return super.act(); return super.act();
} }
@@ -204,7 +206,6 @@ public class Wandmaker extends NPC {
}); });
Quest.given = true; Quest.given = true;
Notes.add( Notes.Landmark.WANDMAKER );
} }
return true; return true;
@@ -368,6 +368,10 @@ public class Notes {
return false; return false;
} }
public static boolean contains( Landmark landmark ){
return records.contains(new LandmarkRecord( landmark, Dungeon.depth));
}
public static boolean remove( Landmark landmark ) { public static boolean remove( Landmark landmark ) {
return records.remove( new LandmarkRecord(landmark, Dungeon.depth) ); return records.remove( new LandmarkRecord(landmark, Dungeon.depth) );
} }
@@ -105,6 +105,11 @@ public class WeakFloorRoom extends SpecialRoom {
//we use a blob to track visibility of the well, yes this sucks //we use a blob to track visibility of the well, yes this sucks
public static class WellID extends Blob { public static class WellID extends Blob {
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.DISTANT_WELL;
}
@Override @Override
protected void evolve() { protected void evolve() {
int cell; int cell;
@@ -115,11 +120,6 @@ public class WeakFloorRoom extends SpecialRoom {
off[cell] = cur[cell]; off[cell] = cur[cell];
volume += off[cell]; volume += off[cell];
if (off[cell] > 0 && Dungeon.level.visited[cell]){
Notes.add( Notes.Landmark.DISTANT_WELL );
fullyClear(); //deletes itself after fulfilling its purpose
return;
}
} }
} }
} }