From c5025653c8d8b64d21a35443afcf65ecd0c459fe Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Tue, 17 Feb 2015 01:32:50 -0500 Subject: [PATCH] v0.2.4: reworked bees and honeypots --- .../actors/mobs/Bee.java | 159 +++++++++++++++ .../actors/mobs/Thief.java | 14 +- .../actors/mobs/npcs/Bee.java | 183 ------------------ .../shatteredpixeldungeon/items/Honeypot.java | 126 +++++++++++- 4 files changed, 289 insertions(+), 193 deletions(-) create mode 100644 src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Bee.java delete mode 100644 src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Bee.java diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Bee.java b/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Bee.java new file mode 100644 index 000000000..69aac467c --- /dev/null +++ b/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Bee.java @@ -0,0 +1,159 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.shatteredpixel.shatteredpixeldungeon.actors.mobs; + +import java.util.HashSet; + +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Amok; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison; +import com.shatteredpixel.shatteredpixeldungeon.levels.Level; +import com.shatteredpixel.shatteredpixeldungeon.sprites.BeeSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Bee extends Mob { + + { + name = "golden bee"; + spriteClass = BeeSprite.class; + + viewDistance = 4; + + flying = true; + state = WANDERING; + } + + private int level; + + //-1 refers to a pot that has gone missing. + private int potPos; + //-1 for no owner + private int potHolder; + + private static final String LEVEL = "level"; + private static final String POTPOS = "potpos"; + private static final String POTHOLDER = "potholder"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle( bundle ); + bundle.put( LEVEL, level ); + bundle.put( POTPOS, potPos ); + bundle.put( POTHOLDER, potHolder ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle( bundle ); + spawn( bundle.getInt( LEVEL ) ); + potPos = bundle.getInt( POTPOS ); + potHolder = bundle.getInt( POTHOLDER ); + } + + public void spawn( int level ) { + this.level = level; + + HT = (2 + level) * 4; + defenseSkill = 9 + level; + } + + public void setPotInfo(int potPos, Char potHolder){ + this.potPos = potPos; + if (potHolder == null) + this.potHolder = -1; + else + this.potHolder = potHolder.id(); + } + + @Override + public int attackSkill( Char target ) { + return defenseSkill; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange( HT / 10, HT / 4 ); + } + + @Override + public int attackProc( Char enemy, int damage ) { + if (enemy instanceof Mob) { + ((Mob)enemy).aggro( this ); + } + return damage; + } + + @Override + protected Char chooseEnemy() { + //if the pot is no longer present, target the hero + if (potHolder == -1 && potPos == -1) + return Dungeon.hero; + + //if something is holding the pot, target that + else if (Actor.findById(potHolder) != null) + return (Char)Actor.findById(potHolder); + + //if the pot is on the ground + else { + + //if already targeting something, and that thing is still alive and near the pot, keeping targeting it. + if (enemy != null && enemy.isAlive() && Level.distance(enemy.pos, potPos) <= 3) return enemy; + + //find all mobs near the pot + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) + if (!(mob instanceof Bee) && Level.distance(mob.pos, potPos) <= 3 && mob.hostile) + enemies.add(mob); + + //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); + else return (Level.distance(Dungeon.hero.pos, potPos) <= 3) ? Dungeon.hero : null ; + } + } + + @Override + protected boolean getCloser(int target) { + if (enemy != null && Actor.findById(potHolder) == enemy) { + target = enemy.pos; + return super.getCloser(target); + } else if (state == WANDERING || (potPos != -1 && Level.distance(target, potPos) > 3)) + this.target = target = potPos; + return super.getCloser( target ); + } + + @Override + public String description() { + return + "Despite their small size, golden bees tend " + + "to protect their home fiercely. This one is very mad, better keep your distance."; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add( Poison.class ); + IMMUNITIES.add( Amok.class ); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} \ No newline at end of file diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Thief.java b/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Thief.java index c030eaf83..776571026 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Thief.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Thief.java @@ -22,6 +22,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.items.Gold; +import com.shatteredpixel.shatteredpixeldungeon.items.Honeypot; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.MasterThievesArmband; import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; @@ -132,8 +133,17 @@ public class Thief extends Mob { GLog.w( TXT_STOLE, this.name, item.name() ); - item.detachAll( hero.belongings.backpack ); - this.item = item; + + + if (item instanceof Honeypot){ + this.item = ((Honeypot)item).shatter(this, this.pos); + item.detach( hero.belongings.backpack ); + } else { + this.item = item; + if ( item instanceof Honeypot.ShatteredPot) + ((Honeypot.ShatteredPot)item).setHolder(this); + item.detachAll( hero.belongings.backpack ); + } return true; } else { diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Bee.java b/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Bee.java deleted file mode 100644 index 40930be4d..000000000 --- a/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Bee.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Pixel Dungeon - * Copyright (C) 2012-2015 Oleg Dolya - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - */ -package com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs; - -import java.util.HashSet; - -import com.shatteredpixel.shatteredpixeldungeon.Dungeon; -import com.shatteredpixel.shatteredpixeldungeon.actors.Char; -import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison; -import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; -import com.shatteredpixel.shatteredpixeldungeon.levels.Level; -import com.shatteredpixel.shatteredpixeldungeon.sprites.BeeSprite; -import com.shatteredpixel.shatteredpixeldungeon.utils.Utils; -import com.watabou.utils.Bundle; -import com.watabou.utils.Random; - -//todo: given the plan for this in shattered, should probably 'bee' a mob. -public class Bee extends NPC { - - { - name = "golden bee"; - spriteClass = BeeSprite.class; - - viewDistance = 4; - - WANDERING = new Wandering(); - - flying = true; - state = WANDERING; - } - - private int level; - - private static final String LEVEL = "level"; - - @Override - public void storeInBundle( Bundle bundle ) { - super.storeInBundle( bundle ); - bundle.put( LEVEL, level ); - } - - @Override - public void restoreFromBundle( Bundle bundle ) { - super.restoreFromBundle( bundle ); - spawn( bundle.getInt( LEVEL ) ); - } - - public void spawn( int level ) { - this.level = level; - - HT = (3 + level) * 5; - defenseSkill = 9 + level; - } - - @Override - public int attackSkill( Char target ) { - return defenseSkill; - } - - @Override - public int damageRoll() { - return Random.NormalIntRange( HT / 10, HT / 4 ); - } - - @Override - public int attackProc( Char enemy, int damage ) { - if (enemy instanceof Mob) { - ((Mob)enemy).aggro( this ); - } - return damage; - } - - @Override - protected boolean act() { - HP--; - if (HP <= 0) { - die( null ); - return true; - } else { - return super.act(); - } - } - - protected Char chooseEnemy() { - - if (enemy == null || !enemy.isAlive()) { - HashSet enemies = new HashSet(); - for (Mob mob:Dungeon.level.mobs) { - if (mob.hostile && Level.fieldOfView[mob.pos]) { - enemies.add( mob ); - } - } - - return enemies.size() > 0 ? Random.element( enemies ) : null; - - } else { - - return enemy; - - } - } - - @Override - public String description() { - return - "Despite their small size, golden bees tend " + - "to protect their master fiercely. They don't live long though."; - } - - @Override - public void interact() { - - int curPos = pos; - - moveSprite( pos, Dungeon.hero.pos ); - move( Dungeon.hero.pos ); - - Dungeon.hero.sprite.move( Dungeon.hero.pos, curPos ); - Dungeon.hero.move( curPos ); - - Dungeon.hero.spend( 1 / Dungeon.hero.speed() ); - Dungeon.hero.busy(); - } - - private static final HashSet> IMMUNITIES = new HashSet>(); - static { - IMMUNITIES.add( Poison.class ); - } - - @Override - public HashSet> immunities() { - return IMMUNITIES; - } - - private class Wandering implements AiState { - - @Override - public boolean act( boolean enemyInFOV, boolean justAlerted ) { - if (enemyInFOV) { - - enemySeen = true; - - notice(); - state = HUNTING; - target = enemy.pos; - - } else { - - enemySeen = false; - - int oldPos = pos; - if (getCloser( Dungeon.hero.pos )) { - spend( 1 / speed() ); - return moveSprite( oldPos, pos ); - } else { - spend( TICK ); - } - - } - return true; - } - - @Override - public String status() { - return Utils.format( "This %s is wandering", name ); - } - } -} \ No newline at end of file diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/items/Honeypot.java b/src/com/shatteredpixel/shatteredpixeldungeon/items/Honeypot.java index dff38911b..8735d2f9b 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/items/Honeypot.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/items/Honeypot.java @@ -19,18 +19,20 @@ package com.shatteredpixel.shatteredpixeldungeon.items; import java.util.ArrayList; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.watabou.noosa.audio.Sample; import com.watabou.noosa.tweeners.AlphaTweener; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; -import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Bee; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bee; import com.shatteredpixel.shatteredpixeldungeon.effects.Pushing; import com.shatteredpixel.shatteredpixeldungeon.effects.Splash; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; +import com.watabou.utils.Bundle; import com.watabou.utils.Random; public class Honeypot extends Item { @@ -56,10 +58,12 @@ public class Honeypot extends Item { if (action.equals( AC_SHATTER )) { hero.sprite.zap( hero.pos ); - shatter( hero.pos ); detach( hero.belongings.backpack ); - hero.spendAndNext( TIME_TO_THROW ); + + shatter( hero, hero.pos ).collect(); + + hero.next(); } else { super.execute( hero, action ); @@ -71,14 +75,14 @@ public class Honeypot extends Item { if (Level.pit[cell]) { super.onThrow( cell ); } else { - shatter( cell ); + Dungeon.level.drop(shatter( null, cell ), cell); } } - private void shatter( int pos ) { - Sample.INSTANCE.play( Assets.SND_SHATTER ); + public Item shatter( Char owner, int pos ) { if (Dungeon.visible[pos]) { + Sample.INSTANCE.play( Assets.SND_SHATTER ); Splash.at( pos, 0xffd500, 5 ); } @@ -100,16 +104,20 @@ public class Honeypot extends Item { if (newPos != -1) { Bee bee = new Bee(); bee.spawn( Dungeon.depth ); + bee.setPotInfo( pos, owner ); bee.HP = bee.HT; bee.pos = newPos; GameScene.add( bee ); - Actor.addDelayed( new Pushing( bee, pos, newPos ), -1 ); + Actor.addDelayed( new Pushing( bee, pos, newPos ), -1f ); bee.sprite.alpha( 0 ); bee.sprite.parent.add( new AlphaTweener( bee.sprite, 1, 0.15f ) ); Sample.INSTANCE.play( Assets.SND_BEE ); + return new ShatteredPot().setBee( bee ); + } else { + return this; } } @@ -131,6 +139,108 @@ public class Honeypot extends Item { @Override public String info() { return - "There is not much honey in this small honeypot, but there is a golden bee there and it doesn't want to leave it."; + "This large honeypot is only really lined with honey, instead it houses a giant bee! " + + "These sorts of massive bees usually stay in their hives, perhaps the pot is some sort of specialized trapper's cage? " + + "The bee seems pretty content inside the pot with its honey, and buzzes at you warily when you look at it."; + } + + + + //The bee's broken 'home', all this item does is let its bee know where it is, and who owns it (if anyone). + public static class ShatteredPot extends Item { + + { + name = "shattered honeypot"; + image = ItemSpriteSheet.SHATTPOT; + stackable = false; + } + + private int myBee; + private int beeDepth; + + public Item setBee(Char bee){ + myBee = bee.id(); + beeDepth = Dungeon.depth; + return this; + } + + @Override + public boolean doPickUp(Hero hero) { + if ( super.doPickUp(hero) ){ + setHolder( hero ); + return true; + }else + return false; + } + + @Override + public void doDrop(Hero hero) { + super.doDrop(hero); + updateBee( hero.pos, null ); + } + + @Override + protected void onThrow(int cell) { + super.onThrow(cell); + updateBee( cell, null ); + } + + public void setHolder(Char holder){ + updateBee(holder.pos, holder ); + } + + public void goAway(){ + updateBee( -1, null); + } + + private void updateBee( int cell, Char holder){ + //important, as ids are not unique between depths. + if (Dungeon.depth != beeDepth) + return; + + Bee bee = (Bee)Actor.findById( myBee ); + if (bee != null) + bee.setPotInfo( cell, holder ); + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public String info() { + String info = + "The pot has been shattered, only the sticky honey that lines its walls is holding it together, and it is slowly coming apart."; + + if (Actor.findById( myBee ) != null) + info += "\n\nDespite its broken state, the bee still seems quite fond of the pot, and is understandable quite mad."; + else + info += "\n\nNow that its bee is gone, you can't think of a use for this wad of broken clay and drying honey."; + + return info; + } + + private static final String MYBEE = "mybee"; + private static final String BEEDEPTH = "beedepth"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put( MYBEE, myBee ); + bundle.put( BEEDEPTH, beeDepth ); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + myBee = bundle.getInt( MYBEE ); + beeDepth = bundle.getInt( BEEDEPTH ); + } } }