/**
* 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.request;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.sourceforge.kolmafia.AdventureResult;
import net.sourceforge.kolmafia.FamiliarData;
import net.sourceforge.kolmafia.KoLCharacter;
import net.sourceforge.kolmafia.KoLConstants;
import net.sourceforge.kolmafia.KoLConstants.MafiaState;
import net.sourceforge.kolmafia.KoLmafia;
import net.sourceforge.kolmafia.KoLmafiaCLI;
import net.sourceforge.kolmafia.RequestLogger;
import net.sourceforge.kolmafia.RequestThread;
import net.sourceforge.kolmafia.SpecialOutfit;
import net.sourceforge.kolmafia.objectpool.ItemPool;
import net.sourceforge.kolmafia.persistence.ConcoctionDatabase;
import net.sourceforge.kolmafia.persistence.DebugDatabase;
import net.sourceforge.kolmafia.persistence.EquipmentDatabase;
import net.sourceforge.kolmafia.persistence.ItemDatabase;
import net.sourceforge.kolmafia.session.EquipmentManager;
import net.sourceforge.kolmafia.session.InventoryManager;
import net.sourceforge.kolmafia.session.QuestManager;
import net.sourceforge.kolmafia.session.ResultProcessor;
import net.sourceforge.kolmafia.utilities.StringUtilities;
public class EquipmentRequest
extends PasswordHashRequest
{
private static final Pattern CELL_PATTERN = Pattern.compile( "<td>(.*?)</td>" );
// With images:
//
// <table class='item' id="ic653" rel="id=653&s=0&q=1&d=0&g=0&t=0&n=1&m=0&u=."><td class="img"><img src="http://images.kingdomofloathing.com/itemimages/airboat.gif" class="hand ircm" onClick='descitem(126122919,0, event);'></td><td id='i653' valign=top><b class="ircm">intragalactic rowboat</b> <span></span><font size=1><br></font></td></table>
//
// Without images:
//
// <table class='item' id="ic653" rel="id=653&s=0&q=1&d=0&g=0&t=0&n=1&m=0&u=."><td id='i653' valign=top><b class="ircm"><a onClick='javascript:descitem(126122919,0, event);'>intragalactic rowboat</a></b> <span></span><font size=1><br></font></td></table>
private static final Pattern HAT_PATTERN =
Pattern.compile( "Hat</a>:</td>(<td><img[^']*'descitem\\(([\\d]+)[^>]*></td>)?<td><b[^>]*>(.*?)</b>.*?unequip&type=hat" );
private static final Pattern WEAPON_PATTERN =
Pattern.compile( "Weapon</a>:</td>(<td><img[^']*'descitem\\(([\\d]+)[^>]*></td>)?<td><b[^>]*>(.*?)</b>.*?unequip&type=weapon" );
private static final Pattern HOLSTER_PATTERN =
Pattern.compile( "Holstered</a>:</td>(<td><img[^']*'descitem\\(([\\d]+)[^>]*></td>)?<td><b[^>]*>(.*?)</b>.*?action=holster&holster=0" );
private static final Pattern OFFHAND_PATTERN =
Pattern.compile( "Off-Hand</a>:</td>(<td><img[^']*'descitem\\(([\\d]+)[^>]*></td>)?<td><b[^>]*>(.*?)</b>.*?unequip&type=offhand" );
private static final Pattern CONTAINER_PATTERN =
Pattern.compile( "Back</a>:</td>(<td><img[^']*'descitem\\(([\\d]+)[^>]*></td>)?<td><b[^>]*>(.*?)</b>.*?unequip&type=container" );
private static final Pattern SHIRT_PATTERN =
Pattern.compile( "Shirt</a>:</td>(<td><img[^']*'descitem\\(([\\d]+)[^>]*></td>)?<td><b[^>]*>(.*?)</b>.*?unequip&type=shirt" );
private static final Pattern PANTS_PATTERN =
Pattern.compile( "Pants</a>:</td>(<td><img[^']*'descitem\\(([\\d]+)[^>]*></td>)?<td><b[^>]*>(.*?)</b>.*?unequip&type=pants" );
private static final Pattern ACC1_PATTERN =
Pattern.compile( "Accessory</a>(?: 1)?:</td>(<td><img[^']*'descitem\\(([\\d]+)[^>]*></td>)?<td><b[^>]*>([^<]+)</b> *<a[^>]*unequip&type=acc1" );
private static final Pattern ACC2_PATTERN =
Pattern.compile( "Accessory</a>(?: 2)?:</td>(<td><img[^']*'descitem\\(([\\d]+)[^>]*></td>)?<td><b[^>]*>([^<]+)</b> *<a[^>]*unequip&type=acc2" );
private static final Pattern ACC3_PATTERN =
Pattern.compile( "Accessory</a>(?: 3)?:</td>(<td><img[^']*'descitem\\(([\\d]+)[^>]*></td>)?<td><b[^>]*>([^<]+)</b> *<a[^>]*unequip&type=acc3" );
private static final Pattern FAMILIARITEM_PATTERN =
Pattern.compile( "Familiar</a>:</td>(<td><img[^']*'descitem\\(([\\d]+)[^>]*></td>)?<td><b[^>]*>(.*?)</b>.*?unequip&type=familiarequip\"" );
private static final Pattern OUTFITLIST_PATTERN = Pattern.compile( "<select name=whichoutfit>.*?</select>" );
private static final Pattern STICKER_PATTERN = Pattern.compile(
"<td>\\s*(shiny|dull)?\\s*([^<]+)<a [^>]+action=peel|<td>\\s*<img [^>]+magnify" );
private static final Pattern FOLDER_PATTERN = Pattern.compile( "folders/folder(\\d+).gif" );
private static final Pattern OUTFIT_ACTION_PATTERN = Pattern.compile(
"([a-zA-Z])=([^=]+)(?!=)" );
private static final Pattern OUTFIT_PATTERN = Pattern.compile( "whichoutfit=(-?\\d+|last)" );
private static final Pattern SLOT_PATTERN = Pattern.compile( "type=([a-z123]+)" );
private static final Pattern STICKERITEM_PATTERN = Pattern.compile( "sticker=(\\d+)" );
private static final Pattern SLOT1_PATTERN = Pattern.compile( "slot=(\\d+)" );
private static final Pattern OUTFITNAME_PATTERN = Pattern.compile( "outfitname=([^&]*)" );
private static final Pattern OUTFITID_PATTERN = Pattern.compile( "outfitid: (\\d+)" );
private static final Pattern EQUIPPED_PATTERN = Pattern.compile( "(?:Item equipped|equip an item):</td><td>.*?descitem\\((.*?)\\)'> <b>(.*?)</b></td>" );
private static final Pattern UNEQUIPPED_PATTERN = Pattern.compile( "Item unequipped:</td><td>.*?descitem\\((.*?)\\)'> <b>(.*?)</b></td>" );
private static final Pattern HOLSTER_URL_PATTERN = Pattern.compile( "holster=(\\d+)" );
public static final AdventureResult UNEQUIP = ItemPool.get( "(none)", 1 );
public static final AdventureResult TRUSTY = ItemPool.get( ItemPool.TRUSTY, 1 );
public static final int REFRESH = 0;
public static final int EQUIPMENT = 1;
public static final int SAVE_OUTFIT = 2;
public static final int CHANGE_OUTFIT = 3;
public static final int CHANGE_ITEM = 4;
public static final int REMOVE_ITEM = 5;
public static final int UNEQUIP_ALL = 6;
public static final int BEDAZZLEMENTS = 7;
// Array indexed by equipment "slot" from KoLCharacter
//
// Perhaps this should be in that module, except this is closely tied
// to the PHP files that are manipulated by THIS module.
// These are the public names
public static final String[] slotNames =
{
"hat",
"weapon",
"holster",
"off-hand",
"back",
"shirt",
"pants",
"acc1",
"acc2",
"acc3",
"familiar",
"crown-of-thrones",
"sticker1",
"sticker2",
"sticker3",
"card-sleeve",
"folder1",
"folder2",
"folder3",
"folder4",
"folder5",
"buddy-bjorn",
"bootskin",
"bootspur",
"fakehand"
};
// These are the names used in the PHP file
public static final String[] phpSlotNames =
{
"hat",
"weapon",
"holster",
"offhand",
"container",
"shirt",
"pants",
"acc1",
"acc2",
"acc3",
"familiarequip",
"crownofthrones",
"st1",
"st2",
"st3",
"cardsleeve",
"folder1",
"folder2",
"folder3",
"folder4",
"folder5",
"buddybjorn",
"bootskin",
"bootspur",
"fakehand"
};
private int requestType;
private int equipmentSlot;
private AdventureResult changeItem;
private int itemId;
private int equipmentType;
private SpecialOutfit outfit;
private String outfitName;
private String error;
private static boolean shouldSavePreviousOutfit = false;
private static int customOutfitId = 0;
public EquipmentRequest( final int requestType )
{
super( EquipmentRequest.choosePage( requestType ) );
this.requestType = requestType;
this.outfit = null;
this.outfitName = null;
this.error = null;
// Otherwise, add the form field indicating which page
// of the inventory you want to request
switch ( requestType )
{
case EquipmentRequest.EQUIPMENT:
this.addFormField( "which", "2" );
break;
case EquipmentRequest.BEDAZZLEMENTS:
// no fields necessary
break;
case EquipmentRequest.SAVE_OUTFIT:
this.addFormField( "ajax", "1" );
this.addFormField( "which", "2" );
break;
case EquipmentRequest.UNEQUIP_ALL:
this.addFormField( "ajax", "1" );
this.addFormField( "which", "2" );
this.addFormField( "action", "unequipall" );
break;
}
}
private static String choosePage( final int requestType )
{
switch ( requestType )
{
case EquipmentRequest.BEDAZZLEMENTS:
return "bedazzle.php";
case EquipmentRequest.SAVE_OUTFIT:
case EquipmentRequest.UNEQUIP_ALL:
return "inv_equip.php";
default:
return "inventory.php";
}
}
public EquipmentRequest( final String changeName )
{
this( EquipmentRequest.SAVE_OUTFIT );
this.addFormField( "action", "customoutfit" );
this.addFormField( "outfitname", changeName );
this.addFormField( "ajax", "1" );
this.outfitName = changeName;
}
public EquipmentRequest( final AdventureResult changeItem )
{
this( changeItem,
EquipmentRequest.chooseEquipmentSlot( changeItem.getItemId() ),
false );
}
public EquipmentRequest( final AdventureResult changeItem, final int equipmentSlot )
{
this( changeItem, equipmentSlot, false );
}
public EquipmentRequest( final AdventureResult changeItem, final int equipmentSlot, final boolean force )
{
super( EquipmentRequest.chooseEquipmentLocation( equipmentSlot ) );
this.error = null;
switch ( equipmentSlot )
{
case EquipmentManager.CROWNOFTHRONES:
case EquipmentManager.BUDDYBJORN:
break;
case EquipmentManager.STICKER1:
case EquipmentManager.STICKER2:
case EquipmentManager.STICKER3:
this.initializeStickerData( changeItem, equipmentSlot, force );
break;
case EquipmentManager.CARDSLEEVE:
this.initializeCardSleeveData( changeItem );
break;
case EquipmentManager.FOLDER1:
case EquipmentManager.FOLDER2:
case EquipmentManager.FOLDER3:
case EquipmentManager.FOLDER4:
case EquipmentManager.FOLDER5:
this.initializeFolderData( changeItem, equipmentSlot );
break;
case EquipmentManager.BOOTSKIN:
case EquipmentManager.BOOTSPUR:
this.initializeBootData( changeItem, equipmentSlot );
break;
case EquipmentManager.HOLSTER:
this.initializeSixgunData( changeItem, equipmentSlot );
break;
default:
this.initializeChangeData( changeItem, equipmentSlot, force );
}
}
public EquipmentRequest( final SpecialOutfit change )
{
super( "inv_equip.php" );
this.addFormField( "which", "2" );
this.addFormField( "action", "outfit" );
this.addFormField( "whichoutfit",
change == SpecialOutfit.PREVIOUS_OUTFIT ?
"last" :
String.valueOf( change.getOutfitId() ) );
this.addFormField( "ajax", "1" );
this.requestType = EquipmentRequest.CHANGE_OUTFIT;
this.outfit = change;
this.error = null;
}
private static final String chooseEquipmentLocation( final int slot )
{
return slot == EquipmentManager.HOLSTER ? "inventory.php" :
slot < EquipmentManager.SLOTS ? "inv_equip.php" :
slot == EquipmentManager.CROWNOFTHRONES || slot == EquipmentManager.BUDDYBJORN ? "bogus.php" :
( slot >= EquipmentManager.STICKER1 && slot <= EquipmentManager.STICKER3 ) ? "bedazzle.php" :
slot == EquipmentManager.CARDSLEEVE ? "inv_use.php" :
slot == EquipmentManager.FAKEHAND ? "inv_equip.php" :
( slot >= EquipmentManager.FOLDER1 && slot <= EquipmentManager.FOLDER5 ) ? "choice.php" :
( slot == EquipmentManager.BOOTSKIN || slot == EquipmentManager.BOOTSPUR ) ? "inv_use.php" :
"bogus.php";
}
public static boolean isEquipmentChange( final String path )
{
return path.startsWith( "inv_equip.php" ) &&
// Saving a custom outfit is OK
!path.contains( "action=customoutfit" );
}
@Override
protected boolean shouldFollowRedirect()
{
return true;
}
@Override
protected boolean retryOnTimeout()
{
return true;
}
public static final void savePreviousOutfit()
{
EquipmentRequest.shouldSavePreviousOutfit = true;
}
private void initializeChangeData( final AdventureResult changeItem, final int equipmentSlot, final boolean force )
{
this.addFormField( "which", "2" );
this.addFormField( "ajax", "1" );
this.equipmentSlot = equipmentSlot;
if ( changeItem.equals( EquipmentRequest.UNEQUIP ) )
{
this.requestType = EquipmentRequest.REMOVE_ITEM;
this.addFormField( "action", "unequip" );
this.addFormField( "type", EquipmentRequest.phpSlotNames[ equipmentSlot ] );
return;
}
// Find out what item is being equipped
this.itemId = changeItem.getItemId();
// Find out what kind of item it is
this.equipmentType = ItemDatabase.getConsumptionType( this.itemId );
if ( this.equipmentSlot == -1 )
{
this.error = "No suitable slot available for " + changeItem;
return;
}
// Make sure you can equip it in the requested slot
String action = this.getAction( force );
if ( action == null )
{
return;
}
this.requestType = EquipmentRequest.CHANGE_ITEM;
this.changeItem = changeItem.getCount() == 1 ? changeItem : changeItem.getInstance( 1 );
this.addFormField( "action", action );
this.addFormField( "whichitem", String.valueOf( this.itemId ) );
}
private void initializeStickerData( final AdventureResult sticker, final int equipmentSlot, final boolean force )
{
this.equipmentSlot = equipmentSlot;
this.addFormField( "slot", String.valueOf( equipmentSlot - EquipmentManager.STICKER1 + 1 ) );
if ( sticker.equals( EquipmentRequest.UNEQUIP ) )
{
this.requestType = EquipmentRequest.REMOVE_ITEM;
this.addFormField( "action", "peel" );
return;
}
// Find out what item is being equipped
this.itemId = sticker.getItemId();
// Find out what kind of item it is
this.equipmentType = ItemDatabase.getConsumptionType( this.itemId );
if ( this.equipmentType != KoLConstants.CONSUME_STICKER )
{
this.error = "You can't equip a " + ItemDatabase.getItemName( this.itemId ) +
" in a sticker slot.";
return;
}
this.addFormField( "sticker", String.valueOf( this.itemId ) );
this.requestType = EquipmentRequest.CHANGE_ITEM;
this.changeItem = sticker.getCount() == 1 ? sticker : sticker.getInstance( 1 );
if ( EquipmentManager.hasStickerWeapon() )
{
this.addFormField( "action", "stick" );
}
else
{
this.addFormField( "action", "juststick" );
this.removeFormField( "slot" );
}
}
private void initializeCardSleeveData( final AdventureResult card )
{
this.equipmentSlot = EquipmentManager.CARDSLEEVE;
this.addFormField( "whichitem", String.valueOf( ItemPool.CARD_SLEEVE ) );
if ( card.equals( EquipmentRequest.UNEQUIP ) )
{
this.requestType = EquipmentRequest.REMOVE_ITEM;
this.addFormField( "removecard", "1" );
return;
}
// Find out what item is being equipped
this.itemId = card.getItemId();
// Find out what kind of item it is
this.equipmentType = ItemDatabase.getConsumptionType( this.itemId );
if ( this.equipmentType != KoLConstants.CONSUME_CARD )
{
this.error = "You can't slide a " + ItemDatabase.getItemName( this.itemId ) + " into a card sleeze.";
return;
}
this.addFormField( "sleevecard", String.valueOf( this.itemId ) );
this.requestType = EquipmentRequest.CHANGE_ITEM;
this.changeItem = card.getCount() == 1 ? card : card.getInstance( 1 );
}
private void initializeFolderData( final AdventureResult folder, final int slot )
{
this.equipmentSlot = slot;
this.addFormField( "whichchoice", "774" );
if ( folder.equals( EquipmentRequest.UNEQUIP ) )
{
this.requestType = EquipmentRequest.REMOVE_ITEM;
this.addFormField( "slot", String.valueOf( slot - EquipmentManager.FOLDER1 ) );
this.addFormField( "option", "2" );
return;
}
for ( int i = EquipmentManager.FOLDER1; i <= EquipmentManager.FOLDER5; i++ )
{
if ( i != slot && folder.equals( EquipmentManager.getEquipment( i ) ) )
{
this.error = "You can't equip two of the same folder";
return;
}
}
// Find out what item is being equipped
this.itemId = folder.getItemId();
// Find out what kind of item it is
this.equipmentType = ItemDatabase.getConsumptionType( this.itemId );
if ( this.equipmentType != KoLConstants.CONSUME_FOLDER )
{
this.error = "You can't equip a " + ItemDatabase.getItemName( this.itemId ) + " in a folder slot.";
return;
}
this.requestType = EquipmentRequest.CHANGE_ITEM;
this.changeItem = folder;
this.addFormField( "option", "1" );
this.addFormField( "folder", String.valueOf( this.itemId - ItemPool.FOLDER_01 + 1 ) );
}
private void initializeBootData( final AdventureResult decoration, final int slot )
{
this.equipmentSlot = slot;
if ( decoration.equals( EquipmentRequest.UNEQUIP ) )
{
this.error = "You can't undecorate your cowboy boots.";
return;
}
// Find out what item is being equipped
this.itemId = decoration.getItemId();
// Find out what kind of item it is
this.equipmentType = ItemDatabase.getConsumptionType( this.itemId );
if ( this.equipmentType != KoLConstants.CONSUME_BOOTSKIN && this.equipmentType != KoLConstants.CONSUME_BOOTSPUR )
{
this.error = "You can't equip a " + ItemDatabase.getItemName( this.itemId ) + " on your cowboy boots.";
return;
}
if ( this.equipmentSlot == EquipmentManager.BOOTSKIN && this.equipmentType == KoLConstants.CONSUME_BOOTSPUR )
{
this.error = ItemDatabase.getItemName( this.itemId ) + " is a spur, not a skin.";
return;
}
if ( this.equipmentSlot == EquipmentManager.BOOTSPUR && this.equipmentType == KoLConstants.CONSUME_BOOTSKIN )
{
this.error = ItemDatabase.getItemName( this.itemId ) + " is a skin, not a spur.";
return;
}
this.requestType = EquipmentRequest.CHANGE_ITEM;
this.changeItem = decoration;
this.addFormField( "whichitem", String.valueOf( this.itemId ) );
this.addFormField( "ajax", "1" );
UseItemRequest.setLastItemUsed( decoration );
}
private void initializeSixgunData( final AdventureResult sixgun, final int slot )
{
this.equipmentSlot = slot;
if ( sixgun.equals( EquipmentRequest.UNEQUIP ) )
{
this.requestType = EquipmentRequest.REMOVE_ITEM;
this.addFormField( "which", "2h" );
this.addFormField( "action", "holster" );
this.addFormField( "holster", "0" );
this.addFormField( "ajax", "1" );
return;
}
// Find out what item is being equipped
this.itemId = sixgun.getItemId();
// Find out what kind of item it is
this.equipmentType = ItemDatabase.getConsumptionType( this.itemId );
if ( this.equipmentType != KoLConstants.CONSUME_SIXGUN )
{
this.error = "You can't holster a " + ItemDatabase.getItemName( this.itemId );
return;
}
this.requestType = EquipmentRequest.CHANGE_ITEM;
this.changeItem = sixgun;
this.addFormField( "which", "2" );
this.addFormField( "action", "holster" );
this.addFormField( "holster", String.valueOf( this.itemId ) );
this.addFormField( "ajax", "1" );
}
private String getAction( final boolean force )
{
switch ( this.equipmentSlot )
{
case EquipmentManager.HAT:
if ( this.equipmentType == KoLConstants.EQUIP_HAT )
{
return "equip";
}
break;
case EquipmentManager.WEAPON:
if ( this.equipmentType == KoLConstants.EQUIP_WEAPON )
{
return "equip";
}
break;
case EquipmentManager.OFFHAND:
if ( this.equipmentType == KoLConstants.EQUIP_OFFHAND )
{
return "equip";
}
if ( this.equipmentType == KoLConstants.EQUIP_WEAPON &&
EquipmentDatabase.getHands( this.itemId ) == 1 )
{
return "dualwield";
}
break;
case EquipmentManager.CONTAINER:
if ( this.equipmentType == KoLConstants.EQUIP_CONTAINER )
{
return "equip";
}
break;
case EquipmentManager.SHIRT:
if ( this.equipmentType == KoLConstants.EQUIP_SHIRT )
{
return "equip";
}
break;
case EquipmentManager.PANTS:
if ( this.equipmentType == KoLConstants.EQUIP_PANTS )
{
return "equip";
}
break;
case EquipmentManager.ACCESSORY1:
if ( this.equipmentType == KoLConstants.EQUIP_ACCESSORY )
{
this.addFormField( "slot", "1" );
return "equip";
}
break;
case EquipmentManager.ACCESSORY2:
if ( this.equipmentType == KoLConstants.EQUIP_ACCESSORY )
{
this.addFormField( "slot", "2" );
return "equip";
}
break;
case EquipmentManager.ACCESSORY3:
if ( this.equipmentType == KoLConstants.EQUIP_ACCESSORY )
{
this.addFormField( "slot", "3" );
return "equip";
}
break;
case EquipmentManager.FAMILIAR:
switch ( this.equipmentType )
{
case KoLConstants.EQUIP_FAMILIAR:
return "equip";
case KoLConstants.EQUIP_HAT:
case KoLConstants.EQUIP_WEAPON:
case KoLConstants.EQUIP_PANTS:
return "hatrack";
}
break;
case EquipmentManager.FAKEHAND:
if ( this.itemId == ItemPool.FAKE_HAND )
{
return "equip";
}
break;
default:
return "equip";
}
this.error =
"You can't equip a " + ItemDatabase.getItemName( this.itemId ) + " in the " + EquipmentRequest.slotNames[ this.equipmentSlot ] + " slot.";
return null;
}
public static final int chooseEquipmentSlot( final int itemId )
{
switch ( itemId )
{
case ItemPool.SPELUNKY_SPRING_BOOTS:
case ItemPool.SPELUNKY_SPIKED_BOOTS:
// Spelunky only has one "accessory" slot
return EquipmentManager.ACCESSORY1;
}
int equipmentType = ItemDatabase.getConsumptionType( itemId );
switch ( equipmentType )
{
case KoLConstants.EQUIP_HAT:
return EquipmentManager.HAT;
case KoLConstants.EQUIP_WEAPON:
return EquipmentManager.WEAPON;
case KoLConstants.EQUIP_OFFHAND:
return itemId == ItemPool.FAKE_HAND ? EquipmentManager.FAKEHAND : EquipmentManager.OFFHAND;
case KoLConstants.EQUIP_CONTAINER:
return EquipmentManager.CONTAINER;
case KoLConstants.EQUIP_SHIRT:
return EquipmentManager.SHIRT;
case KoLConstants.EQUIP_PANTS:
return EquipmentManager.PANTS;
case KoLConstants.EQUIP_ACCESSORY:
return EquipmentRequest.availableAccessory();
case KoLConstants.EQUIP_FAMILIAR:
return EquipmentManager.FAMILIAR;
case KoLConstants.CONSUME_STICKER:
return EquipmentRequest.availableSticker();
case KoLConstants.CONSUME_CARD:
return EquipmentManager.CARDSLEEVE;
case KoLConstants.CONSUME_FOLDER:
return EquipmentRequest.availableFolder();
case KoLConstants.CONSUME_SIXGUN:
return EquipmentManager.HOLSTER;
default:
return -1;
}
}
private static final int availableAccessory()
{
AdventureResult test = EquipmentManager.getEquipment( EquipmentManager.ACCESSORY1 );
if ( test == null || test.equals( EquipmentRequest.UNEQUIP ) )
{
return EquipmentManager.ACCESSORY1;
}
test = EquipmentManager.getEquipment( EquipmentManager.ACCESSORY2 );
if ( test == null || test.equals( EquipmentRequest.UNEQUIP ) )
{
return EquipmentManager.ACCESSORY2;
}
test = EquipmentManager.getEquipment( EquipmentManager.ACCESSORY3 );
if ( test == null || test.equals( EquipmentRequest.UNEQUIP ) )
{
return EquipmentManager.ACCESSORY3;
}
// All accessory slots are in use. Pick #1
return EquipmentManager.ACCESSORY1;
}
private static final int availableSlot( final int [] slots )
{
return EquipmentRequest.availableSlot( slots, slots.length );
}
private static final int availableSlot( final int [] slots, final int count )
{
for ( int i = 0; i < count; ++i )
{
int slot = slots[ i ];
AdventureResult test = EquipmentManager.getEquipment( slot );
if ( test == null || test.equals( EquipmentRequest.UNEQUIP ) )
{
return slot;
}
}
// All slots are in use. Abort rather than risk peeling the wrong one.
return -1;
}
public static final int [] STICKER_SLOTS = new int[]
{
EquipmentManager.STICKER1,
EquipmentManager.STICKER2,
EquipmentManager.STICKER3,
};
private static final int availableSticker()
{
return EquipmentRequest.availableSlot( STICKER_SLOTS );
}
public static final int [] FOLDER_SLOTS = new int[]
{
EquipmentManager.FOLDER1,
EquipmentManager.FOLDER2,
EquipmentManager.FOLDER3,
EquipmentManager.FOLDER4,
EquipmentManager.FOLDER5,
};
public static final int availableFolder()
{
return EquipmentRequest.availableSlot( FOLDER_SLOTS, KoLCharacter.inHighschool() ? 5 : 3 );
}
public String getOutfitName()
{
return this.outfit == null ? null : this.outfit.toString();
}
/**
* Executes the <code>EquipmentRequest</code>. Note that at the current time, only the character's currently
* equipped items and familiar item will be stored.
*/
@Override
public void run()
{
if ( GenericRequest.abortIfInFightOrChoice() )
{
return;
}
if ( this.requestType == EquipmentRequest.REFRESH )
{
InventoryManager.refresh();
return;
}
// If we were given bogus parameters, report the error now
if ( this.error != null )
{
KoLmafia.updateDisplay( MafiaState.ERROR, this.error );
return;
}
// Outfit changes are a bit quirky, so they're handled
// first for easy visibility.
if ( this.requestType == EquipmentRequest.CHANGE_OUTFIT )
{
// If this is a birthday suit outfit, then remove everything.
if ( this.outfit == SpecialOutfit.BIRTHDAY_SUIT )
{
// See if you are wearing anything.
boolean found = false;
for ( int i = 0; i < EquipmentManager.FAMILIAR; ++i )
{
if ( !EquipmentManager.getEquipment( i ).equals( EquipmentRequest.UNEQUIP ) )
{
found = true;
break;
}
}
// If not, nothing to do
if ( !found )
{
return;
}
// Make a checkpoint, if necessary
if ( EquipmentRequest.shouldSavePreviousOutfit )
{
if ( SpecialOutfit.markImplicitCheckpoint() )
{
( new EquipmentRequest( "Backup" ) ).run();
}
EquipmentRequest.shouldSavePreviousOutfit = false;
}
// Tell KoL to unequip everything
( new EquipmentRequest( EquipmentRequest.UNEQUIP_ALL ) ).run();
return;
}
else if ( this.outfit == SpecialOutfit.PREVIOUS_OUTFIT )
{
// If we are donning KoL's idea of your previous
// outfit, we have no idea what the pieces are.
// *** KoL bug: whichoutfit=last doesn't actually work
// *** Therefore, look up the actual outfit id.
CustomOutfitRequest request = new CustomOutfitRequest( true );
request.run();
int previousOutfitId = request.getPreviousOutfitId();
if ( previousOutfitId >= 0 )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "No previous outfit saved" );
return;
}
this.addFormField( "whichoutfit", String.valueOf( previousOutfitId ) );
}
else
{
// Otherwise, try to retrieve them.
// If you are already wearing the outfit, nothing to do
if ( EquipmentManager.isWearingOutfit( this.outfit ) )
{
return;
}
// Make sure we have all the pieces
if ( !EquipmentManager.retrieveOutfit( this.outfit ) )
{
return;
}
}
// Make a checkpoint, if necessary
if ( EquipmentRequest.shouldSavePreviousOutfit )
{
if ( SpecialOutfit.markImplicitCheckpoint() )
{
( new EquipmentRequest( "Backup" ) ).run();
}
EquipmentRequest.shouldSavePreviousOutfit = false;
}
}
if ( this.requestType == EquipmentRequest.CHANGE_ITEM )
{
// Do not submit a request if the item matches what you
// want to equip on the character.
if ( EquipmentManager.getEquipment( this.equipmentSlot ).equals( this.changeItem ) )
{
return;
}
// If we are equipping a new weapon, a two-handed
// weapon will unequip any pair of weapons. But a
// one-handed weapon much match the type of the
// off-hand weapon. If it doesn't, unequip the off-hand
// weapon first
int itemId = this.changeItem.getItemId();
if ( this.equipmentSlot == EquipmentManager.WEAPON &&
EquipmentDatabase.getHands( itemId ) == 1 )
{
int offhand = EquipmentManager.getEquipment( EquipmentManager.OFFHAND ).getItemId();
if ( ItemDatabase.getConsumptionType( offhand ) == KoLConstants.EQUIP_WEAPON &&
EquipmentDatabase.getWeaponType( itemId ) != EquipmentDatabase.getWeaponType( offhand ) )
{
( new EquipmentRequest( EquipmentRequest.UNEQUIP, EquipmentManager.OFFHAND ) ).run();
}
}
// If you are equipping an off-hand weapon, don't
// bother trying if unless it is compatible with the
// main weapon.
if ( this.equipmentSlot == EquipmentManager.OFFHAND )
{
int itemType = ItemDatabase.getConsumptionType( itemId );
AdventureResult weapon = EquipmentManager.getEquipment( EquipmentManager.WEAPON );
int weaponItemId = weapon.getItemId();
if ( itemType == KoLConstants.EQUIP_WEAPON && weaponItemId <= 0 )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "You can't dual wield unless you already have a main weapon." );
return;
}
if ( EquipmentDatabase.getHands( weaponItemId ) > 1 )
{
String message = itemType == KoLConstants.EQUIP_WEAPON ?
( "You can't wield a " + this.changeItem.getName() + " in your off-hand while wielding a 2-handed weapon." ) :
( "You can't equip a " + this.changeItem.getName() + " in your off-hand while wielding a 2-handed weapon." );
KoLmafia.updateDisplay( MafiaState.ERROR, message );
return;
}
if ( itemType == KoLConstants.EQUIP_WEAPON &&
EquipmentDatabase.getWeaponType( itemId ) != EquipmentDatabase.getWeaponType( weaponItemId ) )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "You can't hold a " + this.changeItem.getName() + " in your off-hand when wielding a " + weapon.getName() );
return;
}
}
if ( !InventoryManager.retrieveItem( this.changeItem ) )
{
return;
}
// Must remove an existing sticker or folder before
// installing a new one in the same slot.
if ( ( ( this.equipmentSlot >= EquipmentManager.STICKER1 && this.equipmentSlot <= EquipmentManager.STICKER3 ) ||
( this.equipmentSlot >= EquipmentManager.FOLDER1 && this.equipmentSlot <= EquipmentManager.FOLDER5 ) ) &&
!EquipmentManager.getEquipment( this.equipmentSlot ).equals( EquipmentRequest.UNEQUIP ) )
{
( new EquipmentRequest( EquipmentRequest.UNEQUIP, this.equipmentSlot ) ).run();
}
}
if ( this.requestType == EquipmentRequest.REMOVE_ITEM &&
equipmentSlot != EquipmentManager.FAKEHAND &&
EquipmentManager.getEquipment( this.equipmentSlot ).equals( EquipmentRequest.UNEQUIP ) )
{
return;
}
if ( this.equipmentSlot >= EquipmentManager.FOLDER1 && this.equipmentSlot <= EquipmentManager.FOLDER5 )
{
( new GenericRequest( "inventory.php?action=useholder" ) ).run();
}
switch ( this.requestType )
{
case EquipmentRequest.EQUIPMENT:
KoLmafia.updateDisplay( "Retrieving equipment..." );
break;
case EquipmentRequest.BEDAZZLEMENTS:
KoLmafia.updateDisplay( "Refreshing stickers..." );
break;
case EquipmentRequest.SAVE_OUTFIT:
KoLmafia.updateDisplay( "Saving outfit: " + this.outfitName );
break;
case EquipmentRequest.CHANGE_OUTFIT:
KoLmafia.updateDisplay( "Putting on outfit: " + this.outfit );
break;
case EquipmentRequest.CHANGE_ITEM:
KoLmafia.updateDisplay(
( this.equipmentSlot == EquipmentManager.WEAPON ? "Wielding " :
this.equipmentSlot == EquipmentManager.OFFHAND ? "Holding " :
this.equipmentSlot == EquipmentManager.CARDSLEEVE ? "Sliding in " :
this.equipmentSlot == EquipmentManager.HOLSTER ? "Holstering " :
"Putting on " ) +
ItemDatabase.getItemName( this.itemId ) + "..." );
break;
case EquipmentRequest.REMOVE_ITEM:
KoLmafia.updateDisplay( ( this.equipmentSlot == EquipmentManager.CARDSLEEVE ? "Sliding out " :
this.equipmentSlot == EquipmentManager.HOLSTER ? "Unholstering " :
"Taking off " ) +
( this.equipmentSlot == EquipmentManager.FAKEHAND ?
"fake hands" :
EquipmentManager.getEquipment( this.equipmentSlot ).getName() ) +
"..." );
break;
case EquipmentRequest.UNEQUIP_ALL:
KoLmafia.updateDisplay( "Taking off everything..." );
break;
}
// You can only change a card in the card sleeve while it is in inventory
boolean changeCardSleeve =
this.equipmentSlot == EquipmentManager.CARDSLEEVE &&
KoLCharacter.hasEquipped( EquipmentManager.CARD_SLEEVE );
if ( changeCardSleeve )
{
RequestThread.postRequest( new EquipmentRequest( EquipmentRequest.UNEQUIP, EquipmentManager.OFFHAND ) );
}
super.run();
if ( !KoLmafia.permitsContinue() )
{
return;
}
if ( changeCardSleeve )
{
RequestThread.postRequest( new EquipmentRequest( EquipmentManager.CARD_SLEEVE, EquipmentManager.OFFHAND ) );
}
switch ( this.requestType )
{
case EquipmentRequest.REFRESH:
return;
case EquipmentRequest.SAVE_OUTFIT:
KoLmafia.updateDisplay( "Outfit saved" );
return;
case EquipmentRequest.CHANGE_ITEM:
case EquipmentRequest.CHANGE_OUTFIT:
case EquipmentRequest.REMOVE_ITEM:
KoLmafia.updateDisplay( "Equipment changed." );
break;
case EquipmentRequest.UNEQUIP_ALL:
KoLmafia.updateDisplay( "Everything removed." );
break;
}
}
@Override
public void processResults()
{
String urlString = this.getURLString();
String responseText = this.responseText;
if ( urlString.startsWith( "bedazzle.php" ) )
{
EquipmentRequest.parseBedazzlements( responseText );
return;
}
if ( urlString.startsWith( "choice.php" ) && urlString.contains( "whichchoice=774" ) )
{
EquipmentRequest.parseFolders( responseText );
return;
}
if ( this.equipmentSlot == EquipmentManager.BOOTSKIN || this.equipmentSlot == EquipmentManager.BOOTSPUR )
{
UseItemRequest.parseConsumption( "", false );
return;
}
switch ( this.requestType )
{
case EquipmentRequest.REFRESH:
return;
case EquipmentRequest.EQUIPMENT:
EquipmentRequest.parseEquipment( urlString, responseText );
return;
case EquipmentRequest.CHANGE_ITEM:
case EquipmentRequest.CHANGE_OUTFIT:
String text = this.responseText == null ? "" : this.responseText;
// What SHOULD we do if get a null responseText?
Matcher resultMatcher = EquipmentRequest.CELL_PATTERN.matcher( text );
if ( resultMatcher.find() )
{
String result = resultMatcher.group( 1 ).replaceAll( "</?b>", "" );
if ( result.contains( "You are already wearing" ) )
{
// Not an error
KoLmafia.updateDisplay( result );
return;
}
// It appears you're already wearing all the
// parts of the outfit 'outfitname' which you
// possess or can wear. ... followed by a
// table of missing pieces
if ( result.contains( "which you possess or can wear" ) )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "You're already wearing as much of that outfit as you can." );
return;
}
if ( this.equipmentSlot != EquipmentManager.HOLSTER &&
!result.contains( "You put" ) &&
!result.contains( "You equip" ) &&
!result.contains( "Item equipped" ) &&
!result.contains( "equips an item" ) &&
!result.contains( "as you put it on" ) &&
!result.contains( "You take the existing card out of the sleeve to make room" ) &&
!result.contains( "You apply the shiny sticker" ) &&
!result.contains( "fold it into an impromptu sword" ) )
{
KoLmafia.updateDisplay( MafiaState.ERROR, result );
return;
}
}
if ( this.equipmentSlot == EquipmentManager.CARDSLEEVE )
{
EquipmentRequest.parseCardSleeve( responseText );
}
else if ( this.getURLString().contains( "ajax=1" ) )
{
if ( EquipmentRequest.parseEquipmentChange( urlString, responseText ) )
{
this.setHasResult( false );
}
}
else if ( this.equipmentSlot == EquipmentManager.HOLSTER )
{
// This redirects to equipment.php?action=message
EquipmentRequest.parseEquipment( urlString, responseText );
}
return;
case EquipmentRequest.SAVE_OUTFIT:
case EquipmentRequest.REMOVE_ITEM:
case EquipmentRequest.UNEQUIP_ALL:
if ( this.equipmentSlot == EquipmentManager.CARDSLEEVE )
{
EquipmentRequest.parseCardSleeve( responseText );
}
else if ( this.getURLString().contains( "ajax=1" ) )
{
EquipmentRequest.parseEquipmentChange( urlString, responseText );
}
else if ( this.equipmentSlot == EquipmentManager.HOLSTER )
{
// This redirects to equipment.php?action=message
// with the previous equipment page of the inventory.
// I.e., with a sixgun holstered.
EquipmentManager.setEquipment( EquipmentManager.HOLSTER, EquipmentRequest.UNEQUIP );
}
return;
}
}
private static final boolean switchItem( final AdventureResult oldItem, final AdventureResult newItem )
{
// If the items are not equivalent, make sure
// the items should get switched out.
if ( newItem.getItemId() == oldItem.getItemId() )
{
return false;
}
// Manually subtract item from inventory to avoid
// excessive list updating.
if ( newItem != EquipmentRequest.UNEQUIP )
{
AdventureResult.addResultToList( KoLConstants.inventory, newItem.getInstance( -1 ) );
QuestManager.updateQuestItemEquipped( newItem.getItemId() );
}
if ( oldItem != EquipmentRequest.UNEQUIP )
{
AdventureResult.addResultToList( KoLConstants.inventory, oldItem.getInstance( 1 ) );
}
return !ConcoctionDatabase.getKnownUses( oldItem ).isEmpty() || !ConcoctionDatabase.getKnownUses( newItem ).isEmpty();
}
public static final void parseBedazzlements( final String responseText )
{
Matcher matcher = EquipmentRequest.STICKER_PATTERN.matcher( responseText );
for ( int slot = EquipmentManager.STICKER1; slot <= EquipmentManager.STICKER3; ++slot )
{
if ( !matcher.find() )
{
return; // presumably doesn't have a sticker weapon
}
AdventureResult newItem;
if ( matcher.group( 2 ) == null )
{
newItem = EquipmentRequest.UNEQUIP;
}
else
{
newItem = ItemPool.get( matcher.group( 2 ).trim(), 1 );
}
AdventureResult oldItem = EquipmentManager.getEquipment( slot );
EquipmentManager.setEquipment( slot, newItem );
if ( !KoLmafia.isRefreshing() &&
!newItem.equals( oldItem ) )
{
if ( !oldItem.equals( EquipmentRequest.UNEQUIP ) &&
!KoLConstants.inventory.contains( oldItem ) )
{
// Item was in the list for this slot
// only so that it could be displayed
// as the current item. Remove it.
EquipmentManager.getEquipmentLists()[ slot ].remove( oldItem );
}
if ( !newItem.equals( EquipmentRequest.UNEQUIP ) )
{
ResultProcessor.processResult( newItem.getInstance( -1 ) );
}
EquipmentManager.setTurns( slot, 20, 20 );
}
if ( matcher.group( 1 ) != null )
{
String adjective = matcher.group( 1 );
if ( adjective.equals( "shiny" ) )
{
EquipmentManager.setTurns( slot, 16, 20 );
}
else if ( adjective.equals( "dull" ) )
{
EquipmentManager.setTurns( slot, 1, 5 );
}
else
{
EquipmentManager.setTurns( slot, 6, 15 );
}
}
}
}
private static final Pattern ACQUIRE_PATTERN = Pattern.compile( "You acquire an item: <b>(.*?)</b>" );
private static final Pattern CONTAINS_PATTERN = Pattern.compile( "Your card sleeve currently contains an <b>(.*?)</b>" );
public static final void parseCardSleeve( final String responseText )
{
// Putting a card into an empty card sleeve
//
// You put the Alice's Army Sniper in the card sleeve.
// Your card sleeve currently contains an Alice's Army Sniper.
//
// Putting a card into an occupied card sleeve
//
// You take the existing card out of the sleeve to make room:
// You acquire an item: Alice's Army Sniper
// You put the Alice's Army Bowman in the card sleeve.
// Your card sleeve currently contains an Alice's Army Bowman.
//
// Removing a card from a card sleeve
//
// You pull the card out of the sleeve.
// You acquire an item: Alice's Army Sniper
// Your card sleeve is currently empty.
Matcher acquiresMatcher = EquipmentRequest.ACQUIRE_PATTERN.matcher( responseText );
String acquired = acquiresMatcher.find() ? acquiresMatcher.group( 1 ) : null;
int acquiredId = ItemDatabase.getItemId( acquired );
Matcher containsMatcher = EquipmentRequest.CONTAINS_PATTERN.matcher( responseText );
String contains = containsMatcher.find() ? containsMatcher.group( 1 ) : null;
int containsId = ItemDatabase.getItemId( contains );
AdventureResult oldItem = acquired != null ? ItemPool.get( acquiredId ) : EquipmentRequest.UNEQUIP;
AdventureResult newItem = contains != null ? ItemPool.get( containsId ) : EquipmentRequest.UNEQUIP;
if ( acquired != null )
{
// *** result processing added it to inventory and tally.
AdventureResult remove = oldItem.getInstance( -1 );
AdventureResult.addResultToList( KoLConstants.tally, remove );
AdventureResult.addResultToList( KoLConstants.inventory, remove );
}
// Put the old item into inventory and remove the new one
EquipmentRequest.switchItem( oldItem, newItem );
EquipmentManager.setEquipment( EquipmentManager.CARDSLEEVE, newItem );
}
public static final AdventureResult idToFolder( final String id )
{
int itemId = ItemPool.FOLDER_01 + StringUtilities.parseInt( id ) - 1;
return ( itemId < ItemPool.FOLDER_01 || itemId > ItemPool.FOLDER_28 ) ?
EquipmentRequest.UNEQUIP :
ItemPool.get( itemId, 1 );
}
public static final void parseFolders( String responseText )
{
int startIndex = responseText.indexOf( "Contents of your Folder Holder" );
int stopIndex = responseText.indexOf( "Folders in your Inventory" );
if ( startIndex == -1 || stopIndex == -1 )
{
return;
}
String text = responseText.substring( startIndex, stopIndex );
Matcher folderMatcher = EquipmentRequest.FOLDER_PATTERN.matcher( text );
int slot = EquipmentManager.FOLDER1;
while ( folderMatcher.find() && slot <= EquipmentManager.FOLDER5 )
{
AdventureResult folder = EquipmentRequest.idToFolder( folderMatcher.group( 1 ) );
EquipmentManager.setEquipment( slot++, folder );
}
while ( slot <= EquipmentManager.FOLDER5 )
{
EquipmentManager.setEquipment( slot++, EquipmentRequest.UNEQUIP );
}
}
public static final void parseEquipment( final String location, final String responseText )
{
if ( location.contains( "onlyitem=" ) )
{
return;
}
AdventureResult[] oldEquipment = EquipmentManager.currentEquipment();
int oldFakeHands = EquipmentManager.getFakeHands();
int newFakeHands = 0;
// Ensure that the inventory stays up-to-date by switching
// items around, as needed.
AdventureResult[] equipment = EquipmentManager.emptyEquipmentArray();
EquipmentRequest.parseEquipment( responseText, equipment,
"unequip&type=hat", EquipmentRequest.HAT_PATTERN,
"Hat: ", EquipmentManager.HAT );
EquipmentRequest.parseEquipment( responseText, equipment,
"unequip&type=weapon", EquipmentRequest.WEAPON_PATTERN,
"Weapon: ", EquipmentManager.WEAPON );
EquipmentRequest.parseEquipment( responseText, equipment,
"action=holster&holster=0", EquipmentRequest.HOLSTER_PATTERN,
"Holstered: ", EquipmentManager.HOLSTER );
EquipmentRequest.parseEquipment( responseText, equipment,
"unequip&type=offhand", EquipmentRequest.OFFHAND_PATTERN,
"Offhand: ", EquipmentManager.OFFHAND );
EquipmentRequest.parseEquipment( responseText, equipment,
"unequip&type=container", EquipmentRequest.CONTAINER_PATTERN,
"Back: ", EquipmentManager.CONTAINER );
EquipmentRequest.parseEquipment( responseText, equipment,
"unequip&type=shirt", EquipmentRequest.SHIRT_PATTERN,
"Shirt: ", EquipmentManager.SHIRT );
EquipmentRequest.parseEquipment( responseText, equipment,
"unequip&type=pants", EquipmentRequest.PANTS_PATTERN,
"Pants: ", EquipmentManager.PANTS );
EquipmentRequest.parseEquipment( responseText, equipment,
"unequip&type=acc1", EquipmentRequest.ACC1_PATTERN,
"Accessory 1: ", EquipmentManager.ACCESSORY1 );
EquipmentRequest.parseEquipment( responseText, equipment,
"unequip&type=acc2", EquipmentRequest.ACC2_PATTERN,
"Accessory 2: ", EquipmentManager.ACCESSORY2 );
EquipmentRequest.parseEquipment( responseText, equipment,
"unequip&type=acc3", EquipmentRequest.ACC3_PATTERN,
"Accessory 3: ", EquipmentManager.ACCESSORY3 );
EquipmentRequest.parseEquipment( responseText, equipment,
"unequip&type=familiarequip", EquipmentRequest.FAMILIARITEM_PATTERN,
"Familiar: ", EquipmentManager.FAMILIAR );
int index = 0;
while ( ( index = responseText.indexOf( "unequip&type=fakehand", index ) ) != -1 )
{
newFakeHands += 1;
index += 21;
}
// First, handle all of the equipment pre-processing,
// like inventory shuffling and the like.
boolean refresh = EquipmentRequest.switchEquipment( oldEquipment, equipment );
// Adjust inventory of fake hands
if ( oldFakeHands != newFakeHands )
{
AdventureResult.addResultToList( KoLConstants.inventory,
ItemPool.get( ItemPool.FAKE_HAND, oldFakeHands - newFakeHands ) );
EquipmentManager.setFakeHands( newFakeHands );
}
EquipmentManager.updateNormalOutfits();
// Look for custom outfits
Matcher outfitsMatcher = EquipmentRequest.OUTFITLIST_PATTERN.matcher( responseText );
SpecialOutfit.checkOutfits( outfitsMatcher.find() ? outfitsMatcher.group() : null );
// Check if familiar equipment is locked
FamiliarData.checkLockedItem( responseText );
// If he's wearing a custom outfit, do additional processing
EquipmentRequest.wearCustomOutfit( location );
// If you need to update your creatables list, do so at
// the end of the processing.
if ( refresh )
{
ConcoctionDatabase.setRefreshNeeded( false );
}
}
private static final void parseEquipment( final String responseText, AdventureResult[] equipment,
final String test, final Pattern pattern,
final String tag, final int slot )
{
if ( !responseText.contains( test ) )
{
return;
}
Matcher matcher = pattern.matcher( responseText );
if ( !matcher.find() )
{
return;
}
String descId = matcher.group( 1 ) != null ? matcher.group( 2 ) : "";
String name = matcher.group( 3 ).trim();
int itemId = ItemDatabase.getItemIdFromDescription( descId );
AdventureResult item;
if ( slot == EquipmentManager.HOLSTER || EquipmentDatabase.contains( itemId ) )
{
item = ItemPool.get( itemId );
}
else
{
RequestLogger.printLine( "Found unknown equipped item: \"" + name + "\" descid = " + descId );
// No itemId available for equipped items!
// ItemDatabase.registerItem( itemId, name, descId );
// Put in a dummy item. If it gets unequipped, we will
// find and identify it in inventory.
item = AdventureResult.tallyItem( name, 1, false );
}
equipment[ slot ] = item;
if ( RequestLogger.isDebugging() )
{
RequestLogger.updateDebugLog( tag + equipment[ slot ] );
}
}
public static final boolean switchEquipment( final AdventureResult [] oldEquipment, final AdventureResult [] newEquipment )
{
boolean refresh = false;
if ( !KoLmafia.isRefreshing() )
{
for ( int i = 0; i < EquipmentManager.SLOTS; ++i )
{
switch ( i )
{
case EquipmentManager.FAMILIAR:
// Omit familiar items, since inventory
// is handled by familiar.setItem()
continue;
case EquipmentManager.HOLSTER:
// No inventory swapping for holstered sixguns
continue;
}
AdventureResult oldItem = oldEquipment[ i ];
AdventureResult newItem = newEquipment[ i ];
refresh |= EquipmentRequest.switchItem( oldItem, newItem );
}
}
// Now update your equipment to make sure that selected
// items are properly selected in the dropdowns.
EquipmentManager.setEquipment( newEquipment );
return refresh;
}
private static final boolean switchItem( final int type, final AdventureResult newItem )
{
boolean refresh = false;
switch ( type )
{
case EquipmentManager.FAMILIAR:
// Inventory is handled by familiar.setItem()
break;
case EquipmentManager.HOLSTER:
// Does not change inventory
break;
case EquipmentManager.WEAPON:
// Wielding a two-handed weapon automatically unequips
// anything in the off-hand.
// Dropping a weapon in the main hand automatically drops a weapon in the off-hand
if ( EquipmentDatabase.getHands( newItem.getItemId() ) > 1 ||
( newItem.equals( EquipmentRequest.UNEQUIP ) && EquipmentManager.isDualWielding() ) )
{
refresh |= EquipmentRequest.switchItem( EquipmentManager.OFFHAND, EquipmentRequest.UNEQUIP );
}
// fall through
default:
AdventureResult oldItem = EquipmentManager.getEquipment( type );
refresh |= EquipmentRequest.switchItem( oldItem, newItem );
break;
}
// Now update your equipment to make sure that selected
// items are properly selected in the dropdowns.
EquipmentManager.setEquipment( type, newItem );
return refresh;
}
public static final boolean parseEquipmentChange( final String location, final String responseText )
{
Matcher matcher = GenericRequest.ACTION_PATTERN.matcher( location );
// We have nothing special to do for simple visits.
if ( !matcher.find() )
{
return false;
}
String action = matcher.group(1);
// inv_equip.php?action=equip&whichitem=2764&slot=1&ajax=1
// inv_equip.php?action=equip&whichitem=1234&ajax=1
if ( action.equals( "equip" ) )
{
// Detect failure to equip
if ( !responseText.contains( "You equip an item" ) &&
!responseText.contains( "Item equipped" ) &&
!responseText.contains( "equips an item" ) )
{
return false;
}
// We equipped an item.
int itemId = EquipmentRequest.parseItemId( location );
if ( itemId < 0 )
{
return false;
}
if ( itemId == ItemPool.FAKE_HAND )
{
int oldFakeHands = EquipmentManager.getFakeHands();
EquipmentManager.setFakeHands( oldFakeHands + 1 );
AdventureResult.addResultToList( KoLConstants.inventory, ItemPool.get( ItemPool.FAKE_HAND, -1 ) );
return false;
}
int slot = EquipmentRequest.findEquipmentSlot( itemId, location );
if ( EquipmentRequest.switchItem( slot, ItemPool.get( itemId, 1 ) ) )
{
ConcoctionDatabase.setRefreshNeeded( false );
}
return false;
}
// inv_equip.php?action=dualwield&whichitem=1325&ajax=1
if ( action.equals( "dualwield" ) )
{
// Detect failure to equip
if ( !responseText.contains( "You equip an item" ) && !responseText.contains( "Item equipped" ) )
{
return false;
}
// We equipped an item.
int itemId = EquipmentRequest.parseItemId( location );
if ( itemId < 0 )
{
return false;
}
if ( EquipmentRequest.switchItem( EquipmentManager.OFFHAND, ItemPool.get( itemId, 1 ) ) )
{
ConcoctionDatabase.setRefreshNeeded( false );
}
return false;
}
// inv_equip.php?action=unequipall&ajax=1
if ( action.equals( "unequipall" ) )
{
// We unequipped everything
if ( !responseText.contains( "All items unequipped" ) )
{
return false;
}
boolean switched = false;
for ( int i = 0; i < EquipmentManager.SLOTS; ++i )
{
// Whether the familiar item is unequipped on
// an unequip all is an account preference.
if ( i == EquipmentManager.FAMILIAR &&
!KoLCharacter.getUnequipFamiliar() )
{
continue;
}
if ( EquipmentRequest.switchItem( i, EquipmentRequest.UNEQUIP ) )
{
switched = true;
}
}
if ( switched )
{
ConcoctionDatabase.setRefreshNeeded( false );
}
}
// inv_equip.php?action=unequip&type=acc3&ajax=1
if ( action.equals( "unequip" ) )
{
// Detect failure to equip
if ( !responseText.contains( "Item unequipped" ) )
{
return false;
}
// We unequipped an item.
String slotName = EquipmentRequest.parseSlotName( location );
if ( slotName == null )
{
return false;
}
int type = EquipmentRequest.slotNumber( slotName );
if ( type < 0 )
{
return false;
}
if ( type == EquipmentManager.FAKEHAND )
{
int oldFakeHands = EquipmentManager.getFakeHands();
AdventureResult.addResultToList( KoLConstants.inventory, ItemPool.get( ItemPool.FAKE_HAND, oldFakeHands ) );
EquipmentManager.setFakeHands( 0 );
return false;
}
if ( EquipmentRequest.switchItem( type, EquipmentRequest.UNEQUIP ) )
{
ConcoctionDatabase.setRefreshNeeded( false );
}
return false;
}
// inv_equip.php?action=hatrack&whichitem=308&ajax=1
if ( action.equals( "hatrack" ) )
{
// Detect failure to equip
if ( !responseText.contains( "equips an item" ) )
{
return false;
}
// We equipped an item.
int itemId = EquipmentRequest.parseItemId( location );
if ( itemId < 0 )
{
return false;
}
if ( EquipmentRequest.switchItem( EquipmentManager.FAMILIAR, ItemPool.get( itemId, 1 ) ) )
{
ConcoctionDatabase.setRefreshNeeded( false );
}
return false;
}
// inventory.php?action=holster&holster=8970&ajax=1
if ( action.equals( "holster" ) )
{
// We equipped an item.
int itemId = EquipmentRequest.parseHolster( location );
if ( itemId < 0 )
{
return false;
}
if ( itemId == 0 )
{
EquipmentManager.setEquipment( EquipmentManager.HOLSTER, EquipmentRequest.UNEQUIP );
}
else
{
EquipmentRequest.switchItem( EquipmentManager.HOLSTER, ItemPool.get( itemId, 1 ) );
}
return false;
}
// inv_equip.php?action=customoutfit&outfitname=Backup
if ( action.equals( "customoutfit" ) )
{
// Detect failure to equip
if ( !responseText.contains( "Your custom outfit has been saved" ) )
{
return false;
}
// We saved a custom outfit. KoL assigned a new outfit
// ID to it and was kind enough to tell it to us in an
// HTML comment: <!-- outfitid: 61 -->
matcher = OUTFITNAME_PATTERN.matcher( location );
if ( !matcher.find() )
{
return false;
}
String name = GenericRequest.decodeField( matcher.group( 1 ) );
matcher = OUTFITID_PATTERN.matcher( responseText );
if ( !matcher.find() )
{
return false;
}
int id = StringUtilities.parseInt( matcher.group( 1 ) );
// Make a new custom outfit
SpecialOutfit outfit = new SpecialOutfit( -id, name );
AdventureResult[] equipment = EquipmentManager.currentEquipment();
// Add our current equipment to it
for ( int slot = 0; slot < EquipmentManager.FAMILIAR; ++slot )
{
AdventureResult piece = equipment[ slot ];
// Make a brand-new AdventureResult for each item
if ( piece != EquipmentRequest.UNEQUIP )
{
piece = ItemPool.get( piece.getItemId() );
}
outfit.addPiece( piece );
}
// Add this outfit to the list of custom outfits.
EquipmentManager.addCustomOutfit( outfit );
return false;
}
// inv_equip.php?action=outfit&whichoutfit=-28&ajax=1
if ( action.equals( "outfit" ) )
{
// Detect failure to equip
if ( !responseText.contains( "You put on" ) )
{
return false;
}
// We changed into an outfit.
// Since KoL doesn't tell us where accessories and
// dual-wielded weapons end up, apply heuristics and
// hope for the best.
EquipmentRequest.donOutfit( responseText );
// Until/unless KoL includes the equipment slot for
// each item changed, "hope" is not enough.
//
// Request status refresh via api.php in order to make
// sure equipment ends up in correct slots.
ApiRequest.updateStatus( true );
// Trigger actions based on outfit name
EquipmentRequest.wearCustomOutfit( location );
return true;
}
return false;
}
private static final void donOutfit( final String responseText )
{
// Since KoL doesn't tell us where accessories end up,
// we could ask for an update, but we'll apply
// heuristics and hope for the best.
// Similarly, if you are dual-wielding two of the same
// weapon, if you replace one of them with another
// weapon, it's problematic.
AdventureResult[] oldEquipment = EquipmentManager.currentEquipment();
AdventureResult[] newEquipment = EquipmentManager.currentEquipment();
// Experimentation suggests that accessories are
// installed in "Item Equipped" order like this:
// - fill empty accessory slots from 1 to 3
// - replace previous accessories from 3 to 1
//
// Note that if an already equipped accessory is part
// of the new outfit, it stays exactly where it was.
// Weapons that are part of the new outfit stay where
// they currently are.
// Iterate over all unequipped items.
Matcher unequipped = UNEQUIPPED_PATTERN.matcher( responseText );
while ( unequipped.find() )
{
String descId = unequipped.group( 1 );
int itemId = ItemDatabase.getItemIdFromDescription( descId );
if ( !EquipmentDatabase.contains( itemId ) )
{
continue;
}
AdventureResult item = ItemPool.get( itemId );
int slot = EquipmentManager.itemIdToEquipmentType( itemId );
switch ( slot )
{
case EquipmentManager.ACCESSORY1:
if ( newEquipment[ EquipmentManager.ACCESSORY3 ].equals( item ) )
{
slot = EquipmentManager.ACCESSORY3;
}
else if ( newEquipment[ EquipmentManager.ACCESSORY2 ].equals( item ) )
{
slot = EquipmentManager.ACCESSORY2;
}
else if ( !newEquipment[ EquipmentManager.ACCESSORY1 ].equals( item ) )
{
// KoL error: accessory not found
continue;
}
break;
case EquipmentManager.WEAPON:
if ( newEquipment[ EquipmentManager.OFFHAND ].equals( item ) )
{
// Heuristic: unequip duplicate
// weapon from offhand slot first
slot = EquipmentManager.OFFHAND;
}
else if ( !newEquipment[ EquipmentManager.WEAPON ].equals( item ) )
{
// KoL error: weapon not found
continue;
}
break;
default:
// Everything else goes into an
// unambiguous slot.
break;
}
newEquipment[ slot ] = EquipmentRequest.UNEQUIP;
}
// Calculate accessory fill order
int [] accessories = new int[] {
EquipmentManager.ACCESSORY1,
EquipmentManager.ACCESSORY2,
EquipmentManager.ACCESSORY3
};
int accessoryIndex = 0;
// Consume unfilled slots from 1 to 3
for ( int slot = EquipmentManager.ACCESSORY1; slot <= EquipmentManager.ACCESSORY3; slot++ )
{
if ( oldEquipment[ slot ] == EquipmentRequest.UNEQUIP )
{
accessories[ accessoryIndex++ ] = slot;
}
}
// Consume filled slots from 3 to 1
for ( int slot = EquipmentManager.ACCESSORY3; accessoryIndex < 3 && slot >= EquipmentManager.ACCESSORY1; slot-- )
{
if ( oldEquipment[ slot ] != EquipmentRequest.UNEQUIP &&
newEquipment[ slot ] == EquipmentRequest.UNEQUIP )
{
accessories[ accessoryIndex++ ] = slot;
}
}
// Calculate weapon fill order
int [] weapons = new int[] {
EquipmentManager.WEAPON,
EquipmentManager.OFFHAND,
};
int weaponIndex = 0;
// If the offhand slot is empty and the weapon slot is
// not, put new weapon into offhand slot
if ( newEquipment[ EquipmentManager.OFFHAND ] == EquipmentRequest.UNEQUIP &&
newEquipment[ EquipmentManager.WEAPON ] != EquipmentRequest.UNEQUIP )
{
weapons[ 0 ] = EquipmentManager.OFFHAND;
weapons[ 1 ] = EquipmentManager.WEAPON;
}
// Reset equip indices
accessoryIndex = 0;
weaponIndex = 0;
// Iterate over all equipped items.
Matcher equipped = EQUIPPED_PATTERN.matcher( responseText );
while ( equipped.find() )
{
String descId = equipped.group( 1 );
int itemId = ItemDatabase.getItemIdFromDescription( descId );
if ( !EquipmentDatabase.contains( itemId ) )
{
continue;
}
AdventureResult item = ItemPool.get( itemId );
int slot = EquipmentManager.itemIdToEquipmentType( itemId );
switch ( slot )
{
case EquipmentManager.ACCESSORY1:
if ( accessoryIndex >= 3 )
{
// KoL error: four accessories
continue;
}
slot = accessories[ accessoryIndex++ ];
break;
case EquipmentManager.WEAPON:
if ( weaponIndex >= 2 )
{
// KoL error: three weapons
continue;
}
slot = weapons[ weaponIndex ];
// A chefstaff must go in the weapon slot,
// but KoL does not always list it first.
if ( slot == EquipmentManager.OFFHAND &&
EquipmentDatabase.isChefStaff( item ) )
{
slot = EquipmentManager.WEAPON;
// Move other weapon to offhand
newEquipment[ EquipmentManager.OFFHAND ] = newEquipment[ EquipmentManager.WEAPON ];
// If we thought we were unequipping offhand
// and leaving weapon equipped, reverse that
if ( weaponIndex == 0 )
{
weapons[ 1 ] = EquipmentManager.OFFHAND;
}
}
weaponIndex++;
break;
default:
// Everything else goes into an
// unambiguous slot.
break;
}
newEquipment[ slot ] = item;
}
if ( EquipmentRequest.switchEquipment( oldEquipment, newEquipment ) )
{
ConcoctionDatabase.setRefreshNeeded( false );
}
}
private static final void wearCustomOutfit( final String urlString )
{
int outfitId = EquipmentRequest.customOutfitId;
EquipmentRequest.customOutfitId = 0;
SpecialOutfit outfit = EquipmentManager.getCustomOutfit( outfitId );
if ( outfit == null )
{
return;
}
Matcher m = EquipmentRequest.OUTFIT_ACTION_PATTERN.matcher( outfit.getName() );
while ( m.find() )
{
String text = m.group( 2 ).trim();
switch ( m.group( 1 ).toLowerCase().charAt( 0 ) )
{
case 'c':
KoLmafiaCLI.DEFAULT_SHELL.executeLine( text );
break;
case 'e':
KoLmafiaCLI.DEFAULT_SHELL.executeCommand(
"equip", "familiar " + text );
break;
case 'f':
KoLmafiaCLI.DEFAULT_SHELL.executeCommand(
"familiar", text );
break;
case 'm':
KoLmafiaCLI.DEFAULT_SHELL.executeCommand(
"mood", text );
break;
case 't':
KoLmafiaCLI.DEFAULT_SHELL.executeCommand(
"enthrone", text );
break;
case 'b':
KoLmafiaCLI.DEFAULT_SHELL.executeCommand(
"bjornify", text );
break;
}
}
}
private static int parseItemId( final String location )
{
Matcher matcher = GenericRequest.WHICHITEM_PATTERN.matcher( location );
return matcher.find() ? StringUtilities.parseInt( matcher.group( 1 ) ) : -1;
}
private static int parseSlot( final String location )
{
Matcher matcher = SLOT1_PATTERN.matcher( location );
return matcher.find() ? StringUtilities.parseInt( matcher.group( 1 ) ) : -1;
}
private static String parseSlotName( final String location )
{
Matcher matcher = EquipmentRequest.SLOT_PATTERN.matcher( location );
return matcher.find() ? matcher.group( 1 ) : null;
}
private static int parseHolster( final String location )
{
Matcher matcher = HOLSTER_URL_PATTERN.matcher( location );
return matcher.find() ? StringUtilities.parseInt( matcher.group( 1 ) ) : -1;
}
public static final int slotNumber( final String name )
{
for ( int i = 0; i < EquipmentRequest.slotNames.length; ++i )
{
if ( name.equalsIgnoreCase( EquipmentRequest.slotNames[ i ] ) )
{
return i;
}
}
return EquipmentRequest.phpSlotNumber( name );
}
public static final int phpSlotNumber( final String name )
{
for ( int i = 0; i < EquipmentRequest.phpSlotNames.length; ++i )
{
if ( name.equalsIgnoreCase( EquipmentRequest.phpSlotNames[ i ] ) )
{
return i;
}
}
return -1;
}
private static int findEquipmentSlot( final int itemId, final String location )
{
int type = EquipmentManager.itemIdToEquipmentType( itemId );
// If it's not an accessory, slot is unambiguous
if ( type != EquipmentManager.ACCESSORY1 )
{
return type;
}
// Accessories might specify the slot in the URL
switch ( EquipmentRequest.parseSlot( location ) )
{
case 1:
return EquipmentManager.ACCESSORY1;
case 2:
return EquipmentManager.ACCESSORY2;
case 3:
return EquipmentManager.ACCESSORY3;
}
// Otherwise, KoL picks the first empty accessory slot.
return EquipmentRequest.availableAccessory();
}
public static final boolean registerRequest( final String urlString )
{
if ( urlString.startsWith( "bedazzle.php" ) )
{
registerBedazzlement( urlString );
return true;
}
if ( urlString.startsWith( "inv_use.php" ) && urlString.contains( "whichitem=5009" ) )
{
return EquipmentRequest.registerCardSleeve( urlString );
}
if ( urlString.startsWith( "inventory.php" ) && urlString.contains( "action=holster" ) )
{
return EquipmentRequest.registerHolster( urlString );
}
if ( !urlString.startsWith( "inv_equip.php" ) )
{
return false;
}
EquipmentRequest.customOutfitId = 0;
Matcher outfitMatcher = EquipmentRequest.OUTFIT_PATTERN.matcher( urlString );
if ( outfitMatcher.find() )
{
String outfitString = outfitMatcher.group( 1 );
if ( outfitString.equals( "last" ) )
{
RequestLogger.updateSessionLog( "outfit last" );
return true;
}
int outfitId = StringUtilities.parseInt( outfitString );
if ( outfitId > 0 )
{
RequestLogger.updateSessionLog( "outfit " + EquipmentDatabase.getOutfit( outfitId ) );
return true;
}
SpecialOutfit outfit = EquipmentManager.getCustomOutfit( outfitId );
String name = outfit == null ? String.valueOf( outfitId ) : outfit.getName();
RequestLogger.updateSessionLog( "custom outfit " + name );
EquipmentRequest.customOutfitId = outfitId;
return true;
}
if ( urlString.contains( "action=unequip" ) )
{
if ( urlString.contains( "terrarium=1" ) )
{
FamiliarRequest.unequipCurrentFamiliar();
return true;
}
String slotName = parseSlotName( urlString );
if ( slotName != null )
{
RequestLogger.updateSessionLog( "unequip " + slotName );
}
return true;
}
int itemId = EquipmentRequest.parseItemId( urlString );
if ( itemId == -1 )
{
return true;
}
String itemName = ItemDatabase.getItemName( itemId );
if ( itemName == null )
{
return true;
}
if ( urlString.contains( "dualwield" ) )
{
RequestLogger.updateSessionLog();
RequestLogger.updateSessionLog( "equip off-hand " + itemName );
}
else if ( urlString.contains( "slot=1" ) )
{
RequestLogger.updateSessionLog();
RequestLogger.updateSessionLog( "equip acc1 " + itemName );
}
else if ( urlString.contains( "slot=2" ) )
{
RequestLogger.updateSessionLog();
RequestLogger.updateSessionLog( "equip acc2 " + itemName );
}
else if ( urlString.contains( "slot=3" ) )
{
RequestLogger.updateSessionLog();
RequestLogger.updateSessionLog( "equip acc3 " + itemName );
}
else if ( urlString.contains( "terrarium=1" ) )
{
FamiliarRequest.equipCurrentFamiliar( itemId );
}
else
{
int slot = EquipmentRequest.chooseEquipmentSlot( ItemDatabase.getItemId( itemName ) );
if ( slot >= 0 && slot < EquipmentRequest.slotNames.length )
{
RequestLogger.updateSessionLog();
RequestLogger.updateSessionLog( "equip " + EquipmentRequest.slotNames[ slot ] + " " + itemName );
}
}
return true;
}
private static final Pattern SLEEVECARD_PATTERN = Pattern.compile( "sleevecard=(\\d+)" );
public static final boolean registerCardSleeve( final String urlString )
{
UseItemRequest.setLastItemUsed( EquipmentManager.CARD_SLEEVE );
Matcher m = SLEEVECARD_PATTERN.matcher( urlString );
String message =
m.find() ?
"equip card-sleeve " + ItemDatabase.getItemName( StringUtilities.parseInt( m.group( 1 ) ) ) :
urlString.contains( "removecard=1" ) ?
"unequip card-sleeve " :
null;
if ( message != null )
{
RequestLogger.updateSessionLog();
RequestLogger.updateSessionLog( message );
}
return true;
}
public static final void registerBedazzlement( final String urlString )
{
if ( urlString.contains( "action=fold" ) )
{
RequestLogger.updateSessionLog( "folded sticker weapon" );
return;
}
if ( urlString.contains( "action=peel" ) )
{
Matcher slotMatcher = EquipmentRequest.SLOT1_PATTERN.matcher( urlString );
if ( slotMatcher.find() )
{
RequestLogger.updateSessionLog( "peeled sticker " + slotMatcher.group( 1 ) );
}
return;
}
Matcher itemMatcher = EquipmentRequest.STICKERITEM_PATTERN.matcher( urlString );
if ( !itemMatcher.find() )
{
return;
}
int itemId = StringUtilities.parseInt( itemMatcher.group( 1 ) );
String itemName = ItemDatabase.getItemName( itemId );
if ( itemName == null )
{
return;
}
if ( urlString.contains( "action=juststick" ) )
{
RequestLogger.updateSessionLog( "stuck " + itemName + " in empty slot" );
}
else if ( urlString.contains( "action=stick" ) )
{
int slot = EquipmentRequest.parseSlot( urlString );
if ( slot > 0 )
{
RequestLogger.updateSessionLog( "stuck " + itemName + " in slot " + slot );
}
}
}
public static final boolean registerHolster( final String urlString )
{
Matcher m = HOLSTER_URL_PATTERN.matcher( urlString );
int itemId = m.find() ? StringUtilities.parseInt( m.group( 1 ) ) : -1;
String message =
itemId > 0 ?
"equip holster " + ItemDatabase.getItemName( itemId ) :
itemId == 0 ?
"unequip holster" :
null;
if ( message != null )
{
RequestLogger.updateSessionLog();
RequestLogger.updateSessionLog( message );
}
return true;
}
public static void checkCowboyBoots()
{
if ( !InventoryManager.hasItem( EquipmentManager.COWBOY_BOOTS ) &&
!KoLCharacter.hasEquipped( EquipmentManager.COWBOY_BOOTS ) )
{
EquipmentManager.setEquipment( EquipmentManager.BOOTSKIN, EquipmentRequest.UNEQUIP );
EquipmentManager.setEquipment( EquipmentManager.BOOTSPUR, EquipmentRequest.UNEQUIP );
return;
}
String text = DebugDatabase.itemDescriptionText( ItemPool.COWBOY_BOOTS, true );
// This is your favorite old pair of trail-worn cowboy boots,
// made of diamondback skin and all gussied up with nicksilver spurs.
// This is your favorite old pair of trail-worn cowboy boots,
// made of fine Corinthian leather and all gussied up with invisible spurs (which might, I admit, not be real).
Pattern BOOT_PATTERN = Pattern.compile( "made of (.*?) and all gussied up with (.* spurs)" );
Matcher matcher = BOOT_PATTERN.matcher( text );
if ( matcher.find() )
{
String skin = matcher.group(1);
if ( skin.equals( "fine Corinthian leather" ) )
{
EquipmentManager.setEquipment( EquipmentManager.BOOTSKIN, EquipmentRequest.UNEQUIP );
}
else
{
EquipmentManager.setEquipment( EquipmentManager.BOOTSKIN, new AdventureResult( skin ) );
}
String spur = matcher.group(2);
if ( spur.equals( "invisible spurs" ) )
{
EquipmentManager.setEquipment( EquipmentManager.BOOTSPUR, EquipmentRequest.UNEQUIP );
}
else
{
EquipmentManager.setEquipment( EquipmentManager.BOOTSPUR, new AdventureResult( spur ) );
}
}
}
public static void checkHolster()
{
if ( !KoLCharacter.isAWoLClass() )
{
EquipmentManager.setEquipment( EquipmentManager.HOLSTER, EquipmentRequest.UNEQUIP );
return;
}
// Have to get it from the Equipment page of the Inventory
RequestThread.postRequest( new EquipmentRequest( EquipmentRequest.EQUIPMENT ) );
}
}