v2.2.0: refactored noisemaker code to more cleanly extend from Bomb

This commit is contained in:
Evan Debenham
2023-07-12 13:02:35 -04:00
parent d39ecceaef
commit 39a50a1dc0
3 changed files with 98 additions and 111 deletions
@@ -321,8 +321,7 @@ public class Heap implements Bundlable {
((Potion) item).shatter(pos); ((Potion) item).shatter(pos);
frozen = true; frozen = true;
} else if (item instanceof Bomb){ } else if (item instanceof Bomb){
((Bomb) item).fuse = null; frozen = frozen || ((Bomb) item).fuse.freeze();
frozen = true;
} }
} }
@@ -107,10 +107,14 @@ public class Bomb extends Item {
super.execute(hero, action); super.execute(hero, action);
} }
protected Fuse createFuse(){
return new Fuse();
}
@Override @Override
protected void onThrow( int cell ) { protected void onThrow( int cell ) {
if (!Dungeon.level.pit[ cell ] && lightingFuse) { if (!Dungeon.level.pit[ cell ] && lightingFuse) {
Actor.addDelayed(fuse = new Fuse().ignite(this), 2); Actor.addDelayed(fuse = createFuse().ignite(this), 2);
} }
if (Actor.findChar( cell ) != null && !(Actor.findChar( cell ) instanceof Hero) ){ if (Actor.findChar( cell ) != null && !(Actor.findChar( cell ) instanceof Hero) ){
ArrayList<Integer> candidates = new ArrayList<>(); ArrayList<Integer> candidates = new ArrayList<>();
@@ -269,7 +273,7 @@ public class Bomb extends Item {
actPriority = BLOB_PRIO+1; //after hero, before other actors actPriority = BLOB_PRIO+1; //after hero, before other actors
} }
private Bomb bomb; protected Bomb bomb;
public Fuse ignite(Bomb bomb){ public Fuse ignite(Bomb bomb){
this.bomb = bomb; this.bomb = bomb;
@@ -289,21 +293,7 @@ public class Bomb extends Item {
for (Heap heap : Dungeon.level.heaps.valueList()) { for (Heap heap : Dungeon.level.heaps.valueList()) {
if (heap.items.contains(bomb)) { if (heap.items.contains(bomb)) {
//FIXME this is a bit hacky, might want to generalize the functionality trigger(heap);
//of bombs that don't explode instantly when their fuse ends
if (bomb instanceof Noisemaker){
((Noisemaker) bomb).setTrigger(heap.pos);
} else {
heap.remove(bomb);
bomb.explode(heap.pos);
}
diactivate();
Actor.remove(this);
return true; return true;
} }
} }
@@ -313,6 +303,18 @@ public class Bomb extends Item {
Actor.remove( this ); Actor.remove( this );
return true; return true;
} }
protected void trigger(Heap heap){
heap.remove(bomb);
bomb.explode(heap.pos);
Actor.remove(this);
}
public boolean freeze(){
bomb.fuse = null;
Actor.remove(this);
return true;
}
} }
@@ -24,14 +24,11 @@ package com.shatteredpixel.shatteredpixeldungeon.items.bombs;
import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Assets;
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.actors.buffs.Buff;
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.effects.CellEmitter; import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.watabou.noosa.audio.Sample; import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Bundle; import com.watabou.utils.Bundle;
@@ -42,122 +39,111 @@ public class Noisemaker extends Bomb {
image = ItemSpriteSheet.NOISEMAKER; image = ItemSpriteSheet.NOISEMAKER;
} }
public void setTrigger(int cell){
Buff.affect(Dungeon.hero, Trigger.class).set(cell);
fuse = null;
}
@Override @Override
public ItemSprite.Glowing glowing() { protected Fuse createFuse() {
if (fuse == null){ return new NoisemakerFuse();
for (Trigger trigger : Dungeon.hero.buffs(Trigger.class)){
Heap heap = Dungeon.level.heaps.get(trigger.cell);
if (heap != null && heap.items.contains(this)) {
return new ItemSprite.Glowing( 0xFF0000, 0.6f);
}
}
}
return super.glowing();
} }
@Override @Override
public boolean doPickUp(Hero hero, int pos) { public boolean doPickUp(Hero hero, int pos) {
if (fuse == null){ //cannot pickup after first trigger
for (Trigger trigger : hero.buffs(Trigger.class)){ if (fuse instanceof NoisemakerFuse && ((NoisemakerFuse) fuse).triggered){
if (trigger.cell == pos) return false; return false;
}
} }
return super.doPickUp(hero, pos); return super.doPickUp(hero, pos);
} }
public static class Trigger extends Buff { //does not instantly explode
public static class NoisemakerFuse extends Fuse {
{ private boolean triggered = false;
revivePersists = true;
}
int cell; private int left;
int floor;
int left;
public void set(int cell){
floor = Dungeon.depth;
this.cell = cell;
left = 0;
}
@Override @Override
public boolean act() { protected boolean act() {
if (!triggered){
//acts like a normal fuse until first trigger
return super.act();
} else {
if (Dungeon.depth != floor){ for (Heap heap : Dungeon.level.heaps.valueList()) {
spend(TICK); if (heap.items.contains(bomb)) {
return true;
}
Noisemaker bomb = null; //active noisemakers cannot be snuffed out, blow it up!
Heap heap = Dungeon.level.heaps.get(cell); if (bomb.fuse != this){
trigger(heap);
if (heap != null){ //check if there is a nearby char, blow up if there is
for (Item i : heap.items){ } else if (Actor.findChar(heap.pos) != null) {
if (i instanceof Noisemaker){
bomb = (Noisemaker) i;
break;
}
}
}
if (bomb == null) {
detach();
} else if (Actor.findChar(cell) != null) {
heap.items.remove(bomb); heap.items.remove(bomb);
if (heap.items.isEmpty()) { if (heap.items.isEmpty()) {
heap.destroy(); heap.destroy();
} }
detach(); trigger(heap);
bomb.explode(cell);
//otherwise tick down our counter to alert
} else { } else {
spend(TICK);
spend(TICK);
left--; left--;
if (left <= 0){ if (left <= 0){
CellEmitter.center( cell ).start( Speck.factory( Speck.SCREAM ), 0.3f, 3 ); CellEmitter.center( heap.pos ).start( Speck.factory( Speck.SCREAM ), 0.3f, 3 );
Sample.INSTANCE.play( Assets.Sounds.ALERT ); Sample.INSTANCE.play( Assets.Sounds.ALERT );
for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) { for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) {
mob.beckon( cell ); mob.beckon( heap.pos );
} }
left = 6; left = 6;
} }
} }
return true; return true;
} }
}
//can't find our bomb, something must have removed it, do nothing.
bomb.fuse = null;
Actor.remove( this );
return true;
}
}
@Override
//first trigger sets the alarm mechanism, second explodes
protected void trigger(Heap heap) {
if (!triggered) {
triggered = true;
} else {
super.trigger(heap);
}
}
@Override
public boolean freeze() {
if (!triggered) {
return super.freeze();
} else {
//noisemakers cannot have their fuse snuffed once triggered
return false;
}
}
private static final String CELL = "cell";
private static final String FLOOR = "floor";
private static final String LEFT = "left"; private static final String LEFT = "left";
@Override @Override
public void storeInBundle(Bundle bundle) { public void storeInBundle(Bundle bundle) {
super.storeInBundle(bundle); super.storeInBundle(bundle);
bundle.put(CELL, cell);
bundle.put(FLOOR, floor);
bundle.put(LEFT, left); bundle.put(LEFT, left);
} }
@Override @Override
public void restoreFromBundle(Bundle bundle) { public void restoreFromBundle(Bundle bundle) {
super.restoreFromBundle(bundle); super.restoreFromBundle(bundle);
cell = bundle.getInt(CELL);
floor = bundle.getInt(FLOOR);
left = bundle.getInt(LEFT); left = bundle.getInt(LEFT);
} }
} }