From ffc1a52ca301332c43f13d8432b3a17a66894b52 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Sun, 21 Jan 2018 18:15:37 -0500 Subject: [PATCH] v0.6.3: overhauled internal logic for alchemy recipes --- .../shatteredpixeldungeon/items/Recipe.java | 152 ++++++++++++++++++ .../items/food/Blandfruit.java | 61 +++++++ .../items/potions/Potion.java | 77 +++++++++ .../windows/WndAlchemy.java | 75 +++------ 4 files changed, 309 insertions(+), 56 deletions(-) create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Recipe.java diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Recipe.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Recipe.java new file mode 100644 index 000000000..939dc5a91 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Recipe.java @@ -0,0 +1,152 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2017 Evan Debenham + * + * 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.items; + +import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon; +import com.shatteredpixel.shatteredpixeldungeon.items.food.Blandfruit; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion; + +import java.util.ArrayList; + +public abstract class Recipe { + + public abstract boolean testIngredients(ArrayList ingredients); + + public abstract int cost(ArrayList ingredients); + + public abstract Item cook(ArrayList ingredients); + + public abstract Item sampleOutput(ArrayList ingredients); + + //subclass for the common situation of a recipe with static inputs and outputs + public static abstract class SimpleRecipe extends Recipe { + + //*** These elements must be filled in by subclasses + protected Class[] inputs; + protected int[] inQuantity; + + protected int cost; + + protected Class output; + protected int outQuantity; + //*** + + @Override + public final boolean testIngredients(ArrayList ingredients) { + boolean found; + for(int i = 0; i < inputs.length; i++){ + found = false; + for (Item ingredient : ingredients){ + if (ingredient.getClass() == inputs[i] + && ingredient.quantity() >= inQuantity[i]){ + found = true; + break; + } + } + if (!found){ + return false; + } + } + return true; + } + + public final int cost(ArrayList ingredients){ + return cost; + } + + @Override + public final Item cook(ArrayList ingredients) { + if (!testIngredients(ingredients)) return null; + + for(int i = 0; i < inputs.length; i++){ + for (Item ingredient : ingredients){ + if (ingredient.getClass() == inputs[i]){ + ingredient.quantity( ingredient.quantity()-inQuantity[i]); + break; + } + } + } + + //sample output and real output are identical in this case. + return sampleOutput(null); + } + + //ingredients are ignored, as output doesn't vary + public final Item sampleOutput(ArrayList ingredients){ + try { + Item result = output.newInstance(); + result.quantity(outQuantity); + return result; + } catch (Exception e) { + ShatteredPixelDungeon.reportException( e ); + return null; + } + } + } + + + //******* + // Static members + //******* + + private static Recipe[] oneIngredientRecipes = new Recipe[]{ + + }; + + private static Recipe[] twoIngredientRecipes = new Recipe[]{ + new Blandfruit.cookFruit() + }; + + private static Recipe[] threeIngredientRecipes = new Recipe[]{ + new Potion.randomPotion() + }; + + public static Recipe findRecipe(ArrayList ingredients){ + + if (ingredients.size() == 1){ + for (Recipe recipe : oneIngredientRecipes){ + if (recipe.testIngredients(ingredients)){ + return recipe; + } + } + + } else if (ingredients.size() == 2){ + for (Recipe recipe : twoIngredientRecipes){ + if (recipe.testIngredients(ingredients)){ + return recipe; + } + } + + } else if (ingredients.size() == 3){ + for (Recipe recipe : threeIngredientRecipes){ + if (recipe.testIngredients(ingredients)){ + return recipe; + } + } + } + + return null; + } + +} + + diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/food/Blandfruit.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/food/Blandfruit.java index 063a09e4c..0c36488a1 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/food/Blandfruit.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/food/Blandfruit.java @@ -30,6 +30,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hunger; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ToxicImbue; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.items.Item; +import com.shatteredpixel.shatteredpixeldungeon.items.Recipe; import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion; import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfExperience; import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfFrost; @@ -50,6 +51,8 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; import com.watabou.utils.Bundle; +import java.util.ArrayList; + public class Blandfruit extends Food { public Potion potionAttrib = null; @@ -227,5 +230,63 @@ public class Blandfruit extends Food { public ItemSprite.Glowing glowing() { return potionGlow; } + + public static class cookFruit extends Recipe { + + @Override + //also sorts ingredients if it can + public boolean testIngredients(ArrayList ingredients) { + if (ingredients.size() != 2) return false; + + if (ingredients.get(0) instanceof Blandfruit){ + if (!(ingredients.get(1) instanceof Seed)){ + return false; + } + } else if (ingredients.get(0) instanceof Seed){ + if (ingredients.get(1) instanceof Blandfruit){ + Item temp = ingredients.get(0); + ingredients.set(0, ingredients.get(1)); + ingredients.set(1, temp); + } else { + return false; + } + } else { + return false; + } + + Blandfruit fruit = (Blandfruit) ingredients.get(0); + Seed seed = (Seed) ingredients.get(1); + + if (fruit.quantity() >= 1 && fruit.potionAttrib == null + && seed.quantity() >= 1){ + return true; + } + + return false; + } + + @Override + public int cost(ArrayList ingredients) { + return 2; + } + + @Override + public Item cook(ArrayList ingredients) { + if (!testIngredients(ingredients)) return null; + + ingredients.get(0).quantity(ingredients.get(0).quantity() - 1); + ingredients.get(1).quantity(ingredients.get(1).quantity() - 1); + + + return new Blandfruit().cook((Seed) ingredients.get(1)); + } + + @Override + public Item sampleOutput(ArrayList ingredients) { + if (!testIngredients(ingredients)) return null; + + return new Blandfruit().cook((Seed) ingredients.get(1)); + } + } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/potions/Potion.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/potions/Potion.java index 183eb66d8..9d3a93784 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/potions/Potion.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/potions/Potion.java @@ -22,7 +22,10 @@ package com.shatteredpixel.shatteredpixeldungeon.items.potions; import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Badges; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon; +import com.shatteredpixel.shatteredpixeldungeon.Statistics; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Fire; @@ -31,18 +34,23 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Ooze; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.effects.Splash; +import com.shatteredpixel.shatteredpixeldungeon.items.Generator; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.ItemStatusHandler; +import com.shatteredpixel.shatteredpixeldungeon.items.Recipe; import com.shatteredpixel.shatteredpixeldungeon.journal.Catalog; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.plants.Plant; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; +import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag; import com.shatteredpixel.shatteredpixeldungeon.windows.WndOptions; import com.watabou.noosa.audio.Sample; import com.watabou.utils.Bundle; +import com.watabou.utils.Random; import java.util.ArrayList; import java.util.HashMap; @@ -327,4 +335,73 @@ public class Potion extends Item { public int price() { return 30 * quantity; } + + + public static class randomPotion extends Recipe{ + + @Override + public boolean testIngredients(ArrayList ingredients) { + if (ingredients.size() != 3) { + return false; + } + + for (Item ingredient : ingredients){ + if (!(ingredient instanceof Plant.Seed && ingredient.quantity() >= 1)){ + return false; + } + } + return true; + } + + @Override + public int cost(ArrayList ingredients) { + return 1; + } + + @Override + public Item cook(ArrayList ingredients) { + if (!testIngredients(ingredients)) return null; + + for (Item ingredient : ingredients){ + ingredient.quantity(ingredient.quantity() - 1); + } + + Item result; + + if (Random.Int( 3 ) == 0) { + + result = Generator.random( Generator.Category.POTION ); + + } else { + + Class itemClass = ((Plant.Seed)Random.element(ingredients)).alchemyClass; + try { + result = itemClass.newInstance(); + } catch (Exception e) { + ShatteredPixelDungeon.reportException(e); + result = Generator.random( Generator.Category.POTION ); + } + + } + + while (result instanceof PotionOfHealing + && Random.Int(10) < Dungeon.LimitedDrops.COOKING_HP.count) { + result = Generator.random(Generator.Category.POTION); + } + + if (result instanceof PotionOfHealing) { + Dungeon.LimitedDrops.COOKING_HP.count++; + } + + Statistics.potionsCooked++; + Badges.validatePotionsCooked(); + + return result; + } + + @Override + public Item sampleOutput(ArrayList ingredients) { + return new WndBag.Placeholder(ItemSpriteSheet.POTION_HOLDER); + } + } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndAlchemy.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndAlchemy.java index 9f87cda1b..d93da7002 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndAlchemy.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndAlchemy.java @@ -24,16 +24,11 @@ package com.shatteredpixel.shatteredpixeldungeon.windows; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Badges; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; -import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon; -import com.shatteredpixel.shatteredpixeldungeon.Statistics; import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; -import com.shatteredpixel.shatteredpixeldungeon.items.Generator; import com.shatteredpixel.shatteredpixeldungeon.items.Item; -import com.shatteredpixel.shatteredpixeldungeon.items.food.Blandfruit; -import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfHealing; +import com.shatteredpixel.shatteredpixeldungeon.items.Recipe; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; -import com.shatteredpixel.shatteredpixeldungeon.plants.Plant; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; @@ -202,15 +197,12 @@ public class WndAlchemy extends Window { } private void updateState(){ - //potion creation - if (filterInput(Plant.Seed.class).size() == 3){ - output.item(new WndBag.Placeholder(ItemSpriteSheet.POTION_HOLDER)); - output.visible = true; - btnCombine.enable(true); - - //blandfruit cooking - } else if (filterInput(Blandfruit.class).size() == 1 && filterInput(Plant.Seed.class).size() == 1){ - output.item(new WndBag.Placeholder(ItemSpriteSheet.SOMETHING)); + + ArrayList ingredients = filterInput(Item.class); + Recipe recipe = Recipe.findRecipe(ingredients); + + if (recipe != null){ + output.item(recipe.sampleOutput(ingredients)); output.visible = true; btnCombine.enable(true); @@ -218,49 +210,18 @@ public class WndAlchemy extends Window { btnCombine.enable(false); output.visible = false; } + } private void combine(){ - ArrayList seeds = filterInput(Plant.Seed.class); - ArrayList fruits = filterInput(Blandfruit.class); + + ArrayList ingredients = filterInput(Item.class); + Recipe recipe = Recipe.findRecipe(ingredients); Item result = null; - //potion creation - if (seeds.size() == 3){ - - if (Random.Int( 3 ) == 0) { - - result = Generator.random( Generator.Category.POTION ); - - } else { - - Class itemClass = Random.element(seeds).alchemyClass; - try { - result = itemClass.newInstance(); - } catch (Exception e) { - ShatteredPixelDungeon.reportException(e); - result = Generator.random( Generator.Category.POTION ); - } - - } - - while (result instanceof PotionOfHealing - && Random.Int(10) < Dungeon.LimitedDrops.COOKING_HP.count) { - result = Generator.random(Generator.Category.POTION); - } - - if (result instanceof PotionOfHealing) { - Dungeon.LimitedDrops.COOKING_HP.count++; - } - - Statistics.potionsCooked++; - Badges.validatePotionsCooked(); - - //blandfruit cooking - } else if (fruits.size() == 1 && seeds.size() == 1) { - result = fruits.get(0); - ((Blandfruit)result).cook(seeds.get(0)); + if (recipe != null){ + result = recipe.cook(ingredients); } if (result != null){ @@ -274,8 +235,10 @@ public class WndAlchemy extends Window { } for (int i = 0; i < inputs.length; i++){ - inputs[i].slot.item(new WndBag.Placeholder(ItemSpriteSheet.SOMETHING)); - inputs[i].item = null; + if (inputs[i].item != null && inputs[i].item.quantity() <= 0) { + inputs[i].slot.item(new WndBag.Placeholder(ItemSpriteSheet.SOMETHING)); + inputs[i].item = null; + } } btnCombine.enable(false); @@ -284,7 +247,7 @@ public class WndAlchemy extends Window { } @Override - public void onBackPressed() { + public void destroy() { for (int i = 0; i < inputs.length; i++) { if (inputs[i].item != null){ if (!inputs[i].item.collect()){ @@ -292,6 +255,6 @@ public class WndAlchemy extends Window { } } } - super.onBackPressed(); + super.destroy(); } }