/**
* Copyright (c) 2005-2017, KoLmafia development team
* http://kolmafia.sourceforge.net/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* [1] Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* [2] Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* [3] Neither the name "KoLmafia" nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package net.sourceforge.kolmafia.persistence;
import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import net.java.dev.spellcast.utilities.LockableListModel;
import net.java.dev.spellcast.utilities.SortedListModel;
import net.sourceforge.kolmafia.AdventureResult;
import net.sourceforge.kolmafia.CoinmasterRegistry;
import net.sourceforge.kolmafia.KoLCharacter;
import net.sourceforge.kolmafia.KoLConstants;
import net.sourceforge.kolmafia.KoLConstants.CraftingType;
import net.sourceforge.kolmafia.KoLConstants.CraftingRequirements;
import net.sourceforge.kolmafia.KoLConstants.CraftingMisc;
import net.sourceforge.kolmafia.KoLConstants.MafiaState;
import net.sourceforge.kolmafia.KoLmafia;
import net.sourceforge.kolmafia.RequestLogger;
import net.sourceforge.kolmafia.RequestThread;
import net.sourceforge.kolmafia.SpecialOutfit;
import net.sourceforge.kolmafia.StaticEntity;
import net.sourceforge.kolmafia.VYKEACompanionData;
import net.sourceforge.kolmafia.listener.NamedListenerRegistry;
import net.sourceforge.kolmafia.objectpool.Concoction;
import net.sourceforge.kolmafia.objectpool.ConcoctionPool;
import net.sourceforge.kolmafia.objectpool.EffectPool;
import net.sourceforge.kolmafia.objectpool.IntegerPool;
import net.sourceforge.kolmafia.objectpool.ItemPool;
import net.sourceforge.kolmafia.persistence.QuestDatabase;
import net.sourceforge.kolmafia.persistence.QuestDatabase.Quest;
import net.sourceforge.kolmafia.preferences.Preferences;
import net.sourceforge.kolmafia.request.CampgroundRequest;
import net.sourceforge.kolmafia.request.ChezSnooteeRequest;
import net.sourceforge.kolmafia.request.ClanLoungeRequest;
import net.sourceforge.kolmafia.request.CreateItemRequest;
import net.sourceforge.kolmafia.request.CrimboCafeRequest;
import net.sourceforge.kolmafia.request.DrinkItemRequest;
import net.sourceforge.kolmafia.request.EatItemRequest;
import net.sourceforge.kolmafia.request.FightRequest;
import net.sourceforge.kolmafia.request.GenericRequest;
import net.sourceforge.kolmafia.request.HellKitchenRequest;
import net.sourceforge.kolmafia.request.HermitRequest;
import net.sourceforge.kolmafia.request.MicroBreweryRequest;
import net.sourceforge.kolmafia.request.PurchaseRequest;
import net.sourceforge.kolmafia.request.StandardRequest;
import net.sourceforge.kolmafia.request.UseItemRequest;
import net.sourceforge.kolmafia.session.ChoiceManager;
import net.sourceforge.kolmafia.session.ClanManager;
import net.sourceforge.kolmafia.session.InventoryManager;
import net.sourceforge.kolmafia.swingui.ItemManageFrame;
import net.sourceforge.kolmafia.utilities.FileUtilities;
import net.sourceforge.kolmafia.utilities.InputFieldUtilities;
import net.sourceforge.kolmafia.utilities.SortedListModelArray;
import net.sourceforge.kolmafia.utilities.StringUtilities;
public class ConcoctionDatabase
{
private static final SortedListModel<AdventureResult> EMPTY_LIST = new SortedListModel<AdventureResult>();
private static final SortedListModel<CreateItemRequest> creatableList = new SortedListModel<CreateItemRequest>();
private static final LockableListModel<Concoction> usableList = new LockableListModel<Concoction>();
public static String excuse; // reason why creation is impossible
private static boolean refreshNeeded = true;
private static boolean recalculateAdventureRange = false;
public static int refreshLevel = 0;
public static int queuedAdventuresUsed = 0;
public static int queuedFreeCraftingTurns = 0;
public static int queuedStillsUsed = 0;
public static int queuedTomesUsed = 0;
public static int queuedExtrudesUsed = 0;
public static int queuedPullsUsed = 0;
public static int queuedMeatSpent = 0;
public static boolean queuedFancyDog = false;
public static int queuedSpeakeasyDrink = 0;
public static int queuedSmores = 0;
public static int lastQueuedMayo = 0;
private static int queuedFullness = 0;
public static final LockableListModel<QueuedConcoction> queuedFood = new LockableListModel<QueuedConcoction>();
private static final SortedListModel<AdventureResult> queuedFoodIngredients = new SortedListModel<AdventureResult>();
private static int queuedInebriety = 0;
public static final LockableListModel<QueuedConcoction> queuedBooze = new LockableListModel<QueuedConcoction>();
private static final SortedListModel<AdventureResult> queuedBoozeIngredients = new SortedListModel<AdventureResult>();
private static int queuedSpleenHit = 0;
public static final LockableListModel<QueuedConcoction> queuedSpleen = new LockableListModel<QueuedConcoction>();
private static final SortedListModel<AdventureResult> queuedSpleenIngredients = new SortedListModel<AdventureResult>();
public static final Concoction stillsLimit = new Concoction( (AdventureResult) null, CraftingType.NOCREATE );
public static final Concoction clipArtLimit = new Concoction( (AdventureResult) null, CraftingType.NOCREATE );
public static final Concoction extrudeLimit = new Concoction( (AdventureResult) null, CraftingType.NOCREATE );
public static final Concoction adventureLimit = new Concoction( (AdventureResult) null, CraftingType.NOCREATE );
public static final Concoction adventureSmithingLimit = new Concoction( (AdventureResult) null, CraftingType.NOCREATE );
public static final Concoction adventureJewelcraftingLimit = new Concoction( (AdventureResult) null, CraftingType.NOCREATE );
public static final Concoction turnFreeLimit = new Concoction( (AdventureResult) null, CraftingType.NOCREATE );
public static final Concoction turnFreeSmithingLimit = new Concoction( (AdventureResult) null, CraftingType.NOCREATE );
public static final Concoction meatLimit = new Concoction( (AdventureResult) null, CraftingType.NOCREATE );
public static final SortedListModelArray<AdventureResult> knownUses = new SortedListModelArray<AdventureResult>();
public static final EnumSet<CraftingType> PERMIT_METHOD = EnumSet.noneOf(CraftingType.class);
public static final Map<CraftingType, Integer> ADVENTURE_USAGE = new EnumMap<CraftingType, Integer>(CraftingType.class);
public static final Map<CraftingType, Integer> CREATION_COST = new EnumMap<CraftingType, Integer>(CraftingType.class);
public static final Map<CraftingType, String> EXCUSE = new EnumMap<CraftingType, String>(CraftingType.class);
public static final EnumSet<CraftingRequirements> REQUIREMENT_MET = EnumSet.noneOf(CraftingRequirements.class);
private static final AdventureResult[] NO_INGREDIENTS = new AdventureResult[ 0 ];
public static final AdventureResult INIGO = EffectPool.get( EffectPool.INIGOS, 0 );
public static final AdventureResult CRAFT_TEA = EffectPool.get( EffectPool.CRAFT_TEA, 0 );
private static final HashMap<Integer,Concoction> chefStaff = new HashMap<Integer,Concoction>();
private static final HashMap<Integer,Concoction> singleUse = new HashMap<Integer,Concoction>();
private static final HashMap<Integer,Concoction> multiUse = new HashMap<Integer,Concoction>();
private static final HashMap<Integer,Concoction> noodles = new HashMap<Integer,Concoction>();
private static final HashMap<Integer,Concoction> meatStack = new HashMap<Integer,Concoction>();
private static CraftingType mixingMethod = null;
private static final EnumSet<CraftingRequirements> requirements = EnumSet.noneOf(CraftingRequirements.class);
private static final EnumSet<CraftingMisc> info = EnumSet.noneOf(CraftingMisc.class);
private static int row = 0;
public static final void resetQueue()
{
LockableListModel<QueuedConcoction> queue = ConcoctionDatabase.queuedFood;
while ( queue.size() > 0 )
{
ConcoctionDatabase.pop( true, false, false );
}
queue = ConcoctionDatabase.queuedBooze;
while ( queue.size() > 0 )
{
ConcoctionDatabase.pop( false, true, false );
}
queue = ConcoctionDatabase.queuedSpleen;
while ( queue.size() > 0 )
{
ConcoctionDatabase.pop( false, false, true );
}
}
static
{
// This begins by opening up the data file and preparing
// a buffered reader; once this is done, every line is
// examined and float-referenced: once in the name-lookup,
// and again in the Id lookup.
BufferedReader reader = FileUtilities.getVersionedReader( "concoctions.txt", KoLConstants.CONCOCTIONS_VERSION );
String[] data;
while ( ( data = FileUtilities.readData( reader ) ) != null )
{
ConcoctionDatabase.addConcoction( data );
}
try
{
reader.close();
}
catch ( Exception e )
{
// This should not happen. Therefore, print
// a stack trace for debug purposes.
StaticEntity.printStackTrace( e );
}
// Add all concoctions to usable list
for ( Concoction item : ConcoctionPool.concoctions() )
{
ConcoctionDatabase.usableList.add( item );
}
ConcoctionDatabase.usableList.sort();
}
private static final void addConcoction( final String[] data )
{
// Need at least concoction name and mixing method
if ( data.length < 2 )
{
return;
}
boolean bogus = false;
ConcoctionDatabase.mixingMethod = null;
ConcoctionDatabase.requirements.clear();
ConcoctionDatabase.info.clear();
ConcoctionDatabase.row = 0;
String name = new String( data[ 0 ] );
String[] mixes = data[ 1 ].split( "\\s*,\\s*" );
for ( int i = 0; i < mixes.length; ++i )
{
String mix = mixes[ i ];
ConcoctionDatabase.addCraftingData( mix, name );
}
if ( ConcoctionDatabase.mixingMethod == null )
{
RequestLogger.printLine( "No mixing method specified for concoction: " + name );
bogus = true;
}
AdventureResult item = AdventureResult.parseItem( name, true );
int itemId = item.getItemId();
if ( itemId < 0 && !ConcoctionDatabase.pseudoItemMixingMethod( ConcoctionDatabase.mixingMethod ) )
{
RequestLogger.printLine( "Unknown concoction: " + name );
bogus = true;
}
AdventureResult[] ingredients = new AdventureResult[ data.length - 2 ];
int param = 0;
if ( data.length >= 2 )
{
for ( int i = 2; i < data.length; ++i )
{
if ( StringUtilities.isNumeric( data[ i ] ) )
{ // Treat all-numeric element as parameter instead of item.
// Up to 4 such parameters can be given if each fits in a byte.
// Currently only used for Clip Art
param = (param << 8) | StringUtilities.parseInt( data[ i ] );
continue;
}
AdventureResult ingredient = AdventureResult.parseItem( data[ i ], true );
if ( ingredient == null || ingredient.getItemId() == -1 || ingredient.getName() == null )
{
RequestLogger.printLine( "Unknown ingredient (" + data[ i ] + ") for concoction: " + name );
bogus = true;
continue;
}
ingredients[ i - 2 ] = ingredient;
}
}
if ( !bogus )
{
Concoction concoction = new Concoction( item, ConcoctionDatabase.mixingMethod,
ConcoctionDatabase.requirements.clone(), ConcoctionDatabase.info.clone(), ConcoctionDatabase.row );
concoction.setParam( param );
Concoction existing = ConcoctionPool.get( item );
if ( concoction.getMisc().contains( CraftingMisc.MANUAL ) ||
( existing != null && existing.getMixingMethod() != CraftingType.NOCREATE ) )
{ // Until multiple recipes are supported...
return;
}
if ( ingredients.length > 0 )
{
for ( int i = 0; i < ingredients.length; ++i )
{
AdventureResult ingredient = ingredients[ i ];
if ( ingredient == null )
{ // Was a parameter, not an ingredient.
continue;
}
concoction.addIngredient( ingredient );
if ( ingredient.getItemId() == ItemPool.MEAT_STACK )
{
ConcoctionDatabase.meatStack.put( IntegerPool.get( itemId ), concoction );
}
}
}
ConcoctionPool.set( concoction );
switch ( ConcoctionDatabase.mixingMethod )
{
case STAFF:
ConcoctionDatabase.chefStaff.put( IntegerPool.get( ingredients[ 0 ].getItemId() ), concoction );
break;
case SINGLE_USE:
ConcoctionDatabase.singleUse.put( IntegerPool.get( ingredients[ 0 ].getItemId() ), concoction );
break;
case MULTI_USE:
ConcoctionDatabase.multiUse.put( IntegerPool.get( ingredients[ 0 ].getItemId() ), concoction );
break;
}
if ( ConcoctionDatabase.requirements.contains( CraftingRequirements.PASTA ) )
{
ConcoctionDatabase.noodles.put( IntegerPool.get( concoction.getItemId() ), concoction );
}
}
}
public static Concoction chefStaffCreation( final int itemId )
{
return ConcoctionDatabase.chefStaff.get( IntegerPool.get( itemId ) );
}
public static Concoction singleUseCreation( final int itemId )
{
return ConcoctionDatabase.singleUse.get( IntegerPool.get( itemId ) );
}
public static Concoction multiUseCreation( final int itemId )
{
return ConcoctionDatabase.multiUse.get( IntegerPool.get( itemId ) );
}
public static Concoction noodleCreation( final int itemId )
{
return ConcoctionDatabase.noodles.get( IntegerPool.get( itemId ) );
}
public static Concoction meatStackCreation( final int itemId )
{
return ConcoctionDatabase.meatStack.get( IntegerPool.get( itemId ) );
}
private static boolean pseudoItemMixingMethod( final CraftingType mixingMethod )
{
return mixingMethod == CraftingType.SUSHI || mixingMethod == CraftingType.VYKEA;
}
public static final SortedListModel<AdventureResult> getKnownUses( final int itemId )//
{
SortedListModel<AdventureResult> uses = ConcoctionDatabase.knownUses.get( itemId );
return uses == null ? ConcoctionDatabase.EMPTY_LIST : uses;
}
public static final SortedListModel<AdventureResult> getKnownUses( final AdventureResult item )
{
return ConcoctionDatabase.getKnownUses( item.getItemId() );
}
public static final boolean isPermittedMethod( final CraftingType method,
final EnumSet<CraftingRequirements> requirements )
{
// If we can't make anything via this method, punt
if ( !ConcoctionDatabase.PERMIT_METHOD.contains( method ) )
{
return false;
}
// If we don't meet special creation requirements for this item, punt
for ( CraftingRequirements requirement : requirements )
{
if ( !ConcoctionDatabase.REQUIREMENT_MET.contains( requirement ) )
{
return false;
}
}
// Otherwise, go for it!
return true;
}
public static final boolean checkPermittedMethod( Concoction conc )
{
// Same as isPermittedMethod(), but sets excuse.
ConcoctionDatabase.excuse = null;
CraftingType method = conc.getMixingMethod();
if ( !ConcoctionDatabase.PERMIT_METHOD.contains( method ) )
{
ConcoctionDatabase.excuse = ConcoctionDatabase.EXCUSE.get( method );
return false;
}
EnumSet<CraftingRequirements> requirements = conc.getRequirements();
for ( CraftingRequirements next : requirements )
{
if ( !ConcoctionDatabase.REQUIREMENT_MET.contains( next ) )
{
ConcoctionDatabase.excuse = "You lack a skill or other prerequisite for creating that item (" +
ConcoctionDatabase.mixingMethodDescription( method, requirements ) + ").";
return false;
}
}
return true;
}
public static final LockableListModel<AdventureResult> getQueuedIngredients( boolean food, boolean booze, boolean spleen )
{
return food ? ConcoctionDatabase.queuedFoodIngredients :
booze ? ConcoctionDatabase.queuedBoozeIngredients :
ConcoctionDatabase.queuedSpleenIngredients;
}
public static final boolean canQueueFood( final int id )
{
switch ( id )
{
case ItemPool.QUANTUM_TACO:
case ItemPool.MUNCHIES_PILL:
return true;
}
if ( ConcoctionDatabase.isMayo( id ) && ConcoctionDatabase.lastQueuedMayo == 0 &&
( !ConcoctionDatabase.queuedFood.isEmpty() || Preferences.getString( "mayoInMouth" ).equals( "" ) ) )
{
AdventureResult workshedItem = CampgroundRequest.getCurrentWorkshedItem();
if ( workshedItem == null || workshedItem.getItemId() != ItemPool.MAYO_CLINIC )
{
return false;
}
return true;
}
return false;
}
public static final boolean isMayo( final int id )
{
switch ( id )
{
case ItemPool.MAYONEX:
case ItemPool.MAYODIOL:
case ItemPool.MAYOSTAT:
case ItemPool.MAYOZAPINE:
case ItemPool.MAYOFLEX:
return true;
}
return false;
}
public static final boolean canQueueBooze( final int id )
{
switch ( id )
{
case ItemPool.SCHRODINGERS_THERMOS:
return true;
}
return false;
}
public static final void push( final Concoction c, final int quantity )
{
LockableListModel<QueuedConcoction> queue;
LockableListModel<AdventureResult> queuedIngredients;
int id = c.getItemId();
int consumpt = ItemDatabase.getConsumptionType( id );
if ( c.getFullness() > 0 || consumpt == KoLConstants.CONSUME_FOOD_HELPER ||
ConcoctionDatabase.canQueueFood( id ) )
{
queue = ConcoctionDatabase.queuedFood;
queuedIngredients = ConcoctionDatabase.queuedFoodIngredients;
if ( ConcoctionDatabase.lastQueuedMayo == ItemPool.MAYODIOL )
{
ConcoctionDatabase.queuedFullness--;
ConcoctionDatabase.queuedInebriety++;
}
}
else if ( c.getInebriety() > 0 || consumpt == KoLConstants.CONSUME_DRINK_HELPER ||
ConcoctionDatabase.canQueueBooze( id ) )
{
queue = ConcoctionDatabase.queuedBooze;
queuedIngredients = ConcoctionDatabase.queuedBoozeIngredients;
}
else
{
queue = ConcoctionDatabase.queuedSpleen;
queuedIngredients = ConcoctionDatabase.queuedSpleenIngredients;
}
// Handle items that affect more than one organ
ConcoctionDatabase.queuedFullness += c.getFullness() * quantity;
ConcoctionDatabase.queuedInebriety += c.getInebriety() * quantity;
ConcoctionDatabase.queuedSpleenHit += c.getSpleenHit() * quantity;
// Get current values of things that a concoction can consume
int meat = ConcoctionDatabase.queuedMeatSpent;
int pulls = ConcoctionDatabase.queuedPullsUsed;
int tome = ConcoctionDatabase.queuedTomesUsed;
int stills = ConcoctionDatabase.queuedStillsUsed;
int extrudes = ConcoctionDatabase.queuedExtrudesUsed;
int free = ConcoctionDatabase.queuedFreeCraftingTurns;
int advs = ConcoctionDatabase.queuedAdventuresUsed;
// Queue the ingredients used by this concoction
ArrayList<AdventureResult> ingredients = new ArrayList<AdventureResult>();
c.queue( queuedIngredients, ingredients, quantity );
// Adjust lists to account for what just changed
meat = ConcoctionDatabase.queuedMeatSpent - meat;
if ( meat != 0 )
{
AdventureResult.addOrRemoveResultToList(
queuedIngredients, new AdventureResult( AdventureResult.MEAT_SPENT, meat ) );
}
pulls = ConcoctionDatabase.queuedPullsUsed - pulls;
if ( pulls != 0 )
{
AdventureResult.addOrRemoveResultToList(
queuedIngredients, new AdventureResult( AdventureResult.PULL, pulls ) );
}
tome = ConcoctionDatabase.queuedTomesUsed - tome;
if ( tome != 0 )
{
AdventureResult.addOrRemoveResultToList(
queuedIngredients, new AdventureResult( AdventureResult.TOME, tome ) );
}
extrudes = ConcoctionDatabase.queuedExtrudesUsed - extrudes;
if ( extrudes != 0 )
{
AdventureResult.addOrRemoveResultToList(
queuedIngredients, new AdventureResult( AdventureResult.EXTRUDE, extrudes ) );
}
stills = ConcoctionDatabase.queuedStillsUsed - stills;
if ( stills != 0 )
{
AdventureResult.addOrRemoveResultToList(
queuedIngredients, new AdventureResult( AdventureResult.STILL, stills ) );
}
advs = ConcoctionDatabase.queuedAdventuresUsed - advs;
if ( advs != 0 )
{
AdventureResult.addOrRemoveResultToList(
queuedIngredients, new AdventureResult( AdventureResult.ADV, advs ) );
}
free = ConcoctionDatabase.queuedFreeCraftingTurns - free;
if ( free != 0 )
{
AdventureResult.addOrRemoveResultToList(
queuedIngredients, new AdventureResult( AdventureResult.FREE_CRAFT, free ) );
}
if ( c.fancydog )
{
ConcoctionDatabase.queuedFancyDog = true;
}
if ( c.speakeasy )
{
ConcoctionDatabase.queuedSpeakeasyDrink += quantity;
}
if ( ConcoctionDatabase.isMayo( id ) )
{
ConcoctionDatabase.lastQueuedMayo = id;
}
else
{
ConcoctionDatabase.lastQueuedMayo = 0;
}
queue.add( new QueuedConcoction( c, quantity, ingredients, meat, pulls, tome, stills, extrudes, advs, free ) );
if ( c.getItemId() == ItemPool.SMORE )
{
ConcoctionDatabase.queuedSmores++;
ConsumablesDatabase.setSmoresData();
}
}
public static final QueuedConcoction pop( boolean food, boolean booze, boolean spleen )
{
LockableListModel<QueuedConcoction> queue;
LockableListModel<AdventureResult> queuedIngredients;
if ( food )
{
queue = ConcoctionDatabase.queuedFood;
queuedIngredients = ConcoctionDatabase.queuedFoodIngredients;
}
else if ( booze )
{
queue = ConcoctionDatabase.queuedBooze;
queuedIngredients = ConcoctionDatabase.queuedBoozeIngredients;
}
else if ( spleen )
{
queue = ConcoctionDatabase.queuedSpleen;
queuedIngredients = ConcoctionDatabase.queuedSpleenIngredients;
}
else
{
return null;
}
if ( queue.isEmpty() )
{
return null;
}
QueuedConcoction qc = (QueuedConcoction)queue.remove( queue.size() - 1 );
Concoction c = qc.getConcoction();
int quantity = qc.getCount();
c.queued -= quantity;
ConcoctionDatabase.queuedFullness -= c.getFullness() * quantity;
ConcoctionDatabase.queuedInebriety -= c.getInebriety() * quantity;
ConcoctionDatabase.queuedSpleenHit -= c.getSpleenHit() * quantity;
ArrayList ingredients = qc.getIngredients();
for ( int i = 0; i < ingredients.size(); ++i )
{
AdventureResult.addOrRemoveResultToList(
queuedIngredients, ( (AdventureResult) ingredients.get( i ) ).getNegation() );
}
int meat = qc.getMeat();
if ( meat != 0 )
{
ConcoctionDatabase.queuedMeatSpent -= meat;
AdventureResult.addOrRemoveResultToList(
queuedIngredients, new AdventureResult( AdventureResult.MEAT_SPENT, -meat ) );
}
int pulls = qc.getPulls();
if ( pulls != 0 )
{
c.queuedPulls -= pulls;
ConcoctionDatabase.queuedPullsUsed -= pulls;
AdventureResult.addOrRemoveResultToList(
queuedIngredients, new AdventureResult( AdventureResult.PULL, -pulls ) );
}
int tome = qc.getTomes();
if ( tome != 0 )
{
ConcoctionDatabase.queuedTomesUsed -= tome;
AdventureResult.addOrRemoveResultToList(
queuedIngredients, new AdventureResult( AdventureResult.TOME, -tome ) );
}
int stills = qc.getStills();
if ( stills != 0 )
{
ConcoctionDatabase.queuedStillsUsed -= stills;
AdventureResult.addOrRemoveResultToList(
queuedIngredients, new AdventureResult( AdventureResult.STILL, -stills ) );
}
int extrudes = qc.getExtrudes();
if ( extrudes != 0 )
{
ConcoctionDatabase.queuedExtrudesUsed -= extrudes;
AdventureResult.addOrRemoveResultToList(
queuedIngredients, new AdventureResult( AdventureResult.EXTRUDE, -extrudes ) );
}
int advs = qc.getAdventures();
if ( advs != 0 )
{
ConcoctionDatabase.queuedAdventuresUsed -= advs;
AdventureResult.addOrRemoveResultToList(
queuedIngredients, new AdventureResult( AdventureResult.ADV, -advs ) );
}
int free = qc.getFreeCrafts();
if ( free != 0 )
{
ConcoctionDatabase.queuedFreeCraftingTurns -= free;
AdventureResult.addOrRemoveResultToList(
queuedIngredients, new AdventureResult( AdventureResult.FREE_CRAFT, -free ) );
}
if ( qc.getConcoction().fancydog )
{
ConcoctionDatabase.queuedFancyDog = false;
}
if ( qc.getConcoction().speakeasy )
{
ConcoctionDatabase.queuedSpeakeasyDrink -= quantity;
}
if ( ConcoctionDatabase.isMayo( c.getItemId() ) )
{
ConcoctionDatabase.lastQueuedMayo = 0;
}
// Is the new last item Mayo ?
if ( !queue.isEmpty() )
{
QueuedConcoction lqc = (QueuedConcoction)queue.get( queue.size() - 1 );
Concoction lc = lqc.getConcoction();
int id = lc.getItemId();
if ( ConcoctionDatabase.isMayo( id ) )
{
ConcoctionDatabase.lastQueuedMayo = id;
if ( id == ItemPool.MAYODIOL )
{
ConcoctionDatabase.queuedFullness++;
ConcoctionDatabase.queuedInebriety--;
}
}
}
if ( c.getItemId() == ItemPool.SMORE )
{
ConcoctionDatabase.queuedSmores--;
ConsumablesDatabase.setSmoresData();
// The last s'more was smaller than the next one, so adjust queued fullness
ConcoctionDatabase.queuedFullness++;
}
return qc;
}
public static final void addUsableConcoction( final Concoction c )
{
ConcoctionDatabase.usableList.add( c );
ConcoctionDatabase.usableList.sort();
}
public static final LockableListModel<Concoction> getUsables()
{
return ConcoctionDatabase.usableList;
}
public static final SortedListModel<CreateItemRequest> getCreatables()
{
return ConcoctionDatabase.creatableList;
}
public static final LockableListModel<QueuedConcoction> getQueue( boolean food, boolean booze, boolean spleen )
{
return food ? ConcoctionDatabase.queuedFood :
booze ? ConcoctionDatabase.queuedBooze :
spleen ? ConcoctionDatabase.queuedSpleen :
null;
}
private static final AdventureResult currentConsumptionHelper( boolean food, boolean booze )
{
return food ? EatItemRequest.currentFoodHelper() :
booze ? DrinkItemRequest.currentDrinkHelper() :
null;
}
private static final void clearConsumptionHelper( boolean food, boolean booze )
{
if ( food )
{
EatItemRequest.clearFoodHelper();
}
else if ( booze )
{
DrinkItemRequest.clearDrinkHelper();
}
}
private static final int lastUnconsumed( int quantity, boolean food, boolean booze )
{
return quantity - ( food ? EatItemRequest.foodConsumed :
booze ? DrinkItemRequest.boozeConsumed :
0 );
}
public static final void handleQueue( boolean food, boolean booze, boolean spleen, int consumptionType )
{
// consumptionType can be:
//
// KoLConstants.NO_CONSUME - create or retrieve items
// KoLConstants.CONSUME_EAT - eat food items
// KoLConstants.CONSUME_DRINK - drink booze items
// KoLConstants.CONSUME_SPLEEN - use spleen items
// KoLConstants.CONSUME_GHOST - binge ghost with food
// KoLConstants.CONSUME_HOBO - binge hobo with booze
QueuedConcoction currentItem;
Stack<QueuedConcoction> toProcess = new Stack<QueuedConcoction>();
// Remove items in inverse order from the queue and push them on a stack.
while ( ( currentItem = ConcoctionDatabase.pop( food, booze, spleen ) ) != null )
{
toProcess.push( currentItem );
}
// If we refreshed concoctions while there were items queued,
// the creatable amounts assume that queued ingredients are
// already spoken for. Refresh again now that the queue is
// empty.
ConcoctionDatabase.refreshConcoctionsNow();
SpecialOutfit.createImplicitCheckpoint();
// Keep track of current consumption helper. These can be
// "queued" by simply "using" them. Account for that.
AdventureResult helper = ConcoctionDatabase.currentConsumptionHelper( food, booze );
// Since items were pushed in inverse order from the queue,
// popping the stack will get items in actual queued order.
while ( !toProcess.isEmpty() )
{
currentItem = toProcess.pop();
Concoction c = currentItem.getConcoction();
int quantity = currentItem.getCount();
if ( consumptionType != KoLConstants.CONSUME_EAT &&
consumptionType != KoLConstants.CONSUME_DRINK &&
consumptionType != KoLConstants.CONSUME_SPLEEN)
{
// Binge familiar or create only
// If it's not an actual item, it's a purchase from a cafe.
// Those are invalid for anything except "use"
if ( c.getItem() == null )
{
continue;
}
int consumpt = ItemDatabase.getConsumptionType( c.getItemId() );
// Skip consumption helpers; we cannot binge a
// familiar with them and we don't "create" them
if ( consumpt == KoLConstants.CONSUME_FOOD_HELPER ||
consumpt == KoLConstants.CONSUME_DRINK_HELPER )
{
continue;
}
// Certain items are virtual consumption
// helpers, but are "used" first. Skip if
// bingeing familiar.
if ( ( consumptionType == KoLConstants.CONSUME_GHOST && consumpt != KoLConstants.CONSUME_EAT ) ||
( consumptionType == KoLConstants.CONSUME_HOBO && consumpt != KoLConstants.CONSUME_DRINK ) )
{
continue;
}
// Retrieve the desired items, creating if necessary
AdventureResult toConsume = c.getItem().getInstance( quantity );
InventoryManager.retrieveItem( toConsume );
if ( consumptionType != KoLConstants.CONSUME_GHOST &&
consumptionType != KoLConstants.CONSUME_HOBO )
{
continue;
}
// Binge the familiar!
RequestThread.postRequest( UseItemRequest.getInstance( consumptionType, toConsume ) );
continue;
}
// "using" the item will either queue a consumption
// helper or actually consume the item.
ConcoctionDatabase.consumeItem( c, quantity, consumptionType );
if ( !KoLmafia.permitsContinue() )
{
// Consumption failed.
// Get current state of appropriate consumption helper
helper = ConcoctionDatabase.currentConsumptionHelper( food, booze );
// If there was a consumption helper queued, clear it
if ( helper != null )
{
ConcoctionDatabase.clearConsumptionHelper( food, booze );
}
// If the "consumption queue" is not visible to
// the user, just quit now.
if ( !Preferences.getBoolean( "addCreationQueue" ) )
{
break;
}
// Otherwise, put the item and remaining
// unprocessed items back on queue
// If there is a consumption helper queued, push that first.
if ( helper != null )
{
ConcoctionDatabase.push( ConcoctionPool.get( helper), helper.getCount() );
}
// Push current item back on consumption queue
ConcoctionDatabase.push( c, ConcoctionDatabase.lastUnconsumed( quantity, food, booze ) );
// Move items from unprocessed queue back to
// consumption queue
while ( !toProcess.isEmpty() )
{
// Pop unprocessed items and push back
// on appropriate consumption queue
currentItem = toProcess.pop();
c = currentItem.getConcoction();
quantity = currentItem.getCount();
ConcoctionDatabase.push( c, quantity );
}
// Done queuing items
KoLmafia.forceContinue();
ConcoctionDatabase.refreshConcoctions();
ConcoctionDatabase.getUsables().sort();
break;
}
// Get current state of appropriate consumption helper
helper = ConcoctionDatabase.currentConsumptionHelper( food, booze );
}
SpecialOutfit.restoreImplicitCheckpoint();
// Refresh again now that ingredients have been deducted
ConcoctionDatabase.refreshConcoctions();
}
private static final void consumeItem( Concoction c, int quantity, int consumptionType )
{
AdventureResult item = c.getItem();
// If it's food we're consuming, we have a MayoMinder set, and we are autostocking it, do so
// Don't get Mayostat if it's a 1 fullness food, or it'd be wasted
// Don't get Mayodiol if it'd cause you to overdrink
String minderSetting = Preferences.getString( "mayoMinderSetting" );
AdventureResult workshedItem = CampgroundRequest.getCurrentWorkshedItem();
if ( item != null && consumptionType == KoLConstants.CONSUME_EAT && !ConcoctionDatabase.isMayo( item.getItemId() ) &&
!minderSetting.equals( "" ) && Preferences.getBoolean( "autoFillMayoMinder" ) &&
!( minderSetting.equals( "Mayostat" ) && c.getFullness() == 1 ) &&
!( minderSetting.equals( "Mayodiol" ) && KoLCharacter.getInebrietyLimit() == KoLCharacter.getInebriety() ) &&
workshedItem != null && workshedItem.getItemId() == ItemPool.MAYO_CLINIC )
{
int mayoCount = Preferences.getString( "mayoInMouth" ).equals( "" ) ? 0 : 1;
if ( quantity > mayoCount )
{
InventoryManager.retrieveItem( minderSetting, quantity - mayoCount );
}
}
// If there's an actual item, it's not from a store
if ( item != null && !c.speakeasy )
{
// If concoction is a normal item, use normal item acquisition methods.
if ( item.getItemId() > 0 )
{
UseItemRequest request;
// First, consume any items which appear in the inventory.
int initial = Math.min( quantity, InventoryManager.getCount( item.getItemId() ) );
if ( initial > 0 )
{
request = UseItemRequest.getInstance( consumptionType, item.getInstance( initial ) );
RequestThread.postRequest( request );
quantity -= initial;
}
// Second, let UseItemRequest acquire remaining items.
if ( quantity > 0 )
{
request = UseItemRequest.getInstance( consumptionType, item.getInstance( quantity ) );
RequestThread.postRequest( request );
}
return;
}
// Otherwise, making item will consume it.
CreateItemRequest request = CreateItemRequest.getInstance( item.getInstance( quantity ) );
request.setQuantityNeeded( quantity );
RequestThread.postRequest( request );
return;
}
// Otherwise, acquire them from the appropriate cafe.
String name = c.getName();
GenericRequest request;
// Don't eat/drink/spleen PvP items without checking stone broken etc
if ( !UseItemRequest.askAboutPvP( name ) )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "Aborted eating " + quantity + " " + name + "." );
return;
}
// Check about Milk (etc), Overdrinking and Ode
if ( consumptionType == KoLConstants.CONSUME_EAT && !EatItemRequest.askAboutMilk( name, quantity ) )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "Aborted eating " + quantity + " " + name + "." );
return;
}
else if ( consumptionType == KoLConstants.CONSUME_DRINK )
{
int available = KoLCharacter.getInebrietyLimit() - KoLCharacter.getInebriety();
int inebriety = ConsumablesDatabase.getInebriety( name );
if ( inebriety > available && DrinkItemRequest.permittedOverdrink != KoLCharacter.getUserId() )
{
if ( ( KoLCharacter.getAdventuresLeft() > 0 ||
KoLCharacter.getFullness() < KoLCharacter.getFullnessLimit() )
&& !InputFieldUtilities.confirm( "Are you sure you want to overdrink?" ) )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "Aborted drinking " + quantity + " " + name + "." );
return;
}
}
if ( !DrinkItemRequest.askAboutOde( name, inebriety, quantity) )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "Aborted drinking " + quantity + " " + name + "." );
return;
}
}
// Check whether player meant to eat if at Drunk limit with Mayodiol in your mouth
if ( Preferences.getString( "mayoInMouth" ).equals( "Mayodiol" ) && KoLCharacter.getInebrietyLimit() == KoLCharacter.getInebriety() )
{
if ( !InputFieldUtilities.confirm( "Eating this will cause you to overdrink due to Mayodiol in your mouth, are you sure ?" ) )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "Aborted eating " + quantity + " " + name + "." );
return;
}
}
// Check whether player meant to eat if at Drunk limit with MayoMinder set to automatically use Mayodiol
if ( Preferences.getString( "mayoInMouth" ).equals( "" ) && KoLCharacter.getInebrietyLimit() == KoLCharacter.getInebriety() &&
Preferences.getString( "mayoMinderSetting" ).equals( "Mayodiol" ) && InventoryManager.hasItem( ItemPool.MAYODIOL ) )
{
if ( !InputFieldUtilities.confirm( "Eating this will cause you to overdrink due to Mayodiol in inventory with Mayo Minder™ set to use it, are you sure ?" ) )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "Aborted eating " + quantity + " " + name + "." );
return;
}
}
if ( ClanLoungeRequest.isHotDog( name ) )
{
request = ClanLoungeRequest.buyHotDogRequest( name );
}
else if ( ClanLoungeRequest.isSpeakeasyDrink( name ) )
{
request = ClanLoungeRequest.buySpeakeasyDrinkRequest( name );
}
else if ( HellKitchenRequest.onMenu( name ) )
{
request = new HellKitchenRequest( name );
}
else if ( ChezSnooteeRequest.onMenu( name ) )
{
request = new ChezSnooteeRequest( name );
}
else if ( MicroBreweryRequest.onMenu( name ) )
{
request = new MicroBreweryRequest( name );
}
else if ( CrimboCafeRequest.onMenu( name ) )
{
request = new CrimboCafeRequest( name );
}
else
{
return;
}
// You can only buy one item at a time from a cafe
for ( int j = 0; j < quantity; ++j )
{
RequestThread.postRequest( request );
}
}
public static final int getQueuedFullness()
{
return ConcoctionDatabase.queuedFullness;
}
public static final int getQueuedInebriety()
{
return ConcoctionDatabase.queuedInebriety;
}
public static final int getQueuedSpleenHit()
{
return ConcoctionDatabase.queuedSpleenHit;
}
private static final List<AdventureResult> getAvailableIngredients()
{
boolean includeCloset =
!KoLConstants.closet.isEmpty() &&
InventoryManager.canUseCloset();
boolean includeStorage =
!KoLConstants.storage.isEmpty() &&
InventoryManager.canUseStorage();
boolean includeStash =
InventoryManager.canUseClanStash() &&
!ClanManager.getStash().isEmpty();
boolean includeQueue =
!ConcoctionDatabase.queuedFoodIngredients.isEmpty() ||
!ConcoctionDatabase.queuedBoozeIngredients.isEmpty() ||
!ConcoctionDatabase.queuedSpleenIngredients.isEmpty();
if ( !includeCloset && !includeStorage && !includeStash && !includeQueue )
{
return KoLConstants.inventory;
}
SortedListModel<AdventureResult> availableIngredients = new SortedListModel<AdventureResult>();
availableIngredients.addAll( KoLConstants.inventory );
if ( includeCloset )
{
for ( int i = 0; i < KoLConstants.closet.size(); ++i )
{
AdventureResult.addResultToList( availableIngredients, (AdventureResult) KoLConstants.closet.get( i ) );
}
}
if ( includeStorage )
{
for ( int i = 0; i < KoLConstants.storage.size(); ++i )
{
AdventureResult.addResultToList( availableIngredients, (AdventureResult) KoLConstants.storage.get( i ) );
}
}
if ( includeStash )
{
List stash = ClanManager.getStash();
for ( int i = 0; i < stash.size(); ++i )
{
AdventureResult.addResultToList( availableIngredients, (AdventureResult) stash.get( i ) );
}
}
if ( !ConcoctionDatabase.queuedFoodIngredients.isEmpty() )
{
for ( int i = 0; i < ConcoctionDatabase.queuedFoodIngredients.size(); ++i )
{
AdventureResult ingredient = (AdventureResult) ConcoctionDatabase.queuedFoodIngredients.get( i );
if ( ingredient.isItem() )
{
AdventureResult.addResultToList(
availableIngredients,
ingredient.getNegation() );
}
}
}
if ( !ConcoctionDatabase.queuedBoozeIngredients.isEmpty() )
{
for ( int i = 0; i < ConcoctionDatabase.queuedBoozeIngredients.size(); ++i )
{
AdventureResult ingredient = (AdventureResult) ConcoctionDatabase.queuedBoozeIngredients.get( i );
if ( ingredient.isItem() )
{
AdventureResult.addResultToList(
availableIngredients,
ingredient.getNegation() );
}
}
}
if ( !ConcoctionDatabase.queuedSpleenIngredients.isEmpty() )
{
for ( int i = 0; i < ConcoctionDatabase.queuedSpleenIngredients.size(); ++i )
{
AdventureResult ingredient = (AdventureResult) ConcoctionDatabase.queuedSpleenIngredients.get( i );
if ( ingredient.isItem() )
{
AdventureResult.addResultToList(
availableIngredients,
ingredient.getNegation() );
}
}
}
return availableIngredients;
}
public static final void deferRefresh( boolean flag )
{
if ( flag )
{
++ConcoctionDatabase.refreshLevel;
}
else if ( ConcoctionDatabase.refreshLevel > 0 )
{
if ( --ConcoctionDatabase.refreshLevel == 0 )
{
ConcoctionDatabase.refreshConcoctions( false );
}
}
}
public static final void setRefreshNeeded( int itemId )
{
switch ( ItemDatabase.getConsumptionType( itemId ) )
{
case KoLConstants.CONSUME_EAT:
case KoLConstants.CONSUME_DRINK:
case KoLConstants.CONSUME_SPLEEN:
case KoLConstants.CONSUME_USE:
case KoLConstants.CONSUME_MULTIPLE:
case KoLConstants.CONSUME_FOOD_HELPER:
case KoLConstants.CONSUME_DRINK_HELPER:
ConcoctionDatabase.setRefreshNeeded( false );
return;
}
switch ( itemId )
{
// Items that affect creatability of other items, but
// aren't explicitly listed in their recipes:
case ItemPool.WORTHLESS_TRINKET:
case ItemPool.WORTHLESS_GEWGAW:
case ItemPool.WORTHLESS_KNICK_KNACK:
// Interchangeable ingredients, which might have been missed
// by the getKnownUses check because the recipes are set to
// use the other possible ingredient:
case ItemPool.SCHLITZ:
case ItemPool.WILLER:
case ItemPool.KETCHUP:
case ItemPool.CATSUP:
case ItemPool.DYSPEPSI_COLA:
case ItemPool.CLOACA_COLA:
case ItemPool.TITANIUM_UMBRELLA:
case ItemPool.GOATSKIN_UMBRELLA:
ConcoctionDatabase.setRefreshNeeded( false );
return;
}
List uses = ConcoctionDatabase.getKnownUses( itemId );
for ( int i = 0; i < uses.size(); ++i )
{
AdventureResult use = (AdventureResult) uses.get( i );
CraftingType method = ConcoctionDatabase.getMixingMethod( use.getItemId() );
EnumSet<CraftingRequirements> requirements = ConcoctionDatabase.getRequirements( use.getItemId() );
if ( ConcoctionDatabase.isPermittedMethod( method, requirements ) )
{
ConcoctionDatabase.setRefreshNeeded( false );
return;
}
}
for ( int i = 0; i < CoinmasterRegistry.COINMASTERS.length; ++i )
{
AdventureResult item = CoinmasterRegistry.COINMASTERS[ i ].getItem();
if ( item != null && itemId == item.getItemId() )
{
ConcoctionDatabase.setRefreshNeeded( false );
return;
}
}
}
public static final void setRefreshNeeded( boolean recalculateAdventureRange )
{
ConcoctionDatabase.refreshNeeded = true;
if ( recalculateAdventureRange )
{
ConcoctionDatabase.recalculateAdventureRange = true;
}
}
/**
* Returns the concoctions which are available given the list of ingredients. The list returned contains formal
* requests for item creation.
*/
public static final void refreshConcoctions()
{
ConcoctionDatabase.refreshConcoctions( true );
}
public static final void refreshConcoctions( boolean force )
{
if ( force )
{
// Remember that refresh is forced, even if deferred
ConcoctionDatabase.refreshNeeded = true;
}
if ( !ConcoctionDatabase.refreshNeeded )
{
// No refresh is currently needed
return;
}
if ( ConcoctionDatabase.refreshLevel > 0 )
{
// Refreshing is deferred
return;
}
if ( FightRequest.initializingAfterFight()||
ChoiceManager.initializingAfterChoice() )
{
// Implicit defer
return;
}
ConcoctionDatabase.refreshConcoctionsNow();
}
public static final synchronized void refreshConcoctionsNow()
{
ConcoctionDatabase.refreshNeeded = false;
List<AdventureResult> availableIngredients = ConcoctionDatabase.getAvailableIngredients();
// Iterate through the concoction table, Initialize each one
// appropriately depending on whether it is an NPC item, a Coin
// Master item, or anything else.
boolean useNPCStores = InventoryManager.canUseNPCStores();
boolean useCoinmasters = InventoryManager.canUseCoinmasters();
for ( Concoction item : ConcoctionPool.concoctions() )
{
// Initialize all the variables
item.resetCalculations();
if ( item.speakeasy )
{
// Has an item number, but can't appear in inventory
continue;
}
AdventureResult concoction = item.concoction;
if ( concoction == null )
{
continue;
}
int itemId = concoction.getItemId();
if ( itemId == ItemPool.WORTHLESS_ITEM )
{
item.price = useNPCStores ? InventoryManager.currentWorthlessItemCost() : 0;
item.initial = HermitRequest.getWorthlessItemCount( true );
item.creatable = 0;
item.total = item.initial;
item.visibleTotal = item.total;
continue;
}
if ( useNPCStores && NPCStoreDatabase.contains( itemId, true ) )
{
if ( itemId != ItemPool.FLAT_DOUGH )
{
// Don't buy flat dough from Degrassi Knoll Bakery -
// buy wads of dough for 20 meat less, instead.
item.price = NPCStoreDatabase.price( itemId );
item.initial = concoction.getCount( availableIngredients );
item.creatable = 0;
item.total = item.initial;
item.visibleTotal = item.total;
continue;
}
}
PurchaseRequest purchaseRequest = item.getPurchaseRequest();
if ( purchaseRequest != null )
{
purchaseRequest.setCanPurchase( useCoinmasters );
int acquirable = purchaseRequest.canPurchase() ?
purchaseRequest.affordableCount() : 0;
item.price = 0;
item.initial = concoction.getCount( availableIngredients );
item.creatable = acquirable;
item.total = item.initial + acquirable;
item.visibleTotal = item.total;
continue;
}
// Set initial quantity of all remaining items.
// Switch to the better of any interchangeable ingredients
ConcoctionDatabase.getIngredients( item.getIngredients(), availableIngredients );
item.initial = concoction.getCount( availableIngredients );
item.price = 0;
item.creatable = 0;
item.total = item.initial;
item.visibleTotal = item.total;
}
// Make assessment of availability of mixing methods.
// This method will also calculate the availability of
// chefs and bartenders automatically so a second call
// is not needed.
ConcoctionDatabase.cachePermitted( availableIngredients );
// Finally, increment through all of the things which are
// created any other way, making sure that it's a permitted
// mixture before doing the calculation.
for ( Concoction item : ConcoctionPool.concoctions() )
{
item.calculate2();
item.calculate3();
}
// Now, to update the list of creatables without removing
// all creatable items. We do this by determining the
// number of items inside of the old list.
boolean changeDetected = false;
boolean considerPulls = !KoLCharacter.canInteract() &&
!KoLCharacter.isHardcore() &&
ConcoctionDatabase.getPullsBudgeted() > ConcoctionDatabase.queuedPullsUsed;
for ( Concoction item : ConcoctionPool.concoctions() )
{
AdventureResult ar = item.getItem();
if ( ar == null )
{
continue;
}
if ( considerPulls &&
ar.getItemId() > 0 &&
item.getPrice() <= 0 &&
ConsumablesDatabase.meetsLevelRequirement( item.getName() ) &&
StandardRequest.isAllowed( "Items", ar.getName() ) )
{
item.setPullable( Math.min ( ar.getCount( KoLConstants.storage ) - item.queuedPulls, ConcoctionDatabase.getPullsBudgeted() - ConcoctionDatabase.queuedPullsUsed ) );
}
else
{
item.setPullable( 0 );
}
CreateItemRequest instance = CreateItemRequest.getInstance( ar, false );
if ( instance == null )
{
continue;
}
int creatable = Math.max( item.creatable, 0 );
int pullable = Math.max( item.pullable, 0 );
instance.setQuantityPossible( creatable );
instance.setQuantityPullable( pullable );
if ( creatable + pullable == 0 )
{
if ( item.wasPossible() )
{
ConcoctionDatabase.creatableList.remove( instance );
item.setPossible( false );
changeDetected = true;
}
}
else if ( !item.wasPossible() )
{
ConcoctionDatabase.creatableList.add( instance );
item.setPossible( true );
changeDetected = true;
}
}
if ( ConcoctionDatabase.recalculateAdventureRange )
{
ConsumablesDatabase.calculateAdventureRanges();
ConcoctionDatabase.recalculateAdventureRange = false;
ConcoctionDatabase.queuedFood.touch();
ConcoctionDatabase.queuedBooze.touch();
ConcoctionDatabase.queuedSpleen.touch();
}
ConcoctionDatabase.creatableList.sort();
ConcoctionDatabase.usableList.sort();
// Now tell the GUI about the changes
ConcoctionDatabase.creatableList.updateFilter( changeDetected );
ConcoctionDatabase.usableList.updateFilter( changeDetected );
}
/**
* Reset concoction stat gains when you've logged in a new
* character.
*/
public static final void resetConcoctionStatGains()
{
for ( Concoction item : ConcoctionPool.concoctions() )
{
item.setStatGain();
}
ConcoctionDatabase.usableList.sort();
}
private static final void calculateBasicItems( final List<AdventureResult> availableIngredients )
{
// Meat paste and meat stacks can be created directly
// and are dependent upon the amount of meat available.
ConcoctionDatabase.setBuyableItem( availableIngredients, ItemPool.MEAT_PASTE, 10 );
ConcoctionDatabase.setBuyableItem( availableIngredients, ItemPool.MEAT_STACK, 100 );
ConcoctionDatabase.setBuyableItem( availableIngredients, ItemPool.DENSE_STACK, 1000 );
}
private static final void setBuyableItem( final List<AdventureResult> availableIngredients, final int itemId, final int price )
{
Concoction creation = ConcoctionPool.get( itemId );
if ( creation == null )
{
return;
}
creation.initial = ItemPool.get( itemId, 1 ).getCount( availableIngredients );
creation.price = price;
creation.creatable = 0;
creation.total = creation.initial;
creation.visibleTotal = creation.total;
}
/**
* Utility method used to cache the current permissions on item creation.
*/
private static final AdventureResult THORS_PLIERS = ItemPool.get( ItemPool.THORS_PLIERS, 1 );
private static final void cachePermitted( final List<AdventureResult> availableIngredients )
{
int toolCost = KoLCharacter.inBadMoon() ? 500 : 1000;
boolean willBuyTool =
KoLCharacter.getAvailableMeat() >= toolCost &&
InventoryManager.canUseNPCStores();
boolean willBuyServant = Preferences.getBoolean( "autoRepairBoxServants" ) &&
( InventoryManager.canUseMall() ||
InventoryManager.canUseClanStash() );
// Adventures are considered Item #0 in the event that the
// concoction will use ADVs.
ConcoctionDatabase.adventureLimit.total = KoLCharacter.getAdventuresLeft() +
ConcoctionDatabase.getFreeCraftingTurns();
ConcoctionDatabase.adventureLimit.initial = ConcoctionDatabase.adventureLimit.total -
ConcoctionDatabase.queuedAdventuresUsed;
ConcoctionDatabase.adventureLimit.creatable = 0;
ConcoctionDatabase.adventureLimit.visibleTotal = ConcoctionDatabase.adventureLimit.total;
// Adventures are considered Item #0 in the event that the
// concoction will use ADVs.
ConcoctionDatabase.adventureSmithingLimit.total = KoLCharacter.getAdventuresLeft() +
ConcoctionDatabase.getFreeCraftingTurns() +
ConcoctionDatabase.getFreeSmithingTurns() +
ConcoctionDatabase.getFreeSmithJewelTurns();
ConcoctionDatabase.adventureSmithingLimit.initial = ConcoctionDatabase.adventureSmithingLimit.total -
ConcoctionDatabase.queuedAdventuresUsed;
ConcoctionDatabase.adventureSmithingLimit.creatable = 0;
ConcoctionDatabase.adventureSmithingLimit.visibleTotal = ConcoctionDatabase.adventureSmithingLimit.total;
// Adventures are considered Item #0 in the event that the
// concoction will use ADVs.
ConcoctionDatabase.adventureJewelcraftingLimit.total = KoLCharacter.getAdventuresLeft() +
ConcoctionDatabase.getFreeCraftingTurns() +
ConcoctionDatabase.getFreeSmithJewelTurns();
ConcoctionDatabase.adventureJewelcraftingLimit.initial = ConcoctionDatabase.adventureJewelcraftingLimit.total -
ConcoctionDatabase.queuedAdventuresUsed;
ConcoctionDatabase.adventureJewelcraftingLimit.creatable = 0;
ConcoctionDatabase.adventureJewelcraftingLimit.visibleTotal = ConcoctionDatabase.adventureJewelcraftingLimit.total;
// If we want to do turn-free crafting, we can only use free turns in lieu of adventures.
ConcoctionDatabase.turnFreeLimit.total = ConcoctionDatabase.getFreeCraftingTurns();
ConcoctionDatabase.turnFreeLimit.initial = ConcoctionDatabase.turnFreeLimit.total -
ConcoctionDatabase.queuedFreeCraftingTurns;
ConcoctionDatabase.turnFreeLimit.creatable = 0;
ConcoctionDatabase.turnFreeLimit.visibleTotal = ConcoctionDatabase.turnFreeLimit.total;
// If we want to do turn-free smithing, we can only use free turns in lieu of adventures. Smithing can't be queued
ConcoctionDatabase.turnFreeSmithingLimit.total = ConcoctionDatabase.getFreeCraftingTurns() +
ConcoctionDatabase.getFreeSmithingTurns() +
ConcoctionDatabase.getFreeSmithJewelTurns();
ConcoctionDatabase.turnFreeSmithingLimit.initial = ConcoctionDatabase.turnFreeSmithingLimit.total -
ConcoctionDatabase.queuedFreeCraftingTurns;
ConcoctionDatabase.turnFreeSmithingLimit.creatable = 0;
ConcoctionDatabase.turnFreeSmithingLimit.visibleTotal = ConcoctionDatabase.turnFreeSmithingLimit.total;
// Stills are also considered Item #0 in the event that the
// concoction will use stills.
ConcoctionDatabase.stillsLimit.total = KoLCharacter.getStillsAvailable();
ConcoctionDatabase.stillsLimit.initial =
ConcoctionDatabase.stillsLimit.total - ConcoctionDatabase.queuedStillsUsed;
ConcoctionDatabase.stillsLimit.creatable = 0;
ConcoctionDatabase.stillsLimit.visibleTotal = ConcoctionDatabase.stillsLimit.total;
// Tomes are also also also considered Item #0 in the event that the
// concoction requires a tome summon.
String pref = KoLCharacter.canInteract() ? "_clipartSummons" : "tomeSummons";
ConcoctionDatabase.clipArtLimit.total = 3 - Preferences.getInteger( pref );
ConcoctionDatabase.clipArtLimit.initial =
ConcoctionDatabase.clipArtLimit.total - ConcoctionDatabase.queuedTomesUsed;
ConcoctionDatabase.clipArtLimit.creatable = 0;
ConcoctionDatabase.clipArtLimit.visibleTotal = ConcoctionDatabase.clipArtLimit.total;
// Terminal Extrudes are also limited
ConcoctionDatabase.extrudeLimit.total = 3 - Preferences.getInteger( "_sourceTerminalExtrudes" );
ConcoctionDatabase.extrudeLimit.initial =
ConcoctionDatabase.extrudeLimit.total - ConcoctionDatabase.queuedExtrudesUsed;
ConcoctionDatabase.extrudeLimit.creatable = 0;
ConcoctionDatabase.extrudeLimit.visibleTotal = ConcoctionDatabase.extrudeLimit.total;
// Meat is also also considered Item #0 in the event that the
// concoction will create paste/stacks or buy NPC items.
ConcoctionDatabase.meatLimit.total = KoLCharacter.getAvailableMeat();
ConcoctionDatabase.meatLimit.initial =
ConcoctionDatabase.meatLimit.total - ConcoctionDatabase.queuedMeatSpent;
ConcoctionDatabase.meatLimit.creatable = 0;
ConcoctionDatabase.meatLimit.visibleTotal = ConcoctionDatabase.meatLimit.total;
ConcoctionDatabase.calculateBasicItems( availableIngredients );
// Clear the maps
ConcoctionDatabase.REQUIREMENT_MET.clear();
ConcoctionDatabase.PERMIT_METHOD.clear();
ConcoctionDatabase.ADVENTURE_USAGE.clear();
ConcoctionDatabase.CREATION_COST.clear();
ConcoctionDatabase.EXCUSE.clear();
int Inigo = ConcoctionDatabase.getFreeCraftingTurns();
if ( KoLCharacter.getGender() == KoLCharacter.MALE )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.MALE );
}
else
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.FEMALE );
}
// It is never possible to create items which are flagged
// NOCREATE
// It is always possible to create items through meat paste
// combination.
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.COMBINE );
ConcoctionDatabase.CREATION_COST.put( CraftingType.COMBINE, 10 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.COMBINE, 0 );
// Un-untinkerable Amazing Ideas
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.ACOMBINE );
ConcoctionDatabase.CREATION_COST.put( CraftingType.ACOMBINE, 10 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.ACOMBINE, 0 );
// The gnomish tinkerer is available if the person is in a
// gnome sign and they can access the Desert Beach.
if ( KoLCharacter.gnomadsAvailable() && !KoLCharacter.inZombiecore() )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.GNOME_TINKER );
ConcoctionDatabase.CREATION_COST.put( CraftingType.GNOME_TINKER, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.GNOME_TINKER, 0 );
}
ConcoctionDatabase.EXCUSE.put( CraftingType.GNOME_TINKER, "Only gnome signs can use the Supertinkerer." );
if ( KoLCharacter.inZombiecore() )
{
ConcoctionDatabase.EXCUSE.put( CraftingType.GNOME_TINKER, "Zombies cannot use the Supertinkerer." );
}
// Smithing of items is possible whenever the person
// has a hammer.
if ( InventoryManager.hasItem( ItemPool.TENDER_HAMMER ) || willBuyTool )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.SMITH );
ConcoctionDatabase.CREATION_COST.put( CraftingType.SMITH, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.SMITH, 1 );
}
if ( InventoryManager.hasItem( ItemPool.GRIMACITE_HAMMER ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.GRIMACITE );
}
// Advanced smithing is available whenever the person can
// smith. The appropriate skill is checked separately.
if ( ConcoctionDatabase.PERMIT_METHOD.contains( CraftingType.SMITH ) )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.SSMITH );
ConcoctionDatabase.CREATION_COST.put( CraftingType.SSMITH, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.SSMITH, 1 );
}
// Standard smithing is also possible if the person is in
// a knoll sign.
if ( KoLCharacter.knollAvailable() && !KoLCharacter.inZombiecore() )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.SMITH );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.SMITH, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.ACOMBINE, 0 );
}
if ( KoLCharacter.canSmithWeapons() )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.SUPER_MEATSMITHING );
}
if ( KoLCharacter.canSmithArmor() )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.ARMORCRAFTINESS );
}
// Jewelry making is possible as long as the person has the
// appropriate pliers.
if ( InventoryManager.hasItem( ItemPool.JEWELRY_PLIERS ) ||
ConcoctionDatabase.THORS_PLIERS.getCount( KoLConstants.closet ) > 0 ||
ConcoctionDatabase.THORS_PLIERS.getCount( KoLConstants.inventory ) > 0 ||
InventoryManager.getEquippedCount( ConcoctionDatabase.THORS_PLIERS ) > 0 )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.JEWELRY );
ConcoctionDatabase.CREATION_COST.put( CraftingType.JEWELRY, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.JEWELRY, 0 );
}
if ( KoLCharacter.canCraftExpensiveJewelry() )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.EXPENSIVE );
}
// Star charts and pixel chart recipes are available to all
// players at all times.
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.STARCHART );
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.PIXEL );
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.MULTI_USE );
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.SINGLE_USE );
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.SUGAR_FOLDING );
ConcoctionDatabase.CREATION_COST.put( CraftingType.STARCHART, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.PIXEL, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.MULTI_USE, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.SINGLE_USE, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.SUGAR_FOLDING, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.STARCHART, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.PIXEL, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.MULTI_USE, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.SINGLE_USE, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.SUGAR_FOLDING, 0 );
// A rolling pin or unrolling pin can be always used in item
// creation because we can get the same effect even without the
// tool.
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.ROLLING_PIN );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.ROLLING_PIN, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.ROLLING_PIN, 0 );
// Rodoric will make chefstaves for mysticality class
// characters who can get to the guild.
if ( KoLCharacter.isMysticalityClass() && KoLCharacter.getGuildStoreOpen() )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.STAFF );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.STAFF, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.STAFF, 0 );
}
ConcoctionDatabase.EXCUSE.put( CraftingType.STAFF, "Only mysticality classes can make chefstaves." );
// Phineas will make things for Seal Clubbers who have defeated
// their Nemesis, and hence have their ULEW
if ( InventoryManager.hasItem( ItemPool.SLEDGEHAMMER_OF_THE_VAELKYR ) )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.PHINEAS );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.PHINEAS, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.PHINEAS, 0 );
}
ConcoctionDatabase.EXCUSE.put( CraftingType.PHINEAS, "Only Seal Clubbers who have defeated Gorgolok can use Phineas." );
// It's not possible to ask Uncle Crimbo 2005 to make toys
// It's not possible to ask Ugh Crimbo 2006 to make toys
// It's not possible to ask Uncle Crimbo 2007 to make toys
// It's not possible to ask Uncle Crimbo 2012 to make toys
// Next, increment through all the box servant creation methods.
// This allows future appropriate calculation for cooking/drinking.
ConcoctionPool.get( ItemPool.CHEF ).calculate2();
ConcoctionPool.get( ItemPool.CLOCKWORK_CHEF ).calculate2();
ConcoctionPool.get( ItemPool.BARTENDER ).calculate2();
ConcoctionPool.get( ItemPool.CLOCKWORK_BARTENDER ).calculate2();
// Cooking is permitted, so long as the person has an oven or a
// range installed in their kitchen
if ( KoLCharacter.hasOven() || KoLCharacter.hasRange() )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.COOK );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.COOK, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.COOK, 0 );
}
ConcoctionDatabase.EXCUSE.put( CraftingType.COOK, "You cannot cook without an oven or a range." );
// If we have a range and a chef installed, cooking fancy foods
// costs no adventure. If we have no chef, cooking takes
// adventures unless we have Inigo's active.
// If you don't have a range, you can't cook fancy food
// We could auto buy & install a range if the character
// has at least 1,000 Meat and autoSatisfyWithNPCs = true
if ( !KoLCharacter.hasRange() && !willBuyTool )
{
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.COOK_FANCY, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.COOK_FANCY, 0 );
ConcoctionDatabase.EXCUSE.put( CraftingType.COOK_FANCY,
"You cannot cook fancy foods without a range." );
}
// If you have (or will have) a chef, fancy cooking is free
else if ( KoLCharacter.hasChef() || willBuyServant ||
ConcoctionDatabase.isAvailable( ItemPool.CHEF, ItemPool.CLOCKWORK_CHEF ) )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.COOK_FANCY );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.COOK_FANCY, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.COOK_FANCY,
MallPriceDatabase.getPrice( ItemPool.CHEF ) / 90 );
}
// If we don't have a chef, Inigo's makes cooking free
/* else if ( Inigo > 0 )
{
ConcoctionDatabase.PERMIT_METHOD[ KoLConstants.COOK_FANCY ] = true;
ConcoctionDatabase.ADVENTURE_USAGE[ KoLConstants.COOK_FANCY ] = 0;
ConcoctionDatabase.CREATION_COST[ KoLConstants.COOK_FANCY ] = 0;
ConcoctionDatabase.EXCUSE[ KoLConstants.COOK_FANCY ] = null;
}*/
// We might not care if cooking takes adventures
else if ( Preferences.getBoolean( "requireBoxServants" ) )
{
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.COOK_FANCY, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.COOK_FANCY, 0 );
ConcoctionDatabase.EXCUSE.put( CraftingType.COOK_FANCY,
"You have chosen not to cook fancy food without a chef-in-the-box." );
}
// Otherwise, spend those adventures!
else
{
if ( KoLCharacter.getAdventuresLeft() + Inigo > 0 )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.COOK_FANCY );
}
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.COOK_FANCY, 1 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.COOK_FANCY, 0 );
ConcoctionDatabase.EXCUSE.put( CraftingType.COOK_FANCY,
"You cannot cook fancy foods without adventures." );
}
// Cooking may require an additional skill.
if ( KoLCharacter.canSummonReagent() )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.REAGENT );
}
if ( KoLCharacter.hasSkill( "The Way of Sauce" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.WAY );
}
if ( KoLCharacter.hasSkill( "Deep Saucery" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.DEEP_SAUCERY );
}
if ( KoLCharacter.canSummonNoodles() )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.PASTA );
}
if ( KoLCharacter.hasSkill( "Transcendental Noodlecraft" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.TRANSNOODLE );
}
if ( KoLCharacter.hasSkill( "Tempuramancy" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.TEMPURAMANCY );
}
if ( KoLCharacter.hasSkill( "Patent Medicine" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.PATENT );
}
// Mixing is permitted, so long as the person has a shaker or a
// cocktailcrafting kit installed in their kitchen
if ( KoLCharacter.hasShaker() || KoLCharacter.hasCocktailKit() )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.MIX );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.MIX, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.MIX, 0 );
ConcoctionDatabase.EXCUSE.put( CraftingType.MIX,
"You cannot mix without a shaker or a cocktailcrafting kit." );
}
// If we have a kit and a bartender installed, mixing fancy drinks
// costs no adventure. If we have no bartender, mixing takes
// adventures unless we have Inigo's active.
// If you don't have a cocktailcrafting kit, you can't mix fancy drinks
// We will auto buy & install a cocktailcrafting kit if the character
// has at least 1,000 Meat and autoSatisfyWithNPCs = true
if ( !KoLCharacter.hasCocktailKit() && !willBuyTool )
{
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.MIX_FANCY, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.MIX_FANCY, 0 );
ConcoctionDatabase.EXCUSE.put( CraftingType.MIX_FANCY,
"You cannot mix fancy drinks without a cocktailcrafting kit." );
}
// If you have (or will have) a bartender, fancy mixing is free
else if ( KoLCharacter.hasBartender() || willBuyServant ||
ConcoctionDatabase.isAvailable( ItemPool.BARTENDER, ItemPool.CLOCKWORK_BARTENDER ) )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.MIX_FANCY );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.MIX_FANCY, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.MIX_FANCY,
MallPriceDatabase.getPrice( ItemPool.BARTENDER ) / 90 );
ConcoctionDatabase.EXCUSE.put( CraftingType.MIX_FANCY, null );
}
// If you are Sneaky Pete with Cocktail Magic, fancy mixing is free
else if ( KoLCharacter.hasSkill( "Cocktail Magic" ) )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.MIX_FANCY );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.MIX_FANCY, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.MIX_FANCY, 0 );
ConcoctionDatabase.EXCUSE.put( CraftingType.MIX_FANCY, null );
}
// If we don't have a bartender, Inigo's makes mixing free
/* else if ( Inigo > 0 )
{
ConcoctionDatabase.PERMIT_METHOD[ KoLConstants.MIX_FANCY ] = true;
ConcoctionDatabase.ADVENTURE_USAGE[ KoLConstants.MIX_FANCY ] = 0;
ConcoctionDatabase.CREATION_COST[ KoLConstants.MIX_FANCY ] = 0;
ConcoctionDatabase.EXCUSE[ KoLConstants.MIX_FANCY ] = null;
}*/
// We might not care if mixing takes adventures
else if ( Preferences.getBoolean( "requireBoxServants" ) )
{
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.MIX_FANCY, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.MIX_FANCY, 0 );
ConcoctionDatabase.EXCUSE.put( CraftingType.MIX_FANCY,
"You have chosen not to mix fancy drinks without a bartender-in-the-box." );
}
// Otherwise, spend those adventures!
else
{
if ( KoLCharacter.getAdventuresLeft() + Inigo > 0 )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.MIX_FANCY );
}
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.MIX_FANCY, 1 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.MIX_FANCY, 0 );
ConcoctionDatabase.EXCUSE.put( CraftingType.MIX_FANCY,
"You cannot mix fancy drinks without adventures." );
}
// Mixing may require an additional skill.
if ( KoLCharacter.canSummonShore() || KoLCharacter.hasSkill( "Mixologist" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.AC );
}
if ( KoLCharacter.hasSkill( "Superhuman Cocktailcrafting" ) || KoLCharacter.hasSkill( "Mixologist" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.SHC );
}
if ( KoLCharacter.hasSkill( "Salacious Cocktailcrafting" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.SALACIOUS );
}
// Using Crosby Nash's Still is possible if the person has
// Superhuman Cocktailcrafting and is a Moxie class character.
if ( ConcoctionDatabase.stillsLimit.total > 0 )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.STILL );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.STILL, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.STILL, Preferences.getInteger( "valueOfStill" ) );
}
ConcoctionDatabase.EXCUSE.put( CraftingType.STILL,
KoLCharacter.isMoxieClass() ? "You have no Still uses remaining."
: "Only moxie classes can use the Still." );
// Summoning Clip Art is possible if the person has that tome,
// and isn't in Bad Moon
boolean hasClipArt = KoLCharacter.hasSkill( "Summon Clip Art" ) &&
( !KoLCharacter.inBadMoon() || KoLCharacter.skillsRecalled() );
boolean clipArtSummonsRemaining = hasClipArt &&
( KoLCharacter.canInteract() ? Preferences.getInteger( "_clipartSummons" ) < 3 :
Preferences.getInteger( "tomeSummons" ) < 3 );
if ( hasClipArt && clipArtSummonsRemaining )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.CLIPART );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.CLIPART, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.CLIPART, Preferences.getInteger( "valueOfTome" ) );
}
ConcoctionDatabase.EXCUSE.put( CraftingType.CLIPART, hasClipArt ? "You have no Tome uses remaining."
: "You don't have the Tome of Clip Art." );
// Using the Malus of Forethought is possible if the person has
// Pulverize and is a Muscle class character.
if ( KoLCharacter.canUseMalus() )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.MALUS );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.MALUS, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.MALUS, 0 );
}
ConcoctionDatabase.EXCUSE.put( CraftingType.MALUS, "You require Malus access to be able to pulverize." );
// You can make Sushi if you have a sushi-rolling mat installed
// in your kitchen.
if ( KoLCharacter.hasSushiMat() )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.SUSHI );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.SUSHI, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.SUSHI, 0 );
}
ConcoctionDatabase.EXCUSE.put( CraftingType.SUSHI, "You cannot make sushi without a sushi-rolling mat." );
// You can ask Grandma to make stuff if you have rescued her.
if ( QuestDatabase.isQuestLaterThan( Quest.SEA_MONKEES, "step8" ) )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.GRANDMA );
ConcoctionDatabase.CREATION_COST.put( CraftingType.GRANDMA, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.GRANDMA, 0 );
}
ConcoctionDatabase.EXCUSE.put( CraftingType.GRANDMA, "You must rescue Grandma first." );
// KOLHS concoctions are "permitted" so that we can calculate
// how many items are allowed given available ingredients
// But only in KOLHS!
if ( KoLCharacter.inHighschool() )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.CHEMCLASS );
ConcoctionDatabase.CREATION_COST.put( CraftingType.CHEMCLASS, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.CHEMCLASS, 0 );
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.ARTCLASS );
ConcoctionDatabase.CREATION_COST.put( CraftingType.ARTCLASS, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.ARTCLASS, 0 );
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.SHOPCLASS );
ConcoctionDatabase.CREATION_COST.put( CraftingType.SHOPCLASS, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.SHOPCLASS, 0 );
}
ConcoctionDatabase.EXCUSE.put( CraftingType.CHEMCLASS, "You cannot make that as you are not at school." );
ConcoctionDatabase.EXCUSE.put( CraftingType.ARTCLASS, "You cannot make that as you are not at school." );
ConcoctionDatabase.EXCUSE.put( CraftingType.SHOPCLASS, "You cannot make that as you are not at school." );
// Making stuff with Beer Garden ingredients needs
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.BEER );
ConcoctionDatabase.CREATION_COST.put( CraftingType.BEER, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.BEER, 0 );
// Making stuff with the Junk Magazine requires the magazine
if ( InventoryManager.hasItem( ItemPool.WORSE_HOMES_GARDENS ) )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.JUNK );
ConcoctionDatabase.CREATION_COST.put( CraftingType.JUNK, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.JUNK, 0 );
}
ConcoctionDatabase.EXCUSE.put( CraftingType.JUNK, "You can't make that without a copy of Worse Homes and Gardens." );
// Making stuff with Winter Garden ingredients is always allowed
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.WINTER );
ConcoctionDatabase.CREATION_COST.put( CraftingType.WINTER, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.WINTER, 0 );
// Making stuff with Rumplestiltskin's Workshop is allowed when have access to it
if ( Preferences.getString( "grimstoneMaskPath" ).equals( "gnome" ) )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.RUMPLE );
ConcoctionDatabase.CREATION_COST.put( CraftingType.RUMPLE, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.RUMPLE, 0 );
}
ConcoctionDatabase.EXCUSE.put( CraftingType.RUMPLE, "You need access to Rumplestiltskin's Workshop to make that." );
// You trade tokens to Coin Masters if you have opted in to do so,
if ( Preferences.getBoolean( "autoSatisfyWithCoinmasters" ) )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.COINMASTER );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.COINMASTER, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.COINMASTER, 0 );
}
ConcoctionDatabase.EXCUSE.put( CraftingType.COINMASTER, "You have not selected the option to trade with coin masters." );
if ( KoLConstants.inventory.contains( ItemPool.get( ItemPool.FIVE_D_PRINTER, 1 ) ) )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.FIVE_D );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.FIVE_D, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.FIVE_D, 0 );
}
ConcoctionDatabase.EXCUSE.put( CraftingType.FIVE_D, "You do not have a Xiblaxian 5D printer." );
if ( VYKEACompanionData.currentCompanion() != VYKEACompanionData.NO_COMPANION )
{
ConcoctionDatabase.EXCUSE.put( CraftingType.VYKEA, "You can only build one VYKEA Companion a day." );
}
else if ( !InventoryManager.hasItem( ItemPool.VYKEA_HEX_KEY ) )
{
ConcoctionDatabase.EXCUSE.put( CraftingType.VYKEA, "You do not have a VYKEA hex key." );
}
else
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.VYKEA );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.VYKEA, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.VYKEA, 0 );
}
// Making stuff with globs of melted wax is always allowed
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.WAX );
ConcoctionDatabase.CREATION_COST.put( CraftingType.WAX, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.WAX, 0 );
// Making stuff with spant chitin/tendons is always allowed
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.SPANT );
ConcoctionDatabase.CREATION_COST.put( CraftingType.SPANT, 0 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.SPANT, 0 );
// Other creatability flags
if ( KoLCharacter.isTorsoAware() )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.TORSO );
}
if ( HolidayDatabase.getHoliday().contains( "St. Sneaky Pete's Day" ) ||
HolidayDatabase.getHoliday().contains( "Drunksgiving" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.SSPD );
}
if ( !KoLCharacter.inBeecore() )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.NOBEE );
}
if ( KoLCharacter.isJarlsberg() )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.JARLS );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.JARLS, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.JARLS, 0 );
if ( KoLCharacter.hasSkill( "Bake" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.BAKE );
}
if ( KoLCharacter.hasSkill( "Blend" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.BLEND );
}
if ( KoLCharacter.hasSkill( "Boil" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.BOIL );
}
if ( KoLCharacter.hasSkill( "Chop" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.CHOP );
}
if ( KoLCharacter.hasSkill( "Curdle" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.CURDLE );
}
if ( KoLCharacter.hasSkill( "Freeze" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.FREEZE );
}
if ( KoLCharacter.hasSkill( "Fry" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.FRY );
}
if ( KoLCharacter.hasSkill( "Grill" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.GRILL );
}
if ( KoLCharacter.hasSkill( "Slice" ) )
{
ConcoctionDatabase.REQUIREMENT_MET.add( CraftingRequirements.SLICE );
}
}
ConcoctionDatabase.EXCUSE.put( CraftingType.JARLS, "You are not an Avatar of Jarlsberg" );
if ( Preferences.getBoolean( "coldAirportAlways" ) ||
Preferences.getBoolean( "hotAirportAlways" ) ||
Preferences.getBoolean( "spookyAirportAlways" ) ||
Preferences.getBoolean( "stenchAirportAlways" ) ||
Preferences.getBoolean( "sleazeAirportAlways" ) ||
Preferences.getBoolean( "_coldAirportToday" ) ||
Preferences.getBoolean( "_hotAirportToday" ) ||
Preferences.getBoolean( "_spookyAirportToday" ) ||
Preferences.getBoolean( "_stenchAirportToday" ) ||
Preferences.getBoolean( "_sleazeAirportToday" ) )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.DUTYFREE );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.DUTYFREE, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.DUTYFREE, 0 );
}
// It's Crimbo, so allow creation!
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.CRIMBO16 );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.CRIMBO16, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.CRIMBO16, 0 );
boolean clanFloundry = ClanLoungeRequest.hasClanLoungeItem( ItemPool.get( ItemPool.CLAN_FLOUNDRY, 1 ) );
boolean gotFloundryItem = InventoryManager.hasItem( ItemPool.CARPE ) ||
InventoryManager.hasItem( ItemPool.CODPIECE ) ||
InventoryManager.hasItem( ItemPool.TROUTSERS ) ||
InventoryManager.hasItem( ItemPool.BASS_CLARINET ) ||
InventoryManager.hasItem( ItemPool.FISH_HATCHET ) ||
InventoryManager.hasItem( ItemPool.TUNAC );
if ( clanFloundry && !gotFloundryItem )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.FLOUNDRY );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.FLOUNDRY, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.FLOUNDRY, 0 );
}
if ( gotFloundryItem )
{
ConcoctionDatabase.EXCUSE.put( CraftingType.FLOUNDRY, "You have already got a Floundry item today." );
}
else if ( !clanFloundry )
{
ConcoctionDatabase.EXCUSE.put( CraftingType.FLOUNDRY, "Your current clan does not have a Floundry." );
}
boolean gotBarrelShrine = Preferences.getBoolean( "barrelShrineUnlocked" );
boolean gotBarrelItem = Preferences.getBoolean( "_barrelPrayer" );
if ( gotBarrelShrine && !gotBarrelItem )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.BARREL );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.BARREL, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.BARREL, 0 );
}
if ( gotBarrelItem )
{
ConcoctionDatabase.EXCUSE.put( CraftingType.BARREL, "You have already got a Barrel Shrine item today." );
}
else if ( !gotBarrelShrine )
{
ConcoctionDatabase.EXCUSE.put( CraftingType.BARREL, "You do not have a Barrel Shrine." );
}
boolean sourceTerminal = KoLConstants.campground.contains( ItemPool.get( ItemPool.SOURCE_TERMINAL ) ) ||
KoLConstants.falloutShelter.contains( ItemPool.get( ItemPool.SOURCE_TERMINAL ) );
boolean sourceTerminalUsable = Preferences.getInteger( "_sourceTerminalExtrudes" ) < 3;
if ( sourceTerminal && sourceTerminalUsable )
{
ConcoctionDatabase.PERMIT_METHOD.add( CraftingType.TERMINAL );
ConcoctionDatabase.ADVENTURE_USAGE.put( CraftingType.TERMINAL, 0 );
ConcoctionDatabase.CREATION_COST.put( CraftingType.TERMINAL, 0 );
}
else if ( sourceTerminal && !sourceTerminalUsable )
{
ConcoctionDatabase.EXCUSE.put( CraftingType.TERMINAL, "You have used all your extrudes for today." );
}
else
{
ConcoctionDatabase.EXCUSE.put( CraftingType.TERMINAL, "You do not have a Source Terminal." );
}
// Now, go through all the cached adventure usage values and if
// the number of adventures left is zero and the request requires
// adventures, it is not permitted.
int value = Preferences.getInteger( "valueOfAdventure" );
for ( CraftingType method : CraftingType.values() )
{
if ( ConcoctionDatabase.PERMIT_METHOD.contains( method ) )
{
int adv = ConcoctionDatabase.getAdventureUsage( method );
if ( adv == 0 )
{
continue;
}
if ( adv > KoLCharacter.getAdventuresLeft() +
( method == CraftingType.SMITH ? ConcoctionDatabase.getFreeCraftingTurns() +
ConcoctionDatabase.getFreeSmithJewelTurns() +
ConcoctionDatabase.getFreeSmithingTurns() :
method == CraftingType.SSMITH ? ConcoctionDatabase.getFreeCraftingTurns() +
ConcoctionDatabase.getFreeSmithJewelTurns() +
ConcoctionDatabase.getFreeSmithingTurns() :
method == CraftingType.JEWELRY ? ConcoctionDatabase.getFreeCraftingTurns() +
ConcoctionDatabase.getFreeSmithJewelTurns() :
ConcoctionDatabase.getFreeCraftingTurns() )
)
{//
ConcoctionDatabase.PERMIT_METHOD.remove( method );
ConcoctionDatabase.EXCUSE.put( method, "You don't have enough adventures left to create that." );
}
else
{
int cost = ConcoctionDatabase.getCreationCost( method );
ConcoctionDatabase.CREATION_COST.put( method, cost + ( adv * value ) );
}
}
}
}
public static int getAdventureUsage( CraftingType method )
{
Integer advs = ConcoctionDatabase.ADVENTURE_USAGE.get( method );
return advs == null ? 0 : advs.intValue();
}
public static int getCreationCost( CraftingType method )
{
Integer advs = ConcoctionDatabase.CREATION_COST.get( method );
return advs == null ? 0 : advs.intValue();
}
public static int getFreeCraftingTurns()
{
return ConcoctionDatabase.INIGO.getCount( KoLConstants.activeEffects ) / 5 +
( KoLCharacter.hasSkill( "Rapid Prototyping" ) &&
StandardRequest.isAllowed( "Skill", "Rapid Prototyping" ) ? 5 - Preferences.getInteger( "_rapidPrototypingUsed" ) : 0 ) +
ConcoctionDatabase.CRAFT_TEA.getCount( KoLConstants.activeEffects ) / 5;
}
public static int getFreeSmithJewelTurns()
{
boolean havePliers = ConcoctionDatabase.THORS_PLIERS.getCount( KoLConstants.closet ) > 0 ||
ConcoctionDatabase.THORS_PLIERS.getCount( KoLConstants.inventory ) > 0 ||
InventoryManager.getEquippedCount( ConcoctionDatabase.THORS_PLIERS ) > 0;
return havePliers ? 10 - Preferences.getInteger( "_thorsPliersCrafting" ) : 0;
}
public static int getFreeSmithingTurns()
{
AdventureResult workshedItem = CampgroundRequest.getCurrentWorkshedItem();
boolean haveWarbearAutoanvil = workshedItem != null && workshedItem.getItemId() == ItemPool.AUTO_ANVIL;
boolean haveJackhammer = InventoryManager.hasItem( ItemPool.LOATHING_LEGION_JACKHAMMER );
return ( haveWarbearAutoanvil ? 5 - Preferences.getInteger( "_warbearAutoAnvilCrafting" ) : 0 ) +
( haveJackhammer ? 3 - Preferences.getInteger( "_legionJackhammerCrafting" ) : 0 );
}
private static final boolean isAvailable( final int servantId, final int clockworkId )
{
// Otherwise, return whether or not the quantity possible for
// the given box servants is non-zero. This works because
// cooking tests are made after item creation tests.
return Preferences.getBoolean( "autoRepairBoxServants" ) &&
( ConcoctionPool.get( servantId ).total > 0 ||
ConcoctionPool.get( clockworkId ).total > 0 );
}
/**
* Returns the mixing method for the item with the given Id.
*/
public static final CraftingType getMixingMethod( final Concoction item )
{
return item == null ? CraftingType.NOCREATE : item.getMixingMethod();
}
public static final CraftingType getMixingMethod( final int itemId )
{
return ConcoctionDatabase.getMixingMethod( ConcoctionPool.get( itemId ) );
}
public static final CraftingType getMixingMethod( final String name )
{
return ConcoctionDatabase.getMixingMethod( ConcoctionPool.get( name ) );
}
public static final CraftingType getMixingMethod( final int itemId, final String name )
{
return ConcoctionDatabase.getMixingMethod( ConcoctionPool.get( itemId, name ) );
}
public static final CraftingType getMixingMethod( final AdventureResult ar )
{
return ConcoctionDatabase.getMixingMethod( ConcoctionPool.get( ar ) );
}
public static final EnumSet<CraftingRequirements> getRequirements( final int itemId )
{
Concoction item = ConcoctionPool.get( itemId );
return item == null ? EnumSet.noneOf(CraftingRequirements.class) : item.getRequirements();
}
/**
* Describes a method of creation in terms of the means of creation and the
* restrictions, if any.
* @param mixingMethod the method to describe
* @return the description
*/
public static String mixingMethodDescription( final CraftingType mixingMethod, EnumSet<CraftingRequirements> mixingRequirements )
{
if ( mixingMethod == CraftingType.NOCREATE )
{
return "[cannot be created]";
}
StringBuilder result = new StringBuilder();
if ( mixingMethod == CraftingType.COMBINE )
{
result.append( "Meatpasting" );
}
else if ( mixingMethod == CraftingType.COOK )
{
result.append( "Cooking" );
}
else if ( mixingMethod == CraftingType.MIX )
{
result.append( "Mixing" );
}
else if ( mixingMethod == CraftingType.SMITH )
{
result.append( "Meatsmithing" );
}
else if ( mixingMethod == CraftingType.SSMITH )
{
result.append( "Meatsmithing (not Innabox)" );
}
else if ( mixingMethod == CraftingType.STILL )
{
result.append( "Nash Crosby's Still" );
}
else if ( mixingMethod == CraftingType.MALUS )
{
result.append( "Malus of Forethought" );
}
else if ( mixingMethod == CraftingType.JEWELRY )
{
result.append( "Jewelry-making pliers" );
}
else if ( mixingMethod == CraftingType.STARCHART )
{
result.append( "star chart" );
}
else if ( mixingMethod == CraftingType.SUGAR_FOLDING )
{
result.append( "sugar sheet" );
}
else if ( mixingMethod == CraftingType.PIXEL )
{
result.append( "Crackpot Mystic" );
}
else if ( mixingMethod == CraftingType.CHEMCLASS )
{
result.append( "Chemistry Class" );
}
else if ( mixingMethod == CraftingType.ARTCLASS )
{
result.append( "Art Class" );
}
else if ( mixingMethod == CraftingType.SHOPCLASS )
{
result.append( "Shop Class" );
}
else if ( mixingMethod == CraftingType.RUMPLE )
{
result.append( "Rumpelstiltskin's Workshop" );
}
else if ( mixingMethod == CraftingType.ROLLING_PIN )
{
result.append( "rolling pin/unrolling pin" );
}
else if ( mixingMethod == CraftingType.GNOME_TINKER )
{
result.append( "Supertinkering" );
}
else if ( mixingMethod == CraftingType.STAFF )
{
result.append( "Rodoric, the Staffcrafter" );
}
else if ( mixingMethod == CraftingType.SUSHI )
{
result.append( "sushi-rolling mat" );
}
else if ( mixingMethod == CraftingType.SINGLE_USE )
{
result.append( "single-use" );
}
else if ( mixingMethod == CraftingType.MULTI_USE )
{
result.append( "multi-use" );
}
else if ( mixingMethod == CraftingType.CRIMBO05 )
{
result.append( "Crimbo Town Toy Factory (Crimbo 2005)" );
}
else if ( mixingMethod == CraftingType.CRIMBO06 )
{
result.append( "Uncle Crimbo's Mobile Home (Crimboween 2006)" );
}
else if ( mixingMethod == CraftingType.CRIMBO07 )
{
result.append( "Uncle Crimbo's Mobile Home (Crimbo 2007)" );
}
else if ( mixingMethod == CraftingType.CRIMBO12 )
{
result.append( "Uncle Crimbo's Futuristic Trailer (Crimboku 2012)" );
}
else if ( mixingMethod == CraftingType.CRIMBO16 )
{
result.append( "Crimbo Lumps Shop (Crimbo 2016)" );
}
else if ( mixingMethod == CraftingType.PHINEAS )
{
result.append( "Phineas" );
}
else if ( mixingMethod == CraftingType.COOK_FANCY )
{
result.append( "Cooking (fancy)" );
}
else if ( mixingMethod == CraftingType.MIX_FANCY )
{
result.append( "Mixing (fancy)" );
}
else if ( mixingMethod == CraftingType.ACOMBINE )
{
result.append( "Meatpasting (not untinkerable)" );
}
else if ( mixingMethod == CraftingType.COINMASTER )
{
result.append( "Coin Master purchase" );
}
else if ( mixingMethod == CraftingType.CLIPART )
{
result.append( "Summon Clip Art" );
}
else if ( mixingMethod == CraftingType.JARLS )
{
result.append( "Jarlsberg's Kitchen" );
}
else if ( mixingMethod == CraftingType.GRANDMA )
{
result.append( "Grandma Sea Monkee" );
}
else if ( mixingMethod == CraftingType.BEER )
{
result.append( "Beer Garden" );
}
else if ( mixingMethod == CraftingType.JUNK )
{
result.append( "Worse Homes and Gardens" );
}
else if ( mixingMethod == CraftingType.WINTER )
{
result.append( "Winter Garden" );
}
else if ( mixingMethod == CraftingType.RUMPLE )
{
result.append( "Rumpelstiltskin's Workshop" );
}
else if ( mixingMethod == CraftingType.FIVE_D )
{
result.append( "Xiblaxian 5D printer" );
}
else if ( mixingMethod == CraftingType.VYKEA )
{
result.append( "VYKEA" );
}
else if ( mixingMethod == CraftingType.DUTYFREE )
{
result.append( "Elemental International Airport Duty Free Shop" );
}
else if ( mixingMethod == CraftingType.FLOUNDRY )
{
result.append( "Clan Floundry" );
}
else if ( mixingMethod == CraftingType.TERMINAL )
{
result.append( "Source Terminal" );
}
else if ( mixingMethod == CraftingType.BARREL )
{
result.append( "shrine to the Barrel god" );
}
else if ( mixingMethod == CraftingType.WAX )
{
result.append( "globs of wax" );
}
else if ( mixingMethod == CraftingType.SPANT )
{
result.append( "spant pieces" );
}
if ( result.length() == 0 )
{
result.append( "[unknown method of creation]" );
}
if ( mixingRequirements.contains( CraftingRequirements.MALE ) )
result.append( " (males only)" );
if ( mixingRequirements.contains( CraftingRequirements.FEMALE ) )
result.append( " (females only)" );
if ( mixingRequirements.contains( CraftingRequirements.SSPD ) )
result.append( " (St. Sneaky Pete's Day only)" );
if ( mixingRequirements.contains( CraftingRequirements.HAMMER ) )
result.append( " (tenderizing hammer)" );
if ( mixingRequirements.contains( CraftingRequirements.GRIMACITE ) )
result.append( " (depleted Grimacite hammer)" );
if ( mixingRequirements.contains( CraftingRequirements.TORSO ) )
result.append( " (Torso Awaregness)" );
if ( mixingRequirements.contains( CraftingRequirements.SUPER_MEATSMITHING ) )
result.append( " (Super-Advanced Meatsmithing)" );
if ( mixingRequirements.contains( CraftingRequirements.ARMORCRAFTINESS ) )
result.append( " (Armorcraftiness)" );
if ( mixingRequirements.contains( CraftingRequirements.EXPENSIVE ) )
result.append( " (Really Expensive Jewelrycrafting)" );
if ( mixingRequirements.contains( CraftingRequirements.REAGENT ) )
result.append( " (Advanced Saucecrafting)" );
if ( mixingRequirements.contains( CraftingRequirements.WAY ) )
result.append( " (The Way of Sauce)" );
if ( mixingRequirements.contains( CraftingRequirements.DEEP_SAUCERY ) )
result.append( " (Deep Saucery)" );
if ( mixingRequirements.contains( CraftingRequirements.PASTA ) )
result.append( " (Pastamastery)" );
if ( mixingRequirements.contains( CraftingRequirements.TRANSNOODLE ) )
result.append( " (Transcendental Noodlecraft)" );
if ( mixingRequirements.contains( CraftingRequirements.TEMPURAMANCY ) )
result.append( " (Tempuramancy)" );
if ( mixingRequirements.contains( CraftingRequirements.PATENT ) )
result.append( " (Patent Medicine)" );
if ( mixingRequirements.contains( CraftingRequirements.AC ) )
result.append( " (Advanced Cocktailcrafting)" );
if ( mixingRequirements.contains( CraftingRequirements.SHC ) )
result.append( " (Superhuman Cocktailcrafting)" );
if ( mixingRequirements.contains( CraftingRequirements.SALACIOUS ) )
result.append( " (Salacious Cocktailcrafting)" );
if ( mixingRequirements.contains( CraftingRequirements.NOBEE ) )
result.append( " (Unavailable in Beecore)" );
if ( mixingRequirements.contains( CraftingRequirements.BAKE ) )
result.append( " (Bake)" );
if ( mixingRequirements.contains( CraftingRequirements.BLEND ) )
result.append( " (Blend)" );
if ( mixingRequirements.contains( CraftingRequirements.BOIL ) )
result.append( " (Boil)" );
if ( mixingRequirements.contains( CraftingRequirements.CHOP ) )
result.append( " (Chop)" );
if ( mixingRequirements.contains( CraftingRequirements.CURDLE ) )
result.append( " (Curdle)" );
if ( mixingRequirements.contains( CraftingRequirements.FREEZE ) )
result.append( " (Freeze)" );
if ( mixingRequirements.contains( CraftingRequirements.FRY ) )
result.append( " (Fry)" );
if ( mixingRequirements.contains( CraftingRequirements.GRILL ) )
result.append( " (Grill)" );
if ( mixingRequirements.contains( CraftingRequirements.SLICE ) )
result.append( " (Slice)" );
return result.toString();
}
/**
* Returns the item Ids of the ingredients for the given item. Note
* that if there are no ingredients, then <code>null</code> will be
* returned instead.
*/
public static final AdventureResult[] getIngredients( final int itemId )
{
return ConcoctionDatabase.getIngredients( ConcoctionDatabase.getStandardIngredients( itemId ) );
}
public static final AdventureResult[] getIngredients( final String name )
{
return ConcoctionDatabase.getIngredients( ConcoctionDatabase.getStandardIngredients( name ) );
}
public static final AdventureResult[] getIngredients( AdventureResult[] ingredients )
{
List<AdventureResult> availableIngredients = ConcoctionDatabase.getAvailableIngredients();
return ConcoctionDatabase.getIngredients( ingredients, availableIngredients );
}
private static final AdventureResult[] getIngredients( AdventureResult[] ingredients, List<AdventureResult> availableIngredients )
{
// Ensure that you're retrieving the same ingredients that
// were used in the calculations. Usually this is the case,
// but ice-cold beer and ketchup are tricky cases.
if ( ingredients.length > 2 )
{ // This is not a standard crafting recipe - and in the one case
// where such a recipe uses one of these ingredients (Sir Schlitz
// for the Staff of the Short Order Cook), it's not interchangeable.
return ingredients;
}
for ( int i = 0; i < ingredients.length; ++i )
{
switch ( ingredients[ i ].getItemId() )
{
case ItemPool.SCHLITZ:
case ItemPool.WILLER:
ingredients[ i ] = ConcoctionDatabase.getBetterIngredient(
ItemPool.SCHLITZ, ItemPool.WILLER, availableIngredients );
break;
case ItemPool.KETCHUP:
case ItemPool.CATSUP:
ingredients[ i ] = ConcoctionDatabase.getBetterIngredient(
ItemPool.KETCHUP, ItemPool.CATSUP, availableIngredients );
break;
case ItemPool.DYSPEPSI_COLA:
case ItemPool.CLOACA_COLA:
ingredients[ i ] = ConcoctionDatabase.getBetterIngredient(
ItemPool.DYSPEPSI_COLA, ItemPool.CLOACA_COLA, availableIngredients );
break;
case ItemPool.TITANIUM_UMBRELLA:
case ItemPool.GOATSKIN_UMBRELLA:
ingredients[ i ] = ConcoctionDatabase.getBetterIngredient(
ItemPool.TITANIUM_UMBRELLA, ItemPool.GOATSKIN_UMBRELLA, availableIngredients );
break;
}
}
return ingredients;
}
public static final int getYield( final int itemId )
{
Concoction item = ConcoctionPool.get( itemId );
return item == null ? 1 : item.getYield();
}
public static final AdventureResult[] getStandardIngredients( final int itemId )
{
return ConcoctionDatabase.getStandardIngredients( ConcoctionPool.get( itemId ) );
}
public static final AdventureResult[] getStandardIngredients( final String name )
{
return ConcoctionDatabase.getStandardIngredients( ConcoctionPool.get( name ) );
}
public static final AdventureResult[] getStandardIngredients( final Concoction item )
{
return item == null ? ConcoctionDatabase.NO_INGREDIENTS : item.getIngredients();
}
private static final AdventureResult getBetterIngredient( final int itemId1, final int itemId2, final List<AdventureResult> availableIngredients )
{
AdventureResult ingredient1 = ItemPool.get( itemId1, 1 );
AdventureResult ingredient2 = ItemPool.get( itemId2, 1 );
int diff = ingredient1.getCount( availableIngredients ) - ingredient2.getCount( availableIngredients );
if ( diff == 0 )
{
diff = MallPriceDatabase.getPrice( itemId2 ) - MallPriceDatabase.getPrice( itemId1 );
}
return diff > 0 ? ingredient1 : ingredient2;
}
public static final int getPullsBudgeted()
{
return ConcoctionDatabase.pullsBudgeted;
}
public static int pullsBudgeted = 0;
public static int pullsRemaining = 0;
public static final int getPullsRemaining()
{
return pullsRemaining;
}
private static void addCraftingData( String mix, String name )
{
CraftingType currentMixingMethod = ConcoctionDatabase.mixingMethod;
// Items anybody can create using meat paste or The Plunger
if ( mix.equals( "COMBINE") )
{
ConcoctionDatabase.mixingMethod = CraftingType.COMBINE;
}
// Items anybody can create with an E-Z Cook Oven or Dramatic Range
else if ( mix.equals( "COOK" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.COOK;
}
// Items anybody can create with a Shaker or Cocktailcrafting Kit
else if ( mix.equals( "MIX" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.MIX;
}
// Items anybody can create with a tenderizing hammer or via Innabox
else if ( mix.equals( "SMITH" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.SMITH;
}
// Items that can only be created with a tenderizing hammer, not via Innabox
else if ( mix.equals( "SSMITH" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.SSMITH;
}
// Items requiring access to Nash Crosby's Still
else if ( mix.equals( "STILL" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.STILL;
}
// Items requiring access to the Malus of Forethought
else if ( mix.equals( "MALUS" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.MALUS;
}
// Items anybody can create with jewelry-making pliers
else if ( mix.equals( "JEWEL" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.JEWELRY;
}
// Items anybody can create with starcharts, stars, and lines
else if ( mix.equals( "STAR" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.STARCHART;
}
// Items anybody can create by folding sugar sheets
else if ( mix.equals( "SUGAR" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.SUGAR_FOLDING;
}
// Items anybody can create with pixels
else if ( mix.equals( "PIXEL" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.PIXEL;
}
// Items anybody can create in KOLHS
else if ( mix.equals( "CHEMCLASS" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.CHEMCLASS;
}
else if ( mix.equals( "ARTCLASS" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.ARTCLASS;
}
else if ( mix.equals( "SHOPCLASS" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.SHOPCLASS;
}
// Items created with a rolling pin or and an unrolling pin
else if ( mix.equals( "ROLL" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.ROLLING_PIN;
}
// Items requiring access to the Gnome supertinker
else if ( mix.equals( "TINKER" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.GNOME_TINKER;
}
// Items requiring access to Roderick the Staffmaker
else if ( mix.equals( "STAFF" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.STAFF;
}
// Items anybody can create with a sushi-rolling mat
else if ( mix.equals( "SUSHI" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.SUSHI;
}
// Items created by single (or multi) using a single item.
// Extra ingredients might also be consumed.
// Multi-using multiple of the item creates multiple results.
else if ( mix.equals( "SUSE" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.SINGLE_USE;
}
// Items created by multi-using specific # of a single item.
// Extra ingredients might also be consumed.
// You must create multiple result items one at a time.
else if ( mix.equals( "MUSE" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.MULTI_USE;
}
// Items formerly creatable in Crimbo Town during Crimbo 2005
else if ( mix.equals( "CRIMBO05" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.CRIMBO05;
}
// Items formerly creatable in Crimbo Town during Crimbo 2006
else if ( mix.equals( "CRIMBO06" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.CRIMBO06;
}
// Items formerly creatable in Crimbo Town during Crimbo 2007
else if ( mix.equals( "CRIMBO07" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.CRIMBO07;
}
// Items formerly creatable in Crimbo Town during Crimbo 2012
else if ( mix.equals( "CRIMBO12" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.CRIMBO12;
}
// Items creatable in Crimbo Town during Crimbo 2016
else if ( mix.equals( "CRIMBO16" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.CRIMBO16;
}
// Items requiring access to Phineas
else if ( mix.equals( "PHINEAS" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.PHINEAS;
}
// Items that require a Dramatic Range
else if ( mix.equals( "COOK_FANCY" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.COOK_FANCY;
}
// Items that require a Cocktailcrafting Kit
else if ( mix.equals( "MIX_FANCY" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.MIX_FANCY;
}
// Un-untinkerable Meatpasting
else if ( mix.equals( "ACOMBINE" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.ACOMBINE;
}
// Summon Clip Art items
else if ( mix.equals( "CLIPART" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.CLIPART;
}
else if ( mix.equals( "MALE" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.MALE );
}
else if ( mix.equals( "FEMALE" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.FEMALE );
}
// Can only be made on St. Sneaky Pete's Day
else if ( mix.equals( "SSPD" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.SSPD );
}
// Requires tenderizing hammer (implied for SMITH & SSMITH)
else if ( mix.equals( "HAMMER" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.HAMMER );
}
// Requires depleted Grimacite hammer
else if ( mix.equals( "GRIMACITE" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.GRIMACITE );
}
// Requires Torso Awaregness
else if ( mix.equals( "TORSO" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.TORSO );
}
// Requires Super-Advanced Meatsmithing
else if ( mix.equals( "WEAPON" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.SUPER_MEATSMITHING );
}
// Requires Armorcraftiness
else if ( mix.equals( "ARMOR" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.ARMORCRAFTINESS );
}
// Requires Really Expensive Jewerlycrafting
else if ( mix.equals( "EXPENSIVE" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.EXPENSIVE );
}
// Requires Advanced Saucecrafting
else if ( mix.equals( "REAGENT" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.REAGENT );
}
// Requires The Way of Sauce
else if ( mix.equals( "WAY" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.WAY );
}
// Requires Deep Saucery
else if ( mix.equals( "DEEP" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.DEEP_SAUCERY );
}
// Requires Pastamastery
else if ( mix.equals( "PASTAMASTERY" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.PASTA );
}
// Requires Transcendental Noodlecraft
// Requires Tempuramancy
else if ( mix.equals( "TEMPURAMANCY" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.TEMPURAMANCY );
}
// Requires Patent Medicine
else if ( mix.equals( "PATENT" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.PATENT );
}
// Requires Advanced Cocktailcrafting
else if ( mix.equals( "AC" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.AC );
}
// Requires Superhuman Cocktailcrafting
else if ( mix.equals( "SHC" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.SHC );
}
// Requires Salacious Cocktailcrafting
else if ( mix.equals( "SALACIOUS" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.SALACIOUS );
}
// Items creatable only if not on Bees Hate You path
else if ( mix.equals( "NOBEE" ) )
{
ConcoctionDatabase.requirements.add( CraftingRequirements.NOBEE );
}
// Saucerors make 3 of this item at a time
else if ( mix.equals( "SX3" ) )
{
ConcoctionDatabase.info.add( CraftingMisc.TRIPLE_SAUCE );
}
// Recipe unexpectedly does not appear in Discoveries, even though
// it uses a discoverable crafting type
else if ( mix.equals( "NODISCOVERY" ) )
{
ConcoctionDatabase.info.add( CraftingMisc.NODISCOVERY );
}
// Recipe should never be used automatically
else if ( mix.equals( "MANUAL" ) )
{
ConcoctionDatabase.info.add( CraftingMisc.MANUAL );
}
// Items requiring Pastamastery
else if ( mix.equals( "PASTA" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.COOK_FANCY;
ConcoctionDatabase.requirements.add( CraftingRequirements.PASTA );
}
// Items requiring Transcendental Noodlecraft
else if ( mix.equals( "TNOODLE" ) || mix.equals( "TRANSNOODLE" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.COOK_FANCY;
ConcoctionDatabase.requirements.add( CraftingRequirements.TRANSNOODLE );
}
// Items requiring Tempuramancy
else if ( mix.equals( "TEMPURA" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.COOK_FANCY;
ConcoctionDatabase.requirements.add( CraftingRequirements.TEMPURAMANCY );
}
// Items requiring Super-Advanced Meatsmithing
else if ( mix.equals( "WSMITH" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.SSMITH;
ConcoctionDatabase.requirements.add( CraftingRequirements.SUPER_MEATSMITHING );
}
// Items requiring Armorcraftiness
else if ( mix.equals( "ASMITH" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.SSMITH;
ConcoctionDatabase.requirements.add( CraftingRequirements.ARMORCRAFTINESS );
}
// Items requiring Advanced Cocktailcrafting
else if ( mix.equals( "ACOCK" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.MIX_FANCY;
ConcoctionDatabase.requirements.add( CraftingRequirements.AC );
}
// Items requiring Superhuman Cocktailcrafting
else if ( mix.equals( "SCOCK" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.MIX_FANCY;
ConcoctionDatabase.requirements.add( CraftingRequirements.SHC );
}
// Items requiring Salacious Cocktailcrafting
else if ( mix.equals( "SACOCK" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.MIX_FANCY;
ConcoctionDatabase.requirements.add( CraftingRequirements.SALACIOUS );
}
// Items requiring pliers and Really Expensive Jewelrycrafting
else if ( mix.equals( "EJEWEL" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.JEWELRY;
ConcoctionDatabase.requirements.add( CraftingRequirements.EXPENSIVE );
}
// Items requiring Advanced Saucecrafting
else if ( mix.equals( "SAUCE" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.COOK_FANCY;
ConcoctionDatabase.requirements.add( CraftingRequirements.REAGENT );
}
// Items requiring The Way of Sauce
else if ( mix.equals( "SSAUCE" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.COOK_FANCY;
ConcoctionDatabase.requirements.add( CraftingRequirements.WAY );
}
// Items requiring Deep Saucery
else if ( mix.equals( "DSAUCE" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.COOK_FANCY;
ConcoctionDatabase.requirements.add( CraftingRequirements.DEEP_SAUCERY );
}
else if ( mix.equals( "JARLS" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.JARLS;
}
else if ( mix.equals( "JARLSBAKE" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.JARLS;
ConcoctionDatabase.requirements.add( CraftingRequirements.BAKE );
}
else if ( mix.equals( "JARLSBLEND" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.JARLS;
ConcoctionDatabase.requirements.add( CraftingRequirements.BLEND );
}
else if ( mix.equals( "JARLSBOIL" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.JARLS;
ConcoctionDatabase.requirements.add( CraftingRequirements.BOIL );
}
else if ( mix.equals( "JARLSCHOP" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.JARLS;
ConcoctionDatabase.requirements.add( CraftingRequirements.CHOP );
}
else if ( mix.equals( "JARLSCURDLE" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.JARLS;
ConcoctionDatabase.requirements.add( CraftingRequirements.CURDLE );
}
else if ( mix.equals( "JARLSFREEZE" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.JARLS;
ConcoctionDatabase.requirements.add( CraftingRequirements.FREEZE );
}
else if ( mix.equals( "JARLSFRY" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.JARLS;
ConcoctionDatabase.requirements.add( CraftingRequirements.FRY );
}
else if ( mix.equals( "JARLSGRILL" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.JARLS;
ConcoctionDatabase.requirements.add( CraftingRequirements.GRILL );
}
else if ( mix.equals( "JARLSSLICE" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.JARLS;
ConcoctionDatabase.requirements.add( CraftingRequirements.SLICE );
}
else if ( mix.equals( "GRANDMA" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.GRANDMA;
}
else if ( mix.equals( "BEER" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.BEER;
}
else if ( mix.equals( "JUNK" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.JUNK;
}
else if ( mix.equals( "WINTER" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.WINTER;
}
else if ( mix.equals( "RUMPLE" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.RUMPLE;
}
else if ( mix.equals( "5D" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.FIVE_D;
}
else if ( mix.equals( "VYKEA" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.VYKEA;
}
else if ( mix.equals( "DUTYFREE" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.DUTYFREE;
}
else if ( mix.equals( "TERMINAL" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.TERMINAL;
}
else if ( mix.equals( "BARREL" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.BARREL;
}
else if ( mix.equals( "WAX" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.WAX;
}
else if ( mix.equals( "SPANT" ) )
{
ConcoctionDatabase.mixingMethod = CraftingType.SPANT;
}
else if ( mix.startsWith( "ROW" ) )
{
ConcoctionDatabase.row = StringUtilities.parseInt( mix.substring( 3 ) );
}
else
{
RequestLogger.printLine( "Unknown mixing method or flag (" + mix + ") for concoction: " + name );
}
if ( currentMixingMethod != null && currentMixingMethod != ConcoctionDatabase.mixingMethod )
{
RequestLogger.printLine( "Multiple mixing methods for concoction: " + name );
}
}
public static final void setPullsRemaining( final int pullsRemaining )
{
ConcoctionDatabase.pullsRemaining = pullsRemaining;
if ( !StaticEntity.isHeadless() )
{
ItemManageFrame.updatePullsRemaining( pullsRemaining );
NamedListenerRegistry.fireChange( "(pullsremaining)" );
}
if ( pullsRemaining < pullsBudgeted )
{
ConcoctionDatabase.setPullsBudgeted( pullsRemaining );
}
}
public static final void setPullsBudgeted( int pullsBudgeted )
{
if ( pullsBudgeted < queuedPullsUsed )
{
pullsBudgeted = queuedPullsUsed;
}
if ( pullsBudgeted > pullsRemaining )
{
pullsBudgeted = pullsRemaining;
}
ConcoctionDatabase.pullsBudgeted = pullsBudgeted;
if ( !StaticEntity.isHeadless() )
{
ItemManageFrame.updatePullsBudgeted( pullsBudgeted );
}
}
public static class QueuedConcoction
{
private final Concoction concoction;
private final int count;
private final ArrayList<AdventureResult> ingredients;
private final int meat;
private final int pulls;
private final int tomes;
private final int stills;
private final int extrudes;
private final int adventures;
private final int freeCrafts;
public QueuedConcoction( final Concoction c, final int count, final ArrayList<AdventureResult> ingredients,
final int meat, final int pulls, final int tomes, final int stills, final int extrudes,
final int adventures, final int freeCrafts )
{
this.concoction = c;
this.count = count;
this.ingredients = ingredients;
this.meat = meat;
this.pulls = pulls;
this.tomes = tomes;
this.stills = stills;
this.extrudes = extrudes;
this.adventures = adventures;
this.freeCrafts = freeCrafts;
}
public Concoction getConcoction()
{
return this.concoction;
}
public int getCount()
{
return this.count;
}
public ArrayList<AdventureResult> getIngredients()
{
return this.ingredients;
}
public int getMeat()
{
return this.meat;
}
public int getPulls()
{
return this.pulls;
}
public int getTomes()
{
return this.tomes;
}
public int getStills()
{
return this.stills;
}
public int getExtrudes()
{
return this.extrudes;
}
public int getAdventures()
{
return this.adventures;
}
public int getFreeCrafts()
{
return this.freeCrafts;
}
public String getName()
{
return this.concoction.getName();
}
public int getItemId()
{
return this.concoction.getItemId();
}
@Override
public String toString()
{
return this.concoction.getName();
}
@Override
public boolean equals( final Object o )
{
return o != null &&
o instanceof QueuedConcoction &&
this.concoction.equals( ( (QueuedConcoction) o ).concoction ) &&
this.count == ( (QueuedConcoction) o ).count;
}
@Override
public int hashCode() {
int hash = ( this.concoction != null ? this.concoction.hashCode() : 0 );
hash = 31 * hash + this.count;
return hash;
}
}
}