/** * 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.combat; import java.util.List; import net.sourceforge.kolmafia.AdventureResult; import net.sourceforge.kolmafia.KoLCharacter; import net.sourceforge.kolmafia.MonsterData; import net.sourceforge.kolmafia.objectpool.ItemPool; import net.sourceforge.kolmafia.persistence.MonsterDatabase; import net.sourceforge.kolmafia.persistence.MonsterDatabase.Element; import net.sourceforge.kolmafia.persistence.MonsterDatabase.Phylum; import net.sourceforge.kolmafia.preferences.Preferences; import net.sourceforge.kolmafia.session.EquipmentManager; import net.sourceforge.kolmafia.session.Limitmode; import net.sourceforge.kolmafia.utilities.StringUtilities; public class MonsterStatusTracker { private static MonsterData monsterData = null; private static String lastMonsterName = ""; private static int healthModifier = 0; private static int attackModifier = 0; private static int defenseModifier = 0; private static int healthManuel = 0; private static int attackManuel = 0; private static int defenseManuel = 0; private static boolean manuelFound = false; private static int originalHealth = 0; private static int originalAttack = 0; private static int originalDefense = 0; public static final void reset() { MonsterStatusTracker.healthModifier = 0; MonsterStatusTracker.attackModifier = 0; MonsterStatusTracker.defenseModifier = 0; MonsterStatusTracker.healthManuel = 0; MonsterStatusTracker.attackManuel = 0; MonsterStatusTracker.defenseManuel = 0; MonsterStatusTracker.manuelFound = false; } public static final MonsterData getLastMonster() { return MonsterStatusTracker.monsterData; } public static final String getLastMonsterName() { return MonsterStatusTracker.lastMonsterName; } public static final void setNextMonsterName( String monsterName ) { MonsterStatusTracker.reset(); MonsterStatusTracker.monsterData = MonsterDatabase.findMonster( monsterName, false ); if ( MonsterStatusTracker.monsterData == null && EquipmentManager.getEquipment( EquipmentManager.WEAPON ).getItemId() == ItemPool.SWORD_PREPOSITIONS ) { monsterName = StringUtilities.lookupPrepositions( monsterName ); MonsterStatusTracker.monsterData = MonsterDatabase.findMonster( monsterName, false ); } if ( MonsterStatusTracker.monsterData == null ) { if ( monsterName.startsWith( "the " ) ) { MonsterStatusTracker.monsterData = MonsterDatabase.findMonster( monsterName.substring( 4 ), false ); if ( MonsterStatusTracker.monsterData != null ) { monsterName = monsterName.substring( 4 ); } } else if ( monsterName.startsWith( "el " ) || monsterName.startsWith( "la " ) ) { MonsterStatusTracker.monsterData = MonsterDatabase.findMonster( monsterName.substring( 3 ), false ); if ( MonsterStatusTracker.monsterData != null ) { monsterName = monsterName.substring( 3 ); } } } if ( MonsterStatusTracker.monsterData == null ) { // Temporarily register the unknown monster so that // consult scripts can see it as such MonsterStatusTracker.monsterData = MonsterDatabase.registerMonster( monsterName ); } // If we saved an array of random modifiers, apply them MonsterStatusTracker.monsterData = MonsterStatusTracker.monsterData.handleRandomModifiers(); MonsterStatusTracker.monsterData = MonsterStatusTracker.monsterData.handleMonsterLevel(); MonsterStatusTracker.originalHealth = MonsterStatusTracker.monsterData.getHP(); MonsterStatusTracker.originalAttack = MonsterStatusTracker.monsterData.getAttack(); MonsterStatusTracker.originalDefense = MonsterStatusTracker.monsterData.getDefense(); MonsterStatusTracker.lastMonsterName = monsterName; } public static final boolean dropsItem( int itemId ) { if ( itemId == 0 || MonsterStatusTracker.monsterData == null ) { return false; } AdventureResult item = ItemPool.get( itemId, 1 ); return MonsterStatusTracker.monsterData.getItems().contains( item ); } public static final boolean dropsItems( List<AdventureResult> items ) { if ( items.isEmpty() || MonsterStatusTracker.monsterData == null ) { return false; } return MonsterStatusTracker.monsterData.getItems().containsAll( items ); } public static final boolean shouldSteal() { // If the user doesn't want smart pickpocket behavior, don't give it if ( !Preferences.getBoolean( "safePickpocket" ) ) { return true; } if ( MonsterStatusTracker.monsterData == null ) { return true; } return MonsterStatusTracker.monsterData.shouldSteal(); } public static final int getMonsterHealth() { if ( MonsterStatusTracker.monsterData == null ) { return 0; } return MonsterStatusTracker.originalHealth - MonsterStatusTracker.healthModifier; } public static final void healMonster( int amount ) { MonsterStatusTracker.healthModifier -= amount; if ( MonsterStatusTracker.healthModifier < 0 ) { MonsterStatusTracker.healthModifier = 0; } } public static final void damageMonster( int amount ) { MonsterStatusTracker.healthModifier += amount; } public static final void resetAttackAndDefense() { MonsterStatusTracker.attackModifier = 0; MonsterStatusTracker.defenseModifier = 0; } public static final int getMonsterBaseAttack() { if ( MonsterStatusTracker.monsterData == null ) { return 0; } return MonsterStatusTracker.monsterData.getAttack(); } public static final int getMonsterAttack() { if ( MonsterStatusTracker.monsterData == null ) { return 0; } int baseAttack = MonsterStatusTracker.originalAttack; int adjustedAttack = baseAttack + MonsterStatusTracker.attackModifier; return baseAttack == 0 ? adjustedAttack: Math.max( adjustedAttack, 1 ); } public static final int getMonsterOriginalAttack() { return MonsterStatusTracker.monsterData == null ? 0 : MonsterStatusTracker.originalAttack; } public static final Element getMonsterAttackElement() { if ( MonsterStatusTracker.monsterData == null ) { return Element.NONE; } return MonsterStatusTracker.monsterData.getAttackElement(); } public static final void lowerMonsterAttack( int amount ) { MonsterStatusTracker.attackModifier -= amount; } public static final int getMonsterAttackModifier() { if ( MonsterStatusTracker.monsterData == null ) { return 0; } return MonsterStatusTracker.attackModifier; } public static final boolean willUsuallyDodge() { return MonsterStatusTracker.willUsuallyDodge( 0 ); } public static final boolean willUsuallyDodge( final int attackModifier ) { if ( MonsterStatusTracker.monsterData == null ) { return false; } return MonsterStatusTracker.monsterData.willUsuallyDodge( MonsterStatusTracker.attackModifier + attackModifier ); } public static final int getMonsterDefense() { if ( MonsterStatusTracker.monsterData == null ) { return 0; } int baseDefense = MonsterStatusTracker.originalDefense; int adjustedDefense = baseDefense + MonsterStatusTracker.defenseModifier; return baseDefense == 0 ? adjustedDefense : Math.max( adjustedDefense, 1 ); } public static final Element getMonsterDefenseElement() { if ( MonsterStatusTracker.monsterData == null ) { return Element.NONE; } return MonsterStatusTracker.monsterData.getDefenseElement(); } public static final Phylum getMonsterPhylum() { if ( MonsterStatusTracker.monsterData == null ) { return Phylum.NONE; } return MonsterStatusTracker.monsterData.getPhylum(); } public static final void lowerMonsterDefense( int amount ) { MonsterStatusTracker.defenseModifier -= amount; } public static final int getMonsterDefenseModifier() { if ( MonsterStatusTracker.monsterData == null ) { return 0; } return MonsterStatusTracker.defenseModifier; } public static final boolean willUsuallyMiss() { return MonsterStatusTracker.willUsuallyMiss( 0 ); } public static final boolean willUsuallyMiss( final int defenseModifier ) { if ( MonsterStatusTracker.monsterData == null ) { return false; } return MonsterStatusTracker.monsterData.willUsuallyMiss( MonsterStatusTracker.defenseModifier + defenseModifier ); } public static final int getMonsterRawInitiative() { if ( MonsterStatusTracker.monsterData == null ) { return 0; } return MonsterStatusTracker.monsterData.getRawInitiative(); } public static final int getMonsterInitiative() { if ( MonsterStatusTracker.monsterData == null ) { return 0; } return MonsterStatusTracker.monsterData.getInitiative(); } public static final int getJumpChance() { if ( MonsterStatusTracker.monsterData == null ) { return 0; } return MonsterStatusTracker.monsterData.getJumpChance(); } public static int getPoisonLevel() { if ( MonsterStatusTracker.monsterData == null ) { return 0; } return MonsterStatusTracker.monsterData.getPoison(); } public static void setManuelStats( int attack, int defense, int hp ) { // Save what Manuel reported. These are the stats at the END of // the round's actions - including those which automatically // fired on round 0 before the player did anything. MonsterStatusTracker.attackManuel = attack; MonsterStatusTracker.defenseManuel = defense; MonsterStatusTracker.healthManuel = hp; // If we don't know anything about this monster, assume that // Manuel is showing the original stats - even though, as // described above, that's not always the case. if ( !manuelFound && MonsterStatusTracker.originalAttack == 0) { MonsterStatusTracker.originalAttack = attack; MonsterStatusTracker.originalDefense = defense; MonsterStatusTracker.originalHealth = hp; } MonsterStatusTracker.manuelFound = true; } public static void applyManuelStats() { if ( manuelFound ) { MonsterStatusTracker.attackModifier = MonsterStatusTracker.attackManuel - MonsterStatusTracker.originalAttack; MonsterStatusTracker.defenseModifier = MonsterStatusTracker.defenseManuel - MonsterStatusTracker.originalDefense; MonsterStatusTracker.healthModifier = MonsterStatusTracker.originalHealth - MonsterStatusTracker.healthManuel; } } }