diff --git a/core/src/main/assets/messages/actors/actors.properties b/core/src/main/assets/messages/actors/actors.properties index cc3d7f029..223dae27c 100644 --- a/core/src/main/assets/messages/actors/actors.properties +++ b/core/src/main/assets/messages/actors/actors.properties @@ -1033,6 +1033,7 @@ actors.mobs.npcs.sheep.desc=This is a magic sheep. What's so magical about it? Y actors.mobs.npcs.shopkeeper.name=shopkeeper actors.mobs.npcs.shopkeeper.thief=Thief, Thief! +actors.mobs.npcs.shopkeeper.warn=Watch it! I won't warn you again. actors.mobs.npcs.shopkeeper.sell=Sell an item actors.mobs.npcs.shopkeeper.talk=Talk actors.mobs.npcs.shopkeeper.buyback=The shopkeeper reluctantly returns your item. diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Shopkeeper.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Shopkeeper.java index 7411e1a37..822ae9bb9 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Shopkeeper.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Shopkeeper.java @@ -25,9 +25,12 @@ import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon; import com.shatteredpixel.shatteredpixeldungeon.Statistics; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.AscensionChallenge; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.BlobImmunity; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; +import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ElmoParticle; import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.Item; @@ -44,9 +47,11 @@ import com.shatteredpixel.shatteredpixeldungeon.windows.WndTitledMessage; import com.shatteredpixel.shatteredpixeldungeon.windows.WndTradeItem; import com.watabou.noosa.Game; import com.watabou.noosa.Image; +import com.watabou.utils.BArray; import com.watabou.utils.Bundlable; import com.watabou.utils.Bundle; import com.watabou.utils.Callback; +import com.watabou.utils.PathFinder; import java.util.ArrayList; @@ -60,6 +65,8 @@ public class Shopkeeper extends NPC { public static int MAX_BUYBACK_HISTORY = 3; public ArrayList buybackItems = new ArrayList<>(); + + private int turnsSinceHarmed = -1; @Override protected boolean act() { @@ -68,6 +75,9 @@ public class Shopkeeper extends NPC { Notes.add(Notes.Landmark.SHOP); } + if (turnsSinceHarmed >= 0){ + turnsSinceHarmed ++; + } sprite.turnTo( pos, Dungeon.hero.pos ); spend( TICK ); @@ -76,17 +86,63 @@ public class Shopkeeper extends NPC { @Override public void damage( int dmg, Object src ) { - flee(); + processHarm(); } @Override public boolean add( Buff buff ) { - if (super.add(buff)) { - flee(); - return true; + if (buff.type == Buff.buffType.NEGATIVE){ + processHarm(); } return false; } + + public void processHarm(){ + + //do nothing if the shopkeeper is out of the hero's FOV + if (!Dungeon.level.heroFOV[pos]){ + return; + } + + if (turnsSinceHarmed == -1){ + turnsSinceHarmed = 0; + yell(Messages.get(this, "warn")); + + //cleanses all harmful blobs in the shop + ArrayList blobs = new ArrayList<>(); + for (Class c : new BlobImmunity().immunities()){ + Blob b = Dungeon.level.blobs.get(c); + if (b != null && b.volume > 0){ + blobs.add(b); + } + } + + PathFinder.buildDistanceMap( pos, BArray.not( Dungeon.level.solid, null ), 4 ); + + for (int i=0; i < Dungeon.level.length(); i++) { + if (PathFinder.distance[i] < Integer.MAX_VALUE) { + + boolean affected = false; + for (Blob blob : blobs) { + if (blob.cur[i] > 0) { + blob.clear(i); + affected = true; + } + } + + if (affected && Dungeon.level.heroFOV[i]) { + CellEmitter.get( i ).burst( Speck.factory( Speck.DISCOVER ), 2 ); + } + + } + } + + //There is a 1 turn buffer before more damage/debuffs make the shopkeeper flee + //This is mainly to prevent stacked effects from causing an instant flee + } else if (turnsSinceHarmed >= 1) { + flee(); + } + } public void flee() { destroy(); @@ -240,10 +296,13 @@ public class Shopkeeper extends NPC { public static String BUYBACK_ITEMS = "buyback_items"; + public static String TURNS_SINCE_HARMED = "turns_since_harmed"; + @Override public void storeInBundle(Bundle bundle) { super.storeInBundle(bundle); bundle.put(BUYBACK_ITEMS, buybackItems); + bundle.put(TURNS_SINCE_HARMED, turnsSinceHarmed); } @Override @@ -255,5 +314,6 @@ public class Shopkeeper extends NPC { buybackItems.add((Item) i); } } + turnsSinceHarmed = bundle.contains(TURNS_SINCE_HARMED) ? bundle.getInt(TURNS_SINCE_HARMED) : -1; } }