From 17facf7cdee9e0fab99f10c309d7395b46fea90d Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Tue, 9 Dec 2014 01:49:10 -0500 Subject: [PATCH] v0.2.3: initial implementation of dried rose --- .../actors/mobs/npcs/Ghost.java | 30 +-- .../items/artifacts/DriedRose.java | 214 ++++++++++++++++++ .../shatteredpixeldungeon/levels/Level.java | 14 ++ 3 files changed, 235 insertions(+), 23 deletions(-) create mode 100644 src/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/DriedRose.java diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Ghost.java b/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Ghost.java index f8ea9e2ca..c6c4042dd 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Ghost.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Ghost.java @@ -41,7 +41,6 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Generator; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor; import com.shatteredpixel.shatteredpixeldungeon.items.food.MysteryMeat; -import com.shatteredpixel.shatteredpixeldungeon.items.quest.RatSkull; import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.CurareDart; @@ -156,7 +155,7 @@ public class Ghost extends NPC { if (Quest.given) { if (Quest.weapon != null) { - if (Quest.processed || Dungeon.hero.belongings.getItem(RatSkull.class) != null) { + if (Quest.processed) { GameScene.show(new WndSadGhost(this, Quest.type)); } else { switch (Quest.type) { @@ -245,7 +244,6 @@ public class Ghost extends NPC { private static int type; private static boolean given; - private static boolean processed; private static int depth; @@ -269,9 +267,6 @@ public class Ghost extends NPC { private static final String DEPTH = "depth"; private static final String WEAPON = "weapon"; private static final String ARMOR = "armor"; - - //for pre-0.2.1 saves, used when restoring quest - private static final String ALTERNATIVE = "alternative"; public static void storeInBundle( Bundle bundle ) { @@ -299,22 +294,10 @@ public class Ghost extends NPC { Bundle node = bundle.getBundle( NODE ); if (!node.isNull() && (spawned = node.getBoolean( SPAWNED ))) { - //logic for pre- 2.1.0 quests - if (node.contains( ALTERNATIVE )){ - if (node.getBoolean( ALTERNATIVE)){ - given = node.getBoolean( GIVEN ); - type = 1; - processed = false; - } else { - type = 1; - given = false; - processed = false; - } - } else { - type = node.getInt(TYPE); - processed = node.getBoolean( PROCESSED ); - given = node.getBoolean( GIVEN ); - } + + type = node.getInt(TYPE); + given = node.getBoolean( GIVEN ); + processed = node.getBoolean( PROCESSED ); depth = node.getInt( DEPTH ); @@ -370,9 +353,10 @@ public class Ghost extends NPC { public static void process() { if (spawned && given && !processed && (depth == Dungeon.depth)) { - GLog.n("Sad ghost: Thank you... come find me..."); + GLog.n("sad ghost: Thank you... come find me..."); Sample.INSTANCE.play( Assets.SND_GHOST ); processed = true; + Generator.Category.ARTIFACT.probs[10] = 1; //flags the dried rose as spawnable. } } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/DriedRose.java b/src/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/DriedRose.java new file mode 100644 index 000000000..8407ed65e --- /dev/null +++ b/src/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/DriedRose.java @@ -0,0 +1,214 @@ +package com.shatteredpixel.shatteredpixeldungeon.items.artifacts; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.NPC; +import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; +import com.shatteredpixel.shatteredpixeldungeon.effects.Pushing; +import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; +import com.shatteredpixel.shatteredpixeldungeon.items.Item; +import com.shatteredpixel.shatteredpixeldungeon.levels.Level; +import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; +import com.shatteredpixel.shatteredpixeldungeon.sprites.GhostSprite; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; +import com.shatteredpixel.shatteredpixeldungeon.sprites.WraithSprite; +import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; +import com.shatteredpixel.shatteredpixeldungeon.windows.WndQuest; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +import java.util.ArrayList; +import java.util.HashSet; + +/** + * Created by debenhame on 21/11/2014. + */ +public class DriedRose extends Artifact { + + { + name = "dried rose"; + image = ItemSpriteSheet.ARTIFACT_ROSE1; + level = 0; + levelCap = 10; + charge = 100; + chargeCap = 100; + defaultAction = AC_SUMMON; + } + + protected boolean talkedTo = false; + protected boolean firstSummon = false; + + public int droppedPetals = 0; + + public static final String AC_SUMMON = "SUMMON"; + + @Override + public ArrayList actions( Hero hero ) { + ArrayList actions = super.actions( hero ); + if (isEquipped( hero ) && charge == chargeCap) + actions.add(AC_SUMMON); + return actions; + } + + @Override + public void execute( Hero hero, String action ) { + if (action.equals(AC_SUMMON)) { + + ArrayList spawnPoints = new ArrayList(); + for (int i=0; i < Level.NEIGHBOURS8.length; i++) { + int p = hero.pos + Level.NEIGHBOURS8[i]; + if (Actor.findChar(p) == null && (Level.passable[p] || Level.avoid[p])) { + spawnPoints.add( p ); + } + } + + if (spawnPoints.size() > 0) { + GhostHero ghost = new GhostHero(); + ghost.pos = Random.element(spawnPoints); + + + GameScene.add( ghost, 1f ); + CellEmitter.get(ghost.pos).start(Speck.factory(Speck.LIGHT), 0.2f, 3); + + hero.spend( 1f ); + hero.busy(); + hero.sprite.operate(hero.pos); + + } + + } else{ + super.execute(hero, action); + } + } + + @Override + protected ArtifactBuff passiveBuff() { + return new roseRecharge(); + } + + public class roseRecharge extends ArtifactBuff { + + } + + public static class Petal extends Item { + + { + name = "dried petal"; + stackable = true; + image = ItemSpriteSheet.PETAL; + } + + @Override + public boolean doPickUp( Hero hero ) { + DriedRose rose = hero.belongings.getItem( DriedRose.class ); + + + + if (rose != null && rose.level < rose.levelCap){ + rose.upgrade(); + if (rose.level == rose.levelCap) { + GLog.p("The rose is completed!"); + Sample.INSTANCE.play( Assets.SND_GHOST ); + GLog.n("sad ghost: Thank you..."); + } else + GLog.i("You add the petal to the rose."); + hero.spendAndNext(TIME_TO_PICK_UP); + return true; + } else { + GLog.w("You have no rose to add this petal to."); + return false; + } + } + + @Override + public String info() { + return "A frail dried up petal, which has somehow survived this far into the dungeon."; + } + + } + + //TODO: needs to: + //have combat stats + //attack only nearby enemies + //Be tethered to the player + //Enemies must be able/want to attack it + //Must be lost on level transition. + public static class GhostHero extends NPC { + + { + name = "sad ghost"; + spriteClass = WraithSprite.class; + + flying = true; + + state = WANDERING; + enemy = DUMMY; + + } + + private static final String TXT_WELCOME = "My spirit is bound to this rose, it was very precious to me, a gift " + + "from my love whom I left on the surface.\n\nI cannot return to him, but thanks to you I have a second " + + "chance to complete my journey. When I am able I will respond to your call and fight with you.\n\n" + + "hopefully you may succeed where I failed..."; + + @Override + public String defenseVerb() { + return "evaded"; + } + + @Override + protected boolean getCloser( int target ) { + if (state == WANDERING) + this.target = target = Dungeon.hero.pos; + return super.getCloser( target ); + } + + @Override + protected Char chooseEnemy() { + if (enemy == DUMMY || !enemy.isAlive()) { + + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + enemy = enemies.size() > 0 ? Random.element( enemies ) : DUMMY; + } + return enemy; + } + + @Override + public void damage( int dmg, Object src ) { + } + + @Override + public void add( Buff buff ) { + } + + @Override + public void interact() { + //if (!talkedTo){ + // talkedTo = true; + // GameScene.show(new WndQuest(this, TXT_WELCOME)); + //} else { + 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(); + //} + } + } + +} diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java b/src/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java index a430d77b2..40918c8fd 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java @@ -44,6 +44,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.Stylus; import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.AlchemistsToolkit; +import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TimekeepersHourglass; import com.shatteredpixel.shatteredpixeldungeon.items.food.Blandfruit; import com.shatteredpixel.shatteredpixeldungeon.items.food.Food; @@ -212,6 +213,19 @@ public abstract class Level implements Bundlable { else addItemToSpawn( new PotionOfMight() ); } + + DriedRose rose = Dungeon.hero.belongings.getItem( DriedRose.class ); + if (rose != null){ + //this way if a rose is dropped later in the game, player still has a chance to max it out. + int petalsNeeded = (int) Math.ceil((float)((Dungeon.depth / 2) - rose.droppedPetals) / 3); + + for (int i=1; i <= petalsNeeded; i++) { + if (rose.droppedPetals < 10) { + addItemToSpawn(new DriedRose.Petal()); + rose.droppedPetals++; + } + } + } if (Dungeon.depth > 1) { switch (Random.Int( 10 )) {