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

View File

@@ -29,7 +29,12 @@ import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
public class Alchemy extends Blob {
protected int pos;
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.ALCHEMY;
}
@Override
protected void evolve() {
int cell;
@@ -40,9 +45,6 @@ public class Alchemy extends Blob {
off[cell] = cur[cell];
volume += off[cell];
if (off[cell] > 0 && Dungeon.level.visited[cell]){
Notes.add( Notes.Landmark.ALCHEMY );
}
}
}
}

View File

@@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.blobs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.watabou.utils.Bundle;
import com.watabou.utils.Rect;
@@ -222,6 +223,12 @@ public class Blob extends Actor {
public void onBuildFlagMaps( Level l ){
//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() {
return null;

View File

@@ -33,7 +33,12 @@ import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
public class Foliage extends Blob {
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.GARDEN;
}
@Override
protected void evolve() {
@@ -70,10 +75,6 @@ public class Foliage extends Blob {
s.prolong();
}
}
if (seen) {
Notes.add( Notes.Landmark.GARDEN );
}
}
@Override

View File

@@ -64,6 +64,11 @@ public class SacrificialFire extends Blob {
private Item prize;
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.SACRIFICIAL_FIRE;
}
@Override
protected void evolve() {
int cell;
@@ -87,8 +92,6 @@ public class SacrificialFire extends Blob {
if (off[cell] > 0 && Dungeon.level.visited[cell]) {
Notes.add( Notes.Landmark.SACRIFICIAL_FIRE);
if (Dungeon.level.mobCount() == 0
&& bonusSpawns > 0) {
if (Dungeon.level.spawnMob(4)) {
@@ -187,7 +190,7 @@ public class SacrificialFire extends Blob {
GLog.w( Messages.get(SacrificialFire.class, "worthy"));
} else {
clear(firePos);
Notes.remove(Notes.Landmark.SACRIFICIAL_FIRE);
if (volume <= 0) Notes.remove( landmark() );
for (int i : PathFinder.NEIGHBOURS9){
CellEmitter.get(firePos+i).burst( SacrificialParticle.FACTORY, 20 );

View File

@@ -88,7 +88,7 @@ public class WaterOfAwareness extends WellWater {
}
@Override
protected Landmark record() {
public Landmark landmark() {
return Landmark.WELL_OF_AWARENESS;
}

View File

@@ -91,7 +91,7 @@ public class WaterOfHealth extends WellWater {
}
@Override
protected Landmark record() {
public Landmark landmark() {
return Landmark.WELL_OF_HEALTH;
}

View File

@@ -44,17 +44,9 @@ public abstract class WellWater extends Blob {
if (Dungeon.level.insideMap(cell)) {
off[cell] = cur[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 ) {
@@ -63,7 +55,8 @@ public abstract class WellWater extends Blob {
if (pos == Dungeon.hero.pos && affectHero( Dungeon.hero )) {
cur[pos] = 0;
clear(pos);
if (volume <= 0 && landmark() != null) Notes.remove(landmark());
return true;
} else if ((heap = Dungeon.level.heaps.get( pos )) != null) {
@@ -85,7 +78,8 @@ public abstract class WellWater extends Blob {
}
heap.sprite.link();
cur[pos] = 0;
clear(pos);
if (volume <= 0 && landmark() != null) Notes.remove(landmark());
return true;
@@ -112,8 +106,6 @@ public abstract class WellWater extends Blob {
protected abstract Item affectItem( Item item, int pos );
protected abstract Notes.Landmark record();
public static void affectCell( int cell ) {
Class<?>[] waters = {WaterOfHealth.class, WaterOfAwareness.class};

View File

@@ -31,6 +31,7 @@ import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
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.buffs.AdrenalineSurge;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.AnkhInvulnerability;
@@ -1518,6 +1519,10 @@ public class Hero extends Char {
Mob target = null;
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) {
visible.add(m);
if (!visibleEnemies.contains( m )) {
@@ -1558,6 +1563,26 @@ public class Hero extends Char {
}
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() {

View File

@@ -87,10 +87,6 @@ public class DemonSpawner extends Mob {
spawnRecorded = true;
}
if (Dungeon.level.visited[pos]){
Notes.add( Notes.Landmark.DEMON_SPAWNER );
}
if (Dungeon.hero.buff(AscensionChallenge.class) != null && spawnCooldown > 20){
spawnCooldown = 20;
}
@@ -145,11 +141,16 @@ public class DemonSpawner extends Mob {
super.damage(dmg, src);
}
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.DEMON_SPAWNER;
}
@Override
public void die(Object cause) {
if (spawnRecorded){
Statistics.spawnersAlive--;
Notes.remove(Notes.Landmark.DEMON_SPAWNER);
Notes.remove(landmark());
}
GLog.h(Messages.get(this, "on_death"));
super.die(cause);

View File

@@ -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.darts.Dart;
import com.shatteredpixel.shatteredpixeldungeon.journal.Bestiary;
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Chasm;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
@@ -990,6 +991,12 @@ public abstract class Mob extends Char {
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 {
boolean act( boolean enemyInFOV, boolean justAlerted );
}

View File

@@ -84,14 +84,6 @@ public class Statue extends Mob {
weapon = (Weapon)bundle.get( WEAPON );
}
@Override
protected boolean act() {
if (levelGenStatue && Dungeon.level.visited[pos]) {
Notes.add( Notes.Landmark.STATUE );
}
return super.act();
}
@Override
public int damageRoll() {
return weapon.damageRoll(this);
@@ -160,11 +152,16 @@ public class Statue extends Mob {
Dungeon.level.drop( weapon, pos ).sprite.drop();
super.die( cause );
}
@Override
public Notes.Landmark landmark() {
return levelGenStatue ? Notes.Landmark.STATUE : null;
}
@Override
public void destroy() {
if (levelGenStatue) {
Notes.remove( Notes.Landmark.STATUE );
if (landmark() != null) {
Notes.remove( landmark() );
}
super.destroy();
}

View File

@@ -57,16 +57,20 @@ public class Blacksmith extends NPC {
properties.add(Property.IMMOVABLE);
}
@Override
public Notes.Landmark landmark() {
return (!Quest.completed() || Quest.rewardsAvailable()) ? Notes.Landmark.TROLL : null;
}
@Override
protected boolean act() {
if (Dungeon.hero.buff(AscensionChallenge.class) != null){
die(null);
Notes.remove( Notes.Landmark.TROLL );
Notes.remove( landmark() );
return true;
}
if (Dungeon.level.visited[pos] && !Quest.started()){
Notes.add( Notes.Landmark.TROLL );
} else if (!Quest.rewardsAvailable() && Quest.completed()){
Notes.remove( landmark() );
}
return super.act();
}
@@ -121,7 +125,6 @@ public class Blacksmith extends NPC {
Quest.given = true;
Quest.completed = false;
Notes.add( Notes.Landmark.TROLL );
Item pick = Quest.pickaxe != null ? Quest.pickaxe : new Pickaxe();
if (pick.doPickUp( Dungeon.hero )) {
GLog.i( Messages.capitalize(Messages.get(Dungeon.hero, "you_now_have", pick.name()) ));

View File

@@ -81,15 +81,18 @@ public class Ghost extends NPC {
}
}
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.GHOST;
}
@Override
protected boolean act() {
if (Dungeon.hero.buff(AscensionChallenge.class) != null){
die(null);
Notes.remove( landmark() );
return true;
}
if (Dungeon.level.heroFOV[pos] && !Quest.completed()){
Notes.add( Notes.Landmark.GHOST );
}
return super.act();
}
@@ -184,7 +187,6 @@ public class Ghost extends NPC {
if (questBoss.pos != -1) {
GameScene.add(questBoss);
Quest.given = true;
Notes.add( Notes.Landmark.GHOST );
Game.runOnRenderThread(new Callback() {
@Override
public void call() {

View File

@@ -54,7 +54,12 @@ public class Imp extends NPC {
}
private boolean seenBefore = false;
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.IMP;
}
@Override
protected boolean act() {
if (Dungeon.hero.buff(AscensionChallenge.class) != null){
@@ -62,7 +67,6 @@ public class Imp extends NPC {
return true;
}
if (!Quest.given && Dungeon.level.visited[pos]) {
Notes.add( Notes.Landmark.IMP );
if (!seenBefore && Dungeon.level.heroFOV[pos]) {
yell(Messages.get(this, "hey", Messages.titleCase(Dungeon.hero.name())));
seenBefore = true;
@@ -123,7 +127,6 @@ public class Imp extends NPC {
tell( Quest.alternative ? Messages.get(this, "monks_1") : Messages.get(this, "golems_1") );
Quest.given = true;
Quest.completed = false;
Notes.add( Notes.Landmark.IMP );
}
return true;

View File

@@ -85,6 +85,11 @@ public class RatKing extends NPC {
}
}
@Override
public Notes.Landmark landmark() {
return Dungeon.depth == 5 ? Notes.Landmark.RAT_KING : null;
}
@Override
protected boolean act() {
if (Dungeon.depth < 5){
@@ -101,10 +106,6 @@ public class RatKing extends NPC {
} else {
target = Dungeon.level.entrance();
}
} else {
if (Dungeon.level.heroFOV[pos]){
Notes.add(Notes.Landmark.RAT_KING);
}
}
return super.act();
}

View File

@@ -68,14 +68,15 @@ public class Shopkeeper extends NPC {
public ArrayList<Item> buybackItems = new ArrayList<>();
private int turnsSinceHarmed = -1;
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.SHOP;
}
@Override
protected boolean act() {
if (Dungeon.level.visited[pos]){
Notes.add(Notes.Landmark.SHOP);
}
if (turnsSinceHarmed >= 0){
turnsSinceHarmed ++;
}
@@ -148,7 +149,7 @@ public class Shopkeeper extends NPC {
public void flee() {
destroy();
Notes.remove(Notes.Landmark.SHOP);
Notes.remove( landmark() );
if (sprite != null) {
sprite.killAndErase();

View File

@@ -65,16 +65,18 @@ public class Wandmaker extends NPC {
properties.add(Property.IMMOVABLE);
}
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.WANDMAKER;
}
@Override
protected boolean act() {
if (Dungeon.hero.buff(AscensionChallenge.class) != null){
die(null);
return true;
}
if (Dungeon.level.visited[pos] && Quest.wand1 != null){
Notes.add( Notes.Landmark.WANDMAKER );
}
return super.act();
}
@@ -204,7 +206,6 @@ public class Wandmaker extends NPC {
});
Quest.given = true;
Notes.add( Notes.Landmark.WANDMAKER );
}
return true;

View File

@@ -367,6 +367,10 @@ public class Notes {
}
return false;
}
public static boolean contains( Landmark landmark ){
return records.contains(new LandmarkRecord( landmark, Dungeon.depth));
}
public static boolean remove( Landmark landmark ) {
return records.remove( new LandmarkRecord(landmark, Dungeon.depth) );

View File

@@ -105,6 +105,11 @@ public class WeakFloorRoom extends SpecialRoom {
//we use a blob to track visibility of the well, yes this sucks
public static class WellID extends Blob {
@Override
public Notes.Landmark landmark() {
return Notes.Landmark.DISTANT_WELL;
}
@Override
protected void evolve() {
int cell;
@@ -115,11 +120,6 @@ public class WeakFloorRoom extends SpecialRoom {
off[cell] = cur[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;
}
}
}
}