/** * 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.session; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import net.sourceforge.kolmafia.AdventureResult; import net.sourceforge.kolmafia.FamiliarData; import net.sourceforge.kolmafia.KoLAdventure; import net.sourceforge.kolmafia.KoLCharacter; import net.sourceforge.kolmafia.KoLConstants; import net.sourceforge.kolmafia.KoLConstants.MafiaState; import net.sourceforge.kolmafia.KoLConstants.Stat; import net.sourceforge.kolmafia.KoLConstants.WeaponType; import net.sourceforge.kolmafia.KoLmafia; import net.sourceforge.kolmafia.Modifiers; import net.sourceforge.kolmafia.RequestLogger; import net.sourceforge.kolmafia.RequestThread; import net.sourceforge.kolmafia.SpecialOutfit; import net.sourceforge.kolmafia.StaticEntity; import net.sourceforge.kolmafia.listener.NamedListenerRegistry; import net.sourceforge.kolmafia.objectpool.EffectPool; import net.sourceforge.kolmafia.objectpool.FamiliarPool; import net.sourceforge.kolmafia.objectpool.ItemPool; import net.sourceforge.kolmafia.objectpool.OutfitPool; import net.sourceforge.kolmafia.persistence.ConcoctionDatabase; import net.sourceforge.kolmafia.persistence.EquipmentDatabase; import net.sourceforge.kolmafia.persistence.ItemDatabase; import net.sourceforge.kolmafia.preferences.Preferences; import net.sourceforge.kolmafia.request.EquipmentRequest; import net.sourceforge.kolmafia.swingui.GearChangeFrame; import net.sourceforge.kolmafia.textui.command.ConditionsCommand; import net.sourceforge.kolmafia.utilities.LockableListFactory; import net.sourceforge.kolmafia.utilities.StringUtilities; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; public class EquipmentManager { public static final int NONE = -1; // Mutable equipment slots public static final int HAT = 0; public static final int WEAPON = 1; public static final int HOLSTER = 2; public static final int OFFHAND = 3; public static final int CONTAINER = 4; public static final int SHIRT = 5; public static final int PANTS = 6; public static final int ACCESSORY1 = 7; public static final int ACCESSORY2 = 8; public static final int ACCESSORY3 = 9; public static final int FAMILIAR = 10; // Count of slots visible on equipment page: HAT to FAMILIAR public static final int SLOTS = 11; // Pseudo-equipment slots public static final int CROWNOFTHRONES = 11; public static final int STICKER1 = 12; public static final int STICKER2 = 13; public static final int STICKER3 = 14; public static final int CARDSLEEVE = 15; public static final int FOLDER1 = 16; public static final int FOLDER2 = 17; public static final int FOLDER3 = 18; public static final int FOLDER4 = 19; public static final int FOLDER5 = 20; public static final int BUDDYBJORN = 21; public static final int BOOTSKIN = 22; public static final int BOOTSPUR = 23; // Count of all equipment slots: HAT to BOOTSPUR public static final int ALL_SLOTS = 24; public static final int FAKEHAND = 24; private static List<AdventureResult> equipment = LockableListFactory.getInstance( AdventureResult.class ); private static final List<AdventureResult> accessories = LockableListFactory.getInstance( AdventureResult.class ); private static final List<AdventureResult>[] equipmentLists = new List[ EquipmentManager.ALL_SLOTS ]; private static final ArrayList<AdventureResult>[] historyLists = new ArrayList[ EquipmentManager.ALL_SLOTS ]; private static int fakeHandCount = 0; private static int stinkyCheeseLevel = 0; private static final List<SpecialOutfit> normalOutfits = LockableListFactory.getInstance( SpecialOutfit.class ); private static final List<SpecialOutfit> customOutfits = LockableListFactory.getInstance( SpecialOutfit.class ); private static final int[] turnsRemaining = new int[ 3 ]; private static AdventureResult lockedFamiliarItem = EquipmentRequest.UNEQUIP; public final static AdventureResult FAKE_HAND = ItemPool.get( ItemPool.FAKE_HAND, 1 ); public final static AdventureResult CARD_SLEEVE = ItemPool.get( ItemPool.CARD_SLEEVE, 1 ); public final static AdventureResult CROWN_OF_THRONES = ItemPool.get( ItemPool.HATSEAT, 1 ); public final static AdventureResult BUDDY_BJORN = ItemPool.get( ItemPool.BUDDY_BJORN, 1 ); public final static AdventureResult FOLDER_HOLDER = ItemPool.get( ItemPool.FOLDER_HOLDER, 1 ); public final static AdventureResult COWBOY_BOOTS = ItemPool.get( ItemPool.COWBOY_BOOTS, 1 ); static { for ( int i = 0; i < EquipmentManager.ALL_SLOTS; ++i ) { EquipmentManager.equipment.add( EquipmentRequest.UNEQUIP ); EquipmentManager.historyLists[ i ] = new ArrayList<AdventureResult>(); switch ( i ) { case EquipmentManager.ACCESSORY1: case EquipmentManager.ACCESSORY2: case EquipmentManager.ACCESSORY3: EquipmentManager.equipmentLists[ i ] = LockableListFactory.getMirror( EquipmentManager.accessories ); break; default: EquipmentManager.equipmentLists[ i ] = LockableListFactory.getSortedInstance( AdventureResult.class ); break; } } } public static void resetEquipment() { for ( int i = 0; i < EquipmentManager.equipmentLists.length; ++i ) { EquipmentManager.equipmentLists[ i ].clear(); EquipmentManager.historyLists[ i ].clear(); } EquipmentManager.accessories.clear(); GearChangeFrame.clearWeaponLists(); EquipmentManager.equipment.clear(); for ( int i = 0; i < EquipmentManager.ALL_SLOTS; ++i ) { EquipmentManager.equipment.add( EquipmentRequest.UNEQUIP ); } EquipmentManager.fakeHandCount = 0; EquipmentManager.stinkyCheeseLevel = 0; EquipmentManager.lockedFamiliarItem = EquipmentRequest.UNEQUIP; EquipmentManager.normalOutfits.clear(); } public static void resetCustomOutfits() { EquipmentManager.customOutfits.clear(); } public static AdventureResult[] emptyEquipmentArray() { return EquipmentManager.emptyEquipmentArray( false ); } public static AdventureResult[] emptyEquipmentArray( boolean all ) { int length = all ? EquipmentManager.ALL_SLOTS : EquipmentManager.SLOTS; AdventureResult[] array = new AdventureResult[ length ]; for ( int i = 0; i < length; ++i ) { array[ i ] = EquipmentRequest.UNEQUIP; } return array; } public static AdventureResult[] currentEquipment() { AdventureResult[] array = new AdventureResult[ EquipmentManager.SLOTS ]; for ( int i = 0; i < EquipmentManager.SLOTS; ++i ) { array[ i ] = EquipmentManager.getEquipment( i ); } return array; } public static AdventureResult[] allEquipment() { AdventureResult[] array = new AdventureResult[ EquipmentManager.ALL_SLOTS ]; array = (AdventureResult[]) EquipmentManager.equipment.toArray( array ); array[ EquipmentManager.FAMILIAR ] = EquipmentManager.getFamiliarItem(); return array; } public static final List<AdventureResult> allEquipmentAsList() { return EquipmentManager.equipment; } public static final void processResult( AdventureResult item ) { int itemId = item.getItemId(); // If your current familiar can use this item, add it to familiar item list if ( KoLCharacter.getFamiliar().canEquip( item ) ) { AdventureResult.addResultToList( EquipmentManager.equipmentLists[ EquipmentManager.FAMILIAR ], item ); if ( ItemDatabase.getConsumptionType( itemId ) == KoLConstants.EQUIP_FAMILIAR ) { return; } // Even though the familiar can use it, it's not a // familiar item. Continue processing, in case the // character can also use the item } if ( !EquipmentManager.canEquip( itemId ) ) { return; } int consumeType = ItemDatabase.getConsumptionType( itemId ); if ( consumeType == KoLConstants.EQUIP_ACCESSORY ) { AdventureResult.addResultToList( EquipmentManager.accessories, item ); } else if ( consumeType == KoLConstants.CONSUME_STICKER ) { // The stickers cannot be combined into a single list, as is done with // accessories, since stickers cannot be moved to a different slot. If a // slot contains your last sticker of a particular type, then that type must // only appear for that slot (so that it can be the initially selected // value), not in the other two slots. There are only six types of stickers, // and no reason to believe that there will ever be many (or even any) more, // so this duplication should not present a problem. // // Make sure the current sticker in each slot remains in the list, even if // there are no more of that type in inventory. for ( int slot = EquipmentManager.STICKER1; slot <= EquipmentManager.STICKER3; ++slot ) { AdventureResult current = EquipmentManager.getEquipment( slot ); AdventureResult.addResultToList( EquipmentManager.equipmentLists[ slot ], item ); if ( !EquipmentManager.equipmentLists[ slot ].contains( current ) ) { EquipmentManager.equipmentLists[ slot ].add( current ); } } } else if ( consumeType == KoLConstants.CONSUME_FOLDER ) { // Folders are similar to stickers for ( int slot = EquipmentManager.FOLDER1; slot <= EquipmentManager.FOLDER5; ++slot ) { AdventureResult current = EquipmentManager.getEquipment( slot ); AdventureResult.addResultToList( EquipmentManager.equipmentLists[ slot ], item ); if ( !EquipmentManager.equipmentLists[ slot ].contains( current ) ) { EquipmentManager.equipmentLists[ slot ].add( current ); } } } else if ( itemId == ItemPool.HATSEAT ) { AdventureResult.addResultToList( EquipmentManager.equipmentLists[ EquipmentManager.HAT ], item ); } else if ( itemId == ItemPool.BUDDY_BJORN ) { AdventureResult.addResultToList( EquipmentManager.equipmentLists[ EquipmentManager.CONTAINER ], item ); } else { int equipmentType = EquipmentManager.consumeFilterToEquipmentType( consumeType ); if ( equipmentType != -1 ) { AdventureResult.addResultToList( EquipmentManager.equipmentLists[ equipmentType ], item ); } switch ( equipmentType ) { case EquipmentManager.HAT: GearChangeFrame.updateHats(); break; case EquipmentManager.WEAPON: case EquipmentManager.OFFHAND: GearChangeFrame.updateWeapons(); break; case EquipmentManager.SHIRT: GearChangeFrame.updateShirts(); break; case EquipmentManager.CONTAINER: GearChangeFrame.updateContainers(); break; case EquipmentManager.PANTS: GearChangeFrame.updatePants(); break; case EquipmentManager.ACCESSORY1: GearChangeFrame.updateAccessories1(); break; case EquipmentManager.ACCESSORY2: GearChangeFrame.updateAccessories2(); break; case EquipmentManager.ACCESSORY3: GearChangeFrame.updateAccessories3(); break; case EquipmentManager.BOOTSKIN: GearChangeFrame.updateBootskins(); break; case EquipmentManager.BOOTSPUR: GearChangeFrame.updateBootspurs(); break; case EquipmentManager.HOLSTER: GearChangeFrame.updateSixguns(); break; } } if ( EquipmentDatabase.getOutfitWithItem( item.getItemId() ) != -1 ) { EquipmentManager.updateNormalOutfits(); } } public static final void autoequipItem( AdventureResult newItem ) { EquipmentManager.autoequipItem( newItem, true ); } public static final void autoequipItem( AdventureResult newItem, boolean addToCheckpoints ) { int slot = EquipmentManager.itemIdToEquipmentType( newItem.getItemId() ); if ( slot < 0 ) { return; } if ( addToCheckpoints ) { SpecialOutfit.replaceEquipmentInSlot( newItem, slot ); } AdventureResult oldItem = EquipmentManager.getEquipment( slot ); if ( newItem.getItemId() == oldItem.getItemId() ) { return; } // Manually subtract item from inventory to avoid // excessive list updating. if ( newItem != EquipmentRequest.UNEQUIP ) { AdventureResult.addResultToList( KoLConstants.inventory, newItem.getInstance( -1 ) ); } if ( oldItem != EquipmentRequest.UNEQUIP ) { AdventureResult.addResultToList( KoLConstants.inventory, oldItem.getInstance( 1 ) ); } EquipmentManager.setEquipment( slot, newItem ); } public static final void setEquipment( final int slot, AdventureResult item ) { // Variable slots do not include the fake hand if ( slot >= EquipmentManager.equipmentLists.length ) { return; } AdventureResult old = EquipmentManager.getEquipment( slot ); // Accessories are special in terms of testing for existence // in equipment lists -- they are all mirrors of accessories. switch ( slot ) { case -1: // unknown item - ignore it return; case ACCESSORY1: case ACCESSORY2: case ACCESSORY3: int index = EquipmentManager.accessories.indexOf( item ); if ( index == -1 ) { EquipmentManager.accessories.add( item ); } else { item = (AdventureResult) EquipmentManager.accessories.get( index ); } break; default: if ( !EquipmentManager.equipmentLists[ slot ].contains( item ) ) { EquipmentManager.equipmentLists[ slot ].add( item ); } break; } EquipmentManager.equipment.set( slot, item ); LockableListFactory.setSelectedItem( EquipmentManager.equipmentLists[ slot ], item ); EquipmentManager.historyLists[ slot ].remove( item ); EquipmentManager.historyLists[ slot ].add( item ); // Certain equipment slots require special update handling // in addition to the above code. switch ( slot ) { case EquipmentManager.WEAPON: case EquipmentManager.OFFHAND: EquipmentManager.checkFamiliar( slot ); GearChangeFrame.updateWeapons(); break; case EquipmentManager.HAT: EquipmentManager.checkFamiliar( slot ); GearChangeFrame.updateHats(); break; case EquipmentManager.PANTS: EquipmentManager.checkFamiliar( slot ); GearChangeFrame.updatePants(); break; case EquipmentManager.SHIRT: GearChangeFrame.updateShirts(); break; case EquipmentManager.CONTAINER: GearChangeFrame.updateContainers(); break; case EquipmentManager.ACCESSORY1: GearChangeFrame.updateAccessories1(); break; case EquipmentManager.ACCESSORY2: GearChangeFrame.updateAccessories2(); break; case EquipmentManager.ACCESSORY3: GearChangeFrame.updateAccessories3(); break; case EquipmentManager.FAMILIAR: EquipmentManager.checkFamiliar( slot ); KoLCharacter.currentFamiliar.setItem( item ); break; case EquipmentManager.BOOTSKIN: GearChangeFrame.updateBootskins(); break; case EquipmentManager.BOOTSPUR: GearChangeFrame.updateBootspurs(); break; case EquipmentManager.HOLSTER: GearChangeFrame.updateSixguns(); break; } // Certain items provide additional skills when equipped. // Handle the addition / removal of those skills here. // Remove skill first if item being removed had one if ( old.getItemId() != item.getItemId() ) { Boolean removed = true; // Some items could be in multiple slots switch ( slot ) { case EquipmentManager.HAT: { AdventureResult hat = EquipmentManager.getEquipment( HAT ); removed = hat.getItemId() != old.getItemId(); } break; case EquipmentManager.WEAPON: { AdventureResult offhand = EquipmentManager.getEquipment( OFFHAND ); AdventureResult familiar = EquipmentManager.getEquipment( FAMILIAR ); removed = offhand.getItemId() != old.getItemId() && familiar.getItemId() != old.getItemId(); } break; case EquipmentManager.OFFHAND: { AdventureResult weapon = EquipmentManager.getEquipment( WEAPON ); AdventureResult familiar = EquipmentManager.getEquipment( FAMILIAR ); removed = weapon.getItemId() != old.getItemId() && familiar.getItemId() != old.getItemId(); } break; case EquipmentManager.PANTS: { AdventureResult pants = EquipmentManager.getEquipment( PANTS ); removed = pants.getItemId() != old.getItemId(); } break; case EquipmentManager.ACCESSORY1: { AdventureResult acc2 = EquipmentManager.getEquipment( ACCESSORY2 ); AdventureResult acc3 = EquipmentManager.getEquipment( ACCESSORY3 ); removed = acc2.getItemId() != old.getItemId() && acc3.getItemId() != old.getItemId(); } break; case EquipmentManager.ACCESSORY2: { AdventureResult acc1 = EquipmentManager.getEquipment( ACCESSORY1 ); AdventureResult acc3 = EquipmentManager.getEquipment( ACCESSORY3 ); removed = acc1.getItemId() != old.getItemId() && acc3.getItemId() != old.getItemId(); } break; case EquipmentManager.ACCESSORY3: { AdventureResult acc1 = EquipmentManager.getEquipment( ACCESSORY1 ); AdventureResult acc2 = EquipmentManager.getEquipment( ACCESSORY2 ); removed = acc1.getItemId() != old.getItemId() && acc2.getItemId() != old.getItemId(); } break; } // If removed, remove conditional skill if ( removed ) { switch ( old.getItemId() ) { case ItemPool.BOTTLE_ROCKET: KoLCharacter.removeAvailableSkill( "Fire red bottle-rocket" ); KoLCharacter.removeAvailableSkill( "Fire blue bottle-rocket" ); KoLCharacter.removeAvailableSkill( "Fire orange bottle-rocket" ); KoLCharacter.removeAvailableSkill( "Fire purple bottle-rocket" ); KoLCharacter.removeAvailableSkill( "Fire black bottle-rocket" ); break; case ItemPool.JEWEL_EYED_WIZARD_HAT: KoLCharacter.removeAvailableSkill( "Magic Missile" ); break; case ItemPool.BAKULA: KoLCharacter.removeAvailableSkill( "Give In To Your Vampiric Urges" ); break; case ItemPool.JOYBUZZER: KoLCharacter.removeAvailableSkill( "Shake Hands" ); break; case ItemPool.V_MASK: KoLCharacter.removeAvailableSkill( "Creepy Grin" ); break; case ItemPool.MAYFLY_BAIT_NECKLACE: KoLCharacter.removeAvailableSkill( "Summon Mayfly Swarm" ); break; case ItemPool.HODGMANS_PORKPIE_HAT: case ItemPool.HODGMANS_LOBSTERSKIN_PANTS: case ItemPool.HODGMANS_BOW_TIE: KoLCharacter.removeAvailableSkill( "Summon hobo underling" ); break; case ItemPool.WILLOWY_BONNET: KoLCharacter.removeAvailableSkill( "Rouse Sapling" ); break; case ItemPool.SACCHARINE_MAPLE_PENDANT: KoLCharacter.removeAvailableSkill( "Spray Sap" ); break; case ItemPool.CROTCHETY_PANTS: KoLCharacter.removeAvailableSkill( "Put Down Roots" ); break; case ItemPool.FIREWORKS: KoLCharacter.removeAvailableSkill( "Fire off a Roman Candle" ); break; case ItemPool.HAIKU_KATANA: KoLCharacter.removeAvailableSkill( "Spring Raindrop Attack" ); KoLCharacter.removeAvailableSkill( "Summer Siesta" ); KoLCharacter.removeAvailableSkill( "Falling Leaf Whirlwind" ); KoLCharacter.removeAvailableSkill( "Winter's Bite Technique" ); KoLCharacter.removeAvailableSkill( "The 17 Cuts" ); break; case ItemPool.PARASITIC_CLAW: case ItemPool.PARASITIC_TENTACLES: case ItemPool.PARASITIC_HEADGNAWER: case ItemPool.PARASITIC_STRANGLEWORM: KoLCharacter.removeAvailableSkill( "Disarm" ); KoLCharacter.removeAvailableSkill( "Entangle" ); KoLCharacter.removeAvailableSkill( "Strangle" ); break; case ItemPool.ELVISH_SUNGLASSES: KoLCharacter.removeAvailableSkill( "Play an Accordion Solo" ); KoLCharacter.removeAvailableSkill( "Play a Guitar Solo" ); KoLCharacter.removeAvailableSkill( "Play a Drum Solo" ); KoLCharacter.removeAvailableSkill( "Play a Flute Solo" ); break; case ItemPool.BAG_O_TRICKS: KoLCharacter.removeAvailableSkill( "Open the Bag o' Tricks" ); break; case ItemPool.FOUET_DE_TORTUE_DRESSAGE: KoLCharacter.removeAvailableSkill( "Apprivoisez la tortue" ); break; case ItemPool.RED_AND_GREEN_SWEATER: KoLCharacter.removeAvailableSkill( "Static Shock" ); break; case ItemPool.STINKY_CHEESE_EYE: KoLCharacter.removeAvailableSkill( "Give Your Opponent the Stinkeye" ); break; case ItemPool.SLEDGEHAMMER_OF_THE_VAELKYR: KoLCharacter.removeAvailableSkill( "Bashing Slam Smash" ); break; case ItemPool.FLAIL_OF_THE_SEVEN_ASPECTS: KoLCharacter.removeAvailableSkill( "Turtle of Seven Tails" ); break; case ItemPool.WRATH_OF_THE_PASTALORDS: KoLCharacter.removeAvailableSkill( "Noodles of Fire" ); break; case ItemPool.WINDSOR_PAN_OF_THE_SOURCE: KoLCharacter.removeAvailableSkill( "Saucemageddon" ); break; case ItemPool.SEEGERS_BANJO: KoLCharacter.removeAvailableSkill( "Funk Bluegrass Fusion" ); break; case ItemPool.TRICKSTER_TRIKITIXA: KoLCharacter.removeAvailableSkill( "Extreme High Note" ); break; case ItemPool.BOTTLE_OF_GOLDENSCHNOCKERED: KoLCharacter.removeAvailableSkill( "Goldenshöwer" ); break; case ItemPool.SPIDER_RING: KoLCharacter.removeAvailableSkill( "Shoot Web" ); break; case ItemPool.STRESS_BALL: KoLCharacter.removeAvailableSkill( "Squeeze Stress Ball" ); break; case ItemPool.PATRIOT_SHIELD: KoLCharacter.removeAvailableSkill( "Throw Shield" ); break; case ItemPool.PLASTIC_VAMPIRE_FANGS: KoLCharacter.removeAvailableSkill( "Feed" ); break; case ItemPool.LORD_FLAMEFACES_CLOAK: KoLCharacter.removeAvailableSkill( "Swirl Cloak" ); break; case ItemPool.RIGHT_BEAR_ARM: KoLCharacter.removeAvailableSkill( "Kodiak Moment" ); KoLCharacter.removeAvailableSkill( "Grizzly Scene" ); KoLCharacter.removeAvailableSkill( "Bear Hug" ); KoLCharacter.removeAvailableSkill( "I Can Bearly Hear You Over the Applause" ); break; case ItemPool.LEFT_BEAR_ARM: KoLCharacter.removeAvailableSkill( "Bear-Backrub" ); KoLCharacter.removeAvailableSkill( "Bear-ly Legal" ); KoLCharacter.removeAvailableSkill( "Bear Hug" ); KoLCharacter.removeAvailableSkill( "I Can Bearly Hear You Over the Applause" ); break; case ItemPool.ELECTRONIC_DULCIMER_PANTS: KoLCharacter.removeAvailableSkill( "Play Hog Fiddle" ); break; case ItemPool.HAGGIS_SOCKS: KoLCharacter.removeAvailableSkill( "Haggis Kick" ); break; case ItemPool.MARK_V_STEAM_HAT: KoLCharacter.removeAvailableSkill( "Fire Death Ray" ); break; case ItemPool.VIOLENCE_LENS: KoLCharacter.removeAvailableSkill( "Violent Gaze" ); break; case ItemPool.VIOLENCE_BRAND: KoLCharacter.removeAvailableSkill( "Brand" ); break; case ItemPool.VIOLENCE_PANTS: KoLCharacter.removeAvailableSkill( "Mosh" ); break; case ItemPool.VIOLENCE_STOMPERS: KoLCharacter.removeAvailableSkill( "Stomp Ass" ); break; case ItemPool.HATRED_LENS: KoLCharacter.removeAvailableSkill( "Hateful Gaze" ); break; case ItemPool.HATRED_STONE: KoLCharacter.removeAvailableSkill( "Chilling Grip" ); break; case ItemPool.HATRED_PANTS: KoLCharacter.removeAvailableSkill( "Static Shock" ); break; case ItemPool.HATRED_GIRDLE: KoLCharacter.removeAvailableSkill( "Tighten Girdle" ); break; case ItemPool.ANGER_BLASTER: KoLCharacter.removeAvailableSkill( "Rage Flame" ); break; case ItemPool.DOUBT_CANNON: KoLCharacter.removeAvailableSkill( "Doubt Shackles" ); break; case ItemPool.FEAR_CONDENSER: KoLCharacter.removeAvailableSkill( "Fear Vapor" ); break; case ItemPool.REGRET_HOSE: KoLCharacter.removeAvailableSkill( "Tear Wave" ); break; case ItemPool.GREAT_WOLFS_LEFT_PAW: case ItemPool.GREAT_WOLFS_RIGHT_PAW: KoLCharacter.removeAvailableSkill( "Great Slash" ); break; case ItemPool.GREAT_WOLFS_ROCKET_LAUNCHER: KoLCharacter.removeAvailableSkill( "Fire Rocket" ); break; case ItemPool.MAYOR_GHOSTS_GAVEL: KoLCharacter.removeAvailableSkill( "Hammer Ghost" ); break; case ItemPool.PANTSGIVING: KoLCharacter.removeAvailableSkill( "Talk About Politics" ); KoLCharacter.removeAvailableSkill( "Pocket Crumbs" ); KoLCharacter.removeAvailableSkill( "Air Dirty Laundry" ); break; case ItemPool.WARBEAR_OIL_PAN: if ( KoLCharacter.getClassType() == KoLCharacter.SAUCEROR ) { KoLCharacter.removeAvailableSkill( "Spray Hot Grease" ); } break; case ItemPool.WOLF_WHISTLE: KoLCharacter.removeAvailableSkill( "Blow Wolf Whistle" ); break; case ItemPool.TOMMY_GUN: KoLCharacter.removeAvailableSkill( "Unload Tommy Gun" ); break; case ItemPool.CREEPY_VOICE_BOX: KoLCharacter.removeAvailableSkill( "Pull Voice Box String" ); break; case ItemPool.COAL_SHOVEL: KoLCharacter.removeAvailableSkill( "Shovel Hot Coal" ); break; case ItemPool.SPACE_HEATER: KoLCharacter.removeAvailableSkill( "Heat Space" ); break; case ItemPool.CAP_GUN: KoLCharacter.removeAvailableSkill( "Bang! Bang! Bang! Bang!" ); break; case ItemPool.THORS_PLIERS: KoLCharacter.removeAvailableSkill( "Ply Reality" ); break; case ItemPool.CUDDLY_TEDDY_BEAR: KoLCharacter.removeAvailableSkill( "Overload Teddy Bear" ); break; case ItemPool.TOY_CRIMBOT_FACE: KoLCharacter.removeAvailableSkill( "LIGHT" ); break; case ItemPool.TOY_CRIMBOT_GLOVE: KoLCharacter.removeAvailableSkill( "ZAP" ); break; case ItemPool.TOY_CRIMBOT_FIST: KoLCharacter.removeAvailableSkill( "POW" ); break; case ItemPool.TOY_CRIMBOT_LEGS: KoLCharacter.removeAvailableSkill( "BURN" ); break; case ItemPool.RING_OF_TELLING_SKELETONS_WHAT_TO_DO: KoLCharacter.removeAvailableSkill( "Tell a Skeleton What To Do" ); KoLCharacter.removeAvailableSkill( "Tell This Skeleton What To Do" ); break; case ItemPool.SEWAGE_CLOGGED_PISTOL: KoLCharacter.removeAvailableSkill( "Fire Sewage Pistol" ); break; case ItemPool.LOTS_ENGAGEMENT_RING: KoLCharacter.removeAvailableSkill( "Propose To Your Opponent" ); break; case ItemPool.PROTON_ACCELERATOR: KoLCharacter.removeAvailableSkill( "Shoot Ghost" ); KoLCharacter.removeAvailableSkill( "Trap Ghost" ); break; case ItemPool.STANDARDS_AND_PRACTICES: KoLCharacter.removeAvailableSkill( "Censurious Lecture" ); break; } } } // Add skill if appropriate switch ( item.getItemId() ) { case ItemPool.BOTTLE_ROCKET: KoLCharacter.addAvailableSkill( "Fire red bottle-rocket" ); KoLCharacter.addAvailableSkill( "Fire blue bottle-rocket" ); KoLCharacter.addAvailableSkill( "Fire orange bottle-rocket" ); KoLCharacter.addAvailableSkill( "Fire purple bottle-rocket" ); KoLCharacter.addAvailableSkill( "Fire black bottle-rocket" ); break; case ItemPool.JEWEL_EYED_WIZARD_HAT: KoLCharacter.addAvailableSkill( "Magic Missile" ); break; case ItemPool.BAKULA: KoLCharacter.addAvailableSkill( "Give In To Your Vampiric Urges" ); break; case ItemPool.JOYBUZZER: KoLCharacter.addAvailableSkill( "Shake Hands" ); break; case ItemPool.V_MASK: KoLCharacter.addAvailableSkill( "Creepy Grin" ); break; case ItemPool.MAYFLY_BAIT_NECKLACE: KoLCharacter.addAvailableSkill( "Summon Mayfly Swarm" ); break; case ItemPool.HODGMANS_PORKPIE_HAT: case ItemPool.HODGMANS_LOBSTERSKIN_PANTS: case ItemPool.HODGMANS_BOW_TIE: if ( EquipmentManager.isWearingOutfit( OutfitPool.HODGMANS_REGAL_FRIPPERY ) ) { KoLCharacter.addAvailableSkill( "Summon hobo underling" ); } break; case ItemPool.WILLOWY_BONNET: KoLCharacter.addAvailableSkill( "Rouse Sapling" ); break; case ItemPool.SACCHARINE_MAPLE_PENDANT: KoLCharacter.addAvailableSkill( "Spray Sap" ); break; case ItemPool.CROTCHETY_PANTS: KoLCharacter.addAvailableSkill( "Put Down Roots" ); break; case ItemPool.FIREWORKS: KoLCharacter.addAvailableSkill( "Fire off a Roman Candle" ); break; case ItemPool.HAIKU_KATANA: KoLCharacter.addAvailableSkill( "Spring Raindrop Attack" ); KoLCharacter.addAvailableSkill( "Summer Siesta" ); KoLCharacter.addAvailableSkill( "Falling Leaf Whirlwind" ); KoLCharacter.addAvailableSkill( "Winter's Bite Technique" ); KoLCharacter.addAvailableSkill( "The 17 Cuts" ); break; case ItemPool.PARASITIC_CLAW: case ItemPool.PARASITIC_TENTACLES: case ItemPool.PARASITIC_HEADGNAWER: case ItemPool.PARASITIC_STRANGLEWORM: if ( EquipmentManager.isWearingOutfit( OutfitPool.MUTANT_COUTURE ) ) { KoLCharacter.addAvailableSkill( "Disarm" ); KoLCharacter.addAvailableSkill( "Entangle" ); KoLCharacter.addAvailableSkill( "Strangle" ); } break; case ItemPool.ELVISH_SUNGLASSES: KoLCharacter.addAvailableSkill( "Play an Accordion Solo" ); KoLCharacter.addAvailableSkill( "Play a Guitar Solo" ); KoLCharacter.addAvailableSkill( "Play a Drum Solo" ); KoLCharacter.addAvailableSkill( "Play a Flute Solo" ); break; case ItemPool.BAG_O_TRICKS: KoLCharacter.addAvailableSkill( "Open the Bag o' Tricks" ); break; case ItemPool.FOUET_DE_TORTUE_DRESSAGE: KoLCharacter.addAvailableSkill( "Apprivoisez la tortue" ); break; case ItemPool.RED_AND_GREEN_SWEATER: KoLCharacter.addAvailableSkill( "Static Shock" ); break; case ItemPool.STINKY_CHEESE_EYE: KoLCharacter.addAvailableSkill( "Give Your Opponent the Stinkeye" ); break; case ItemPool.SLEDGEHAMMER_OF_THE_VAELKYR: KoLCharacter.addAvailableSkill( "Bashing Slam Smash" ); break; case ItemPool.FLAIL_OF_THE_SEVEN_ASPECTS: KoLCharacter.addAvailableSkill( "Turtle of Seven Tails" ); break; case ItemPool.WRATH_OF_THE_PASTALORDS: KoLCharacter.addAvailableSkill( "Noodles of Fire" ); break; case ItemPool.WINDSOR_PAN_OF_THE_SOURCE: KoLCharacter.addAvailableSkill( "Saucemageddon" ); break; case ItemPool.SEEGERS_BANJO: KoLCharacter.addAvailableSkill( "Funk Bluegrass Fusion" ); break; case ItemPool.TRICKSTER_TRIKITIXA: KoLCharacter.addAvailableSkill( "Extreme High Note" ); break; case ItemPool.BOTTLE_OF_GOLDENSCHNOCKERED: KoLCharacter.addAvailableSkill( "Goldenshöwer" ); break; case ItemPool.SPIDER_RING: KoLCharacter.addAvailableSkill( "Shoot Web" ); break; case ItemPool.STRESS_BALL: KoLCharacter.addAvailableSkill( "Squeeze Stress Ball" ); break; case ItemPool.PATRIOT_SHIELD: KoLCharacter.addAvailableSkill( "Throw Shield" ); break; case ItemPool.PLASTIC_VAMPIRE_FANGS: KoLCharacter.addAvailableSkill( "Feed" ); break; case ItemPool.LORD_FLAMEFACES_CLOAK: KoLCharacter.addAvailableSkill( "Swirl Cloak" ); break; case ItemPool.RIGHT_BEAR_ARM: KoLCharacter.addAvailableSkill( "Kodiak Moment" ); KoLCharacter.addAvailableSkill( "Grizzly Scene" ); if ( KoLCharacter.hasEquipped( ItemPool.get( ItemPool.LEFT_BEAR_ARM, 1 ) ) ) { KoLCharacter.addAvailableSkill( "Bear Hug" ); KoLCharacter.addAvailableSkill( "I Can Bearly Hear You Over the Applause" ); } break; case ItemPool.LEFT_BEAR_ARM: KoLCharacter.addAvailableSkill( "Bear-Backrub" ); KoLCharacter.addAvailableSkill( "Bear-ly Legal" ); if ( KoLCharacter.hasEquipped( ItemPool.get( ItemPool.RIGHT_BEAR_ARM, 1 ) ) ) { KoLCharacter.addAvailableSkill( "Bear Hug" ); KoLCharacter.addAvailableSkill( "I Can Bearly Hear You Over the Applause" ); } break; case ItemPool.ELECTRONIC_DULCIMER_PANTS: KoLCharacter.addAvailableSkill( "Play Hog Fiddle" ); break; case ItemPool.HAGGIS_SOCKS: KoLCharacter.addAvailableSkill( "Haggis Kick" ); break; case ItemPool.MARK_V_STEAM_HAT: KoLCharacter.addAvailableSkill( "Fire Death Ray" ); break; case ItemPool.VIOLENCE_LENS: KoLCharacter.addAvailableSkill( "Violent Gaze" ); break; case ItemPool.VIOLENCE_BRAND: KoLCharacter.addAvailableSkill( "Brand" ); break; case ItemPool.VIOLENCE_PANTS: KoLCharacter.addAvailableSkill( "Mosh" ); break; case ItemPool.VIOLENCE_STOMPERS: KoLCharacter.addAvailableSkill( "Stomp Ass" ); break; case ItemPool.HATRED_LENS: KoLCharacter.addAvailableSkill( "Hateful Gaze" ); break; case ItemPool.HATRED_STONE: KoLCharacter.addAvailableSkill( "Chilling Grip" ); break; case ItemPool.HATRED_PANTS: KoLCharacter.addAvailableSkill( "Static Shock" ); break; case ItemPool.HATRED_GIRDLE: KoLCharacter.addAvailableSkill( "Tighten Girdle" ); break; case ItemPool.ANGER_BLASTER: KoLCharacter.addAvailableSkill( "Rage Flame" ); break; case ItemPool.DOUBT_CANNON: KoLCharacter.addAvailableSkill( "Doubt Shackles" ); break; case ItemPool.FEAR_CONDENSER: KoLCharacter.addAvailableSkill( "Fear Vapor" ); break; case ItemPool.REGRET_HOSE: KoLCharacter.addAvailableSkill( "Tear Wave" ); break; case ItemPool.GREAT_WOLFS_LEFT_PAW: case ItemPool.GREAT_WOLFS_RIGHT_PAW: KoLCharacter.addAvailableSkill( "Great Slash" ); break; case ItemPool.GREAT_WOLFS_ROCKET_LAUNCHER: KoLCharacter.addAvailableSkill( "Fire Rocket" ); break; case ItemPool.MAYOR_GHOSTS_GAVEL: KoLCharacter.addAvailableSkill( "Hammer Ghost" ); break; case ItemPool.PANTSGIVING: KoLCharacter.addAvailableSkill( "Talk About Politics" ); KoLCharacter.addAvailableSkill( "Pocket Crumbs" ); KoLCharacter.addAvailableSkill( "Air Dirty Laundry" ); break; case ItemPool.WARBEAR_OIL_PAN: if ( KoLCharacter.getClassType() == KoLCharacter.SAUCEROR ) { KoLCharacter.addAvailableSkill( "Spray Hot Grease" ); } break; case ItemPool.WOLF_WHISTLE: KoLCharacter.addAvailableSkill( "Blow Wolf Whistle" ); break; case ItemPool.TOMMY_GUN: KoLCharacter.addAvailableSkill( "Unload Tommy Gun" ); break; case ItemPool.CREEPY_VOICE_BOX: KoLCharacter.addAvailableSkill( "Pull Voice Box String" ); break; case ItemPool.COAL_SHOVEL: KoLCharacter.addAvailableSkill( "Shovel Hot Coal" ); break; case ItemPool.SPACE_HEATER: KoLCharacter.addAvailableSkill( "Heat Space" ); break; case ItemPool.CAP_GUN: KoLCharacter.addAvailableSkill( "Bang! Bang! Bang! Bang!" ); break; case ItemPool.THORS_PLIERS: KoLCharacter.addAvailableSkill( "Ply Reality" ); break; case ItemPool.CUDDLY_TEDDY_BEAR: KoLCharacter.addAvailableSkill( "Overload Teddy Bear" ); break; case ItemPool.TOY_CRIMBOT_FACE: KoLCharacter.addAvailableSkill( "LIGHT" ); break; case ItemPool.TOY_CRIMBOT_GLOVE: KoLCharacter.addAvailableSkill( "ZAP" ); break; case ItemPool.TOY_CRIMBOT_FIST: KoLCharacter.addAvailableSkill( "POW" ); break; case ItemPool.TOY_CRIMBOT_LEGS: KoLCharacter.addAvailableSkill( "BURN" ); break; case ItemPool.RING_OF_TELLING_SKELETONS_WHAT_TO_DO: KoLCharacter.addAvailableSkill( "Tell a Skeleton What To Do" ); KoLCharacter.addAvailableSkill( "Tell This Skeleton What To Do" ); break; case ItemPool.SEWAGE_CLOGGED_PISTOL: KoLCharacter.addAvailableSkill( "Fire Sewage Pistol" ); break; case ItemPool.LOTS_ENGAGEMENT_RING: KoLCharacter.addAvailableSkill( "Propose To Your Opponent" ); break; case ItemPool.PROTON_ACCELERATOR: KoLCharacter.addAvailableSkill( "Shoot Ghost" ); KoLCharacter.addAvailableSkill( "Trap Ghost" ); break; case ItemPool.STANDARDS_AND_PRACTICES: KoLCharacter.addAvailableSkill( "Censurious Lecture" ); break; } // If we are either swapping out or in a stinky cheese item, // recalculate stinky cheese level. if ( ItemDatabase.isStinkyCheeseItem( old.getItemId() ) || ItemDatabase.isStinkyCheeseItem( item.getItemId() ) ) { AdventureResult weapon = EquipmentManager.getEquipment( WEAPON ); AdventureResult offhand = EquipmentManager.getEquipment( OFFHAND ); AdventureResult pants = EquipmentManager.getEquipment( PANTS ); AdventureResult acc1 = EquipmentManager.getEquipment( ACCESSORY1 ); AdventureResult acc2 = EquipmentManager.getEquipment( ACCESSORY2 ); AdventureResult acc3 = EquipmentManager.getEquipment( ACCESSORY3 ); AdventureResult fam = EquipmentManager.getEquipment( FAMILIAR ); boolean sword = weapon.getItemId() == ItemPool.STINKY_CHEESE_SWORD || offhand.getItemId() == ItemPool.STINKY_CHEESE_SWORD || fam.getItemId() == ItemPool.STINKY_CHEESE_SWORD; boolean staff = weapon.getItemId() == ItemPool.STINKY_CHEESE_STAFF; boolean diaper = pants.getItemId() == ItemPool.STINKY_CHEESE_DIAPER; boolean wheel = offhand.getItemId() == ItemPool.STINKY_CHEESE_WHEEL; boolean eye = acc1.getItemId() == ItemPool.STINKY_CHEESE_EYE || acc2.getItemId() == ItemPool.STINKY_CHEESE_EYE || acc3.getItemId() == ItemPool.STINKY_CHEESE_EYE; EquipmentManager.stinkyCheeseLevel = ( sword ? 1 : 0 ) + ( staff ? 1 : 0 ) + ( diaper ? 1 : 0 ) + ( wheel ? 1 : 0 ) + ( eye ? 1 : 0 ); } // If Tuxedo Shirt put on or off, and autoTuxedo not set, several booze adventure gains change if ( !Preferences.getBoolean( "autoTuxedo" ) && ( old.getItemId() == ItemPool.TUXEDO_SHIRT || item.getItemId() == ItemPool.TUXEDO_SHIRT ) ) { ConcoctionDatabase.setRefreshNeeded( true ); } } public static final void transformEquipment( AdventureResult before, AdventureResult after ) { SpecialOutfit.replaceEquipment( before, after ); for ( int slot = 0 ; slot <= EquipmentManager.FAMILIAR ; ++slot ) { if ( KoLCharacter.hasEquipped( before, slot ) ) { EquipmentManager.setEquipment( slot, EquipmentRequest.UNEQUIP ); // FamiliarData.setItem moved the current // familiar item to inventory when we // unequipped it above if ( slot != EquipmentManager.FAMILIAR ) { AdventureResult.addResultToList( KoLConstants.inventory, before ); } ResultProcessor.processResult( before.getInstance( -1 ) ); EquipmentManager.setEquipment( slot, after ); return; } } RequestLogger.printLine( "(unable to determine slot of transformed equipment)" ); } public static final int removeEquipment( final int itemId ) { return EquipmentManager.removeEquipment( ItemPool.get( itemId, 1 ) ); } public static final int removeEquipment( final AdventureResult item ) { for ( int slot = 0; slot <= EquipmentManager.FAMILIAR; ++slot ) { if ( EquipmentManager.removeEquipment( item, slot ) ) { return slot; } } return -1; } public static final boolean removeEquipment( final AdventureResult item, final int slot ) { if ( !KoLCharacter.hasEquipped( item, slot ) ) { return false; } EquipmentManager.setEquipment( slot, EquipmentRequest.UNEQUIP ); // FamiliarData.setItem moved the current familiar item to // inventory when we unequipped it above if ( slot != EquipmentManager.FAMILIAR ) { AdventureResult.addResultToList( KoLConstants.inventory, item ); } return true; } public static final void removeAllEquipment() { for ( int slot = 0; slot <= EquipmentManager.FAMILIAR; ++slot ) { AdventureResult item = EquipmentManager.getEquipment( slot ); if ( !item.equals( EquipmentRequest.UNEQUIP ) ) { EquipmentManager.setEquipment( slot, EquipmentRequest.UNEQUIP ); // FamiliarData.setItem moved the current familiar item to // inventory when we unequipped it above if ( slot != EquipmentManager.FAMILIAR ) { AdventureResult.addResultToList( KoLConstants.inventory, item ); } } } } public static final int discardEquipment( final int itemId ) { return EquipmentManager.discardEquipment( itemId, true ); } public static final int discardEquipment( final int itemId, boolean deleteFromCheckpoints ) { return EquipmentManager.discardEquipment( ItemPool.get( itemId, 1 ), deleteFromCheckpoints ); } public static final int discardEquipment( final AdventureResult item ) { return EquipmentManager.discardEquipment( item, true ); } public static final int discardEquipment( final AdventureResult item, boolean deleteFromCheckpoints ) { if ( deleteFromCheckpoints ) { SpecialOutfit.forgetEquipment( item ); } int slot = EquipmentManager.removeEquipment( item ); if ( slot != -1 ) { ResultProcessor.processItem( item.getItemId(), -1 ); } return slot; } public static final void discardSpelunkyEquipment( final int itemId ) { // We only discard Spelunky equipment when we throw it from the offhand slot. // If we kill the monster by doing that and find and autoequip an offhand item // - even the same one - the previous item will be in inventory, not equipped. // Therefore, if the item is in inventory, take it from there. // Otherwise, take it from the offhand slot. AdventureResult item = ItemPool.get( itemId, 1 ); // Remove from saved checkpoint SpecialOutfit.forgetEquipment( item ); // Move from offhand to inventory if necessary if ( InventoryManager.getCount( item ) == 0 && !EquipmentManager.removeEquipment( item, EquipmentManager.OFFHAND ) ) { // Not equipped. How odd. return; } // Discard it from inventory ResultProcessor.processItem( item.getItemId(), -1 ); } public static final void breakEquipment( int itemId, String msg ) { switch ( itemId ) { // Breaking sugar equipment resets sugar counter case ItemPool.SUGAR_CHAPEAU: case ItemPool.SUGAR_SHANK: case ItemPool.SUGAR_SHIELD: case ItemPool.SUGAR_SHILLELAGH: case ItemPool.SUGAR_SHIRT: case ItemPool.SUGAR_SHOTGUN: case ItemPool.SUGAR_SHORTS: Preferences.setInteger( "sugarCounter" + String.valueOf( itemId ), 0 ); break; // Breaking cozy equipment resets cozy counter case ItemPool.COZY_SCIMITAR: case ItemPool.COZY_STAFF: case ItemPool.COZY_BAZOOKA: Preferences.setInteger( "cozyCounter" + String.valueOf( itemId ), 0 ); break; } // Discard the item, but do not clear it from outfit checkpoints yet. int slot = EquipmentManager.discardEquipment( itemId, false ); if ( slot == -1 ) { RequestLogger.printLine( "(unable to determine slot of broken equipment)" ); return; } AdventureResult item = ItemPool.get( itemId, 1 ); int action = Preferences.getInteger( "breakableHandling" + itemId ); if ( action == 0 ) { action = Preferences.getInteger( "breakableHandling" ); } // 1: abort // 2: equip previous // 3: re-equip from inventory, or abort // 4: re-equip from inventory, or previous // 5: acquire & re-equip if ( action >= 5 ) { InventoryManager.retrieveItem( item ); action -= 2; } if ( action >= 3 ) { if ( InventoryManager.hasItem( item ) ) { RequestLogger.printLine( msg ); RequestThread.postRequest( new EquipmentRequest( item, slot ) ); return; } action -= 2; } if ( action <= 1 ) { SpecialOutfit.forgetEquipment( item ); KoLmafia.updateDisplay( MafiaState.PENDING, msg ); return; } ArrayList list = EquipmentManager.historyLists[ slot ]; for ( int i = list.size() - 1; i >= 0; --i ) { AdventureResult prev = (AdventureResult) list.get( i ); if ( prev.equals( EquipmentRequest.UNEQUIP ) || prev.equals( item ) || !InventoryManager.hasItem( prev ) || ( slot == EquipmentManager.FAMILIAR && !KoLCharacter.getFamiliar().canEquip( prev ) ) ) { continue; } SpecialOutfit.replaceEquipment( item, prev ); RequestLogger.printLine( msg ); RequestThread.postRequest( new EquipmentRequest( prev, slot ) ); return; } SpecialOutfit.forgetEquipment( item ); KoLmafia.updateDisplay( msg + " No previous item to equip." ); } public static final void checkFamiliar( final int slot ) { switch ( KoLCharacter.getFamiliar().getId() ) { case FamiliarPool.HATRACK: if ( slot == EquipmentManager.HAT ) { EquipmentManager.updateEquipmentList( EquipmentManager.FAMILIAR ); } else if ( slot == EquipmentManager.FAMILIAR ) { EquipmentManager.updateEquipmentList( EquipmentManager.HAT ); } break; case FamiliarPool.HAND: if ( slot == EquipmentManager.WEAPON || slot == EquipmentManager.OFFHAND ) { EquipmentManager.updateEquipmentList( EquipmentManager.FAMILIAR ); } else if ( slot == EquipmentManager.FAMILIAR ) { EquipmentManager.updateEquipmentList( EquipmentManager.WEAPON ); EquipmentManager.updateEquipmentList( EquipmentManager.OFFHAND ); } break; case FamiliarPool.SCARECROW: if ( slot == EquipmentManager.PANTS ) { EquipmentManager.updateEquipmentList( EquipmentManager.FAMILIAR ); } else if ( slot == EquipmentManager.FAMILIAR ) { EquipmentManager.updateEquipmentList( EquipmentManager.PANTS ); } break; } } /** * Accessor method to set the equipment the character is currently * using. This does not take into account the power of the item or * anything of that nature; only the item's name is stored. Note that * if no item is equipped, the value should be <code>none</code>, not * <code>null</code> or the empty string. * * @param equipment All of the available equipment, stored in an array * index by the constants */ public static final void setEquipment( final AdventureResult[] equipment ) { // Sanity check: must set ALL equipment slots if ( equipment.length < EquipmentManager.SLOTS ) { StaticEntity.printStackTrace( "Equipment array slot mismatch: " + EquipmentManager.SLOTS + " expected, " + equipment.length + " provided." ); return; } for ( int i = 0; i < EquipmentManager.ALL_SLOTS && i < equipment.length; ++i ) { if ( equipment[ i ] == null ) { continue; } else if ( equipment[ i ].equals( EquipmentRequest.UNEQUIP ) ) { setEquipment( i, EquipmentRequest.UNEQUIP ); } else { setEquipment( i, equipment[ i ] ); } } } public static final void setCustomOutfits( final List<SpecialOutfit> newOutfits ) { // Rebuild outfits if given a new list if ( newOutfits != null ) { EquipmentManager.customOutfits.clear(); EquipmentManager.customOutfits.add( SpecialOutfit.NO_CHANGE ); EquipmentManager.customOutfits.addAll( newOutfits ); } } public static final boolean isDualWielding() { AdventureResult mainhand = EquipmentManager.equipment.get( EquipmentManager.WEAPON ); AdventureResult offhand = EquipmentManager.equipment.get( EquipmentManager.OFFHAND ); return !mainhand.equals( EquipmentRequest.UNEQUIP ) && ItemDatabase.getConsumptionType( offhand ) == KoLConstants.EQUIP_WEAPON; } /** * Accessor method to retrieve the name of the item equipped on the * character's familiar. * * @return The name of the item equipped on the character's familiar, * <code>none</code> if no such item exists */ public static final AdventureResult getFamiliarItem() { return KoLCharacter.currentFamiliar == null ? EquipmentRequest.UNEQUIP : KoLCharacter.currentFamiliar.getItem(); } public static final AdventureResult lockedFamiliarItem() { return EquipmentManager.lockedFamiliarItem; } public static final boolean familiarItemLockable() { return FamiliarData.lockableItem( EquipmentManager.getFamiliarItem() ); } public static final boolean familiarItemLocked() { return EquipmentManager.lockedFamiliarItem != EquipmentRequest.UNEQUIP; } public static final void lockFamiliarItem() { EquipmentManager.lockFamiliarItem( EquipmentManager.familiarItemLocked() && EquipmentManager.familiarItemLockable() ); } public static final void lockFamiliarItem( boolean lock ) { EquipmentManager.lockFamiliarItem( lock ? EquipmentManager.getFamiliarItem() : EquipmentRequest.UNEQUIP ); } public static final void lockFamiliarItem( AdventureResult item ) { if ( EquipmentManager.lockedFamiliarItem != item ) { EquipmentManager.lockedFamiliarItem = item; NamedListenerRegistry.fireChange( "(familiarLock)" ); } } public static final int getFakeHands() { return EquipmentManager.fakeHandCount; } public static final void setFakeHands( final int hands ) { if ( EquipmentManager.fakeHandCount != hands ) { EquipmentManager.fakeHandCount = hands; NamedListenerRegistry.fireChange( "(fakehands)" ); } } public static final int getStinkyCheeseLevel() { return EquipmentManager.stinkyCheeseLevel; } /** * Accessor method to retrieve the name of a piece of equipment * * @param type the type of equipment * @return The name of the equipment, <code>none</code> if no such item exists */ public static final AdventureResult getEquipment( final int type ) { if ( type == EquipmentManager.FAMILIAR ) { return getFamiliarItem(); } if ( type >= 0 && type < equipment.size() ) { return (AdventureResult) equipment.get( type ); } return EquipmentRequest.UNEQUIP; } public static final int getTurns( int slot ) { return EquipmentManager.turnsRemaining[ slot - EquipmentManager.STICKER1 ]; } public static final void setTurns( int slot, int minTurns, int maxTurns ) { int curr = EquipmentManager.turnsRemaining[ slot - EquipmentManager.STICKER1 ]; if ( curr > maxTurns ) { curr = maxTurns; } if ( curr < minTurns ) { curr = minTurns; } EquipmentManager.turnsRemaining[ slot - EquipmentManager.STICKER1 ] = curr; GearChangeFrame.updateStickers( EquipmentManager.turnsRemaining[ 0 ], EquipmentManager.turnsRemaining[ 1 ], EquipmentManager.turnsRemaining[ 2 ] ); } public static final boolean isStickerWeapon( AdventureResult item ) { return item != null && isStickerWeapon( item.getItemId() ); } public static final boolean isStickerWeapon( int itemId ) { return itemId == ItemPool.STICKER_SWORD || itemId == ItemPool.STICKER_CROSSBOW; } public static final boolean usingStickerWeapon() { return isStickerWeapon( getEquipment( EquipmentManager.WEAPON ) ) || isStickerWeapon( getEquipment( EquipmentManager.OFFHAND ) ) || isStickerWeapon( getEquipment( EquipmentManager.FAMILIAR ) ); } public static final boolean usingStickerWeapon( AdventureResult[] equipment ) { return isStickerWeapon( equipment[ EquipmentManager.WEAPON ] ) || isStickerWeapon( equipment[ EquipmentManager.OFFHAND ] ) || isStickerWeapon( equipment[ EquipmentManager.FAMILIAR ] ); } public static final boolean hasStickerWeapon() { return EquipmentManager.usingStickerWeapon() || InventoryManager.hasItem( ItemPool.STICKER_SWORD ) || InventoryManager.hasItem( ItemPool.STICKER_CROSSBOW ); } public static final void incrementEquipmentCounters() { for ( int i = 0; i < EquipmentManager.SLOTS; ++i ) { int itemId = EquipmentManager.getEquipment( i ).getItemId(); switch ( itemId ) { case ItemPool.SUGAR_CHAPEAU: case ItemPool.SUGAR_SHANK: case ItemPool.SUGAR_SHIELD: case ItemPool.SUGAR_SHILLELAGH: case ItemPool.SUGAR_SHIRT: case ItemPool.SUGAR_SHOTGUN: case ItemPool.SUGAR_SHORTS: Preferences.increment( "sugarCounter" + String.valueOf( itemId ), 1 ); break; case ItemPool.COZY_SCIMITAR: case ItemPool.COZY_STAFF: case ItemPool.COZY_BAZOOKA: Preferences.increment( "cozyCounter" + String.valueOf( itemId ), 1 ); break; } } } public static final void decrementTurns() { if ( usingStickerWeapon() ) { GearChangeFrame.updateStickers( --EquipmentManager.turnsRemaining[ 0 ], --EquipmentManager.turnsRemaining[ 1 ], --EquipmentManager.turnsRemaining[ 2 ] ); } EquipmentManager.incrementEquipmentCounters(); } public static final void stickersExpired( int count ) { for ( int i = 0; i < 3; ++i ) { if ( EquipmentManager.turnsRemaining[ i ] <= 0 && getEquipment( EquipmentManager.STICKER1 + i ) != EquipmentRequest.UNEQUIP ) { setEquipment( EquipmentManager.STICKER1 + i, EquipmentRequest.UNEQUIP ); --count; } } if ( count != 0 ) // we've lost count somewhere, refresh { RequestThread.postRequest( new EquipmentRequest( EquipmentRequest.BEDAZZLEMENTS ) ); } } /** * Accessor method to retrieve a list of all available items which can be equipped by familiars. Note this lists * items which the current familiar cannot equip. */ public static final List<AdventureResult>[] getEquipmentLists() { return EquipmentManager.equipmentLists; } public static final void updateEquipmentList( final int listIndex ) { int consumeFilter = EquipmentManager.equipmentTypeToConsumeFilter( listIndex ); if ( consumeFilter == -1 ) { return; } AdventureResult equippedItem = EquipmentManager.getEquipment( listIndex ); switch ( listIndex ) { case EquipmentManager.ACCESSORY1: case EquipmentManager.ACCESSORY2: return; // do all the work when updating ACC3 case EquipmentManager.ACCESSORY3: EquipmentManager.updateEquipmentList( consumeFilter, EquipmentManager.accessories ); AdventureResult accessory = EquipmentManager.getEquipment( EquipmentManager.ACCESSORY1 ); if ( accessory != EquipmentRequest.UNEQUIP ) { AdventureResult.addResultToList( EquipmentManager.accessories, accessory ); } accessory = EquipmentManager.getEquipment( EquipmentManager.ACCESSORY2 ); if ( accessory != EquipmentRequest.UNEQUIP ) { AdventureResult.addResultToList( EquipmentManager.accessories, accessory ); } accessory = EquipmentManager.getEquipment( EquipmentManager.ACCESSORY3 ); if ( accessory != EquipmentRequest.UNEQUIP ) { AdventureResult.addResultToList( EquipmentManager.accessories, accessory ); } break; case EquipmentManager.FAMILIAR: // If we are looking at familiar items, include those // which can be universally equipped, but are currently // on another familiar. EquipmentManager.updateEquipmentList( consumeFilter, EquipmentManager.equipmentLists[ EquipmentManager.FAMILIAR ] ); FamiliarData[] familiarList = new FamiliarData[ KoLCharacter.familiars.size() ]; KoLCharacter.familiars.toArray( familiarList ); FamiliarData currentFamiliar = KoLCharacter.getFamiliar(); for ( int i = 0; i < familiarList.length; ++i ) { AdventureResult currentItem = familiarList[ i ].getItem(); if ( currentItem != EquipmentRequest.UNEQUIP && currentFamiliar.canEquip( currentItem ) ) { AdventureResult.addResultToList( EquipmentManager.equipmentLists[ EquipmentManager.FAMILIAR ], currentItem ); } } break; default: EquipmentManager.updateEquipmentList( consumeFilter, EquipmentManager.equipmentLists[ listIndex ] ); if ( !EquipmentManager.equipmentLists[ listIndex ].contains( equippedItem ) ) { EquipmentManager.equipmentLists[ listIndex ].add( equippedItem ); } break; } LockableListFactory.setSelectedItem( EquipmentManager.equipmentLists[ listIndex ], equippedItem ); } private static final void updateEquipmentList( final int filterId, final List<AdventureResult> currentList ) { ArrayList<AdventureResult> temporary = new ArrayList<AdventureResult>(); temporary.add( EquipmentRequest.UNEQUIP ); // If the character is currently equipped with a one-handed // weapon and the character has the ability to dual-wield // weapons, then also allow one-handed weapons in the off-hand. boolean dual = getWeaponHandedness() == 1 && KoLCharacter.hasSkill( "Double-Fisted Skull Smashing" ); WeaponType weaponType = EquipmentManager.getWeaponType(); FamiliarData currentFamiliar = KoLCharacter.getFamiliar(); for ( int i = 0; i < KoLConstants.inventory.size(); ++i ) { AdventureResult currentItem = (AdventureResult) KoLConstants.inventory.get( i ); String currentItemName = currentItem.getName(); int itemId = currentItem.getItemId(); int type = ItemDatabase.getConsumptionType( itemId ); // If we want off-hand items and we can dual wield, // allow one-handed weapons of same type if ( filterId == KoLConstants.EQUIP_OFFHAND && type == KoLConstants.EQUIP_WEAPON && dual ) { if ( EquipmentDatabase.isMainhandOnly( itemId ) || EquipmentDatabase.getWeaponType( itemId ) != weaponType ) { continue; } } // If we are equipping familiar items, make sure // current familiar can use this one else if ( filterId == KoLConstants.EQUIP_FAMILIAR ) { if ( currentFamiliar.canEquip( currentItem ) ) { temporary.add( currentItem.getInstance( 1 ) ); } continue; } // Otherwise, slot and item type must match else if ( filterId != type ) { continue; } else if ( filterId == KoLConstants.EQUIP_WEAPON && dual ) { if ( EquipmentDatabase.getHands( itemId ) == 1 && EquipmentDatabase.getWeaponType( itemId ) != weaponType ) { continue; } } temporary.add( currentItem ); } currentList.retainAll( temporary ); temporary.removeAll( currentList ); currentList.addAll( temporary ); } /** * Accessor method to retrieve a list of the custom outfits available to this character, based on the last time the * equipment screen was requested. * * @return A <code>List</code> of the available outfits */ public static final List<SpecialOutfit> getCustomOutfits() { return EquipmentManager.customOutfits; } public static SpecialOutfit getCustomOutfit( int id ) { for ( SpecialOutfit outfit : EquipmentManager.customOutfits ) { if ( outfit.getOutfitId() == id ) { return outfit; } } return null; } public static SpecialOutfit getCustomOutfit( String name ) { for ( SpecialOutfit outfit : EquipmentManager.customOutfits ) { if ( outfit.getName().equals( name ) ) { return outfit; } } return null; } /** * Accessor method to add or replace a custom outfit in the list of * custom outfits available to this character */ public static void addCustomOutfit( SpecialOutfit outfit ) { List<SpecialOutfit> newOutfits = LockableListFactory.getSortedInstance( SpecialOutfit.class ); String name = outfit.getName(); for ( SpecialOutfit current : EquipmentManager.customOutfits ) { if ( current == SpecialOutfit.NO_CHANGE ) { continue; } if ( !current.getName().equals( name ) ) { newOutfits.add( current ); } } newOutfits.add( outfit ); SpecialOutfit.checkImplicitOutfit( outfit ); EquipmentManager.setCustomOutfits( newOutfits ); } /** * Accessor method to retrieve a list of the all the outfits available to this character, based on the last time the * equipment screen was requested. * * @return A <code>List</code> of the available outfits */ public static final List<SpecialOutfit> getOutfits() { return EquipmentManager.normalOutfits; } public static final void updateEquipmentLists() { KoLCharacter.resetTriggers(); for ( int i = 0; i < EquipmentManager.ALL_SLOTS; ++i ) { EquipmentManager.updateEquipmentList( i ); } EquipmentManager.updateNormalOutfits(); } public static final int equipmentTypeToConsumeFilter( final int equipmentType ) { switch ( equipmentType ) { case EquipmentManager.HAT: return KoLConstants.EQUIP_HAT; case EquipmentManager.WEAPON: return KoLConstants.EQUIP_WEAPON; case EquipmentManager.OFFHAND: return KoLConstants.EQUIP_OFFHAND; case EquipmentManager.SHIRT: return KoLConstants.EQUIP_SHIRT; case EquipmentManager.PANTS: return KoLConstants.EQUIP_PANTS; case EquipmentManager.CONTAINER: return KoLConstants.EQUIP_CONTAINER; case EquipmentManager.ACCESSORY1: case EquipmentManager.ACCESSORY2: case EquipmentManager.ACCESSORY3: return KoLConstants.EQUIP_ACCESSORY; case EquipmentManager.FAMILIAR: return KoLConstants.EQUIP_FAMILIAR; case EquipmentManager.STICKER1: case EquipmentManager.STICKER2: case EquipmentManager.STICKER3: return KoLConstants.CONSUME_STICKER; case EquipmentManager.CARDSLEEVE: return KoLConstants.CONSUME_CARD; case EquipmentManager.FOLDER1: case EquipmentManager.FOLDER2: case EquipmentManager.FOLDER3: case EquipmentManager.FOLDER4: case EquipmentManager.FOLDER5: return KoLConstants.CONSUME_FOLDER; case EquipmentManager.BOOTSKIN: return KoLConstants.CONSUME_BOOTSKIN; case EquipmentManager.BOOTSPUR: return KoLConstants.CONSUME_BOOTSPUR; case EquipmentManager.HOLSTER: return KoLConstants.CONSUME_SIXGUN; default: return -1; } } public static final int consumeFilterToEquipmentType( final int consumeFilter ) { switch ( consumeFilter ) { case KoLConstants.EQUIP_HAT: return EquipmentManager.HAT; case KoLConstants.EQUIP_WEAPON: return EquipmentManager.WEAPON; case KoLConstants.EQUIP_OFFHAND: return EquipmentManager.OFFHAND; case KoLConstants.EQUIP_SHIRT: return EquipmentManager.SHIRT; case KoLConstants.EQUIP_PANTS: return EquipmentManager.PANTS; case KoLConstants.EQUIP_CONTAINER: return EquipmentManager.CONTAINER; case KoLConstants.EQUIP_ACCESSORY: return EquipmentManager.ACCESSORY1; case KoLConstants.EQUIP_FAMILIAR: return EquipmentManager.FAMILIAR; case KoLConstants.CONSUME_STICKER: return EquipmentManager.STICKER1; case KoLConstants.CONSUME_CARD: return EquipmentManager.CARDSLEEVE; case KoLConstants.CONSUME_FOLDER: return EquipmentManager.FOLDER1; case KoLConstants.CONSUME_BOOTSKIN: return EquipmentManager.BOOTSKIN; case KoLConstants.CONSUME_BOOTSPUR: return EquipmentManager.BOOTSPUR; case KoLConstants.CONSUME_SIXGUN: return EquipmentManager.HOLSTER; default: return -1; } } public static final int itemIdToEquipmentType( final int itemId ) { return EquipmentManager.consumeFilterToEquipmentType( ItemDatabase.getConsumptionType( itemId ) ); } /** * Accessor method to retrieve # of hands character's weapon uses * * @return int number of hands needed */ public static final int getWeaponHandedness() { return EquipmentDatabase.getHands( EquipmentManager.getEquipment( EquipmentManager.WEAPON ).getItemId() ); } /** * Accessor method to determine if character is currently dual-wielding * * @return boolean true if character has two weapons equipped */ public static final boolean usingTwoWeapons() { return EquipmentDatabase.getHands( EquipmentManager.getEquipment( EquipmentManager.OFFHAND ).getItemId() ) == 1; } /** * Accessor method to determine if character's weapon is a chefstaff * * @return boolean true if weapon is a chefstaff */ public static final boolean usingChefstaff() { return EquipmentDatabase.isChefStaff( EquipmentManager.getEquipment( EquipmentManager.WEAPON ) ); } /** * Accessor method to determine if character's off-hand is a bean can * * @return boolean true if off-hand is a bean can */ public static final boolean usingCanOfBeans() { return EquipmentDatabase.isCanOfBeans( EquipmentManager.getEquipment( EquipmentManager.OFFHAND ) ); } /** * Accessor method to determine if character has a sixgun holstered * * @return boolean true if off-hand is a bean can */ public static final boolean holsteredSixgun() { return EquipmentManager.getEquipment( EquipmentManager.HOLSTER ) != EquipmentRequest.UNEQUIP; } /** * Accessor method to determine if character's weapon's is a club * * @return boolean true if weapon is a club */ public static final boolean wieldingClub() { return EquipmentManager.wieldingClub( true ); } /** * Here's a version which allows you to include or exclude the Iron Palm * effect for the purpose of determining whether a sword counts as a * club. Mother Hellseals require an actual club... */ public static final AdventureResult IRON_PALMS = EffectPool.get( EffectPool.IRON_PALMS ); public static final boolean wieldingClub( final boolean includeEffect ) { String type = EquipmentDatabase.getItemType( EquipmentManager.getEquipment( EquipmentManager.WEAPON ).getItemId() ); return type.equals( "club" ) || ( includeEffect && KoLConstants.activeEffects.contains( EquipmentManager.IRON_PALMS ) && type.equals( "sword" ) ); } public static final boolean wieldingKnife() { String type = EquipmentDatabase.getItemType( EquipmentManager.getEquipment( EquipmentManager.WEAPON ).getItemId() ); return type.equals( "knife" ); } public static final boolean wieldingAccordion() { String type = EquipmentDatabase.getItemType( EquipmentManager.getEquipment( EquipmentManager.WEAPON ).getItemId() ); return type.equals( "accordion" ); } /** * Accessor method to determine if character is currently using a shield * * @return boolean true if character has a shield equipped */ public static final boolean usingShield() { return EquipmentDatabase.getItemType( EquipmentManager.getEquipment( OFFHAND ).getItemId() ).equals( "shield" ); } /** * Accessor method to determine what type of weapon the character is * wielding. * * @return int MELEE or RANGED */ public static final WeaponType getWeaponType() { return EquipmentDatabase.getWeaponType( EquipmentManager.getEquipment( EquipmentManager.WEAPON ).getItemId() ); } /** * Accessor method to determine which stat determines the character's * chance to hit. * * @return int MOXIE or MUSCLE */ public static final Stat getHitStatType() { switch ( EquipmentManager.getWeaponType() ) { case RANGED: return Stat.MOXIE; default: if ( KoLCharacter.getAdjustedMoxie() >= KoLCharacter.getAdjustedMuscle() && EquipmentManager.wieldingKnife() && KoLCharacter.hasSkill( "Tricky Knifework" ) ) { return Stat.MOXIE; } return Stat.MUSCLE; } } /** * Accessor method to determine character's adjusted hit stat * * @return int adjusted muscle, mysticality, or moxie */ public static final int getAdjustedHitStat() { int hitStat; switch ( getHitStatType() ) { default: case MUSCLE: if ( KoLCharacter.currentBooleanModifier( Modifiers.ATTACKS_CANT_MISS ) ) { return Integer.MAX_VALUE; } hitStat = KoLCharacter.getAdjustedMuscle(); if ( Modifiers.unarmed && KoLCharacter.hasSkill( "Master of the Surprising Fist" ) ) { hitStat += 20; } return hitStat; case MYSTICALITY: return KoLCharacter.getAdjustedMysticality(); case MOXIE: hitStat = KoLCharacter.getAdjustedMoxie(); if ( EquipmentManager.wieldingAccordion() && KoLCharacter.hasSkill( "Crab Claw Technique" ) ) { hitStat += 50; } return hitStat; } } public static final boolean hasOutfit( final int id ) { return EquipmentManager.normalOutfits.contains( EquipmentDatabase.normalOutfits.get( id ) ); } public static final void updateNormalOutfits() { ArrayList<SpecialOutfit> available = new ArrayList<SpecialOutfit>(); for ( SpecialOutfit outfit : EquipmentDatabase.normalOutfits ) { if ( outfit != null && outfit.hasAllPieces() ) { available.add( outfit ); } } for ( SpecialOutfit outfit : EquipmentDatabase.weirdOutfits ) { if ( outfit != null && outfit.hasAllPieces() ) { available.add( outfit ); } } Collections.sort( available ); EquipmentManager.normalOutfits.clear(); // Start with the three constant outfits EquipmentManager.normalOutfits.add( SpecialOutfit.NO_CHANGE ); EquipmentManager.normalOutfits.add( SpecialOutfit.BIRTHDAY_SUIT ); EquipmentManager.normalOutfits.add( SpecialOutfit.PREVIOUS_OUTFIT ); // Finally any standard outfits EquipmentManager.normalOutfits.addAll( available ); // We may have gotten the war hippy or frat outfits NamedListenerRegistry.fireChange( "(outfit)" ); } /** * Utility method which determines whether or not the equipment corresponding to the given outfit is already * equipped. */ public static final boolean isWearingOutfit( final int outfitId ) { if ( outfitId < 0 ) { return true; } if ( outfitId == 0 ) { return false; } return EquipmentManager.isWearingOutfit( EquipmentDatabase.normalOutfits.get( outfitId ) ); } /** * Utility method which determines whether or not the equipment * corresponding to the given outfit is already equipped. */ public static final boolean isWearingOutfit( final SpecialOutfit outfit ) { return outfit != null && outfit.isWearing(); } public static final boolean retrieveOutfit( final SpecialOutfit outfit ) { return outfit != null && outfit.retrieve(); } public static final boolean addOutfitConditions( final KoLAdventure adventure ) { int outfitId = EquipmentDatabase.getOutfitId( adventure ); if ( outfitId <= 0 ) { return false; } EquipmentManager.addOutfitConditions( outfitId ); return true; } public static final void addOutfitConditions( final int outfitId ) { // Ignore custom outfits, since there's // no way to know what they are (yet). if ( outfitId < 0 ) { return; } AdventureResult[] pieces = EquipmentDatabase.normalOutfits.get( outfitId ).getPieces(); for ( int i = 0; i < pieces.length; ++i ) { if ( !KoLCharacter.hasEquipped( pieces[ i ] ) ) { ConditionsCommand.update( "set", pieces[ i ].getName() ); } } } /** * Utility method which determines the outfit ID the character is * currently wearing */ public static final SpecialOutfit currentOutfit() { for ( SpecialOutfit outfit : EquipmentDatabase.normalOutfits ) { if ( outfit == null ) { continue; } if ( outfit.isWearing() ) { return outfit; } } return null; } public static final SpecialOutfit currentOutfit( AdventureResult[] equipment ) { int hash = SpecialOutfit.equipmentHash( equipment ); for ( SpecialOutfit outfit : EquipmentDatabase.normalOutfits ) { if ( outfit == null ) { continue; } if ( outfit.isWearing( equipment, hash ) ) { return outfit; } } return null; } public static final boolean canEquip( final AdventureResult item ) { return EquipmentManager.canEquip( item.getItemId() ); } public static final boolean canEquip( final String itemName ) { return EquipmentManager.canEquip( ItemDatabase.getItemId( itemName ) ); } public static final boolean canEquip( final int itemId ) { if ( itemId == -1 ) { return false; } int type = ItemDatabase.getConsumptionType( itemId ); if ( type == KoLConstants.CONSUME_SIXGUN ) { return KoLCharacter.isAWoLClass(); } if ( type == KoLConstants.EQUIP_SHIRT && !KoLCharacter.isTorsoAware() ) { return false; } if ( type == KoLConstants.EQUIP_FAMILIAR ) { return KoLCharacter.getFamiliar().canEquip( ItemPool.get( itemId, 1 ) ); } if ( KoLCharacter.inFistcore() && ( type == KoLConstants.EQUIP_WEAPON || type == KoLConstants.EQUIP_OFFHAND ) ) { return false; } if ( KoLCharacter.inAxecore() && ( type == KoLConstants.EQUIP_WEAPON || type == KoLConstants.EQUIP_OFFHAND ) ) { return itemId == ItemPool.TRUSTY; } if ( KoLCharacter.isHardcore() ) { Modifiers mods = Modifiers.getItemModifiers( itemId ); if ( mods != null && mods.getBoolean( Modifiers.SOFTCORE ) ) { return false; } } if ( KoLCharacter.getClassType() != KoLCharacter.ACCORDION_THIEF && EquipmentDatabase.isSpecialAccordion( itemId ) ) { return false; } String requirement = EquipmentDatabase.getEquipRequirement( itemId ); int req; if ( requirement.startsWith( "Mus:" ) ) { req = StringUtilities.parseInt( requirement.substring( 5 ) ); return KoLCharacter.getBaseMuscle() >= req || KoLCharacter.muscleTrigger( req, itemId ); } if ( requirement.startsWith( "Mys:" ) ) { req = StringUtilities.parseInt( requirement.substring( 5 ) ); return KoLCharacter.getBaseMysticality() >= req || KoLCharacter.mysticalityTrigger( req, itemId ); } if ( requirement.startsWith( "Mox:" ) ) { req = StringUtilities.parseInt( requirement.substring( 5 ) ); return KoLCharacter.getBaseMoxie() >= req || KoLCharacter.moxieTrigger( req, itemId ); } return true; } public static final SpecialOutfit getMatchingOutfit( final String name ) { String lowercaseName = name.toLowerCase().trim(); if ( lowercaseName.equals( "birthday suit" ) || lowercaseName.equals( "nothing" ) ) { return SpecialOutfit.BIRTHDAY_SUIT; } if ( lowercaseName.equals( "last" ) ) { return SpecialOutfit.PREVIOUS_OUTFIT; } // Check for exact matches. for ( SpecialOutfit outfit : EquipmentManager.customOutfits ) { if ( outfit == SpecialOutfit.NO_CHANGE ) { continue; } if ( lowercaseName.equals( outfit.toString().toLowerCase() ) ) { return outfit; } } for ( SpecialOutfit outfit : EquipmentDatabase.normalOutfits ) { if ( outfit == null ) { continue; } if ( lowercaseName.equals( outfit.toString().toLowerCase() ) ) { return outfit; } } // Check for substring matches. for ( SpecialOutfit outfit : EquipmentManager.customOutfits ) { if ( outfit == SpecialOutfit.NO_CHANGE ) { continue; } if ( outfit.toString().toLowerCase().contains( lowercaseName ) ) { return outfit; } } for ( SpecialOutfit outfit : EquipmentDatabase.normalOutfits ) { if ( outfit == null ) { continue; } if ( outfit.toString().toLowerCase().contains( lowercaseName ) ) { return outfit; } } return null; } public static AdventureResult equippedItem( final int itemId ) { if ( itemId == 0 ) { return EquipmentRequest.UNEQUIP; } String name = ItemDatabase.getItemDataName( itemId ); if ( name == null ) { // Fetch descid from api.php?what=item // and register new item. ItemDatabase.registerItem( itemId ); } return ItemPool.get( itemId, 1 ); } public static final void parseStatus( final JSONObject JSON ) throws JSONException { // "equipment":{ // "hat":"1323", // "shirt":"2586", // "pants":"1324", // "weapon":"1325", // "offhand":"1325", // "acc1":"3337", // "acc2":"1232", // "acc3":"1226", // "container":"482", // "familiarequip":"3343", // "fakehands":0, // "card sleeve":"4968" // }, // "stickers":[0,0,0], // "folder_holder":["01","22","12","00","00"] AdventureResult[] current = EquipmentManager.allEquipment(); AdventureResult[] equipment = EquipmentManager.emptyEquipmentArray( true ); int fakeHands = 0; JSONObject equip = JSON.getJSONObject( "equipment" ); Iterator keys = equip.keys(); while ( keys.hasNext() ) { String slotName = (String) keys.next(); if ( slotName.equals( "fakehands" ) ) { fakeHands = equip.getInt( slotName ); continue; } int slot = EquipmentRequest.phpSlotNumber( slotName ); if ( slot == -1 ) { continue; } equipment[ slot ] = EquipmentManager.equippedItem( equip.getInt( slotName ) ); } // Read stickers JSONArray stickers = JSON.getJSONArray( "stickers" ); for ( int i = 0; i < 3; ++i ) { AdventureResult item = EquipmentManager.equippedItem( stickers.getInt( i ) ); equipment[ EquipmentManager.STICKER1 + i ] = item; } // Read folders JSONArray folders = JSON.getJSONArray( "folder_holder" ); for ( int i = 0; i < 5; ++i ) { int folder = folders.getInt( i ); AdventureResult item = folder == 0 ? EquipmentRequest.UNEQUIP : ItemPool.get( ItemPool.FOLDER_01 - 1 + folder, 1 ); equipment[ EquipmentManager.FOLDER1 + i ] = item; } // We can't read these from api.php (yet?) equipment[ EquipmentManager.CROWNOFTHRONES ] = current[ EquipmentManager.CROWNOFTHRONES ]; equipment[ EquipmentManager.BUDDYBJORN ] = current[ EquipmentManager.BUDDYBJORN ]; equipment[ EquipmentManager.BOOTSKIN ] = current[ EquipmentManager.BOOTSKIN ]; equipment[ EquipmentManager.BOOTSPUR ] = current[ EquipmentManager.BOOTSPUR ]; equipment[ EquipmentManager.HOLSTER ] = current[ EquipmentManager.HOLSTER ]; // For debug purposes, print wherever KoLmafia's model differs // from KoL's model. if ( !KoLmafia.isRefreshing() ) { for ( int i = 0; i < EquipmentManager.ALL_SLOTS; ++i ) { if ( !current[ i ].equals( equipment[ i ] ) ) { String slotName = EquipmentRequest.slotNames[ i ]; String message = "*** slot " + slotName + ": KoL has " + equipment[ i ] + " but KoLmafia has " + current[ i ]; RequestLogger.printLine( message ); RequestLogger.updateSessionLog( message ); } } } // Shuffle inventory and load up KoL's model of equipment EquipmentRequest.switchEquipment( current, equipment ); // *** Locked familiar item // Fake hands must be handled separately EquipmentManager.setFakeHands( fakeHands ); } }