code:
//Combat 2.0

package classes.Scenes.Combat
{
import classes.*;
import adobe.utils.CustomActions;
import classes.BodyParts.*;
import classes.GlobalFlags.*;
import classes.Items.*;
import classes.Items.Shields.FlamegritShield;
import classes.Scenes.Areas.Desert.*;
import classes.Scenes.Areas.Forest.*;
import classes.Scenes.Areas.GlacialRift.*;
import classes.Scenes.Areas.HighMountains.*;
import classes.Scenes.Areas.Mountain.*;
import classes.Scenes.Areas.VolcanicCrag.CorruptedSandWitch;
import classes.Scenes.Areas.VolcanicCrag.VolcanicGolem;
import classes.Scenes.Dungeons.HelDungeon.*;
import classes.Scenes.Dungeons.LethicesKeep.*;
import classes.Scenes.Monsters.*;
import classes.Scenes.NPCs.*;
import classes.Scenes.Places.MothCave.Outsider;
import classes.Scenes.Places.TelAdre.UmasShop;
import classes.StatusEffects.Combat.*;
import classes.display.SpriteDb;
	import classes.Scenes.Dungeons.Manor.*

import coc.view.MainView;
import coc.view.MonsterStatsView;

public class Combat extends BaseContent
	{
		public function Combat() {}

		public var combatAbilities:CombatAbilities = new CombatAbilities();
		public var combatTeases:CombatTeases = new CombatTeases();

		public var plotFight:Boolean = false; //Used to restrict random drops from overlapping uniques
		public var combatRound:int = 0;
		public var damage:Number = 0;
		public var damageTaken:Number = 0;
		public var currEnemy:int = 0;
		public var currTarget:int = 0;
		public var currAbilityUsed:CombatAbility;
		public var playerTurn:Boolean = true;
		//Variables used for multi enemy fights. It's actually less messy this way.
		public var hpvictoryFunc:Function = null;
		public var hplossFunc:Function = null;
		public var lustvictoryFunc:Function = null;
		public var lustlossFunc:Function = null;
		public var description:String = "";

		//Basic damage types, used to get proper reactions if a monster has unique combat interactions.
		public var damageType:String = ""; //defines what damageDealt type was dealt by the player this turn.
		public var monsterDamageType:String = ""; //same thing but for the enemy
		public const DAMAGE_NO_ATTACK:String = "NoAttack";
		public const DAMAGE_PHYSICAL_MELEE:String = "PhysicalM";
		public const DAMAGE_PHYSICAL_RANGED:String = "PhysicalR";
		public const DAMAGE_MAGICAL_MELEE:String = "MagicalM";
		public const DAMAGE_MAGICAL_RANGED:String = "MagicalR";
		public const DAMAGE_FIRE:String = "Fire";
		public const DAMAGE_ICE:String = "Ice";
		public const DAMAGE_LIGHTNING:String = "Lightning";

		//Used to display image of the enemy while fighting
		//Set once during beginCombat() to prevent it from changing every combat turn
		private var imageText:String = "";

		public function get inCombat():Boolean {
			return game.inCombat;
		}

		public function set inCombat(mode:Boolean):void {
			game.inCombat = mode;
		}

		//Victory & Loss
		//If multiple enemies are fighting, then the specific victory function defined at the start must run. Otherwise, go for the default.

		public function endHpVictory():void {
			generalCleanup();
			if (player.statusEffectv2(StatusEffects.TFSupercharging) > 0 && monster.level >= player.level && achievements[kACHIEVEMENTS.NIGHT_SUN] == 0) {
				awardAchievement("Night Sun", kACHIEVEMENTS.NIGHT_SUN);
				doNext(hpvictoryFunc);
			}
			else hpvictoryFunc();
		}
		public function endLustVictory():void {
            generalCleanup();
			lustvictoryFunc();
		}
		public function endHpLoss():void {
            generalCleanup();
			hplossFunc();
		}
		public function endLustLoss():void {
            generalCleanup();
			if (player.hasStatusEffect(StatusEffects.Infested) && flags[kFLAGS.CAME_WORMS_AFTER_COMBAT] == 0) {
				flags[kFLAGS.CAME_WORMS_AFTER_COMBAT] = 1;
				game.mountain.wormsScene.infestOrgasm();
				lustlossFunc();
			} else {
				if (monsterArray.length == 1) monster.won_(false, false);
				else lustlossFunc();
			}
		}

		public function generalCleanup():void{
            mainView.endCombatView();
			spriteSelect(null);
			imageSelect(null);
            combatAbilities.fireMagicLastTurn = -100;
            combatAbilities.fireMagicCumulated = 0;
            combatAbilities.flurryAmount = 1;
            currMonsterIndex = 0;
            maxMonsterIndex = 0;
            currTarget = 0;
            combatAttackData.resetDistance();
			if (player.weapon == weapons.G_KNUCKLE) player.setWeapon(WeaponLib.FISTS);
		}

		//Combat is over. Clear shit out and go to main. Also given different name to avoid conflicts with BaseContent.
		public function cleanupAfterCombat(nextFunc:Function = null):void {
			generalCleanup();
            //mainView.endCombatView();
			if (nextFunc == null) nextFunc = camp.returnToCampUseOneHour;
			if (prison.inPrison && prison.prisonCombatWinEvent != null) nextFunc = prison.prisonCombatWinEvent;
			if (inCombat) {
				//clear status
				clearStatuses();

				//reset the stored image for next monster
				imageText = "";
				//Clear itemswapping in case it hung somehow
		//No longer used:		itemSwapping = false;
				//Player won
				if (totalHP() < 1 || lustVictory()) {
					if (totalHP() < 1) flags[kFLAGS.TOTAL_HP_VICTORIES]++;
					awardPlayer(nextFunc);
				}
				//Player lost
				else {
					if (monster.statusEffectv1(StatusEffects.Sparring) == 2) {
						outputText("The cow-girl has defeated you in a practice fight!");
						outputText("\n\nYou have to lean on Isabella's shoulder while the two of your hike back to camp.  She clearly won.");
						inCombat = false;
						player.HP = 1;
						statScreenRefresh();
						doNext(nextFunc);
						return;
					}
					//Next button is handled within the minerva loss function
					if (monster.hasStatusEffect(StatusEffects.PeachLootLoss)) {
						inCombat = false;
						player.HP = 1;
						statScreenRefresh();
						return;
					}
					if (monster.short == "Ember" || monster.short == "Sylvia" || monster.short == "moth-girl" || monster.short == "outsider") {
						inCombat = false;
						if (player.HP < 1) player.HP = 1;
						statScreenRefresh();
						doNext(nextFunc);
						return;
					}
					temp = rand(10) + 1 + Math.round(monster.level / 2);
					if (inDungeon) temp += 20 + monster.level * 2;
					//Increases gems lost in NG+.
					temp *= 1 + (player.newGamePlusMod() * 0.5);
					//Round gems.
					temp = Math.round(temp);
					//Keep gems from going below zero.
					if (temp > player.gems) temp = player.gems;
					var timePasses:int = monster.handleCombatLossText(inDungeon, temp); //Allows monsters to customize the loss text and the amount of time lost
					player.gems -= temp;
					inCombat = false;
					if (prison.inPrison == false && flags[kFLAGS.PRISON_CAPTURE_CHANCE] > 0 && rand(100) < flags[kFLAGS.PRISON_CAPTURE_CHANCE] && (prison.trainingFeed.prisonCaptorFeedingQuestTrainingIsTimeUp() || !prison.trainingFeed.prisonCaptorFeedingQuestTrainingExists()) && (monster.short == "goblin" || monster.short == "goblin assassin" || monster.short == "imp" || monster.short == "imp lord" || monster.short == "imp warlord" || monster.short == "hellhound" || monster.short == "minotaur" || monster.short == "satyr" || monster.short == "gnoll" || monster.short == "gnoll spear-thrower" || monster.short == "basilisk")) {
						outputText("  You feel yourself being dragged and carried just before you black out.");
						doNext(prison.prisonIntro);
						return;
					}
					//BUNUS XPZ
					if (flags[kFLAGS.COMBAT_BONUS_XP_VALUE] > 0) {
						player.XP += flags[kFLAGS.COMBAT_BONUS_XP_VALUE];
						outputText("  Somehow you managed to gain " + flags[kFLAGS.COMBAT_BONUS_XP_VALUE] + " XP from the situation.");
						flags[kFLAGS.COMBAT_BONUS_XP_VALUE] = 0;
					}
					//Bonus lewts
					if (flags[kFLAGS.BONUS_ITEM_AFTER_COMBAT_ID] != "") {
						outputText("  Somehow you came away from the encounter with " + ItemType.lookupItem(flags[kFLAGS.BONUS_ITEM_AFTER_COMBAT_ID]).longName + ".\n\n");
						inventory.takeItem(ItemType.lookupItem(flags[kFLAGS.BONUS_ITEM_AFTER_COMBAT_ID]), createCallBackFunction(camp.returnToCamp, timePasses));
					}
					else doNext(createCallBackFunction(camp.returnToCamp, timePasses));
				}
			}
			//Not actually in combat
			else doNext(nextFunc);
		}

		public var distanceSelfAb:CombatAbility;
		public var approachSelf:CombatAbility;
		public function setDistanceSelf():void{
			distanceSelfAb = new CombatAbility({
			abilityFunc: combatAbilities.distanceSelf,
			availableWhen: true,
			disabledWhen: function ():Boolean{
								return monster.distance == CombatAttackData.DISTANCE_DISTANT || monster.hasStatusEffect(StatusEffects.Level) || !player.canMove();
							},
			tooltip: function ():String {
								return "Attempt to distance yourself from an enemy. Chance is based on speed. " + player.movementChance(monster) +"%" ;
							},
			disabledTooltip: function ():String {return player.canMove() ? "You cannot distance yourself any more!" : "You're unable to move!";},
			cost: 15,
			isSelf: true,
			spellName: "Distance",
			spellShort: "Distance",
			range: CombatAttackData.RANGE_SELF,
			abilityType: CombatAbility.PHYSICAL
		});
		}

		public function setApproach():void{
			approachSelf = new CombatAbility({
			abilityFunc: combatAbilities.approach,
			availableWhen: true,
			tooltip: function ():String {
								return "Attempt to close the distance from an enemy. Chance is based on speed. " + player.movementChance(monster) +"%" ;
							},
			disabledWhen: function ():Boolean{
											return monster.distance == CombatAttackData.DISTANCE_MELEE || monster.hasStatusEffect(StatusEffects.Level) || !player.canMove();
										},
			disabledTooltip: function ():String {return player.canMove() ? "You cannot approach this enemy!" : "You're unable to move!";},
			cost: 15,
			isSelf: true,
			spellName: "Approach",
			spellShort: "Approach",
			range: CombatAttackData.RANGE_SELF,
			abilityType: CombatAbility.PHYSICAL
		});
		}

		public function checkAchievementDamage(damage:Number):void
		{
			flags[kFLAGS.ACHIEVEMENT_PROGRESS_TOTAL_DAMAGE] += damage;
			if (flags[kFLAGS.ACHIEVEMENT_PROGRESS_TOTAL_DAMAGE] >= 50000) game.awardAchievement("Bloodletter", kACHIEVEMENTS.COMBAT_BLOOD_LETTER);
			if (damage >= 50) game.awardAchievement("Pain", kACHIEVEMENTS.COMBAT_PAIN);
			if (damage >= 100) game.awardAchievement("Fractured Limbs", kACHIEVEMENTS.COMBAT_FRACTURED_LIMBS);
			if (damage >= 250) game.awardAchievement("Broken Bones", kACHIEVEMENTS.COMBAT_BROKEN_BONES);
			if (damage >= 500) game.awardAchievement("Overkill", kACHIEVEMENTS.COMBAT_OVERKILL);
		}

		private function isPlayerBound():Boolean
		{
			var temp:Boolean = false;
			if (player.hasStatusEffect(StatusEffects.HarpyBind) || player.hasStatusEffect(StatusEffects.GooBind) || player.hasStatusEffect(StatusEffects.TentacleBind) || player.hasStatusEffect(StatusEffects.NagaBind) || monster.hasStatusEffect(StatusEffects.QueenBind) || monster.hasStatusEffect(StatusEffects.PCTailTangle)) temp = true;
			if (player.hasStatusEffect(StatusEffects.HolliConstrict)) temp = true;
			if (player.hasStatusEffect(StatusEffects.GooArmorBind)) temp = true;
			if (player.hasStatusEffect(StatusEffects.MinotaurEntangled)) {
				outputText("\nYou're bound up in the minotaur lord's chains!  All you can do is try to struggle free!");
				temp = true;
			}
			if(player.hasStatusEffect(StatusEffects.YamataEntwine)){
				outputText("You are bound by Yamata’s snake-like hair. The only thing you can do is try to struggle free!\n\n")
				temp = true;
			}
			if (player.hasStatusEffect(StatusEffects.UBERWEB)) temp = true;
			if (player.hasStatusEffect(StatusEffects.Bound)) temp = true;
			if (player.hasStatusEffect(StatusEffects.Chokeslam)) temp = true;
			if (player.hasStatusEffect(StatusEffects.Titsmother)) temp = true;
			if (player.hasStatusEffect(StatusEffects.GiantGrabbed)) {
				outputText("\nYou're trapped in the giant's hand!  All you can do is try to struggle free!");
				temp = true;
			}
			if (player.hasStatusEffect(StatusEffects.CorrWitchBind)) {
				outputText("\nYou're pinned by the Witch's body! All you can do is try to overpower her!");
				temp = true;
			}
			if (player.hasStatusEffect(StatusEffects.Tentagrappled)) {
				outputText("\nThe demonesses tentacles are constricting your limbs!");
				temp = true;
			}
			if (player.hasStatusEffect(StatusEffects.Grappled)) temp = true;
			return temp;
		}

		private function isPlayerStunned(newRound:Boolean):Boolean
		{
			var temp:Boolean = false;
			if (!newRound) return false;
			if (player.hasStatusEffect(StatusEffects.IsabellaStunned) || player.hasStatusEffect(StatusEffects.Stunned)) {
				outputText("\nYou're too stunned to attack!  All you can do is wait and try to recover!");
				temp = true;
			}
			if (player.hasStatusEffect(StatusEffects.Whispered)) {
				outputText("\nYour mind is too addled to focus on combat!  All you can do is try and recover!");
				temp = true;
			}
			if (player.hasStatusEffect(StatusEffects.Confusion)) {
				outputText("\nYou're too confused about who you are to try to attack!");
				temp = true;
			}
			if (player.hasStatusEffect(StatusEffects.Revelation)) {
				if (player.statusEffectv1(StatusEffects.Resolve) == 8 || rand(3) == 0){
					outputText("\nYour mind is flooded with eldritch revelations that attempt to shatter your sanity, but you stand strong, and continue the fight!");
				}else{
					outputText("\nThe knowledge imparted upon you is too much to bear! You can't act!");
					temp = true;
				}

			}
			//Depressed - There can be no hope in this hell. No hope at all.
			if (player.statusEffectv1(StatusEffects.Resolve) == 8 && rand(4) == 0){
				outputText("\nHopeless. The mission is utterly hopeless! You do not bother attacking!");
				temp = true;
			}
			//Stalwart - Many fall in the face of chaos; but not this one, not today.
			if (player.statusEffectv1(StatusEffects.Resolve) == 7 && temp){
				outputText("\n\nYou shake away your daze and focus on the enemy. You will not succumb to weakness!");
				if(player.hasStatusEffect(StatusEffects.Confusion)) player.removeStatusEffect(StatusEffects.Confusion);
				if(player.hasStatusEffect(StatusEffects.IsabellaStunned)) player.removeStatusEffect(StatusEffects.IsabellaStunned);
				if(player.hasStatusEffect(StatusEffects.Stunned)) player.removeStatusEffect(StatusEffects.Stunned);
				if(player.hasStatusEffect(StatusEffects.Whispered)) player.removeStatusEffect(StatusEffects.Whispered);
			}
			return temp;
		}

		public function fancifyDamageRange(minDamage:Number,maxDamage:Number,chance:* = null):String{
        var retv:String = "(" + Math.round(minDamage) + "-" +Math.round(maxDamage) + ")";
        if(chance != null) retv += "(" + Math.round(chance) + "%)";
        return retv;
    	}

        public function fancifyHealRange(minDamage:Number,maxDamage:Number,chance:* = null):String{
            var retv:String = "(" + Math.round(minDamage) + "-" +Math.round(maxDamage) + ")";
            if(chance != null) retv += "(" + Math.round(chance) + "%)";
            return retv;
        }

		public function displayDamage():String{
			return "(" + Math.round(monster.reduceDamageMin(calcDamage(false,player.isDoubleAttacking()),0,true)) + " - " + Math.round(monster.reduceDamageMax(calcDamage(false,player.isDoubleAttacking()),0,true)) + ")";
		}

		public function displayChance():String{
			var retv:String = " (" + hitChance(0);
			if (getNumAttacks() > 0) for (var i:int = 1; i < getNumAttacks(); i++) retv += "/" + hitChance(i);
			retv += "%)";
			return retv;
		}

		//Check to see if the fight is over (health is depleted or lust is full for the champion or all enemies), return true if so.
		public function endFightCheck():Boolean {
			if (!inCombat) return false;
			if (totalHP() < 1) {
				doNext(endHpVictory);
				return true;
			}
			if (lustVictory()) {
				doNext(endLustVictory);
				return true;
			}
			if(monsterArray.length == 1) monsterArray[0] = monster;
			for each(var currMonster:Monster in monsterArray) {
				if (currMonster.playerWinCondition() != null) {
					doNext(currMonster.playerWinCondition());
					return true;
				}
				if (currMonster.playerLossCondition() != null) {
					doNext(currMonster.playerLossCondition());
					return true;
				}
			}
            removeDownedTempMonsters();
			if (player.HP < 1) {
				doNext(endHpLoss);
				return true;
			}
			if (player.lust >= player.maxLust()) {
				doNext(endLustLoss);
				return true;
			}
			return false;
		}

		public function combatMenu(newRound:Boolean = true):void { //If returning from a sub menu set newRound to false
			clearOutput();
			mainView.monsterStatsView.show();
			overrideEndOfRoundFunction = null;
			if(newRound) playerTurn = true;
			mainView.updateCombatView();
			if (monsterArray.length != 0){//have to put this here, at least for now. Putting it in monsterAI screws duplicate calls, same for putting it in combatRoundOver.
				for (var i:int = 0; i < monsterArray.length; i++) monsterArray[i].tookAction = false;
				monster = monsterArray[currTarget];
			}else{
				monster.tookAction = false;
			}
			flags[kFLAGS.IN_COMBAT_USE_PLAYER_WAITED_FLAG] = 0;
			mainView.hideMenuButton(MainView.MENU_DATA);
			mainView.hideMenuButton(MainView.MENU_APPEARANCE);
			mainView.hideMenuButton(MainView.MENU_PERKS);
			hideUpDown();
			if (newRound) combatStatusesUpdate(); //Update Combat Statuses
			display();
			statScreenRefresh();
		//This is now automatic - newRound arg defaults to true:	menuLoc = 0;
			if (combatRoundOver()) return;
			menu();
			var attacks:Function = normalAttack;
			//Standard menu before modifications.
			if (!isWieldingRangedWeapon())
				addButton(0, "Attack", attacks).hint("Attempt to attack the enemy with your " + player.weaponName + " " + displayDamage() + displayChance() + ".  Damage done is determined by your strength and weapon.");
			else if (player.weapon.isMagicStaff())
				addButton(0, "M.Bolt", attacks).hint("Attempt to attack the enemy with a magic bolt from your " + player.weaponName + " " + displayDamage() + displayChance() + ". Damage done is determined by your intelligence, speed and weapon.", "Magic Bolt");
			else if (player.weapon.ammoMax > 0 && flags[kFLAGS.RANGED_AMMO] <= 0)
				addButton(0, "Reload", attacks).hint("Your " + player.weaponName + " is out of ammo.  You'll have to reload it before attacking.");
			else
				addButton(0, "Shoot", attacks).hint("Fire a round at your opponent with your " + player.weaponName + " " + displayDamage() + displayChance() + "  Damage done is determined by your strength, speed and weapon.");

			addButton(1, "Tease", combatTeases.teaseAttack).hint("Attempt to make an enemy more aroused by striking a seductive pose and exposing parts of your body.");
			if (combatAbilities.canUseMagic()) addButton(2, "Spells", combatAbilities.magicMenu).hint("Opens your spells menu, where you can cast any spells you have learned.  Beware, casting spells increases your fatigue, and if you become exhausted you will be easier to defeat.");
			addButton(3, "Items", inventory.inventoryMenu).hint("The inventory allows you to use an item.  Be careful as this leaves you open to a counterattack when in combat.");
			if (player.weaponName != "Light Rail Avenger"){
				addButton(4, "Run", runAway).hint("Choosing to run will let you try to escape from your enemy. However, it will be hard to escape enemies that are faster than you and if you fail, your enemy will get a free attack.").disableIf(!player.canMove(), "You're unable to move.");
			}else{
				addButton(4, "Avenge", combatAbilities.lightRailAvenger).hint("A true follower of the Bushido never flees. Unleash your unique technique, the Light Rail Avenger, and smite this fool!");
			}
			addButton(5, "P. Specials", combatAbilities.physicalSpecials).hint("Physical special attack menu.", "Physical Specials");
			addButton(6, "M. Specials", combatAbilities.magicalSpecials).hint("Mental and supernatural special attack menu.", "Magical Specials");
			addButton(7, "Wait", wait).hint("Take no action for this round.  Why would you do this?  This is a terrible idea.");
			if (monster.hasStatusEffect(StatusEffects.Level)) addButton(7, "Climb", wait).hint("Climb the sand to move away from the sand trap.");
			addButton(8, "Fantasize", fantasize).hint("Fantasize about your opponent in a sexual way.  Its probably a pretty bad idea to do this unless you want to end up getting raped.");
			distanceSelfAb.createButton(10);
			approachSelf.createButton(11);
			if (CoC_Settings.debugBuild && !debug) addButton(9, "Inspect", debugInspect).hint("Use your debug powers to inspect your enemy.");
			if (monster is VolcanicGolem) addButton(7, "Distance", wait).hint("Execute a strategic retreat to avoid the golem's devastating strikes.");
			if (player.hasStatusEffect(StatusEffects.Disarmed) && monster is Dullahan) addButton(7, "Grab Weapon", wait).hint("Rush and grab your weapon!");
			if (player.hasStatusEffect(StatusEffects.TFTerraStar)) addButton(13, "Control Star", combatAbilities.tfTerraStarAttack, true).hint("Guide your star manually for improved accuracy and a chance of additional effects.");
			if (monsterArray.length != 0){
				if (monsterArray[currTarget].HP <= 0 || monsterArray[currTarget].hasStatusEffect(StatusEffects.GuardAB) || (monsterArray[currTarget].lust >= monsterArray[currTarget].maxLust() && !monsterArray[currTarget].ignoreLust)) multiAttack(getLowestLivingTarget());
				if (combatRound == 0 && newRound) multiAttack(0);
			}

			if (monster.hasStatusEffect(StatusEffects.AttackDisabled)) {
				outputText("\nChained up as you are, you can't manage any real physical attacks!");
				addButtonDisabled(0, "Attack", "Chained up as you are, you can't manage any physical attacks!");
			}

			//Disabled physical attacks
			if (!combatAbilities.canUsePAtk()) {
				outputText("  Even physical special attacks are out of the question.");
				addButtonDisabled(5,"P. Specials", "You can't use physical attacks!");
			}

			//Silence: Disables magic menu.
			if (!combatAbilities.canUseMagic() && player.spellCount() > 0) {
				addButtonDisabled(2, "Spells", "You can't use spells!");
			}

			if (!combatAbilities.canUseMAtk()){
				addButtonDisabled(6, "M. Specials", "You can't use Magical abilities!");
			}

			if (player.hasStatusEffect(StatusEffects.SentinelPhysicalDisabled) || player.isAtrophied || !combatAttackData.canReach(player,monster,monster.distance,player.weapon.getAttackRange())){
				addButtonDisabled(0, "Attack", getAttackBlockReason());
			}

			if (player.hasStatusEffect(StatusEffects.SentinelNoTease) || player.isPrude){
				addButtonDisabled(1, "Tease", "You can't tease!");
			}
			//Bound: Struggle or wait
			if (isPlayerBound()) {
				menu();
				addButton(0, "Struggle", struggle);
				addButton(1, "Wait", wait);
			}

			//Stunned: Recover, lose 1 turn.
			if (isPlayerStunned(newRound)) {
				menu();
				addButton(0, "Recover", wait);
			}
			else if (monster.hasStatusEffect(StatusEffects.Constricted)) {
				menu();
				addButton(0, "Squeeze", player.armor.id == armors.VINARMR.id ? combatAbilities.vineConstrict : game.desert.nagaScene.naggaSqueeze).hint("Squeeze some HP out of your opponent! \n\nFatigue Cost: " + player.physicalCost(20) + "");
				if (player.lowerBody.type == LowerBody.NAGA) addButton(1, "Tease", game.desert.nagaScene.naggaTease);
				addButton(4, "Release", game.desert.nagaScene.nagaLeggoMyEggo);
			}
			if (player.hasStatusEffect(StatusEffects.TFSupercharging)) {
				menu();
				addButton(0, "Gather Energy", combatAbilities.tfSupercharge);
			}
		}

		public function canTarget(target:int):Boolean{
			return monsterArray[target].HP > 0 && (monsterArray[target].lust < monsterArray[target].maxLust() || monsterArray[target].ignoreLust) && !monsterArray[target].hasStatusEffect(StatusEffects.GuardAB)
		}

		public function multiAttack(target:int,refresh:Boolean = true):void{
			currTarget = target;
			monster = monsterArray[currTarget];
			if(refresh)combatMenu(false);
		}

		private function getLowestLivingTarget():Number{
			for (var i:int = 0; i < monsterArray.length; i++){
				if (monsterArray[i].HP > 0 && !monsterArray[i].hasStatusEffect(StatusEffects.GuardAB) && (monsterArray[i].lust < monsterArray[i].maxLust() || monsterArray[i].ignoreLust)) return i;
			}
			return i;
		}
		private function normalAttack():void {
			clearOutput();
			attack();
		}

		public function packAttack():void {
			//Determine if dodged!
			var result:Object = combatAvoidDamage({attacker:monster, defender:player, doDodge:true, doParry:false, doBlock:false});
			if (result.dodge == player.EVASION_SPEED) {
				outputText("You duck, weave, and dodge.  Despite their best efforts, the throng of demons only hit the air and each other.");
			}
			//Determine if evaded
			else if (result.dodge == player.EVASION_EVADE) {
				outputText("Using your skills at evading attacks, you anticipate and sidestep " + monster.a + monster.short + "' attacks.");
			}
			//("Misdirection"
			else if (result.dodge == player.EVASION_MISDIRECTION) {
				outputText("Using Raphael's teachings, you anticipate and sidestep " + monster.a + monster.short + "' attacks.");
			}
			//Determine if cat'ed
			else if (result.dodge == player.EVASION_FLEXIBILITY) {
				outputText("With your incredible flexibility, you squeeze out of the way of " + monster.a + monster.short + "' attacks.");
			}
			else if(result.dodge != null) outputText("You duck, weave, and dodge.  Despite their best efforts, the throng of demons only hit the air and each other.");
			else {
				temp = player.reduceDamage(monster.str + monster.weaponAttack,monster); //Determine damage - str
				// modified by enemy toughness!
				if (temp <= 0) {
					temp = 0;
					if (!monster.plural)
						outputText("You deflect and block every " + monster.weaponVerb + " " + monster.a + monster.short + " throw at you.");
					else outputText("You deflect " + monster.a + monster.short + " " + monster.weaponVerb + ".");
				}
				else {
					if (temp <= 5)
						outputText("You are struck a glancing blow by " + monster.a + monster.short + "! ");
					else if (temp <= 10)
						outputText(monster.capitalA + monster.short + " wound you! ");
					else if (temp <= 20)
						outputText(monster.capitalA + monster.short + " stagger you with the force of " + monster.pronoun3 + " " + monster.weaponVerb + "s! ");
					else outputText(monster.capitalA + monster.short + " mutilates you with powerful fists and " + monster.weaponVerb + "s! ");
					takeDamage(temp, true);
				}
				statScreenRefresh();
				outputText("\n");
			}

		}

		public function lustAttack():void {
			if (player.lust < 35) {
				outputText("The " + monster.short + " press in close against you and although they fail to hit you with an attack, the sensation of their skin rubbing against yours feels highly erotic.");
			}
			else if (player.lust < 65) {
				outputText("The push of the " + monster.short + "' sweaty, seductive bodies sliding over yours is deliciously arousing and you feel your ");
				if (player.cocks.length > 0)
					outputText(player.multiCockDescriptLight() + " hardening ");
				else if (player.vaginas.length > 0) outputText(player.vaginaDescript(0) + " get wetter ");
				else outputText("crotch warm up slightly, despite it's featurelessness, ");
				outputText("in response to all the friction.");
			}
			else {
				outputText("As the " + monster.short + " mill around you, their bodies rub constantly over yours, and it becomes harder and harder to keep your thoughts on the fight or resist reaching out to touch a well lubricated cock or pussy as it slips past.  You keep subconsciously moving your ");
				if (player.gender == 1) outputText(player.multiCockDescriptLight() + " towards the nearest inviting hole.");
				if (player.gender == 2) outputText(player.vaginaDescript(0) + " towards the nearest swinging cock.");
				if (player.gender == 3) outputText("aching cock and thirsty pussy towards the nearest thing willing to fuck it.");
				if (player.gender == 0) outputText("groin, before you remember there is nothing there to caress.");
			}
			var lustDmg:int = 10 + player.sens / 10;
			player.takeLustDamage(lustDmg, true);

		}

		private function wait():void {
            flags[kFLAGS.IN_COMBAT_USE_PLAYER_WAITED_FLAG] = 1;
            if(!beforePlayerTurn()){
                return;
            }
			//Gain fatigue if not fighting sand tarps
			if (!monster.hasStatusEffect(StatusEffects.Level)) player.changeFatigue( -5);
			if (player.hasStatusEffect(StatusEffects.Whispered)) {
				clearOutput();
				outputText("You shake off the mental compulsions and ready yourself to fight!\n\n");
				player.removeStatusEffect(StatusEffects.Whispered);
			}
			else if (player.hasStatusEffect(StatusEffects.IsabellaStunned)) {
				clearOutput();
				outputText("You wobble about for some time but manage to recover. Isabella capitalizes on your wasted time to act again.\n\n");
				player.removeStatusEffect(StatusEffects.IsabellaStunned);

			}
			else if (player.hasStatusEffect(StatusEffects.Stunned)) {
				clearOutput();
				outputText("You wobble about, stunned for a moment.  After shaking your head, you clear the stars from your vision, but by then you've squandered your chance to act.\n\n");
				player.removeStatusEffect(StatusEffects.Stunned);
			}
			else if (player.hasStatusEffect(StatusEffects.Confusion)) {
				clearOutput();
				outputText("You shake your head and file your memories in the past, where they belong.  It's time to fight!\n\n");
				player.removeStatusEffect(StatusEffects.Confusion);
			}
			else if(monster.react(monster.CON_PLAYERWAITED)){
				clearOutput();
				outputText("You decide not to take any action this round.\n\n");
				player.createStatusEffect(StatusEffects.WaitReadiness, 0, 0, 0, 0);
			}
			startMonsterTurn();
		}

		private function struggle():void {
			if (monster.hasStatusEffect(StatusEffects.PCTailTangle)) {
				(monster as Kitsune).kitsuneStruggle();
			}
			else if (player.hasStatusEffect(StatusEffects.HolliConstrict)) {
				(monster as Holli).struggleOutOfHolli();
			}
			else if (monster.hasStatusEffect(StatusEffects.QueenBind)) {
				(monster as HarpyQueen).ropeStruggles();
			}
			else if (player.hasStatusEffect(StatusEffects.HarpyBind)) {
				(monster as HarpyMob).harpyHordeGangBangStruggle();
			}
			else if (player.hasStatusEffect(StatusEffects.GooArmorBind)) {
				(monster as GooArmor).struggleAtGooBind();
			}
			else if (player.hasStatusEffect(StatusEffects.GiantGrabbed)) {
				(monster as FrostGiant).giantGrabStruggle();
			}
			else if (player.hasStatusEffect(StatusEffects.CorrWitchBind)) {
				(monster as CorruptedSandWitch).corrWitchStruggle();
			}
			else monster.struggle();
			startMonsterTurn();
		}

		private function debugInspect():void {
			outputText(monster.generateDebugDescription());
			doNext(playerMenu);
		}

		//Fantasize
		public function fantasize():void {
			if(!beforePlayerTurn()){
                return;
            }
			var lustDmg:int =  0;
			doNext(combatMenu);
			clearOutput();
			if (monster.short == "frost giant" && (player.hasStatusEffect(StatusEffects.GiantBoulder))) {
				lustDmg = 10 + rand(player.lib / 5 + player.cor / 8);
				player.takeLustDamage(lustDmg, true, false);
				(monster as FrostGiant).giantBoulderFantasize();
				startMonsterTurn();
				return;
			}
			if (monster.short == "outsider") {
				outputText("Something about this being makes you start to fantasize about it. There's nothing erotic about its form, per se, but still, you begin to feel hot just looking at it.");
				lustDmg = 5 + rand(player.lib/8+player.cor/8)
			}
			else if (player.armorName == "goo armor") {
				outputText("As you fantasize, you feel Valeria rubbing her gooey body all across your sensitive skin");
				if (player.gender > 0) outputText(" and genitals");
				outputText(", arousing you even further.\n");
				lustDmg = 25 + rand(player.lib/8+player.cor/8)
			}
			else if (player.balls > 0 && player.ballSize >= 10 && rand(2) == 0) {
				outputText("You daydream about fucking " + monster.a + monster.short + ", feeling your balls swell with seed as you prepare to fuck " + monster.pronoun2 + " full of cum.");
				lustDmg = 5 + rand(player.lib/8+player.cor/8);
				outputText("You aren't sure if it's just the fantasy, but your " + player.ballsDescriptLight() + " do feel fuller than before...");
				player.hoursSinceCum += 50;
			}
			else if (player.biggestTitSize() >= 6 && rand(2) == 0) {
				outputText("You fantasize about grabbing " + monster.a + monster.short + " and shoving " + monster.pronoun2 + " in between your jiggling mammaries, nearly suffocating " + monster.pronoun2 + " as you have your way.");
				lustDmg = 5 + rand(player.lib/8+player.cor/8)
			}
			else if (player.biggestLactation() >= 6 && rand(2) == 0) {
				outputText("You fantasize about grabbing " + monster.a + monster.short + " and forcing " + monster.pronoun2 + " against a " + player.nippleDescript(0) + ", and feeling your milk let down.  The desire to forcefeed SOMETHING makes your nipples hard and moist with milk.");
				lustDmg = 5 + rand(player.lib/8+player.cor/8)
			}
			else {
				outputText("You fill your mind with perverted thoughts about " + monster.a + monster.short + ", picturing " + monster.pronoun2 + " in all kinds of perverse situations with you.");
				lustDmg = 10+rand(player.lib/5+player.cor/8);
			}
			if (lustDmg >= 20) outputText("The fantasy is so vivid and pleasurable you wish it was happening now.  You wonder if " + monster.a + monster.short + " can tell what you were thinking.");

			player.takeLustDamage(lustDmg, true, false);
			outputText("\n\n");
			if (player.lust >= player.maxLust()) {
				if (monster.short == "pod") {
					outputText("You nearly orgasm, but the terror of the situation reasserts itself, muting your body's need for release.  If you don't escape soon, you have no doubt you'll be too fucked up to ever try again!");
					player.lust = 99;
					player.takeLustDamage(-25, true);
					outputText("\n\n");
				}
				else {
					doNext(endLustLoss);
					return;
				}
			}
			startMonsterTurn();
		}

		public function fatigueRecovery():void {
			player.changeFatigue(-1);
			if (player.findPerk(PerkLib.EnlightenedNinetails) >= 0 || player.findPerk(PerkLib.CorruptedNinetails) >= 0) player.changeFatigue(-(1+rand(3)));
		}

		//Hit chance
		public function hitChance(attackNum:int = 0):Number{
			var toHitChance:Number = monster.standardDodgeFunc(player);
			toHitChance -= attackNum * 20;
			if (player.weapon === WeaponLib.FISTS) {
				toHitChance += 2 * player.masteryLevel(MasteryLib.Fist);
				if (player.hasPerk(PerkLib.WarDance)) toHitChance += 20;
			}
			else toHitChance += player.weapon.masteryLevel();
			return toHitChance;
		}

		public function getNumAttacks():int{
			if (player.isDoubleAttacking()) return 2;
			return 1;
		}

		//ATTACK
		public function attack():void {
			var numAttacks:int = getNumAttacks();
			fatigueRecovery();
			if (player.weapon.masteryLevel() >= 5) player.changeFatigue(-1 - rand(2));

            if(!beforePlayerTurn()){
				return;
			}
			if (player.hasStatusEffect(StatusEffects.Sealed) && player.statusEffectv2(StatusEffects.Sealed) == 0 && !isWieldingRangedWeapon()) {
				outputText("You attempt to attack, but at the last moment your body wrenches away, preventing you from even coming close to landing a blow!  The kitsune's seals have made normal attack impossible!  Maybe you could try something else?\n\n");
				startMonsterTurn();
				return;
			}
			if ((game.fetishManager.compare(FetishManager.FETISH_NO_COMBAT) && (rand(3) > 0 || monster is Ceraph)) && !game.urtaQuest.isUrta() && !isWieldingRangedWeapon()) {
				outputText("You attempt to attack, but at the last moment your body wrenches away, preventing you from even coming close to landing a blow!  Ceraph's piercings have made normal attack impossible!  Maybe you could try something else?\n\n");
				startMonsterTurn();
				return;
			}
			flags[kFLAGS.LAST_ATTACK_TYPE] = 0;

			if (player.statusEffectv2(StatusEffects.CounterAB) == 3){
				outputText("You move into the stance taught to you by the Dullahan. You'll not be able to strike as effectively, but you have a chance of countering enemy attacks!\n");
			}
			//Blind
			if (player.hasStatusEffect(StatusEffects.Blind) && player.statusEffectv1(StatusEffects.CounterAB) != 1) {
				outputText("You attempt to attack, but as blinded as you are right now, you doubt you'll have much luck!  ");
			}

			for (var i:int = 0; i < numAttacks;i++){
				if (performRegularAttack(i)){
					outputText("\n");
					break;
				}else{
					outputText("\n");
				}
			}
			if (isWieldingRangedWeapon()) flags[kFLAGS.LAST_ATTACK_TYPE] = 4;
			if (player.weapon.isMagicStaff() && player.findPerk(PerkLib.StaffChanneling) >= 0) flags[kFLAGS.LAST_ATTACK_TYPE] = 2;
			checkAchievementDamage(damage);
			startMonsterTurn();
			return;
		}

		public function performRegularAttack(currAttack:Number):Boolean{
			return performAttack(calcDamage(true,player.isDoubleAttacking()),currAttack);
		}

		public function performAttack(_damage:Number,attackNumber:int = 0,forceCrit:Boolean = false,extraAP:Number = 0,ignoreDecreasingHitChance:Boolean = false):Boolean{
			damage = _damage;
			var thisHitChance:Number = hitChance(ignoreDecreasingHitChance ? attackNumber : 0);
			if (player.weapon.ammoMax != 0){
				if (flags[kFLAGS.RANGED_AMMO] <= 0){
					flags[kFLAGS.RANGED_AMMO] = player.weapon.ammoMax;
					outputText("You open the chamber of your " + player.weapon.name + " to reload the ammunition. This takes up an action.");
					return true;
				}else flags[kFLAGS.RANGED_AMMO]--;
			}
			if (!monster.react(monster.CON_BEFOREATTACKED)) return true;

			player.weapon.weaponXP(2+rand(7));
			//Determine if dodged!
			var attackResult:Object = combatAvoidDamage({attacker:player,defender:monster,doFatigue:true,toHitChance:thisHitChance});
			if (attackResult.dodge != null && player.statusEffectv1(StatusEffects.CounterAB) != 1) {
				//Akbal dodges special education
				if (monster.short == "Akbal") outputText("Akbal moves like lightning, weaving in and out of your furious strikes with the speed and grace befitting his jaguar body.");
				else if (monster.short == "plain girl") outputText("You wait patiently for your opponent to drop her guard. She ducks in and throws a right cross, which you roll away from before smacking your " + player.weaponName + " against her side. Astonishingly, the attack appears to phase right through her, not affecting her in the slightest. You glance down to your " + player.weaponName + " as if betrayed.");
				else if (monster.short == "kitsune") {
					//Player Miss:
					outputText("You swing your [weapon] ferociously, confident that you can strike a crushing blow.  To your surprise, you stumble awkwardly as the attack passes straight through her - a mirage!  You curse as you hear a giggle behind you, turning to face her once again.");
				}
				else {
					if (player.weapon == weapons.HNTCANE && rand(2) == 0) {
						if (rand(2) == 0) outputText("You slice through the air with your cane, completely missing your enemy.");
						else outputText("You lunge at your enemy with the cane.  It glows with a golden light but fails to actually hit anything.");
					}
					switch(rand(3)){
					case 0: outputText(monster.capitalA + monster.short + " narrowly avoids your attack!");
							break;
					case 1: outputText(monster.capitalA + monster.short + " dodges your attack with superior quickness!");
							break;
					case 2: outputText(monster.capitalA + monster.short + " deftly avoids your slow attack.");
							break;
					}
					if (player.hasPerk(PerkLib.Scattering)){
						outputText("Your [weapon]'s scattering attack manages to damage " + monster.a + monster.short + "!");
						damage = doDamage(damage * player.perkv1(PerkLib.Scattering),true,true);
					}
				}
			player.weapon.weaponXP(1+rand(4));
			return false;
			}
			//BLOCKED ATTACK:
			if (monster.hasStatusEffect(StatusEffects.Earthshield) && rand(4) == 0) {
				outputText("Your strike is deflected by the wall of sand, dirt, and rock!  Damn!");
				/*if (player.hasStatusEffect(StatusEffects.FirstAttack)) {
					attack();
					return;
				}*/
				return false;
			}
			if (attackResult.block){
				outputText(monster.capitalA + monster.short + " manages to block your attack with " + monster.pronoun3 + " " + monster.shieldName + "!");
				return false;
			}
			if (attackResult.parry){
				outputText(monster.capitalA + monster.short + " manages to parry your attack with " + monster.pronoun3 + " " + monster.weaponName + "!");
				return false;
			}
			if (player.weapon === WeaponLib.FISTS && player.hasPerk(PerkLib.WarDance)) damage *= 1.15;
			//Determine if critical hit!
			var crit:Boolean = false;
			crit = combatCritical(player,monster) || forceCrit;
			if (crit && inCombat){
				var critDamage:Number = 1.75;
                	critDamage *= player.getBonusStatMultiplicative(BonusDerivedStats.critD);
					damage *= critDamage;
				}
			if (player.statusEffectv2(StatusEffects.CounterAB) == 3){
                damage *= .75;
			}
			//One final round
            damage = Math.round(monster.reduceDamage(damage,player,0,false,false,false,false,true));

			if (!monster.react(monster.CON_WHENATTACKED)){
				return true;
			}

			if (player.weapon == weapons.HNTCANE) {
				switch(rand(2)) {
					case 0:
						outputText("You swing your cane through the air. The light wood lands with a loud CRACK that is probably more noisy than painful. ");
                        damage *= 0.5;
						break;
					case 1:
						outputText("You brandish your cane like a sword, slicing it through the air. It thumps against your adversary, but doesn’t really seem to harm them much. ");
                        damage *= 0.5;
						break;
					default:
				}
			}

			if (damage > 0) {
                damage = doDamage(damage);
			}

			if (damage <= 0) {
                damage = 0;
				outputText("Your attacks are deflected or blocked by " + monster.a + monster.short + ".");
			}
			else {
				outputText("You hit " + monster.a + monster.short + "! ");
				if (crit) outputText("Critical hit! ");
				outputText("(" + damage + ")")
			}
			if (player.findPerk(PerkLib.BrutalBlows) >= 0 && player.str > 75 && !isWieldingRangedWeapon()) {
				if (monster.armorDef > 0) outputText("\nYour hits are so brutal that you damage " + monster.a + monster.short + "'s defenses!");
				if (monster.armorDef * 0.75 > 0) monster.armorDef *= 0.75;
				else monster.armorDef = 0;
			}
			if(player.hasPerk(PerkLib.SeverTendons) && rand(100) <= 25){
				outputText("\nYour precision strikes partially cripple [themonster], causing permanent damage to [monster.pronoun3] strength and speed!");
				monster.spe -= 5;
				monster.str -= 5;
			}
			//Damage cane.
			if (player.weapon == weapons.HNTCANE) {
				flags[kFLAGS.ERLKING_CANE_ATTACK_COUNTER]++;
				//Break cane
				if (flags[kFLAGS.ERLKING_CANE_ATTACK_COUNTER] >= 10 && rand(20) == 0) {
					outputText("\nThe cane you're wielding finally snaps! It looks like you won't be able to use it anymore.");
					player.setWeapon(WeaponLib.FISTS);
				}
			}

			if (damage > 0) {
				player.weapon.execEffect();//applies any weapon effect a weapon might have. Check WeaponEffects.as for the list.
				if (player.hasStatusEffect(StatusEffects.Leeching)){
					var healAmount:Number = Math.round((damage * player.statusEffectv1(StatusEffects.Leeching))/100);
					player.HPChange(healAmount, false);
					outputText("(" + healAmount + ")");
				}
			}
			if (player.weaponName == "katana" && monster.HP <= 0 && player.statusEffectv1(StatusEffects.CounterAB) == 1) {
				awardAchievement("Revengeance", kACHIEVEMENTS.COMBAT_REVENGEANCE);
			}
			if (!monster.react(monster.CON_AFTERATTACKED) || !monster.react(monster.CON_AFTERDAMAGED)) return true;
			return false;
	}

		public function combatCritical(attacker:Creature,defender:Creature):Boolean {
			var critChance:Number = attacker.getBaseCritChance();
            if (defender is VolcanicGolem && defender.hasStatusEffect(StatusEffects.Stunned)) critChance += 40;
            if(attacker.hasPerk(PerkLib.Bloodhound) && defender.isBleeding()) critChance += 10;
			return rand(100) <= critChance;
		}

		public function combatBlock(attacker:Creature, defender:Creature, doFatigue:Boolean = false):Boolean {
			if (defender.hasStatusEffect(StatusEffects.TFSupercharging)) return false;
			//Set chance
			var blockChance:int = 20 + defender.shieldBlock + Math.floor((defender.str - attacker.str) / 5);
			if (defender.findPerk(PerkLib.ShieldMastery) >= 0 && defender.tou >= 50) blockChance += (defender.tou - 50) / 5;
			if (defender.masteryLevel(MasteryLib.Shield) >= 5) blockChance += 5;
			if (defender is Player && player.shield == shields.AKBSHLD) {
				if ((attacker as Monster).hasTag("Demon")) blockChance += 10;
			}
			//Masochistic. Those who covet injury find it in no short supply.
			if (defender.statusEffectv1(StatusEffects.Resolve) == 2) blockChance -= defender.statusEffectv3(StatusEffects.Resolve);
			if (blockChance < 10) blockChance = 10;
			//Fatigue limit
			var fatigueLimit:int = defender.maxFatigue() - defender.physicalCost(10);
			if (blockChance >= (rand(100) + 1) && defender.fatigue <= fatigueLimit && defender.shieldName != "nothing" && defender.shieldName != "") {
				if (doFatigue) defender.changeFatigue(10, 2);
				if (defender is Player) player.masteryXP(MasteryLib.Shield, 5+rand(31));
				return true;
			}
			else {
				if (defender is Player && defender.shieldName != "nothing" && defender.shieldName != "") player.masteryXP(MasteryLib.Shield, 5+rand(11));
				return false;
			}
		}
		/**returns an object that tells you all you need to know about if a defender avoided an attack. Attacks are only parried if they're not dodged, and only blocked if they're not parried.
		* @param doDodge whether or not dodge should be possible.
		* @param toHitChance chance to hit. If not set, standardDodgeFunction will be used.
		* @param doParry whether or not parry should be possible.
		* @param doBlock whether or not blocking should be possible. Enemies cannot block, but they can parry.
		* @param doFatigue if block is possible, whether or not doing so will drain fatigue.
		*/
		public function combatAvoidDamage(def:*):Object{
			//attacker:Creature, defender:Creature, doDodge:Boolean = true, doParry:Boolean = true, doBlock:Boolean = true, doFatigue:Boolean = false, toHitChance:Number = NaN
			var attacker:Creature = def.attacker || game.player;
			var defender:Creature = def.defender || game.monster;
			var doDodge:Boolean = def.doDodge == null ? true : def.doDodge;
			var doParry:Boolean = def.doParry == null ? true : def.doParry;
			var doBlock:Boolean = def.doBlock == null ? true : def.doBlock;
            var doCounter:Boolean = def.doCounter == null ? false : def.doCounter;
			var doFatigue:Boolean = def.doFatigue || false;
			var toHitChance:Number = def.toHitChance || defender.standardDodgeFunc(attacker);
			//if (isNaN(toHitChance)) toHitChance = defender.standardDodgeFunc(attacker);
			var defenderReaction:Object = {dodge:null, parry:false, block:false, counter:false, failed:true, success:false};
			if(doCounter){
                defenderReaction.counter = attacker.attackCountered(defender);
			}
			if (doDodge) {
				defenderReaction.dodge = defender.getEvasionReason(attacker, toHitChance);
				if (attacker.hasPerk(PerkLib.Frustration)){
					if (defenderReaction.dodge) attacker.addPerkValue(PerkLib.Frustration, 1, 10);
					else attacker.setPerkValue(PerkLib.Frustration, 1, 0);
				}
			}
            if(defender.hasStatusEffect(StatusEffects.Backstab) && (defenderReaction.dodge == null || !defenderReaction.dodge)) defender.changeStatusValue(StatusEffects.Backstab,1,1);
			if (defenderReaction.dodge == null){
				if (doParry) defenderReaction.parry = defender.combatParry();
				if (defenderReaction.parry == false && doBlock) defenderReaction.block = combatBlock(attacker,defender,doFatigue);
			}
			defenderReaction.failed = !defenderReaction.counter && !defenderReaction.parry && !defenderReaction.block && (defenderReaction.dodge == null);
			defenderReaction.success = !defenderReaction.failed; //this redundancy is here just to make my bad stoopid brain get better good think
			return defenderReaction;
		}

		public function isWieldingRangedWeapon():Boolean {
			if (player.weapon.getAttackRange() == CombatAttackData.RANGE_RANGED) return true;
			else return false;
		}

		public function removeDownedTempMonsters():void{
			if(monsterArray.length == 1) return;
			for(var i:int = 0;i < monsterArray.length;i++){
                if ((monsterArray[i].HP <= 0 || (monsterArray[i].lust >= monsterArray[i].maxLust() && !monsterArray[i].ignoreLust)) && monsterArray[i].temporary){
                    monsterArray.splice(i,1);
					if(currTarget == i) currTarget = 0;
                }
			}

		}

		public function globalMod(damage:Number):Number{//physMod applies only to physical attacks. spellMod only applies to magical attacks. globalMod applies to everything.
				//Powerful. Anger is power - unleash it!
				if (player.statusEffectv1(StatusEffects.Resolve) == 5) damage *= player.statusEffectv2(StatusEffects.Resolve);
				//Depressed. There can be no hope in this hell, no hope at all.
				if (player.statusEffectv1(StatusEffects.Resolve) == 6) damage *= player.statusEffectv2(StatusEffects.Resolve);
				// Uma's Massage Bonuses
				var stat:StatusEffect = player.statusEffectByType(StatusEffects.UmasMassage);
				if (stat != null) {
					if (stat.value1 == UmasShop.MASSAGE_POWER) {
						damage *= stat.value2;
					}
				}
				if (monster.hasPerk(PerkLib.Invincible)) damage = 0;
				if (player.hasStatusEffect(StatusEffects.Nothingness) && (damageType == DAMAGE_PHYSICAL_MELEE || damageType == DAMAGE_PHYSICAL_RANGED)) damage = 0;
				damage *= player.getBonusStatMultiplicative(BonusDerivedStats.globalMod);
				return Math.round(damage);
		}
		//Moved this here so we can get attack damage outside of combat.
        public function getBase(init:Number,doubleAttack:Boolean):Number {
			var retv:Number = init;
            if (doubleAttack) {
				var max:Number = 60;
				if(!player.isResetAscension()){
					max += player.newGamePlusMod() * 15;
				}
				retv = Math.min(retv, max);
            }
			return retv;
        }

		public function getBaseAndAttributeBonus(doubleAttack:Boolean):Number{
            // init value depending on weapon type
            if (isWieldingRangedWeapon()) {
                if (player.weapon.isMagicStaff()){
                    damageType = DAMAGE_MAGICAL_RANGED;
                    return getBase(player.inte + player.spe * 0.1, doubleAttack);

                }else{
                    damageType = DAMAGE_PHYSICAL_RANGED;
                    return getBase(player.spe + player.inte * 0.2, doubleAttack);
                }
            }else{
                damageType = DAMAGE_PHYSICAL_MELEE;
                return (player.weapon.isLarge() ? getBase(player.str * 1.3, doubleAttack) : getBase(player.str, doubleAttack));
            }
		}

		public function calcDamage(inCombat:Boolean = true, doubleAttack:Boolean = false):Number{
			var damage:Number = 0;
			//------------
			// DAMAGE
			//------------
			//Determine damage
			//BASIC DAMAGE STUFF
			damage += getBaseAndAttributeBonus(doubleAttack);
			//Weapon addition!
			damage += player.weaponAttack;
			if (damage < 10) damage = 10;
            damage += player.getBonusStat(BonusDerivedStats.attackDamage);
			//Damage post processing!
			damage *= player.getBonusStatMultiplicative(BonusDerivedStats.attackDamage);
			//Player countering
			if (player.statusEffectv1(StatusEffects.CounterAB) == 1) damage *= .5;
			if (player.findPerk(PerkLib.ChiReflowMagic) >= 0) damage *= UmasShop.NEEDLEWORK_MAGIC_REGULAR_MULTI;
			if (player.findPerk(PerkLib.ChiReflowAttack) >= 0) damage *= UmasShop.NEEDLEWORK_ATTACK_REGULAR_MULTI;
			damage *= player.physMod();
			damage = doDamage(damage, false, false, false);
			return globalMod(damage);
		}

		/**
		 * Deal damage to opponent.
		 * @param	damage	The amount of damage dealt.
		 * @param	apply	If true, deducts HP from monster.
		 * @param	display	If true, displays the damage done.
		 * @param   react 	Whether the enemy should react to the damage dealt.
		 * @param   applyMod Whether to apply global damage modifiers like Sadist.
		 * @return	damage	The amount of damage.
		 */
		//Certain perks are applied here, because they're global, not restricted to regular attacks.
		public function doDamage(damage:Number, apply:Boolean = true, display:Boolean = false, react:Boolean = true,applyMod:Boolean = false):Number {
			if (damageType == DAMAGE_NO_ATTACK && apply){
				trace("doDamage called with no damageType set. Defaulting to DAMAGE_PHYSICAL_MELEE");
				damageType = DAMAGE_PHYSICAL_MELEE;
			}
			if (react) damage = monster.handleDamaged(damage, apply);
			if (player.findPerk(PerkLib.Sadist) >= 0 && applyMod) {
				player.takeLustDamage(3, true);
			}
			damage = Math.round(damage);
			if (damage < 0) damage = 1;
			if (apply){
			monster.HP -= damage;
			}
			if (display){output.text(getDamageText(damage));
				if(react) monster.react(monster.CON_AFTERDAMAGED);
			}
			//Isabella gets mad
			if (apply && monster.short == "Isabella" && !monster.hasStatusEffect(StatusEffects.Sparring)) {
				flags[kFLAGS.ISABELLA_AFFECTION]--;
				//Keep in bounds
				if (flags[kFLAGS.ISABELLA_AFFECTION] < 0) flags[kFLAGS.ISABELLA_AFFECTION] = 0;
			}
			//Interrupt gigaflare if necessary.
			if (monster.hasStatusEffect(StatusEffects.Gigafire)) monster.addStatusValue(StatusEffects.Gigafire, 1, damage);
			//Keep shit in bounds.
			if (monster.HP < 0) monster.HP = 0;
			return damage;
		}

		public function takeDamage(damage:Number, display:Boolean = false):Number {
			return player.takeDamage(damage, display);
		}

		public function getDamageText(damage:Number):String
		{
			var color:String;
			if (damage > 0)  color = mainViewManager.colorHpMinus();
			if (damage == 0) color = "#000080";
			if (damage < 0)  color = mainViewManager.colorHpPlus();
			return " (" + damage + ") ";
		}

		public function finishCombat():void
		{
			var hpVictory:Boolean = totalHP() < 1;
			if (hpVictory) {
				outputText("You defeat " + monster.a + monster.short + ".\n");
			} else {
				outputText("You smile as " + monster.a + monster.short + " collapses and begins masturbating feverishly.");
			}
			cleanupAfterCombat();
		}
		public function dropItem(monster:Monster, nextFunc:Function = null):void {
			if (nextFunc == null) nextFunc = camp.returnToCampUseOneHour;
			if (monster.hasStatusEffect(StatusEffects.NoLoot)) {
				return;
			}
			var itype:ItemType = monster.dropLoot();
			if (monster.short == "tit-fucked Minotaur") {
				itype = consumables.MINOCUM;
			}
			if (monster is Minotaur) {
				if (monster.weaponName == "axe") {
					if (rand(2) == 0) {
						//50% breakage!
						if (rand(2) == 0) {
							itype = weapons.L__AXE;
							if (player.tallness < 78 && player.str < 90) {
								outputText("\nYou find a large axe on the minotaur, but it is too big for a person of your stature to comfortably carry.  ");
								if (rand(2) == 0) itype = null;
								else itype = consumables.SDELITE;
							}
							//Not too tall, dont rob of axe!
							else plotFight = true;
						}
						else outputText("\nThe minotaur's axe appears to have been broken during the fight, rendering it useless.  ");
					}
					else itype = consumables.MINOBLO;
				}
			}
			if (monster is BeeGirl) {
				//force honey drop if milked
				if (flags[kFLAGS.FORCE_BEE_TO_PRODUCE_HONEY] == 1) {
					if (rand(2) == 0) itype = consumables.BEEHONY;
					else itype = consumables.PURHONY;
					flags[kFLAGS.FORCE_BEE_TO_PRODUCE_HONEY] = 0;
				}
			}
			if (monster is Jojo && flags[kFLAGS.JOJO_STATUS] > 4) {
				if (rand(2) == 0) itype = consumables.INCUBID;
				else {
					if (rand(2) == 0) itype = consumables.B__BOOK;
					else itype = consumables.SUCMILK;
				}
			}
			if (monster is Harpy || monster is Sophie) {
				if (rand((player.findPerk(PerkLib.HistoryThief2) >= 0) ? 9 : 10) == 0) itype = armors.W_ROBES;
				else if (rand(3) == 0 && player.findPerk(PerkLib.LuststickAdapted) >= 0) itype = consumables.LUSTSTK;
				else itype = consumables.GLDSEED;
			}
			//Chance of armor if at level 1 pierce fetish
			if (!plotFight && !(monster is Ember) && !(monster is Kiha) && !(monster is Hel) && !(monster is Isabella)
					&& game.fetishManager.Fetish == FetishManager.FETISH_EXHIBITION && rand(10) == 0 && !player.hasItem(armors.SEDUCTA, 1) && !game.ceraphFollowerScene.ceraphIsFollower()) {
				itype = armors.SEDUCTA;
			}

			if (itype == null && !plotFight && rand((player.findPerk(PerkLib.HistoryThief2) >= 0) ? 150 : 200) == 0 && player.level >= 7) itype = consumables.BROBREW;
			if (itype == null && !plotFight && rand((player.findPerk(PerkLib.HistoryThief2) >= 0) ? 150 : 200) == 0 && player.level >= 7) itype = consumables.BIMBOLQ;
			if (itype == null && !plotFight && rand((player.findPerk(PerkLib.HistoryThief2) >= 0) ? 750 : 1000) == 0 && player.level >= 7) itype = consumables.RAINDYE;
			//Chance of eggs if Easter!
			if (itype == null && !plotFight && rand((player.findPerk(PerkLib.HistoryThief2) >= 0) ? 5 : 6) == 0 && isEaster()) {
				temp = rand(13);
				if (temp == 0) itype =consumables.BROWNEG;
				if (temp == 1) itype =consumables.L_BRNEG;
				if (temp == 2) itype =consumables.PURPLEG;
				if (temp == 3) itype =consumables.L_PRPEG;
				if (temp == 4) itype =consumables.BLUEEGG;
				if (temp == 5) itype =consumables.L_BLUEG;
				if (temp == 6) itype =consumables.PINKEGG;
				if (temp == 7) itype =consumables.NPNKEGG;
				if (temp == 8) itype =consumables.L_PNKEG;
				if (temp == 9) itype =consumables.L_WHTEG;
				if (temp == 10) itype =consumables.WHITEEG;
				if (temp == 11) itype =consumables.BLACKEG;
				if (temp == 12) itype = consumables.L_BLKEG;
				flags[kFLAGS.ACHIEVEMENT_PROGRESS_EGG_HUNTER]++;
			}
			//Ring drops!
			if (itype == null && !plotFight && rand((player.findPerk(PerkLib.HistoryThief2) >= 0) ? 150 : 200) <= 0 + Math.min(6, Math.floor(monster.level / 10))) { //Ring drops!
				var ringDropTable:Array = [];
				ringDropTable.push(jewelries.SILVRNG);
				if (monster.level < 10) ringDropTable.push(jewelries.SILVRNG);
				if (monster.level < 15 && rand(2) == 0) ringDropTable.push(jewelries.SILVRNG);
				ringDropTable.push(jewelries.GOLDRNG);
				if (monster.level < 20) ringDropTable.push(jewelries.GOLDRNG);
				ringDropTable.push(jewelries.PLATRNG);
				if (rand(2) == 0) ringDropTable.push(jewelries.DIAMRNG);
				if (monster.level >= 15 && rand(4) == 0) ringDropTable.push(jewelries.LTHCRNG);
				if (monster.level >= 25 && rand(3) == 0) ringDropTable.push(jewelries.LTHCRNG);
				if (monster.level >= 1 && monster.level < 15) {
					ringDropTable.push(jewelries.CRIMRN1);
					ringDropTable.push(jewelries.FERTRN1);
					ringDropTable.push(jewelries.ICE_RN1);
					ringDropTable.push(jewelries.CRITRN1);
					ringDropTable.push(jewelries.REGNRN1);
					ringDropTable.push(jewelries.LIFERN1);
					ringDropTable.push(jewelries.MYSTRN1);
					ringDropTable.push(jewelries.POWRRN1);
				}
				if (monster.level >= 11 && monster.level < 25) {
					ringDropTable.push(jewelries.CRIMRN2);
					ringDropTable.push(jewelries.FERTRN2);
					ringDropTable.push(jewelries.ICE_RN2);
					ringDropTable.push(jewelries.CRITRN2);
					ringDropTable.push(jewelries.REGNRN2);
					ringDropTable.push(jewelries.LIFERN2);
					ringDropTable.push(jewelries.MYSTRN2);
					ringDropTable.push(jewelries.POWRRN2);
				}
				if (monster.level >= 21) {
					ringDropTable.push(jewelries.CRIMRN3);
					ringDropTable.push(jewelries.FERTRN3);
					ringDropTable.push(jewelries.ICE_RN3);
					ringDropTable.push(jewelries.CRITRN3);
					ringDropTable.push(jewelries.REGNRN3);
					ringDropTable.push(jewelries.LIFERN3);
					ringDropTable.push(jewelries.MYSTRN3);
					ringDropTable.push(jewelries.POWRRN3);
				}

			itype = ringDropTable[rand(ringDropTable.length)];
			}
			//Bonus loot overrides others
			if (flags[kFLAGS.BONUS_ITEM_AFTER_COMBAT_ID] != "") {
				itype = ItemType.lookupItem(flags[kFLAGS.BONUS_ITEM_AFTER_COMBAT_ID]);
			}
			monster.handleAwardItemText(itype); //Each monster can now override the default award text
			if (itype != null) {
				if (inDungeon)
					inventory.takeItem(itype, playerMenu);
				else inventory.takeItem(itype, nextFunc);
			}
		}
		public function awardPlayer(nextFunc:Function = null):void
		{
			monster = monsterArray[0];
			if (nextFunc == null) nextFunc = camp.returnToCampUseOneHour; //Default to returning to camp.
			var totalGems:Number = 0;
			for (var i:int = 0; i < monsterArray.length; i++) {
				totalGems += monsterArray[i].gems;

				if (player.findPerk(PerkLib.HistoryWhore) >= 0 || player.findPerk(PerkLib.HistoryWhore2) >= 0) {
					var bonusGems3:int = (totalGems * 0.04) * player.masteryLevel(MasteryLib.Tease);
					if (monsterArray[i].lust >= monsterArray[i].maxLust()) totalGems += bonusGems3;
				}
			}
			if (player.countCockSocks("gilded") > 0) {
				var bonusGems:int = totalGems * 0.15 + 5 * player.countCockSocks("gilded");
				totalGems += bonusGems;
			}
			if (player.findPerk(PerkLib.HistoryFortune) >= 0 || player.findPerk(PerkLib.HistoryFortune2) >= 0) {
				var bonusGems2:int = totalGems * 0.15;
				totalGems += bonusGems2;
			}
			if (player.findPerk(PerkLib.HistoryThief2) >= 0) {
				totalGems *= 1 + (player.spe * 0.0015);
			}
			if (player.findPerk(PerkLib.AscensionFortune) >= 0) {
				totalGems *= 1 + (player.perkv1(PerkLib.AscensionFortune) * 0.1);
			}
			totalGems = Math.round(totalGems);

			var totalXP:Number = 0;
			for (var i:int = 0; i < monsterArray.length; i++) totalXP += monsterArray[i].XP;
			if (player.isChild()) totalXP *= 1.2;
			if (player.isTeen()) totalXP *= 1.05;
			if (player.isElder()) totalXP *= 0.7;
			totalXP = Math.round(totalXP);

			monster.gems = totalGems;
			monster.XP = totalXP;
			monster.handleAwardText(); //Each monster can now override the default award text

			if (!inDungeon && !inRoomedDungeon && !prison.inPrison) { //Not in dungeons
				if (nextFunc != null) doNext(nextFunc);
				else doNext(playerMenu);
			}
			else {
				if (nextFunc != null) doNext(nextFunc);
				else doNext(playerMenu);
			}
			dropItem(monster, nextFunc);
			inCombat = false;

			player.gems += totalGems;
			player.XP += totalXP;
			mainView.statsView.showStatUp('xp');
			dynStats("lust", 0, "scale", false); //Forces up arrow.
		}

		//Clear statuses
		public function clearStatuses():void {
			player.clearStatuses();
			for (var a:/*StatusEffect*/Array=monster.statusEffects.slice(),n:int=a.length,i:int=0;i<n;i++) {
				// Using a copy of array because some effects will be removed
				a[i].onCombatEnd();
			}
		}
		//Update combat status effects
		private function combatStatusesUpdate():void {
			//old outfit used for fetish cultists
			var oldOutfit:String = "";
			var changed:Boolean = false;
			//Reset menuloc
		//This is now automatic - newRound arg defaults to true:	menuLoc = 0;
			hideUpDown();
			if (player.hasStatusEffect(StatusEffects.Sealed)) {
				//Countdown and remove as necessary
				if (player.statusEffectv1(StatusEffects.Sealed) > 0) {
					player.addStatusValue(StatusEffects.Sealed,1,-1);
					if (player.statusEffectv1(StatusEffects.Sealed) <= 0) player.removeStatusEffect(StatusEffects.Sealed);
					else outputText("One of your combat abilities is currently sealed by magic!\n\n");
				}
			}
			if (monsterArray.length == 1) monster.combatRoundUpdate();
			else{
				for (var i:int = 0; i < monsterArray.length; i++){
					monsterArray[i].combatRoundUpdate();
				}
			}
			if (player.hasStatusEffect(StatusEffects.WaitReadiness)) {
                player.removeStatusEffect(StatusEffects.WaitReadiness);
				if(player.hasPerk(PerkLib.Patience)){
					player.setPerkValue(PerkLib.Patience,0,20);
                    player.setPerkValue(PerkLib.Patience,1,10);
                    player.setPerkValue(PerkLib.Patience,2,10);
				}
            }else{
                if(player.hasPerk(PerkLib.Patience)){
                    player.setPerkValue(PerkLib.Patience,0,0);
                    player.setPerkValue(PerkLib.Patience,1,0);
                    player.setPerkValue(PerkLib.Patience,2,0);
                }
			}
			//Counter ability
			if (player.hasStatusEffect(StatusEffects.CounterAB)){
				player.addStatusValue(StatusEffects.CounterAB, 2, -1);
				if(player.statusEffectv2(StatusEffects.CounterAB) >= 0) outputText("You're still in a countering stance.\n");
				else{
					outputText("You have left your countering stance!\n");
					player.removeStatusEffect(StatusEffects.CounterAB);
				}
			}
			if (player.hasStatusEffect(StatusEffects.SentinelNoTease)){
				player.addStatusValue(StatusEffects.SentinelNoTease, 1, -1);
				if (player.statusEffectv1(StatusEffects.SentinelNoTease) <= 0){
					player.removeStatusEffect(StatusEffects.SentinelNoTease);
					outputText("You've regained your ability to tease!\n\n");
				}else outputText("Your ability to tease is still sealed!\n\n");
			}
			if (player.hasStatusEffect(StatusEffects.SentinelOmniSilence)){
				player.addStatusValue(StatusEffects.SentinelOmniSilence, 1, -1);
				if (player.statusEffectv1(StatusEffects.SentinelOmniSilence) <= 0){
					player.removeStatusEffect(StatusEffects.SentinelOmniSilence);
					outputText("You've regained your ability to use magic!\n\n");
				}else outputText("Your ability to use magic is still sealed!\n\n");
			}
			if (player.hasStatusEffect(StatusEffects.SentinelPhysicalDisabled)){
				player.addStatusValue(StatusEffects.SentinelPhysicalDisabled, 1, -1);
				if (player.statusEffectv1(StatusEffects.SentinelPhysicalDisabled) <= 0){
					player.removeStatusEffect(StatusEffects.SentinelPhysicalDisabled);
					outputText("You've regained your ability to use physical attacks!\n\n");

				}else outputText("Your ability to use physical attacks is still sealed!\n\n");
			}
			if (player.hasStatusEffect(StatusEffects.ArmorRent)){
					if (player.findPerk(PerkLib.Medicine) >= 0 && rand(100) <= 14) {
					outputText("You manage to cleanse the Sapper's poison with your knowledge of medicine!\n\n");
					player.removeStatusEffect(StatusEffects.ArmorRent);
				}else outputText("The Sapper's poison is increasing physical damage taken by: "  + Math.round(player.statusEffectv1(StatusEffects.ArmorRent)) +"%\n");
			}
			//Leech spell
			if (player.hasStatusEffect(StatusEffects.Leeching)){
				player.addStatusValue(StatusEffects.Leeching, 2, -1);
				if(player.statusEffectv2(StatusEffects.Leeching) >= 0) outputText("Your [weapon] is still draining health with every strike.\n");
				else{
					outputText("The incantation surrounding your [weapon] fades away.\n");
					player.removeStatusEffect(StatusEffects.Leeching);
				}
			}
			//Nameless Horror
			if (player.hasStatusEffect(StatusEffects.Revelation)){
				player.addStatusValue(StatusEffects.Revelation, 1, -1);
				if (player.statusEffectv1(StatusEffects.Revelation) >= 0){
					outputText("Your mind is still overwhelmed by vast amounts of eldritch knowledge!\n");
				}else{
					outputText("The brain-blasting knowledge leaves your mind, and you regain your sense of self!\n");
					player.short = (monster as NamelessHorror).originalName;
					player.removeStatusEffect(StatusEffects.Revelation);
				}
			}

			if (player.hasStatusEffect(StatusEffects.Nothingness)){
				player.addStatusValue(StatusEffects.Nothingness, 1, -1);
				if (player.statusEffectv1(StatusEffects.Nothingness) >= 0){
					outputText("Free yourself. Embrace nothingness, become eternal.\n");
				}else{
					outputText("The creature's spell fades - you are material again!\n");
					player.removeStatusEffect(StatusEffects.Nothingness);
				}
			}
			if (player.hasStatusEffect(StatusEffects.Refashioned)){
				player.addStatusValue(StatusEffects.Refashioned, 1, -1);
				if (player.statusEffectv1(StatusEffects.Refashioned) >= 0){
					outputText("You're still remade by the Nameless Horror.\n");
				}else{
					outputText("You notice you've become your old self again!\n");
					player.removeStatusEffect(StatusEffects.Refashioned);
					player._str = (monster as NamelessHorror).playerStats[0];
					player._tou = (monster as NamelessHorror).playerStats[1];
					player._inte = (monster as NamelessHorror).playerStats[2];
					player._spe = (monster as NamelessHorror).playerStats[3];
				}
			}
			//End of Nameless Horror
			//[Silence warning]
			if (player.hasStatusEffect(StatusEffects.ThroatPunch)) {
				player.addStatusValue(StatusEffects.ThroatPunch,1,-1);
				if (player.statusEffectv1(StatusEffects.ThroatPunch) >= 0) outputText("Thanks to Isabella's wind-pipe crushing hit, you're having trouble breathing and are unable to cast spells as a consequence.\n\n");
				else {
					outputText("Your wind-pipe recovers from Isabella's brutal hit.  You'll be able to focus to cast spells again!\n\n");
					player.removeStatusEffect(StatusEffects.ThroatPunch);
				}
			}
			if (player.hasStatusEffect(StatusEffects.GooArmorSilence)) {
				if (player.statusEffectv1(StatusEffects.GooArmorSilence) >= 2 || rand(20) + 1 + player.str/10 >= 15) {
					//if passing str check, output at beginning of turn
					outputText("The sticky slop covering your mouth pulls away reluctantly, taking more force than you would expect, but you've managed to free your mouth enough to speak!\n\n");
					player.removeStatusEffect(StatusEffects.GooArmorSilence);
				}
				else {
					outputText("Your mouth is obstructed by sticky goo!  You are silenced!\n\n");
					player.addStatusValue(StatusEffects.GooArmorSilence,1,1);
				}
			}
			if (player.hasStatusEffect(StatusEffects.LustStones)) {
				//[When witches activate the stones for goo bodies]
				if (player.isGoo()) {
					outputText("The stones start vibrating again, making your liquid body ripple with pleasure.  The witches snicker at the odd sight you are right now.");
				}
				//[When witches activate the stones for solid bodies]
				else {
					outputText("The smooth stones start vibrating again, sending another wave of teasing bliss throughout your body.  The witches snicker at you as you try to withstand their attack.");
				}
				player.takeLustDamage(player.statusEffectv1(StatusEffects.LustStones) + 4, true);
				outputText("\n\n");
			}
			if (player.hasStatusEffect(StatusEffects.WebSilence)) {
				if (player.statusEffectv1(StatusEffects.WebSilence) >= 2 || rand(20) + 1 + player.str/10 >= 15) {
					outputText("You rip off the webbing that covers your mouth with a cry of pain, finally able to breathe normally again!  Now you can cast spells!\n\n");
					player.removeStatusEffect(StatusEffects.WebSilence);
				}
				else {
					outputText("Your mouth and nose are obstructed by sticky webbing, making it difficult to breathe and impossible to focus on casting spells.  You try to pull it off, but it just won't work!\n\n");
					player.addStatusValue(StatusEffects.WebSilence,1,1);
				}
			}
			if (player.hasStatusEffect(StatusEffects.HolliConstrict)) {
				outputText("You're tangled up in Holli's verdant limbs!  All you can do is try to struggle free...\n\n");
			}
			if (player.hasStatusEffect(StatusEffects.UBERWEB))
				outputText("You're pinned under a pile of webbing!  You should probably struggle out of it and get back in the fight!\n\n");
			if (player.hasStatusEffect(StatusEffects.Blind) && !monster.hasStatusEffect(StatusEffects.Sandstorm))
			{
				if (player.hasStatusEffect(StatusEffects.SheilaOil))
				{
					if (player.statusEffectv1(StatusEffects.Blind) <= 0) {
						outputText("You finish wiping the demon's tainted oils away from your eyes; though the smell lingers, you can at least see.  Sheila actually seems happy to once again be under your gaze.\n\n");
						player.removeStatusEffect(StatusEffects.Blind);
					}
					else {
						outputText("You scrub at the oily secretion with the back of your hand and wipe some of it away, but only smear the remainder out more thinly.  You can hear the demon giggling at your discomfort.\n\n");
						player.addStatusValue(StatusEffects.Blind,1,-1);
					}
				}
				else
				{
					//Remove blind if countdown to 0
					if (player.statusEffectv1(StatusEffects.Blind) == 0)
					{
						player.removeStatusEffect(StatusEffects.Blind);
						//Alert PC that blind is gone if no more stacks are there.
						if (!player.hasStatusEffect(StatusEffects.Blind))
						{
							outputText("Your eyes have cleared and you are no longer blind!\n\n");
						}
						else outputText("You are blind, and many physical attacks will miss much more often.\n\n");
					}
					else
					{
						player.addStatusValue(StatusEffects.Blind,1,-1);
						outputText("You are blind, and many physical attacks will miss much more often.\n\n");
					}
				}
			}
			//Basilisk compulsion
			if (player.hasStatusEffect(StatusEffects.BasiliskCompulsion)) {
				StareMonster.speedReduce(player,15);
				//Continuing effect text:
				outputText("You still feel the spell of those gray eyes, making your movements slow and difficult, the remembered words tempting you to look into its eyes again. You need to finish this fight as fast as your heavy limbs will allow.\n\n");
				flags[kFLAGS.BASILISK_RESISTANCE_TRACKER]++;
			}
			if(player.hasStatusEffect(StatusEffects.IzmaBleed)) player.updateBleed();
			if (player.hasStatusEffect(StatusEffects.AcidSlap)) {
				var slap:Number = 3 + (player.maxHP() * 0.02);
				outputText("Your muscles twitch in agony as the acid keeps burning you. (" + slap + ")\n\n");
			}
			if (player.findPerk(PerkLib.ArousingAura) >= 0 && monster.lustVuln > 0 && player.isCorruptEnough(70)) {
				if (monster.lust100 < 50) outputText("Your aura seeps into " + monster.a + monster.short + " but does not have any visible effects just yet.\n\n");
				else if (monster.lust100 < 60) {
					if (!monster.plural) outputText(monster.capitalA + monster.short + " starts to squirm a little from your unholy presence.\n\n");
					else outputText(monster.capitalA + monster.short + " start to squirm a little from your unholy presence.\n\n");
				}
				else if (monster.lust100 < 75) outputText("Your arousing aura seems to be visibly affecting " + monster.a + monster.short + ", making " + monster.pronoun2 + " squirm uncomfortably.\n\n");
				else if (monster.lust100 < 85) {
					if (!monster.plural) outputText(monster.capitalA + monster.short + "'s skin colors red as " + monster.pronoun1 + " inadvertently basks in your presence.\n\n");
					else outputText(monster.capitalA + monster.short + "' skin colors red as " + monster.pronoun1 + " inadvertently bask in your presence.\n\n");
				}
				else {
					if (!monster.plural) outputText("The effects of your aura are quite pronounced on " + monster.a + monster.short + " as " + monster.pronoun1 + " begins to shake and steal glances at your body.\n\n");
					else outputText("The effects of your aura are quite pronounced on " + monster.a + monster.short + " as " + monster.pronoun1 + " begin to shake and steal glances at your body.\n\n");
				}
				if(monster.lustVuln > 0)monster.teased(2 + rand(4));//so weak and so hard to get. It ignores lust resistance now.
				outputText("\n\n");
			}
			if (player.hasStatusEffect(StatusEffects.Bound) && game.fetishManager.compare(FetishManager.FETISH_BONDAGE)) {
				outputText("The feel of tight leather completely immobilizing you turns you on more and more.  Would it be so bad to just wait and let her play with you like this?");
				player.takeLustDamage(3, true);
				outputText("\n\n");
			}
			if (monster is Dullahan && monster.lust >= 40){
				outputText("The Dullahan scowls for a moment, focusing on you. It seems she has managed to convince her body to ignore some of its growing lust.\n\n");
				monster.lust -= 10;
				if (monster.lust < 0) monster.lust = 0;
			}

			if (player.hasStatusEffect(StatusEffects.ParasiteSlugMusk)){
				if(player.statusEffectv1(StatusEffects.ParasiteSlugMusk) > 0){
				outputText("The parasite musk continues to permeate the battlefield.\n\n");
				if (monster.lust < 50) outputText("It doesn't seem to have affected" + monster.a + monster.short + " just yet.\n\n");
				if (monster.lust < 70 && monster.lust >= 50) outputText("It seems to bother " + monster.a + monster.short + ", as " + monster.pronoun1 + " squirms a bit and breathes heavily.\n\n");
				if (monster.lust >= 70) outputText(monster.pronoun1 + " is visibly aroused, and willingly inhales the musk whenever he can.\n\n");
				if (player.lust > 90) outputText("You're definitely affected as well. You can barely keep from masturbating on the spot! You need to finish this.\n\n");
				player.addStatusValue(StatusEffects.ParasiteSlugMusk, 1, -1);
				monster.teased(10*monster.lustVuln);
				dynStats("lus", 5);
				}else{
					player.removeStatusEffect(StatusEffects.ParasiteSlugMusk);
					outputText("The musk fades and both you and the enemy breathe freely again.");
				}
			}

			if (player.hasStatusEffect(StatusEffects.Marked)){
				if (player.statusEffectv1(StatusEffects.Marked) > 0){
					outputText("You're still hexed.\n\n");
					player.addStatusValue(StatusEffects.Marked, 1, -1);
				}else{
					outputText("You're no longer hexed!\n\n");
					player.removeStatusEffect(StatusEffects.Marked);
				}
			}

			if (player.hasStatusEffect(StatusEffects.GooArmorBind)) {
				if (game.fetishManager.compare(FetishManager.FETISH_BONDAGE)) {
					outputText("The feel of the all-encapsulating goo immobilizing your helpless body turns you on more and more.  Maybe you should just wait for it to completely immobilize you and have you at its mercy.");
					player.takeLustDamage(3, true);
				}
				else outputText("You're utterly immobilized by the goo flowing around you.  You'll have to struggle free!");
				outputText("\n\n");
			}
			if (player.hasStatusEffect(StatusEffects.HarpyBind)) {
				if (game.fetishManager.compare(FetishManager.FETISH_BONDAGE)) {
					outputText("The harpies are holding you down and restraining you, making the struggle all the sweeter!");
					player.takeLustDamage(3, true);
					outputText("\n\n");
				}
				else outputText("You're restrained by the harpies so that they can beat on you with impunity.  You'll need to struggle to break free!\n\n");
			}
			if (player.hasStatusEffect(StatusEffects.NagaBind) && game.fetishManager.compare(FetishManager.FETISH_BONDAGE)) {
				outputText("Coiled tightly by the naga and utterly immobilized, you can't help but become aroused thanks to your bondage fetish.");
				player.takeLustDamage(5, true);
				outputText("\n\n");
			}
			if (player.hasStatusEffect(StatusEffects.TentacleBind)) {
				outputText("You are firmly trapped in the tentacle's coils.  The only thing you can try to do is struggle free!\n\n");
				if (game.fetishManager.compare(FetishManager.FETISH_BONDAGE)) {
					outputText("Wrapped tightly in the tentacles, you find it hard to resist becoming more and more aroused...");
					player.takeLustDamage(3, true);
					outputText("\n\n");
				}
			}
			if (player.hasStatusEffect(StatusEffects.DriderKiss)) {
				//(VENOM OVER TIME: WEAK)
				if (player.statusEffectv1(StatusEffects.DriderKiss) == 0) {
					outputText("Your heart hammers a little faster as a vision of the drider's nude, exotic body on top of you assails you.  It'll only get worse if she kisses you again...");
					player.takeLustDamage(8, true);
					outputText("\n\n");
				}
				//(VENOM OVER TIME: MEDIUM)
				else if (player.statusEffectv1(StatusEffects.DriderKiss) == 1) {
					outputText("You shudder and moan, nearly touching yourself as your ");
					if (player.gender > 0) outputText("loins tingle and leak, hungry for the drider's every touch.");
					else outputText("asshole tingles and twitches, aching to be penetrated.");
					outputText("  Gods, her venom is getting you so hot.  You've got to end this quickly!");
					player.takeLustDamage(15, true);
					outputText("\n\n");
				}
				//(VENOM OVER TIME: MAX)
				else {
					outputText("You have to keep pulling your hands away from your crotch - it's too tempting to masturbate here on the spot and beg the drider for more of her sloppy kisses.  Every second that passes, your arousal grows higher.  If you don't end this fast, you don't think you'll be able to resist much longer.  You're too turned on... too horny... too weak-willed to resist much longer...");
					player.takeLustDamage(25, true);
					outputText("\n\n");
				}
			}
			//Harpy lip gloss
			if (player.hasCock() && player.hasStatusEffect(StatusEffects.Luststick) && (monster.short == "harpy" || monster.short == "Sophie")) {
				//Chance to cleanse!
				if (player.findPerk(PerkLib.Medicine) >= 0 && rand(100) <= 14) {
					outputText("You manage to cleanse the harpy lip-gloss from your system with your knowledge of medicine!\n\n");
					player.removeStatusEffect(StatusEffects.Luststick);
				}
				else if (rand(5) == 0) {
					if (rand(2) == 0) outputText("A fantasy springs up from nowhere, dominating your thoughts for a few moments.  In it, you're lying down in a soft nest.  Gold-rimmed lips are noisily slurping around your " + player.cockDescript(0) + ", smearing it with her messy aphrodisiac until you're completely coated in it.  She looks up at you knowingly as the two of you get ready to breed the night away...\n\n");
					else outputText("An idle daydream flutters into your mind.  In it, you're fucking a harpy's asshole, clutching tightly to her wide, feathery flanks as the tight ring of her pucker massages your " + player.cockDescript(0) + ".  She moans and turns around to kiss you on the lips, ensuring your hardness.  Before long her feverish grunts of pleasure intensify, and you feel the egg she's birthing squeezing against you through her internal walls...");
					player.takeLustDamage(20, true);
					outputText("\n\n");
				}
			}
			if (player.hasStatusEffect(StatusEffects.StoneLust)) {
				if (player.vaginas.length > 0) {
					if (player.lust100 < 40) outputText("You squirm as the smooth stone orb vibrates within you.");
					if (player.lust100 >= 40 && player.lust100 < 70) outputText("You involuntarily clench around the magical stone in your twat, in response to the constant erotic vibrations.");
					if (player.lust100 >= 70 && player.lust100 < 85) outputText("You stagger in surprise as a particularly pleasant burst of vibrations erupt from the smooth stone sphere in your " + player.vaginaDescript(0) + ".");
					if (player.lust100 >= 85) outputText("The magical orb inside of you is making it VERY difficult to keep your focus on combat, white-hot lust suffusing your body with each new motion.");
				}
				else {
					outputText("The orb continues vibrating in your ass, doing its best to arouse you.");
				}
				player.takeLustDamage(7 + int(player.sens)/10, true);
				outputText("\n\n");
			}
			if (player.hasStatusEffect(StatusEffects.KissOfDeath)) {
				//Effect
				outputText("Your lips burn with an unexpected flash of heat.  They sting and burn with unholy energies as a puff of ectoplasmic gas escapes your lips.  That puff must be a part of your soul!  It darts through the air to the succubus, who slurps it down like a delicious snack.  You feel feverishly hot and exhausted...");
				player.takeLustDamage(5, true);
				takeDamage(15);
				outputText("\n\n");
			}
			if (player.hasStatusEffect(StatusEffects.DemonSeed)) {
				outputText("You feel something shift inside you, making you feel warm.  Finding the desire to fight this... hunk gets harder and harder.\n\n");
				player.takeLustDamage((player.statusEffectv1(StatusEffects.DemonSeed) + int(player.sens/30) + int(player.lib/30) + int(player.cor/30)), true);
			}
			if (player.inHeat && player.vaginas.length > 0 && monster.totalCocks() > 0) {
				player.takeLustDamage((rand(player.lib/5) + 3 + rand(5)), true);
				outputText("Your " + player.vaginaDescript(0) + " clenches with an instinctual desire to be touched and filled.  ");
				outputText("If you don't end this quickly you'll give in to your heat.\n\n");
			}
			if (player.inRut && player.totalCocks() > 0 && monster.hasVagina()) {
				player.takeLustDamage((rand(player.lib/5) + 3 + rand(5)), true);
				if (player.totalCocks() > 1) outputText("Each of y");
				else outputText("Y");
				if (monster.plural) outputText("our " + player.multiCockDescriptLight() + " dribbles pre-cum as you think about plowing " + monster.a + monster.short + " right here and now, fucking " + monster.pronoun3 + " " + monster.vaginaDescript() + "s until they're totally fertilized and pregnant.\n\n");
				else outputText("our " + player.multiCockDescriptLight() + " dribbles pre-cum as you think about plowing " + monster.a + monster.short + " right here and now, fucking " + monster.pronoun3 + " " + monster.vaginaDescript() + " until it's totally fertilized and pregnant.\n\n");
			}
			if (player.hasStatusEffect(StatusEffects.TemporaryHeat)) {
				//Chance to cleanse!
				if (player.findPerk(PerkLib.Medicine) >= 0 && rand(100) <= 14) {
					outputText("You manage to cleanse the heat and rut drug from your system with your knowledge of medicine!\n\n");
					player.removeStatusEffect(StatusEffects.TemporaryHeat);
				}
				else {
					dynStats("lus", (player.lib/12 + 5 + rand(5)) * player.statusEffectv2(StatusEffects.TemporaryHeat));
					if (player.hasVagina()) {
						outputText("Your " + player.vaginaDescript(0) + " clenches with an instinctual desire to be touched and filled.  ");
					}
					else if (player.totalCocks() > 0) {
						outputText("Your " + player.cockDescript(0) + " pulses and twitches, overwhelmed with the desire to breed.  ");
					}
					if (player.gender == 0) {
						outputText("You feel a tingle in your " + player.assholeDescript() + ", and the need to touch and fill it nearly overwhelms you.  ");
					}
					outputText("If you don't finish this soon you'll give in to this potent drug!\n\n");
				}
			}
			//Poison
			if (player.hasStatusEffect(StatusEffects.Poison)) {
				//Chance to cleanse!
				if (player.findPerk(PerkLib.Medicine) >= 0 && rand(100) <= 14) {
					outputText("You manage to cleanse the poison from your system with your knowledge of medicine!\n\n");
					player.removeStatusEffect(StatusEffects.Poison);
				}
				else {
					outputText("The poison continues to work on your body, wracking you with pain!\n\n");
					takeDamage(8+rand(player.maxHP()/20) * player.statusEffectv2(StatusEffects.Poison));
				}
			}
			//Mosquito Poison
			if (player.hasStatusEffect(StatusEffects.MosquitoNumb)) {
				player.addStatusValue(StatusEffects.MosquitoNumb, 1, player.hasPerk(PerkLib.Medicine) ? -2 : -1);
				if (player.statusEffectv1(StatusEffects.MosquitoNumb) > 0) outputText("The mosquito's numbing agent continues to ravage your body, impairing your fighting abilities.\n\n");
				else outputText("The mosquito's numbing agent has finally been completely flushed out of your system!");
			}
			//Bondage straps + bondage fetish
			if (game.fetishManager.compare(FetishManager.FETISH_BONDAGE) && player.armorName == "barely-decent bondage straps") {
				outputText("The feeling of the tight, leather straps holding tightly to your body while exposing so much of it turns you on a little bit more.");
				player.takeLustDamage(2, true);
				outputText("\n\n");
			}
			//Giant boulder
			if (player.hasStatusEffect(StatusEffects.GiantBoulder)) {
				outputText("There is a large boulder coming your way. If you don't avoid it in time, you might take some serious damage.\n\n");
			}
			//Drider Incubus' purple haze
			if (player.hasStatusEffect(StatusEffects.PurpleHaze)) {
				outputText("The purple haze is filling your vision with unsubtle erotic imagery, arousing you.");
				player.takeLustDamage(3, true);
				outputText("\n\n");
			}
			//Minotaur King's musk
			if (player.hasStatusEffect(StatusEffects.MinotaurKingMusk)) {
				outputText("The smell of the minotaur pheronome is intense, turning you on. You should try to deal with him as soon as possible.");
				player.takeLustDamage(2, true);
				outputText("\n\n");
			}
			//Minotaur King Touched
			if (player.hasStatusEffect(StatusEffects.MinotaurKingsTouch)) {
				outputText("The residual cum from the Minotaur King continues to arouse you.");
				player.takeLustDamage(1, true);
				outputText("\n\n");
			}
			//Pigby's Hands
			if (player.hasStatusEffect(StatusEffects.PigbysHands)) {
				player.takeLustDamage(3, true);
			}
			//Whip Silence
			if (player.hasStatusEffect(StatusEffects.WhipSilence)) {
				if (player.statusEffectv1(StatusEffects.WhipSilence) > 0) {
					outputText("You are silenced by the burning cord wrapped around your neck. It's painful... and arousing too. ");
					player.takeDamage(10 + rand(8), true);
					player.takeLustDamage(4, true);
					player.addStatusValue(StatusEffects.WhipSilence, 1, -1);
					outputText("\n\n");
				}
				else {
					outputText("The cord has finally came loose and falls off your neck. It dissipates immediately. You can cast spells again now!\n\n");
					player.removeStatusEffect(StatusEffects.WhipSilence);
				}
			}
			for (var a:/*StatusEffect*/Array=player.statusEffects.slice(),n:int=a.length,i:int=0;i<n;i++) {
				// Using a copy of array because some effects will be removed
				a[i].onCombatRound();
			}
			for each(var currMonster:Monster in monsterArray){
                for (a=currMonster.statusEffects.slice(),n=a.length,i=0;i<n;i++) {
                    a[i].onCombatRound();
                }
			}

			regeneration(true);
			if (player.lust >= player.maxLust()) doNext(endLustLoss);
			if (player.HP <= 0) doNext(endHpLoss);
		}

		public function getAttackBlockReason():String{
			if (!combatAttackData.canReach(player,monster,monster.distance,player.weapon.getAttackRange())){
				return "You can't reach your target with regular attacks!";
			}
			if (player.isAtrophied){
				return "You are atrophied, and can't attack!";
			}
			return "You can't attack!";
		}

		public function regeneration(combat:Boolean = true):void {
			player.regeneration(combat);
			for each(var m:Monster in monsterArray){
				monster.regeneration(combat,true);
			}
		}

		public function beginCombat(monster_:Monster, plotFight_:Boolean = false, showNext:Boolean = true):void {
            monsterArray = new Vector.<Monster>();
			monsterArray.push(monster_);
            hpvictoryFunc = curry(monster_.defeated_,true);
            hplossFunc = curry(monster_.won_,true,player.hasStatusEffect(StatusEffects.Infested) ? true : false);
            lustvictoryFunc = curry(monster_.defeated_,false);
            lustlossFunc = curry(monster_.won_,false, player.hasStatusEffect(StatusEffects.Infested) ? true : false);
            monster = monster_;
            setUpCombatEnvironment(plotFight_, showNext);
		}

		public function setUpCombatEnvironment(plotFight_:Boolean = false, showNext:Boolean = true):void{
            combatRound = 0;
            plotFight = plotFight_;
            mainView.hideMenuButton( MainView.MENU_DATA );
            mainView.hideMenuButton( MainView.MENU_APPEARANCE );
            mainView.hideMenuButton( MainView.MENU_LEVEL );
            mainView.hideMenuButton( MainView.MENU_PERKS );
            mainView.hideMenuButton( MainView.MENU_STATS );
            showStats();
            //Flag the game as being "in combat"
            inCombat = true;
            combatAbilities.fireMagicLastTurn = -100;
            combatAbilities.fireMagicCumulated = 0;
            combatAbilities.flurryAmount = 1;
            currMonsterIndex = 0;
            maxMonsterIndex = 0;
			currTarget = 0;
            combatAttackData.resetDistance();
            combatAbilities.setSpells();
            setDistanceSelf();
            setApproach();
            //Set image once, at the beginning of combat
            if (monsterArray[0].imageName != "")
            {
                var monsterName:String = "monster-" + monsterArray[0].imageName;
                imageText = images.showImage(monsterName);
            } else imageText = "";

			for each(var currMonster:Monster in monsterArray){
				if (currMonster.armorDef <= 10) currMonster.armorDef = 0;
				else currMonster.armorDef -= 10;
				if(!player.isResetAscension()){
                    currMonster.str += 25 * player.newGamePlusMod();
                    currMonster.tou += 25 * player.newGamePlusMod();
                    currMonster.spe += 25 * player.newGamePlusMod();
                    currMonster.inte += 25 * player.newGamePlusMod();
                    currMonster.level += 30 * player.newGamePlusMod();
                    //Adjust lust vulnerability in New Game+.
                    if (player.newGamePlusMod() == 1) currMonster.lustVuln *= 0.8;
                    else if (player.newGamePlusMod() == 2) currMonster.lustVuln *= 0.65;
                    else if (player.newGamePlusMod() == 3) currMonster.lustVuln *= 0.5;
                    else if (player.newGamePlusMod() >= 4) currMonster.lustVuln *= 0.4;
				}

				if (flags[kFLAGS.GRIMDARK_MODE] > 0) {
					currMonster.level = Math.round(Math.pow(currMonster.level, 1.4));
				}
				currMonster.HP = currMonster.maxHP();
				currMonster.XP = currMonster.totalXP();
				//Reduce enemy def if player has precision!
				if (player.findPerk(PerkLib.Precision) >= 0 && player.inte >= 25) {
					if (currMonster.armorDef <= 10) currMonster.armorDef = 0;
					else currMonster.armorDef -= 10;
				}
            }
            //Raises lust~ Not disabled because it's an item perk :3
            if (player.findPerk(PerkLib.WellspringOfLust) >= 0 && player.lust < 50) {
                player.lust = 50;
            }
            if (player.findPerk(PerkLib.Spellsword) >= 0 && player.perkv1(PerkLib.Spellsword) == 0) {
                if (flags[kFLAGS.MAGIC_SWITCH] == 0 && player.lust100 < combatAbilities.getWhiteMagicLustCap() && player.hasStatusEffect(StatusEffects.KnowsCharge)) combatAbilities.spellChargeWeapon(true); // XXX: message?
				if (flags[kFLAGS.MAGIC_SWITCH] == 1 && player.hasPerk(PerkLib.TerrestrialFire) && player.masteryLevel(MasteryLib.TerrestrialFire) >= 2) combatAbilities.tfInflame(true);
            }
            if (player.findPerk(PerkLib.Battlemage) >= 0 && player.lust >= 50 && player.perkv1(PerkLib.Battlemage) == 0) {
                combatAbilities.spellMight(true); // XXX: message?
            }

            if (player.weapon.ammoMax != 0) flags[kFLAGS.RANGED_AMMO] = player.weapon.ammoMax;
            if (prison.inPrison && prison.prisonCombatAutoLose) {
                dynStats("lus", player.maxLust(), "resisted", false);
                doNext(endLustLoss);
                return;
            }
            if (showNext) doNext(playerMenu);
			else playerMenu();
		}

		public function beginCombatMultiple(monsters_:Vector.<Monster>,hpvictoryFunc_:Function,hplossFunc_:Function,lustvictoryFunc_:Function,lustlossFunc_:Function,description_:String = "", plotFight_:Boolean = false, showNext:Boolean = true):void {
			currTarget = 0;
            monsterArray = new Vector.<Monster>();
            monsterArray = monsters_.slice(0);
			hpvictoryFunc = hpvictoryFunc_;
			hplossFunc = hplossFunc_;
			lustvictoryFunc = lustvictoryFunc_;
			lustlossFunc = lustlossFunc_;
			description = description_;
			monster = monsterArray[0];
			setUpCombatEnvironment(plotFight_, showNext);
		}

		public function display():void {
			if (monsterArray.length == 1) displaySingle();
			else displayMulti();
		}

		public function displaySingle():void{
			if (!monster.checkCalled){
				outputText("/!\\BUG! Monster.checkMonster() is not called! Calling it now...\n");
				monster.checkMonster();
			}
			if (monster.checkError != ""){
				outputText("/!\\BUG! Monster is not correctly initialized! "+
						monster.checkError+"\n");
			}
			var hpDisplay:String = "";
			var lustDisplay:String = "";

			var math:Number = monster.HPRatio();
			/*hpDisplay   = Math.floor(monster.HP) + " / " + monster.maxHP() + " (" + floor(math*100,1) + "%)";
			lustDisplay = Math.floor(monster.lust) + " / " + monster.maxLust();*/
			outputText(imageText);
			outputText("Turn: " + (combatRound + 1) + "\n");
			outputText("You are fighting ");
			outputText(monster.a + monster.short + ": \n");
			if (player.hasStatusEffect(StatusEffects.Blind)) {
				outputText("It's impossible to see anything!\n");
			}
			else {
				outputText(monster.long + "\n\n");
				//Bonus sand trap stuff
				if (monster.hasStatusEffect(StatusEffects.Level)) {
					temp = monster.statusEffectv1(StatusEffects.Level);
					//[(new PG for PC height levels)PC level 4:
					if (temp == 4) outputText("You are right at the edge of its pit.  If you can just manage to keep your footing here, you'll be safe.");
					else if (temp == 3) outputText("The sand sinking beneath your feet has carried you almost halfway into the creature's pit.");
					else outputText("The dunes tower above you and the hissing of sand fills your ears.  The leering sandtrap is almost on top of you!");
					//no new PG)
					outputText("  You could try attacking it with your " + player.weaponName + ", but that will carry you straight to the bottom.  Alternately, you could try to tease it or hit it at range, or wait and maintain your footing until you can clamber up higher.");
					outputText("\n\n");
				}
				outputText("\n\n" + capitalizeFirstLetter(monster.short) + "'s Status\n")
				if (monster.plural) {
					if (math >= 1) outputText("You see " + monster.pronoun1 + " are in perfect health.  ");
					else if (math > .75) outputText("You see " + monster.pronoun1 + " aren't very hurt.  ");
					else if (math > .5) outputText("You see " + monster.pronoun1 + " are slightly wounded.  ");
					else if (math > .25) outputText("You see " + monster.pronoun1 + " are seriously hurt.  ");
					else outputText("You see " + monster.pronoun1 + " are unsteady and close to death.  ");
				}
				else {
					if (math >= 1) outputText("You see " + monster.pronoun1 + " is in perfect health.  ");
					else if (math > .75) outputText("You see " + monster.pronoun1 + " isn't very hurt.  ");
					else if (math > .5) outputText("You see " + monster.pronoun1 + " is slightly wounded.  ");
					else if (math > .25) outputText("You see " + monster.pronoun1 + " is seriously hurt.  ");
					else outputText("You see " + monster.pronoun1 + " is unsteady and close to death.  ");
				}
				showMonsterLust();
				/*
				outputText("Level: " + monster.level + "\n");
				outputText("HP: " + hpDisplay + "\n");
				outputText("Lust: " + lustDisplay + "\n");
				if (player.hasPerk(PerkLib.Awareness)) outputText("Armor: " + monster.armorDef + "%\nCorruption: " + monster.cor + "\n");*/
			}
			if (debug){
				outputText("\n----------------------------\n");
				outputText(monster.generateDebugDescription());
			}
		}

		public function displayMulti():void{
			if (monsterArray.length != 0){
				if (monsterArray.length > 4){
					outputText("/!\\Monster array is too big! Popping until fixed.");
					monsterArray.length = 4;
				}
			}
			var hpDisplay:String = "\n";
			var lustDisplay:String = "";
			outputText(imageText);
			outputText("Turn: " + combatRound + "\n");
			outputText("You are fighting ");
			outputText("a group of enemies: \n");
			outputText(description + "\n");
			if (player.hasStatusEffect(StatusEffects.Blind)) {
				outputText("It's impossible to see anything!\n");
			}
			else {
				for (var i:int = 0; i < monsterArray.length; i++){
					/*hpDisplay = Math.floor(monsterArray[i].HP) + " / " + monsterArray[i].maxHP() + " (" + (int(monsterArray[i].HPRatio() * 1000) / 10) + "%)";
					lustDisplay = Math.floor(monsterArray[i].lust) + " / " + monsterArray[i].maxLust();
					//showMonsterLust();
					outputText("\n\n");
					if (currTarget == i) outputText(">");
					outputText("Level: " + monsterArray[i].level + "\n");
					outputText("HP: " + hpDisplay + "\n");
					outputText("Lust: " + lustDisplay + "\n");
					if (player.hasPerk(PerkLib.Awareness)) outputText("Armor: " + monsterArray[i].armorDef + "%\nCorruption: " + monsterArray[i].cor + "\n");*/
					outputText("" + capitalizeFirstLetter(monsterArray[i].short) + "'s Status\n")
					if (monsterArray[i].plural && monsterArray[i].unitHP > 0) outputText("Units: " + (monsterArray[i].HP > 0 ? monsterArray[i].unitAmount : 0)  + "\n");
					if (monsterArray[i].HPRatio() >= 1) outputText("You see " + monsterArray[i].pronoun1 + (monsterArray[i].plural ? " are" : " is") + " in perfect health.  ");
					else if (monsterArray[i].HPRatio() > .75) outputText("You see " + monsterArray[i].pronoun1 + (monsterArray[i].plural ? " aren't" : " isn't") + " very hurt.  ");
					else if (monsterArray[i].HPRatio() > .5) outputText("You see " + monsterArray[i].pronoun1 + (monsterArray[i].plural ? " are" : " is") + " slightly wounded.  ");
					else if (monsterArray[i].HPRatio() > .25) outputText("You see " + monsterArray[i].pronoun1 + (monsterArray[i].plural ? " are" : " is") + " seriously hurt.  ");
					else if (monsterArray[i].HPRatio() > 0) outputText("You see " + monsterArray[i].pronoun1 + (monsterArray[i].plural ? " are" : " is") + " unsteady and close to death.  ");
					else outputText("You see " + monsterArray[i].pronoun1 + (monsterArray[i].plural ? " have" : " has") + " fainted.");
					if (monsterArray[i].lust >= monsterArray[i].maxLust() && !monsterArray[i].ignoreLust) outputText("You see " + monsterArray[i].pronoun1 + (monsterArray[i].plural ? " are" : " is") + " too overwhelmed by lust to care about fighting.");
					outputText("\n\n");
					outputText("\n\n");
					/*if (monsterArray[i].hasStatusEffect(StatusEffects.Stunned)) outputText("Stunned  ");
					if (monsterArray[i].hasStatusEffect(StatusEffects.Blind)) outputText("Blinded  ");
					if (monsterArray[i].hasStatusEffect(StatusEffects.Fear)) outputText("Frightened  ");
					if (monsterArray[i].hasStatusEffect(StatusEffects.NagaVenom)) outputText("Poisoned(Naga)  ");
					if (monsterArray[i].hasStatusEffect(StatusEffects.Whispered)) outputText("Whispered  ");
					if (monsterArray[i].hasStatusEffect(StatusEffects.IzmaBleed)) outputText("Bleeding  ");*/
				}
			}
			outputText("\nClick on an enemy's stat box to change your current target.");

		}

		public function showMonsterLust():void {
			//Entrapped
			if (monster.hasStatusEffect(StatusEffects.Constricted)) {
				outputText(monster.capitalA + monster.short + " is currently wrapped up in your tail-coils!  ");
			}
			//Venom stuff!
			if (monster.hasStatusEffect(StatusEffects.NagaVenom)) {
				if (monster.plural) {
					if (monster.statusEffectv1(StatusEffects.NagaVenom) <= 1) {
						outputText("You notice " + monster.pronoun1 + " are beginning to show signs of weakening, but there still appears to be plenty of fight left in " + monster.pronoun2 + ".  ");
					}
		    	    else {
						outputText("You notice " + monster.pronoun1 + " are obviously affected by your venom, " + monster.pronoun3 + " movements become unsure, and " + monster.pronoun3 + " balance begins to fade. Sweat begins to roll on " + monster.pronoun3 + " skin. You wager " + monster.pronoun1 + " are probably beginning to regret provoking you.  ");
					}
				}
				//Not plural
				else {
					if (monster.statusEffectv1(StatusEffects.NagaVenom) <= 1) {
						outputText("You notice " + monster.pronoun1 + " is beginning to show signs of weakening, but there still appears to be plenty of fight left in " + monster.pronoun2 + ".  ");
					}
		    	    else {
						outputText("You notice " + monster.pronoun1 + " is obviously affected by your venom, " + monster.pronoun3 + " movements become unsure, and " + monster.pronoun3 + " balance begins to fade. Sweat is beginning to roll on " + monster.pronoun3 + " skin. You wager " + monster.pronoun1 + " is probably beginning to regret provoking you.  ");
					}
				}
				monster.spe -= monster.statusEffectv1(StatusEffects.NagaVenom);
				monster.str -= monster.statusEffectv1(StatusEffects.NagaVenom);
				if (monster.spe < 1) monster.spe = 1;
				if (monster.str < 1) monster.str = 1;
			}
			if (monster.short == "harpy") {
				//(Enemy slightly aroused)
				if (monster.lust100 >= 45 && monster.lust100 < 70) outputText("The harpy's actions are becoming more and more erratic as she runs her mad-looking eyes over your body, her chest jiggling, clearly aroused.  ");
				//(Enemy moderately aroused)
				if (monster.lust100 >= 70 && monster.lust100 < 90) outputText("She stops flapping quite so frantically and instead gently sways from side to side, showing her soft, feathery body to you, even twirling and raising her tail feathers, giving you a glimpse of her plush pussy, glistening with fluids.");
				//(Enemy dangerously aroused)
				if (monster.lust100 >= 90) outputText("You can see her thighs coated with clear fluids" + (noFur() ? "" : ", the feathers matted and sticky") + " as she struggles to contain her lust.");
			}
			else if (monster is Clara)
			{
				//Clara is becoming aroused
				if (monster.lust100 <= 40)	 {}
				else if (monster.lust100 <= 65) outputText("The anger in her motions is weakening.");
				//Clara is somewhat aroused
				else if (monster.lust100 <= 75) outputText("Clara seems to be becoming more aroused than angry now.");
				//Clara is very aroused
				else if (monster.lust100 <= 85) outputText("Clara is breathing heavily now, the signs of her arousal becoming quite visible now.");
				//Clara is about to give in
				else outputText("It looks like Clara is on the verge of having her anger overwhelmed by her lusts.");
			}
			//{Bonus Lust Descripts}
			else if (monster.short == "Minerva") {
				if (monster.lust100 < 40) {}
				//(40)
				else if (monster.lust100 < 60) outputText("Letting out a groan Minerva shakes her head, focusing on the fight at hand.  The bulge in her short is getting larger, but the siren ignores her growing hard-on and continues fighting.  ");
				//(60)
				else if (monster.lust100 < 80) outputText("Tentacles are squirming out from the crotch of her shorts as the throbbing bulge grows bigger and bigger, becoming harder and harder... for Minerva to ignore.  A damp spot has formed just below the bulge.  ");
				//(80)
				else outputText("She's holding onto her weapon for support as her face is flushed and pain-stricken.  Her tiny, short shorts are painfully holding back her quaking bulge, making the back of the fabric act like a thong as they ride up her ass and struggle against her cock.  Her cock-tentacles are lashing out in every direction.  The dampness has grown and is leaking down her leg.");
			}
			else if (monster.short == "Cum Witch") {
				//{Bonus Lust Desc (40+)}
				if (monster.lust100 < 40) {}
				else if (monster.lust100 < 50) outputText("Her nipples are hard, and poke two visible tents into the robe draped across her mountainous melons.  ");
				//{Bonus Lust Desc (50-75)}
				else if (monster.lust100 < 75) outputText("Wobbling dangerously, you can see her semi-hard shaft rustling the fabric as she moves, evidence of her growing needs.  ");
				//{75+}
				if (monster.lust100 >= 75) outputText("Swelling obscenely, the Cum Witch's thick cock stands out hard and proud, its bulbous tip rustling through the folds of her fabric as she moves and leaving dark smears in its wake.  ");
				//(85+}
				if (monster.lust100 >= 85) outputText("Every time she takes a step, those dark patches seem to double in size.  ");
				//{93+}
				if (monster.lust100 >= 93) outputText("There's no doubt about it, the Cum Witch is dripping with pre-cum and so close to caving in.  Hell, the lower half of her robes are slowly becoming a seed-stained mess.  ");
				//{Bonus Lust Desc (60+)}
				if (monster.lust100 >= 70) outputText("She keeps licking her lips whenever she has a moment, and she seems to be breathing awfully hard.  ");
			}
			else if (monster.short == "Kelt") {
				//Kelt Lust Levels
				//(sub 50)
				if (monster.lust100 < 50) outputText("Kelt actually seems to be turned off for once in his miserable life.  His maleness is fairly flaccid and droopy.  ");
				//(sub 60)
				else if (monster.lust100 < 60) outputText("Kelt's gotten a little stiff down below, but he still seems focused on taking you down.  ");
				//(sub 70)
				else if (monster.lust100 < 70) outputText("Kelt's member has grown to its full size and even flared a little at the tip.  It bobs and sways with every movement he makes, reminding him how aroused you get him.  ");
				//(sub 80)
				else if (monster.lust100 < 80) outputText("Kelt is unabashedly aroused at this point.  His skin is flushed, his manhood is erect, and a thin bead of pre has begun to bead underneath.  ");
				//(sub 90)
				else if (monster.lust100 < 90) outputText("Kelt seems to be having trouble focusing.  He keeps pausing and flexing his muscles, slapping his cock against his belly and moaning when it smears his pre-cum over his equine underside.  ");
				//(sub 100)
				else outputText("There can be no doubt that you're having quite the effect on Kelt.  He keeps fidgeting, dripping pre-cum everywhere as he tries to keep up the facade of fighting you.  His maleness is continually twitching and bobbing, dripping messily.  He's so close to giving in...");
			}
			else if (monster.short == "green slime") {
				if (monster.lust100 >= 45 && monster.lust100 < 65) outputText("A lump begins to form at the base of the figure's torso, where its crotch would be.  ");
				if (monster.lust100 >= 65 && monster.lust100 < 85) outputText("A distinct lump pulses at the base of the slime's torso, as if something inside the creature were trying to escape.  ");
				if (monster.lust100 >= 85 && monster.lust100 < 93) outputText("A long, thick pillar like a small arm protrudes from the base of the slime's torso.  ");
				if (monster.lust100 >= 93) outputText("A long, thick pillar like a small arm protrudes from the base of the slime's torso.  Its entire body pulses, and it is clearly beginning to lose its cohesion.  ");
			}
			else if (monster.short == "Sirius, a naga hypnotist") {
				if (monster.lust100 < 40) {}
				else if (monster.lust100 >= 40) outputText("You can see the tip of his reptilian member poking out of its protective slit. ");
				else if (monster.lust100 >= 60) outputText("His cock is now completely exposed and half-erect, yet somehow he still stays focused on your eyes and his face is inexpressive.  ");
				else outputText("His cock is throbbing hard, you don't think it will take much longer for him to pop.   Yet his face still looks inexpressive... despite the beads of sweat forming on his brow.  ");

			}
			else if (monster.short == "kitsune") {
				//Kitsune Lust states:
				//Low
				if (monster.lust100 > 30 && monster.lust100 < 50) outputText("The kitsune's face is slightly flushed.  She fans herself with her hand, watching you closely.");
				//Med
				else if (monster.lust100 > 30 && monster.lust100 < 75) outputText("The kitsune's cheeks are bright pink, and you can see her rubbing her thighs together and squirming with lust.");
				//High
				else if (monster.lust100 > 30) {
					//High (redhead only)
					if (monster.hair.color == "red") outputText("The kitsune is openly aroused, unable to hide the obvious bulge in her robes as she seems to be struggling not to stroke it right here and now.");
					else outputText("The kitsune is openly aroused, licking her lips frequently and desperately trying to hide the trail of fluids dripping down her leg.");
				}
			}
			else if (monster.short == "demons") {
				if (monster.lust100 > 30 && monster.lust100 < 60) outputText("The demons lessen somewhat in the intensity of their attack, and some even eye up your assets as they strike at you.");
				if (monster.lust100 >= 60 && monster.lust100 < 80) outputText("The demons are obviously steering clear from damaging anything you might use to fuck and they're starting to leave their hands on you just a little longer after each blow. Some are starting to cop quick feels with their other hands and you can smell the demonic lust of a dozen bodies on the air.");
				if (monster.lust100 >= 80) outputText(" The demons are less and less willing to hit you and more and more willing to just stroke their hands sensuously over you. The smell of demonic lust is thick on the air and part of the group just stands there stroking themselves openly.");
			}
			else {
				if (monster.plural) {
					if (monster.lust100 > 50 && monster.lust100 < 60) outputText(monster.capitalA + monster.short + "' skin remains flushed with the beginnings of arousal.  ");
					if (monster.lust100 >= 60 && monster.lust100 < 70) outputText(monster.capitalA + monster.short + "' eyes constantly dart over your most sexual parts, betraying " + monster.pronoun3 + " lust.  ");
					if (monster.cocks.length > 0) {
						if (monster.lust100 >= 70 && monster.lust100 < 85) outputText(monster.capitalA + monster.short + " are having trouble moving due to the rigid protrusion in " + monster.pronoun3 + " groins.  ");
						if (monster.lust100 >= 85) outputText(monster.capitalA + monster.short + " are panting and softly whining, each movement seeming to make " + monster.pronoun3 + " bulges more pronounced.  You don't think " + monster.pronoun1 + " can hold out much longer.  ");
					}
					if (monster.vaginas.length > 0) {
						if (monster.lust100 >= 70 && monster.lust100 < 85) outputText(monster.capitalA + monster.short + " are obviously turned on, you can smell " + monster.pronoun3 + " arousal in the air.  ");
						if (monster.lust100 >= 85) outputText(monster.capitalA + monster.short + "' " + monster.vaginaDescript() + "s are practically soaked with their lustful secretions.  ");
					}
				}
				else {
					if (monster.lust100 > 50 && monster.lust100 < 60) outputText(monster.capitalA + monster.short + "'s skin remains flushed with the beginnings of arousal.  ");
					if (monster.lust100 >= 60 && monster.lust100 < 70) outputText(monster.capitalA + monster.short + "'s eyes constantly dart over your most sexual parts, betraying " + monster.pronoun3 + " lust.  ");
					if (monster.cocks.length > 0) {
						if (monster.lust100 >= 70 && monster.lust100 < 85) outputText(monster.capitalA + monster.short + " is having trouble moving due to the rigid protrusion in " + monster.pronoun3 + " groin.  ");
						if (monster.lust100 >= 85) outputText(monster.capitalA + monster.short + " is panting and softly whining, each movement seeming to make " + monster.pronoun3 + " bulge more pronounced.  You don't think " + monster.pronoun1 + " can hold out much longer.  ");
					}
					if (monster.vaginas.length > 0) {
						if (monster.lust100 >= 70 && monster.lust100 < 85) outputText(monster.capitalA + monster.short + " is obviously turned on, you can smell " + monster.pronoun3 + " arousal in the air.  ");
						if (monster.lust100 >= 85) outputText(monster.capitalA + monster.short + "'s " + monster.vaginaDescript() + " is practically soaked with her lustful secretions.  ");
					}
				}
			}
		}

		public var currMonsterIndex:int = 0;
		private var maxMonsterIndex:int = 0;
		public var blockTurn:Boolean;

		public function execMonsterAI(monsterAIIndex:int):void{
            if(monsterAIIndex >= maxMonsterIndex){
                endMonsterTurn();
                return;
            }
            currMonsterIndex = monsterAIIndex;
            blockTurn = false;
			monster = monsterArray[monsterAIIndex];
            if(monster.neverAct){
                monster.tookAction = true;
                execMonsterAI(monsterAIIndex+1);
                return;
            }
            outputText("\n───────────────────────────────────────\n");
            if (flags[kFLAGS.ANNEMARIE_STATUS] == 1 && !inDungeon && !(monster.hasStatusEffect(StatusEffects.Spar) || monster.hasStatusEffect(StatusEffects.Sparring))) game.bog.anneMarieScene.mysteriousStranger();
            if (monster.HP < 0) monster.HP = 0;
            if (monster.lust > monster.maxLust()) monster.lust = monster.maxLust();
            if (monster.HP > 0 && (monster.lust < monster.maxLust() || monster.ignoreLust) && !monster.tookAction){
                monster.doAI();
            }
            // else if(monster.tookAction) outputText("[Themonster] has already acted this turn."); //Saying that the monster already acted looks messy and leads to confusion, particularly while grappled. Better to just display nothing here.
			else if (!monster.tookAction) outputText("You've knocked the resistance out of " + monster.a + monster.short + ".");
            flags[kFLAGS.ENEMY_CRITICAL] = 0;
            monster.tookAction = true;
			if(!blockTurn)execMonsterAI(monsterAIIndex+1);
		}

		public function removeMonster(index:int, range:int):void{
            game.monsterArray[1].HP = 0;
            game.monsterArray[2].HP = 0;
            game.monsterArray[3].HP = 0;
            currTarget = 0;
			maxMonsterIndex -= range;
            game.monsterArray.splice(index, range);
		}
		public function startMonsterTurn():void{
			afterPlayerAttack(); //Do stuff that should happen between the player's action and the enemy's turn
			outputText("\n");
			playerTurn = false;
			maxMonsterIndex = monsterArray.length;
			currMonsterIndex = 0;
			execMonsterAI(currMonsterIndex);
		}

		public function endMonsterTurn():void{
            for (var a:/*StatusEffect*/Array=player.statusEffects.slice(),n:int=a.length,i:int=0;i<n;i++) {
                // Using a copy of array because some effects will be removed
                a[i].onTurnEnd();
            }
            for each(var currMonster:Monster in monsterArray){
                for (a=currMonster.statusEffects.slice(),n=a.length,i=0;i<n;i++) {
                    a[i].onTurnEnd();
                }
            }

            combatRoundOver(true);
		}
		//VICTORY OR DEATH?

		public function totalHP():Number{
			var totalHP:Number = 0;
			if (monsterArray.length == 1) return monster.HP;
			else{
				for (var i:int = 0; i < monsterArray.length; i++){
				if (monsterArray[i].lust >= monsterArray[i].maxLust() && !monsterArray[i].ignoreLust) continue;
				if(monsterArray[i].HP > 0) totalHP += monsterArray[i].HP;
				}
			}
		return totalHP;
		}

		public function lustVictory():Boolean{
			if (monsterArray.length == 1){
				if(monster.lust >= monster.maxLust() && !monster.ignoreLust) return true;
			}
			else{
				for (var i:int = 0; i < monsterArray.length; i++){
				if (monsterArray[i].lust < monsterArray[i].maxLust() || monsterArray[i].ignoreLust){
					return false;
				}
				}
			return true;
			}
			return false;
		}

        public var overrideEndOfRoundFunction:Function = null;

		public function combatRoundOver(newRound:Boolean = false):Boolean { //Called after the monster's action. Given a different name to avoid conflicing with BaseContent.
			blockTurn = false;
			currEnemy = 0;
			currAbilityUsed = null;
			damageTaken = 0;
			if (newRound){
				combatAbilities.updateCooldowns();
				combatRound++;
				inventory.usedItem = false;
				player.resetSeals();
			}
			statScreenRefresh();
			damageType = DAMAGE_NO_ATTACK; //Reset damage type.
			monsterDamageType = DAMAGE_NO_ATTACK;

			if (endFightCheck()) return true;
			doNext(overrideEndOfRoundFunction == null ? playerMenu : overrideEndOfRoundFunction ); //This takes us back to the combatMenu and a new combat round
			return false;
		}

		public function runAway(callHook:Boolean = true):void {
			if (callHook && monster.onPcRunAttempt != null){
				monster.onPcRunAttempt();
				return;
			}
			clearOutput();
			if (inCombat && player.hasStatusEffect(StatusEffects.Sealed) && player.statusEffectv2(StatusEffects.Sealed) == 4) {
				clearOutput();
				outputText("You try to run, but you just can't seem to escape.  Your ability to run was sealed, and now you've wasted a chance to attack!\n\n");
				startMonsterTurn();
				return;
			}
			//Rut doesnt let you run from dicks.
			if (player.inRut && monster.totalCocks() > 0) {
				outputText("The thought of another male in your area competing for all the pussy infuriates you!  No way will you run!");
				menu();
				addButton(0, "Next", combatMenu, false);
				return;
			}
			if (monster.hasStatusEffect(StatusEffects.Level) && player.canFly()) {
				clearOutput();
				outputText("You flex the muscles in your back and, shaking clear of the sand, burst into the air!  Wasting no time you fly free of the sandtrap and its treacherous pit.  \"One day your wings will fall off, little ant,\" the snarling voice of the thwarted androgyne carries up to you as you make your escape.  \"And I will be waiting for you when they do!\"");
				doRunAway();
				clearStatuses();
				return;
			}
			if (monster.hasStatusEffect(StatusEffects.GenericRunDisabled) || game.urtaQuest.isUrta()) {
				outputText("You can't escape from this fight!");
				menu();
				addButton(0, "Next", combatMenu, false);
				return;
			}
			if (monster.hasStatusEffect(StatusEffects.Level) && monster.statusEffectv1(StatusEffects.Level) < 4) {
				outputText("You're too deeply mired to escape!  You'll have to climb some first!");
				menu();
				addButton(0, "Next", combatMenu, false);
				return;
			}
			if (monster.hasStatusEffect(StatusEffects.RunDisabled)) {
				outputText("You'd like to run, but you can't scale the walls of the pit with so many demonic hands pulling you down!");
				menu();
				addButton(0, "Next", combatMenu, false);
				return;
			}
			if (flags[kFLAGS.MINOTAUR_SONS_WASTED_TURN] == 1 && (monster.short == "minotaur gang" || monster.short == "minotaur tribe")) {
				flags[kFLAGS.MINOTAUR_SONS_WASTED_TURN] = 0;
				//(Free run away)
				outputText("You slink away while the pack of brutes is arguing.  Once they finish that argument, they'll be sorely disappointed!");
				doRunAway();
				clearStatuses();
				return;
			}
			else if (monster.short == "minotaur tribe" && monster.HPRatio() >= 0.75) {
				outputText("There's too many of them surrounding you to run!");
				menu();
				addButton(0, "Next", combatMenu, false);
				return;
			}
			if (inDungeon || inRoomedDungeon) {
				outputText("You're trapped in your foe's home turf - there is nowhere to run!\n\n");
				startMonsterTurn();
				return;
			}
			if (prison.inPrison && !prison.prisonCanEscapeRun()) {
				addButton(0, "Next", combatMenu, false);
				return;
			}
			//Attempt texts!
			if (monster.short == "Marae") {
				outputText("Your boat is blocked by tentacles! ");
				if (!player.canFly()) outputText("You may not be able to swim fast enough. ");
				else outputText("You grit your teeth with effort as you try to fly away but the tentacles suddenly grab your " + player.legs() + " and pull you down. ");
				outputText("It looks like you cannot escape. ");
				startMonsterTurn();
				return;
			}
			if (monster.short == "Ember") {
				outputText("You take off");
				if (!player.canFly()) outputText(" running");
				else outputText(", flapping as hard as you can");
				outputText(", and Ember, caught up in the moment, gives chase.  ");
			}
			if (monster.short == "lizan rogue") {
				outputText("As you retreat the lizan doesn't even attempt to stop you. When you look back to see if he's still there you find nothing but the empty bog around you.");
				doRunAway();
				clearStatuses();
				return;
			}
			else if (player.canFly()) outputText("Gritting your teeth with effort, you beat your wings quickly and lift off!  ");
			//Nonflying PCs
			else {
				//In prison!
				if (prison.inPrison) {
					outputText("You make a quick dash for the door and attempt to escape! ");
				}
				//Stuck!
				else if (player.hasStatusEffect(StatusEffects.NoFlee)) {
					if (monster.short == "goblin") outputText("You try to flee but get stuck in the sticky white goop surrounding you.\n\n");
					else outputText("You put all your skills at running to work and make a supreme effort to escape, but are unable to get away!\n\n");
					startMonsterTurn();
					return;
				}
				//Nonstuck!
				else outputText("You turn tail and attempt to flee!  ");
			}

			//Calculations
			var escapeMod:Number = 20 + monster.level * 3;
			if (debug) escapeMod -= 300;
			if(monster.hasPerk(PerkLib.Immovable)) escapeMod -= 30;
            if(monster.distance == monster.DISTANCE_DISTANT) escapeMod -= 50;
			if (player.tail.type == Tail.RACCOON && player.ears.type == Ears.RACCOON && player.findPerk(PerkLib.Runner) >= 0) escapeMod -= 25;
			if (monster.hasStatusEffect(StatusEffects.Stunned)) escapeMod -= 50;
			if (player.findPerk(PerkLib.HistoryThief2) >= 0) escapeMod -= 30;

			//Big tits doesn't matter as much if ya can fly!
			if (!player.canFly()) {
				if (player.biggestTitSize() >= 35) escapeMod += 5;
				if (player.biggestTitSize() >= 66) escapeMod += 10;
				if (player.hips.rating >= 20) escapeMod += 5;
				if (player.butt.rating >= 20) escapeMod += 5;
				if (player.ballSize >= 24 && player.balls > 0) escapeMod += 5;
				if (player.ballSize >= 48 && player.balls > 0) escapeMod += 10;
				if (player.ballSize >= 120 && player.balls > 0) escapeMod += 10;
			}
			//run the hell away if nuke is coming!
			if (monster.short == "Volcanic Golem" && (monster.hasStatusEffect(StatusEffects.Uber) || monster.hasStatusEffect(StatusEffects.VolcanicUberHEAL))){
				outputText("You make the smart decision to run as fast and as far away as you can. A few moments later, far enough away that you can barely see the golem, you feel heavy heat on your back, almost burning it. Had you stood there, you'd certainly have perished.");
				flags[kFLAGS.VOLCANICGOLEMHP] = monster.HP;
				doRunAway();
				return;
			}
			//Dullahan doesn't chase you.
			if (monster.short == "Dark Knight" || monster.short == "Dullahan"){
				outputText("You turn tail and flee! The knight stares and laughs ominously as you run away.");
				doRunAway();
				return;
			}
			//ANEMONE OVERRULES NORMAL RUN
			if (monster.short == "anemone") {
				//Autosuccess - less than 60 lust
				if (player.lust100 < 60) {
					outputText("Marshalling your thoughts, you frown at the strange girl and turn to march up the beach.  After twenty paces inshore you turn back to look at her again.  The anemone is clearly crestfallen by your departure, pouting heavily as she sinks beneath the water's surface.");
					doRunAway();
					clearStatuses();
					return;
				}
				//Speed dependent
				else {
					//Success
					if (player.spe > rand(monster.spe+escapeMod)) {
						clearStatuses();
						outputText("Marshalling your thoughts, you frown at the strange girl and turn to march up the beach.  After twenty paces inshore you turn back to look at her again.  The anemone is clearly crestfallen by your departure, pouting heavily as she sinks beneath the water's surface.");
						doRunAway();
						return;
					}
					//Run failed:
					else {
						outputText("You try to shake off the fog and run but the anemone slinks over to you and her tentacles wrap around your waist.  \"Stay?\" she asks, pressing her small breasts into you as a tentacle slides inside your " + player.armorName + " and down to your nethers.  The combined stimulation of the rubbing and the tingling venom causes your knees to buckle, hampering your resolve and ending your escape attempt.");
						//(gain lust, temp lose spd/str)
						(monster as Anemone).applyVenom((4+player.sens/20));

						return;
					}
				}
			}
			//Ember is SPUCIAL
			if (monster.short == "Ember") {
				//GET AWAY
				if (player.spe > rand(monster.spe + escapeMod) || (player.findPerk(PerkLib.Runner) >= 0 && rand(100) < 50)) {
					if (player.findPerk(PerkLib.Runner) >= 0) outputText("Using your skill at running, y");
					else outputText("Y");
					outputText("ou easily outpace the dragon, who begins hurling imprecations at you.  [say: What the hell, [name], you weenie; are you so scared that you can't even stick out your punishment?]");
					outputText("\n\nNot to be outdone, you call back, taunting her for her inability to catch you as she fumes in the distance.");
					doRunAway();
					clearStatuses();
				}
				//Fail:
				else {
					outputText("Despite some impressive jinking, " + game.emberScene.emberMF("he", "she") + " catches you, tackling you to the ground.\n\n");
					startMonsterTurn();
				}
				return;
			}
			//SUCCESSFUL FLEE
			if (player.spe > rand(monster.spe + escapeMod)) {
				//Escape prison
				if (prison.inPrison) {
					outputText("You quickly bolt out of the main entrance and after hiding for a good while, there's no sign of " + monster.a + " " + monster.short + ". You sneak back inside to retrieve whatever you had before you were captured. ");
					doRunAway();
					clearStatuses();
					prison.prisonEscapeSuccessText();
					doNext(prison.prisonEscapeFinalePart1);
					return;
				}
				//Fliers flee!
				else if (player.canFly()) outputText(monster.capitalA + monster.short + " can't catch you.");
				//sekrit benefit: if you have coon ears, coon tail, and Runner perk, change normal Runner escape to flight-type escape
				else if (player.tail.type == Tail.RACCOON && player.ears.type == Ears.RACCOON && player.findPerk(PerkLib.Runner) >= 0) {
					outputText("Using your running skill, you build up a head of steam and jump, then spread your arms and flail your tail wildly; your opponent dogs you as best " + monster.pronoun1 + " can, but stops and stares dumbly as your spastic tail slowly propels you several meters into the air!  You leave " + monster.pronoun2 + " behind with your clumsy, jerky, short-range flight.");
				}
				//Non-fliers flee
				else outputText(monster.capitalA + monster.short + " rapidly disappears into the shifting landscape behind you.");
				if (monster.short == "Izma") {
					outputText("\n\nAs you leave the tigershark behind, her taunting voice rings out after you.  \"Oooh, look at that fine backside!  Are you running or trying to entice me?  Haha, looks like we know who's the superior specimen now!  Remember: next time we meet, you owe me that ass!\"  Your cheek tingles in shame at her catcalls.");
				}
				if(monster is VolcanicGolem) flags[kFLAGS.VOLCANICGOLEMHP] = monster.HP;
				doRunAway();
				clearStatuses();
				return;
			}
			//Runner perk chance
			else if (player.findPerk(PerkLib.Runner) >= 0 && rand(100) < 50) {
				outputText("Thanks to your talent for running, you manage to escape.");
				if (monster.short == "Izma") {
					outputText("\n\nAs you leave the tigershark behind, her taunting voice rings out after you.  \"Oooh, look at that fine backside!  Are you running or trying to entice me?  Haha, looks like we know who's the superior specimen now!  Remember: next time we meet, you owe me that ass!\"  Your cheek tingles in shame at her catcalls.");
				}
				clearStatuses();
				doRunAway();
				return;
			}
			//FAIL FLEE
			else {
				if (monster.short == "Holli") {
					(monster as Holli).escapeFailWithHolli();
					return;
				}
				//Flyers get special failure message.
				if (player.canFly()) {
					if (monster.plural) outputText(monster.capitalA + monster.short + " manage to grab your " + player.legs() + " and drag you back to the ground before you can fly away!");
					else outputText(monster.capitalA + monster.short + " manages to grab your " + player.legs() + " and drag you back to the ground before you can fly away!");
				}
				//fail
				else if (player.tail.type == Tail.RACCOON && player.ears.type == Ears.RACCOON && player.findPerk(PerkLib.Runner) >= 0) outputText("Using your running skill, you build up a head of steam and jump, but before you can clear the ground more than a foot, your opponent latches onto you and drags you back down with a thud!");
				//Nonflyer messages
				else {
					//Huge balls messages
					if (player.balls > 0 && player.ballSize >= 24) {
						if (player.ballSize < 48) outputText("With your " + player.ballsDescriptLight() + " swinging ponderously beneath you, getting away is far harder than it should be.  ");
						else outputText("With your " + player.ballsDescriptLight() + " dragging along the ground, getting away is far harder than it should be.  ");
					}
					//FATASS BODY MESSAGES
					if (player.biggestTitSize() >= 35 || player.butt.rating >= 20 || player.hips.rating >= 20)
					{
						//FOR PLAYERS WITH GIANT BREASTS
						if (player.biggestTitSize() >= 35 && player.biggestTitSize() < 66)
						{
							if (player.hips.rating >= 20)
							{
								outputText("Your " + player.hipDescript() + " forces your gait to lurch slightly side to side, which causes the fat of your " + player.skin.tone + " ");
								if (player.butt.rating >= 20) outputText(player.buttDescript() + " and ");
								outputText(player.chestDesc() + " to wobble immensely, throwing you off balance and preventing you from moving quick enough to escape.");
							}
							else if (player.butt.rating >= 20) outputText("Your " + player.skin.tone + player.buttDescript() + " and " + player.chestDesc() + " wobble and bounce heavily, throwing you off balance and preventing you from moving quick enough to escape.");
							else outputText("Your " + player.chestDesc() + " jiggle and wobble side to side like the " + player.skin.tone + " sacks of milky fat they are, with such force as to constantly throw you off balance, preventing you from moving quick enough to escape.");
						}
						//FOR PLAYERS WITH MASSIVE BREASTS
						else if (player.biggestTitSize() >= 66) {
							if (player.hips.rating >= 20) {
								outputText("Your " + player.chestDesc() + " nearly drag along the ground while your " + player.hipDescript() + " swing side to side ");
								if (player.butt.rating >= 20) outputText("causing the fat of your " + player.skin.tone + player.buttDescript() + " to wobble heavily, ");
								outputText("forcing your body off balance and preventing you from moving quick enough to get escape.");
							}
							else if (player.butt.rating >= 20) outputText("Your " + player.chestDesc() + " nearly drag along the ground while the fat of your " + player.skin.tone + player.buttDescript() + " wobbles heavily from side to side, forcing your body off balance and preventing you from moving quick enough to escape.");
							else outputText("Your " + player.chestDesc() + " nearly drag along the ground, preventing you from moving quick enough to get escape.");
						}
						//FOR PLAYERS WITH EITHER GIANT HIPS OR BUTT BUT NOT THE BREASTS
						else if (player.hips.rating >= 20) {
							outputText("Your " + player.hipDescript() + " swing heavily from side to side ");
							if (player.butt.rating >= 20) outputText("causing your " + player.skin.tone + player.buttDescript() + " to wobble obscenely ");
							outputText("and forcing your body into an awkward gait that slows you down, preventing you from escaping.");
						}
						//JUST DA BOOTAH
						else if (player.butt.rating >= 20) outputText("Your " + player.skin.tone + player.buttDescript() + " wobbles so heavily that you're unable to move quick enough to escape.");
					}
					//NORMAL RUN FAIL MESSAGES
					else if (monster.plural) outputText(monster.capitalA + monster.short + " stay hot on your heels, denying you a chance at escape!");
					else outputText(monster.capitalA + monster.short + " stays hot on your heels, denying you a chance at escape!");
				}
			}
			outputText("\n\n");
			startMonsterTurn();
		}

		public function doRunAway():void {
			//if (monster.monsterCounters != null) monster.monsterCounters.ranfrom++;
			generalCleanup();
			monsterArray.length = 0;
			//mainView.endCombatView();
			inCombat = false;
			clearStatuses();
			doNext(camp.returnToCampUseOneHour);
		}

		public function beforePlayerTurn():Boolean{
			var continueTurn:Boolean = true;
            for each(var currMonster:Monster in monsterArray){
                statScreenRefresh();
                if(!currMonster.react(monster.CON_TURNSTART)){
                    startMonsterTurn();
                    continueTurn = false;
                }
			}

			return continueTurn;
		}

		public function afterPlayerAttack():void {
			if (player.hasStatusEffect(StatusEffects.TFQuake) && (player.createOrFindStatusEffect(StatusEffects.TFQuake) as TFQuakeBuff).getDuration() < 3) {
				combatAbilities.tfQuakeAftershocks();
			}
			if (player.hasStatusEffect(StatusEffects.TFTerraCore)) {
				if (player.statusEffectv1(StatusEffects.TFTerraCore) > 0) combatAbilities.tfTerraCoreRetry();
				else player.addStatusValue(StatusEffects.TFTerraCore, 1, 1);
			}
			if (player.hasStatusEffect(StatusEffects.TFTerraStar) && !player.hasStatusEffect(StatusEffects.TFSupercharging)) {
				if (player.statusEffectv1(StatusEffects.TFTerraStar) > 0) player.changeStatusValue(StatusEffects.TFTerraStar, 1, 0);
				else combatAbilities.tfTerraStarAttack();
			}
		}
	}

}