v0.6.3: overhauled internal logic for alchemy recipes

This commit is contained in:
Evan Debenham 2018-01-21 18:15:37 -05:00
parent 7a36840f77
commit ffc1a52ca3
4 changed files with 309 additions and 56 deletions

View File

@ -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 <http://www.gnu.org/licenses/>
*/
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<Item> ingredients);
public abstract int cost(ArrayList<Item> ingredients);
public abstract Item cook(ArrayList<Item> ingredients);
public abstract Item sampleOutput(ArrayList<Item> 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<?extends Item>[] inputs;
protected int[] inQuantity;
protected int cost;
protected Class<?extends Item> output;
protected int outQuantity;
//***
@Override
public final boolean testIngredients(ArrayList<Item> 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<Item> ingredients){
return cost;
}
@Override
public final Item cook(ArrayList<Item> 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<Item> 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<Item> 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;
}
}

View File

@ -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;
@ -228,4 +231,62 @@ public class Blandfruit extends Food {
return potionGlow;
}
public static class cookFruit extends Recipe {
@Override
//also sorts ingredients if it can
public boolean testIngredients(ArrayList<Item> 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<Item> ingredients) {
return 2;
}
@Override
public Item cook(ArrayList<Item> 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<Item> ingredients) {
if (!testIngredients(ingredients)) return null;
return new Blandfruit().cook((Seed) ingredients.get(1));
}
}
}

View File

@ -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<Item> 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<Item> ingredients) {
return 1;
}
@Override
public Item cook(ArrayList<Item> 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<? extends Item> 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<Item> ingredients) {
return new WndBag.Placeholder(ItemSpriteSheet.POTION_HOLDER);
}
}
}

View File

@ -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<Item> 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<Plant.Seed> seeds = filterInput(Plant.Seed.class);
ArrayList<Blandfruit> fruits = filterInput(Blandfruit.class);
ArrayList<Item> 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<? extends Item> 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,9 +235,11 @@ public class WndAlchemy extends Window {
}
for (int i = 0; i < inputs.length; i++){
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();
}
}