From 36a0bcbcc5aaf5ff52b415d184055bb138baa69a Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Mon, 24 Nov 2014 16:48:45 -0500 Subject: [PATCH] v0.2.3: first implementation of Alchemist's toolkit, a bit rough. --- .../shatteredpixeldungeon/items/Heap.java | 66 +++-- .../items/artifacts/AlchemistsToolkit.java | 242 ++++++++++++++++++ .../shatteredpixeldungeon/levels/Level.java | 9 +- .../shatteredpixeldungeon/windows/WndBag.java | 17 +- 4 files changed, 303 insertions(+), 31 deletions(-) create mode 100644 src/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/AlchemistsToolkit.java diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/items/Heap.java b/src/com/shatteredpixel/shatteredpixeldungeon/items/Heap.java index 5d2d9cf47..197bbb88b 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/items/Heap.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/items/Heap.java @@ -17,16 +17,11 @@ */ package com.shatteredpixel.shatteredpixeldungeon.items; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedList; - -import com.shatteredpixel.shatteredpixeldungeon.items.food.Blandfruit; -import com.watabou.noosa.audio.Sample; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Badges; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.Statistics; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Wraith; import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; @@ -34,17 +29,26 @@ import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; import com.shatteredpixel.shatteredpixeldungeon.effects.Splash; import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ElmoParticle; import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle; +import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.AlchemistsToolkit; +import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.Artifact; +import com.shatteredpixel.shatteredpixeldungeon.items.food.Blandfruit; import com.shatteredpixel.shatteredpixeldungeon.items.food.ChargrilledMeat; import com.shatteredpixel.shatteredpixeldungeon.items.food.FrozenCarpaccio; import com.shatteredpixel.shatteredpixeldungeon.items.food.MysteryMeat; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfExperience; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll; import com.shatteredpixel.shatteredpixeldungeon.plants.Plant.Seed; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; import com.watabou.utils.Bundlable; import com.watabou.utils.Bundle; import com.watabou.utils.Random; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; + public class Heap implements Bundlable { private static final int SEEDS_TO_POTION = 3; @@ -272,32 +276,52 @@ public class Heap implements Bundlable { } } - if (count >= SEEDS_TO_POTION) { - + //TODO: test this thoroughly + //alchemists toolkit gives a chance to cook a potion in two or even one seeds + Artifact.ArtifactBuff alchemy = Dungeon.hero.buff(AlchemistsToolkit.alchemy.class); + int seeds_to_potion = SEEDS_TO_POTION; + int bonus = 0; + if (alchemy != null){ + bonus = alchemy.level(); + if (Random.int(25) < 10+bonus){ + seeds_to_potion--; + if (Random.Int(30) < bonus){ + seeds_to_potion--; + } + } + } + + if (count >= seeds_to_potion) { + CellEmitter.get( pos ).burst( Speck.factory( Speck.WOOL ), 6 ); Sample.INSTANCE.play( Assets.SND_PUFF ); - - if (Random.Int( count ) == 0) { - + + //not a buff per-se, meant to cancel out higher potion accuracy when ppl are farming for potions of exp. + if (bonus != 0) + if (Random.Int(1000/bonus) == 0) + return new PotionOfExperience(); + + if (Random.Int( count + bonus ) == 0) { + CellEmitter.center( pos ).burst( Speck.factory( Speck.EVOKE ), 3 ); - + destroy(); - + Statistics.potionsCooked++; Badges.validatePotionsCooked(); - + return Generator.random( Generator.Category.POTION ); - + } else { - + Seed proto = (Seed)items.get( Random.chances( chances ) ); Class itemClass = proto.alchemyClass; - + destroy(); - + Statistics.potionsCooked++; Badges.validatePotionsCooked(); - + if (itemClass == null) { return Generator.random( Generator.Category.POTION ); } else { @@ -307,8 +331,8 @@ public class Heap implements Bundlable { return null; } } - } - + } + } else { return null; } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/AlchemistsToolkit.java b/src/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/AlchemistsToolkit.java new file mode 100644 index 000000000..a3c710884 --- /dev/null +++ b/src/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/AlchemistsToolkit.java @@ -0,0 +1,242 @@ +package com.shatteredpixel.shatteredpixeldungeon.items.artifacts; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.items.Generator; +import com.shatteredpixel.shatteredpixeldungeon.items.Item; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfExperience; +import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; +import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; +import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; + +import java.util.ArrayList; +import java.util.Collections; + +/** + * Created by debenhame on 24/11/2014. + */ +public class AlchemistsToolkit extends Artifact { + //TODO: core functionality finished, but really rough. Look to improve code quality and add general polish. TEST. + + { + name = "Alchemists Toolkit"; + image = 0; + + levelCap = 10; + //charge, chargecap, partialcharge, and exp are unused. + } + + public static final String AC_BREW = "BREW"; + + //arrays used in containing potion collections for mix logic. + //strings are used so that different potions of the same class are considered equal + public final ArrayList combination = new ArrayList(); + public ArrayList curGuess = new ArrayList(); + public ArrayList bstGuess = new ArrayList(); + + public int numWrongPlace = 0; + public int numRight = 0; + + protected String inventoryTitle = "Select a potion"; + protected WndBag.Mode mode = WndBag.Mode.POTION; + + public AlchemistsToolkit() { + super(); + + for (int i = 1; i <= 4; i++){ + Potion potion; + do{ + potion = (Potion)Generator.random(Generator.Category.POTION); + } while (combination.contains(potion.name()) || potion instanceof PotionOfExperience); + combination.add(potion.name()); + } + } + + @Override + public ArrayList actions( Hero hero ) { + ArrayList actions = super.actions( hero ); + if (isEquipped( hero ) && level < levelCap && !cursed) + actions.add(AC_BREW); + return actions; + } + + @Override + public void execute(Hero hero, String action ) { + if (action.equals(AC_BREW)){ + GameScene.selectItem(itemSelector, mode, inventoryTitle); + } else { + super.execute(hero, action); + } + } + + public void guessBrew() { + if (curGuess.size() != 4) + return; + + int numWrongPlace = 0; + int numRight = 0; + + for (String potion : curGuess) { + if (combination.contains(potion)) { + if (curGuess.indexOf(potion) == combination.indexOf(potion)) { + numRight++; + } else { + numWrongPlace++; + } + } + } + + int score = (numRight *2) + numWrongPlace; + + if (numRight+numWrongPlace == 4) + score ++; + + if (score == 9) + score ++; + + if (score == 0){ + + GLog.i("Your brew is complete, but none of the potions you used seem to react well. " + + "The brew is useless, you throw it away."); + + } else if (score > level) { + + level = score; + bstGuess = curGuess; + this.numRight = numRight; + this.numWrongPlace = numWrongPlace; + + if (level == 10){ + bstGuess = new ArrayList(); + GLog.p("The mixture you've created seems perfect, you don't think there is any way to improve it!"); + } else { + GLog.i("you finish mixing, " + brewDesc(numWrongPlace, numRight) + + "\nthis is your best brew yet!"); + } + + } else { + + GLog.i("you finish mixing, " + brewDesc(numWrongPlace, numRight) + + "\nthis brew isn't as good as the current one, you throw it away."); + } + curGuess = new ArrayList(); + + } + + private String brewDesc(int numWrongPlace, int numRight){ + String result = ""; + if (numWrongPlace > 0){ + result += "there were " + numWrongPlace + " potions that reacted well, but were added at the wrong time"; + if (numRight > 0) + result += " and "; + } + if (numRight > 0){ + result += "there were " + numRight + " potions that reacted perfectly"; + } + return result; + } + + @Override + protected ArtifactBuff passiveBuff() { + return new alchemy(); + } + + @Override + public String desc() { + String result = "This worn toolkit contains a number of regents and herbs used to improve the process of " + + "cooking potions. While wearing the toolkit, the number of seeds needed for alchemy will be " + + "reduced, and you will be more likely to create a potion relating to the seeds you use.\n\n"; + + if (isEquipped(Dungeon.hero)) + if (cursed) + result += "The cursed toolkit has bound itself to your side, and refuses to let you use alchemy.\n\n"; + else + result += "The toolkit rests on your hip, the various tools inside make a light jingling sound as you move.\n\n"; + + if (level == 0){ + result += "The toolkit seems to be missing a key tool, a catalyst mixture. You'll have to make your own " + + "out of four common potions to get the most out of the toolkit."; + } else if (level == 10) { + result += "The mixture you have created seems perfect, and the toolkit is working at maximum efficiency."; + } else if (!bstGuess.isEmpty()) { + result += "Your current best mixture is made from: a " + bstGuess.get(0) + ", " + bstGuess.get(1) + ", " + + bstGuess.get(2) + ", and " + bstGuess.get(3) + ", in that order.\n\n"; + result += "In that mix, " + brewDesc(numWrongPlace, numRight) + "."; + + //would only trigger if an upgraded toolkit was gained through transmutation. + } else { + result += "The toolkit seems to have a catalyst mixture already in it, but it isn't ideal. Unfortunately " + + "you have no idea what's in the mixture."; + } + return result; + } + + private static final String COMBINATION = "combination"; + private static final String CURGUESS = "curguess"; + private static final String BSTGUESS = "bstguess"; + + private static final String NUMWRONGPLACE = "numwrongplace"; + private static final String NUMRIGHT = "numright"; + + @Override + public void storeInBundle(Bundle bundle){ + super.storeInBundle(bundle); + bundle.put(NUMWRONGPLACE, numWrongPlace); + bundle.put(NUMRIGHT, numRight); + + bundle.put(COMBINATION, combination.toArray(new String[combination.size()])); + bundle.put(CURGUESS, curGuess.toArray(new String[curGuess.size()])); + bundle.put(BSTGUESS, bstGuess.toArray(new String[bstGuess.size()])); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + numWrongPlace = bundle.getInt(NUMWRONGPLACE); + numRight = bundle.getInt(NUMRIGHT); + + combination.clear(); + Collections.addAll( combination, bundle.getStringArray( COMBINATION )); + Collections.addAll( curGuess, bundle.getStringArray( CURGUESS )); + Collections.addAll( bstGuess, bundle.getStringArray( BSTGUESS )); + } + + + public class alchemy extends ArtifactBuff { + + } + + protected WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null && item instanceof Potion && item.isIdentified()){ + if (!curGuess.contains(item.name())) { + + Hero hero = Dungeon.hero; + hero.sprite.operate( hero.pos ); + hero.busy(); + hero.spend( 2f ); + Sample.INSTANCE.play(Assets.SND_DRINK); + + item.detach(hero.belongings.backpack); + + curGuess.add(item.name()); + if (curGuess.size() == 4){ + guessBrew(); + } else { + GLog.i("You mix the potion into your current brew."); + } + } else { + GLog.w("Your current brew already contains that potion."); + } + } else { + GLog.w("You need to select an identified potion."); + } + } + }; + +} diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java b/src/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java index da269748a..d18e314aa 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java @@ -43,6 +43,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Heap; 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.food.Blandfruit; import com.shatteredpixel.shatteredpixeldungeon.items.food.Food; import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion; @@ -578,8 +579,12 @@ public abstract class Level implements Bundlable { } - if ((map[cell] == Terrain.ALCHEMY) && (item instanceof BlandfruitBush.Seed || !(item instanceof Plant.Seed || - (item instanceof Blandfruit && ((Blandfruit) item).potionAttrib == null && heaps.get(cell) == null)))) { + //TODO: test this thoroughly + if ((map[cell] == Terrain.ALCHEMY) && ( + !(item instanceof Plant.Seed || item instanceof Blandfruit) || + item instanceof BlandfruitBush.Seed || + (item instanceof Blandfruit && (((Blandfruit) item).potionAttrib != null || heaps.get(cell) != null))|| + Dungeon.hero.buff(AlchemistsToolkit.alchemy.class) != null && Dungeon.hero.buff(AlchemistsToolkit.alchemy.class).isCursed())) { int n; do { n = cell + NEIGHBOURS8[Random.Int( 8 )]; diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndBag.java b/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndBag.java index 61f549743..306c0b16e 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndBag.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndBag.java @@ -18,13 +18,6 @@ package com.shatteredpixel.shatteredpixeldungeon.windows; import android.graphics.RectF; - -import com.shatteredpixel.shatteredpixeldungeon.items.food.Food; -import com.watabou.gltextures.TextureCache; -import com.watabou.noosa.BitmapText; -import com.watabou.noosa.ColorBlock; -import com.watabou.noosa.Image; -import com.watabou.noosa.audio.Sample; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Belongings; @@ -36,6 +29,8 @@ import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag; import com.shatteredpixel.shatteredpixeldungeon.items.bags.ScrollHolder; import com.shatteredpixel.shatteredpixeldungeon.items.bags.SeedPouch; import com.shatteredpixel.shatteredpixeldungeon.items.bags.WandHolster; +import com.shatteredpixel.shatteredpixeldungeon.items.food.Food; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion; import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Boomerang; @@ -47,6 +42,11 @@ import com.shatteredpixel.shatteredpixeldungeon.ui.Icons; import com.shatteredpixel.shatteredpixeldungeon.ui.ItemSlot; import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlot; import com.shatteredpixel.shatteredpixeldungeon.utils.Utils; +import com.watabou.gltextures.TextureCache; +import com.watabou.noosa.BitmapText; +import com.watabou.noosa.ColorBlock; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Sample; public class WndBag extends WndTabbed { @@ -61,7 +61,7 @@ public class WndBag extends WndTabbed { WAND, SEED, FOOD, - + POTION } protected static final int COLS = 4; @@ -352,6 +352,7 @@ public class WndBag extends WndTabbed { mode == Mode.WAND && (item instanceof Wand) || mode == Mode.SEED && (item instanceof Seed) || mode == Mode.FOOD && (item instanceof Food) || + mode == Mode.POTION && (item instanceof Potion) || mode == Mode.ALL ); }