code:
package classes {

	import flash.utils.Dictionary;

	public class MasteryType extends BaseContent {

		private static var MASTERY_LIBRARY:Dictionary = new Dictionary();

		public static function lookupMastery(id:String):MasteryType {
			return MASTERY_LIBRARY[id];
		}

		public static function getMasteryLibrary():Dictionary {
			return MASTERY_LIBRARY;
		}

		public function MasteryType(id:String, name:String, category:String = "General", desc:String = "", xpCurve:Number = 1.5, maxLevel:int = 5, permable:Boolean = true) {
			this._id = id;
			this._name = name;
			this._category = category;
			this._desc = desc;
			this._xpCurve = xpCurve;
			this._maxLevel = maxLevel;
			this._permable = permable;
			MASTERY_LIBRARY[id] = this;
		}

		private var _id:String; //Internal ID, should be unique. Also used to match against weapon tags.
		private var _name:String; //Different masteries can have the same name, or the name can change, only the ID has to be unique and static.
		private var _desc:String; //Not sure yet how this will be used/displayed.
		private var _category:String; //For organising and grouping masteries, and defining default behaviour.
		private var _xpCurve:Number; //Determines how much xp requirement grows with each level. 1 means no curve, each level is gained at the same rate. 2 means each level takes twice as much xp as the last.
		private var _maxLevel:int; //Should be self-explanatory.
		private var _permable:Boolean; //Determines whether the mastery can be kept on ascension

		public function get id():String {
			return _id;
		}

		public function get name():String {
			return _name;
		}

		public function get desc():String {
			return _desc;
		}

		public function get category():String {
			return _category;
		}

		public function get maxLevel():int {
			return _maxLevel;
		}

		public function get xpCurve():Number {
			return _xpCurve;
		}

		public function get permable():Boolean {
			return _permable;
		}

		//Run when first gaining the mastery
		public function onAttach(output:Boolean = true):void {
			if (output) outputText("\nYou've begun training " + _name + " mastery.\n");
		}

		//Run on levelup
		public function onLevel(level:int, output:Boolean = true):void {
			if (output) outputText("\n" + _name + " mastery is now level " + level + "\n");
		}

		public var bonusStats:BonusDerivedStats = new BonusDerivedStats();
		public var host:Creature;

        public function boostsHealthRegenPercentage(value:*, mult:Boolean = false):MasteryType {
            bonusStats.boostStat(BonusDerivedStats.healthRegenPercent,value,mult,name);
            return this;
        }

        public function boostsMinLust(value:*, mult:Boolean = false):MasteryType {
            bonusStats.boostStat(BonusDerivedStats.minLust,value,mult,name);
            return this;
        }

        public function boostsLustResistance(value:*, mult:Boolean = false):MasteryType {
            bonusStats.boostStat(BonusDerivedStats.lustRes,value,mult,name);
            return this;
        }

        public function boostsSpellMod(value:*, mult:Boolean = false):MasteryType {
			bonusStats.boostStat(BonusDerivedStats.spellMod,value,mult,name);
			return this;
    	}

        public function boostsPhysDamage(value:*, mult:Boolean = false):MasteryType {
            bonusStats.boostStat(BonusDerivedStats.physDmg,value,mult,name);
            return this;
        }

        public function boostsSpellCost(value:*, mult:Boolean = false):MasteryType {
            bonusStats.boostStat(BonusDerivedStats.spellCost,value,mult,name);
            return this;
        }
        public function boostsDodge(value:*, mult:Boolean = false):MasteryType {
            bonusStats.boostStat(BonusDerivedStats.dodge,value,mult,name);
            return this;
        }

		public function boostsCritChance(value:*, mult:Boolean = false):MasteryType {
            bonusStats.boostStat(BonusDerivedStats.critC,value,mult,name);
            return this;
        }

        public function boostsAttackDamage(value:*, mult:Boolean = false):MasteryType {
            bonusStats.boostStat(BonusDerivedStats.attackDamage,value,mult,name);
            return this;
        }

        public function boostsGlobalDamage(value:*, mult:Boolean = false):MasteryType {
            bonusStats.boostStat(BonusDerivedStats.globalMod,value,mult,name);
            return this;
        }

        public function boostsWeaponDamage(value:*, mult:Boolean = false):MasteryType {
            bonusStats.boostStat(BonusDerivedStats.weaponDamage,value,mult,name);
            return this;
        }

        public function boostsSeduction(value:*, mult:Boolean = false):MasteryType {
            bonusStats.boostStat(BonusDerivedStats.seduction,value,mult,name);
            return this;
        }

        public function boostsSexiness(value:*, mult:Boolean = false):MasteryType {
            bonusStats.boostStat(BonusDerivedStats.sexiness,value,mult,name);
            return this;
        }

        public function boostsMaxFatigue(value:*, mult:Boolean = false):MasteryType {
            bonusStats.boostStat(BonusDerivedStats.fatigueMax,value,mult,name);
            return this;
        }
	}
}


code:
package classes
{
	import classes.GlobalFlags.kFLAGS;
	import classes.GlobalFlags.kGAMECLASS;
	import classes.internals.Utils;
	/**
	 * Class to make the measurement methods taken from PlayerAppearance globally accessible
	 * @since  19.08.2016
	 * @author Stadler76
	 */
	public class Measurements
	{
		public static function footInchOrMetres(inches:Number, precision:int = 2):String
		{
			if (kGAMECLASS.flags[kFLAGS.USE_METRICS])
				return (Math.round(inches * 2.54) / Math.pow(10, precision)).toFixed(precision) + " metres";

			return Math.floor(inches / 12) + " foot " + inches % 12 + " inch";
		}

		public static function numInchesOrCentimetres(inches:Number):String
		{
			if (inches < 1) return inchesOrCentimetres(inches);

			var value:int = Math.round(inches);

			if (kGAMECLASS.flags[kFLAGS.USE_METRICS]) {
				value = Math.round(inches * 2.54);
				return Utils.num2Text(value) + (value === 1 ? " centimetre" : " centimetres");
			}

			if (inches % 12 === 0)
				return (inches === 12 ? "a foot" : Utils.num2Text(inches / 12) + " feet");

			return Utils.num2Text(value) + (value === 1 ? " inch" : " inches");
		}

		public static function inchesOrCentimetres(inches:Number, precision:int = 1):String
		{
			var value:Number = Math.round(inchToCm(inches) * Math.pow(10, precision)) / Math.pow(10, precision);
			var text:String = value + (kGAMECLASS.flags[kFLAGS.USE_METRICS] ? " centimetre" : " inch");

			if (value === 1) return text;

			return text + (kGAMECLASS.flags[kFLAGS.USE_METRICS] ? "s" : "es");
		}

		public static function shortSuffix(inches:Number, precision:int = 1):String
		{
			var value:Number = Math.round(inchToCm(inches) * Math.pow(10, precision)) / Math.pow(10, precision);
			return value + (kGAMECLASS.flags[kFLAGS.USE_METRICS] ? "-cm" : "-inch");
		}

		public static function inchToCm(inches:Number):Number
		{
			return kGAMECLASS.flags[kFLAGS.USE_METRICS] ? inches * 2.54 : inches;
		}

		//Returns shorthand such as 5'6" or 168cm
		public static function briefHeight(inches:Number):String {
			var value:int = Math.round(inches);
			var ret:String = "";

			if (kGAMECLASS.flags[kFLAGS.USE_METRICS]) {
				value = Math.round(inches * 2.54);
				return value + "cm";
			}

			if (inches >= 12) ret += int(inches/12) + "'";
			if ((inches % 12) > 0) ret += int(inches % 12) + "\"";
			return ret;
		}
	}
}

license: unknown


code:
package classes
{
	import classes.BodyParts.*;
import classes.GlobalFlags.kACHIEVEMENTS;
import classes.GlobalFlags.kFLAGS;
import classes.GlobalFlags.kGAMECLASS;
import classes.GlobalFlags.kGAMECLASS;
	import classes.Items.ArmorLib;
	import classes.Items.ConsumableLib;
	import classes.Items.JewelryLib;
	import classes.Items.UseableLib;
	import classes.Items.WeaponLib;
	import classes.Items.ShieldLib;
	import classes.Items.UndergarmentLib;
	import classes.Scenes.Areas.VolcanicCrag.VolcanicGolem;
	import classes.Scenes.Dungeons.Factory.SecretarialSuccubus;
	import classes.Scenes.NPCs.Kiha;
	import classes.Scenes.Quests.UrtaQuest.MilkySuccubus;
	import classes.StatusEffects.Combat.BasiliskSlowDebuff;
import classes.StatusEffects.Combat.CombatBuff;
import classes.internals.ChainedDrop;

import mx.controls.ToolTip;

//import classes.internals.MonsterCounters;
	import classes.internals.RandomDrop;
	import classes.internals.Utils;
	import classes.internals.WeightedDrop;
	import classes.Scenes.Areas.Forest.AkbalUnsealed;

	import flash.utils.getQualifiedClassName;

	/**
	 * ...
	 * @author Yoffy, Fake-Name, aimozg
	 */
	public class Monster extends Creature
	{

		protected var attackContainer:Object = {
			attacker: this,
			defender: null,
			doDodge: true,
			doParry: false,
			doBlock: false,
			doCounter: false,
			doFatigue: false,
			toHitChance:  null
		};

		protected final function get player():Player
		{
			return game.player;
		}
		protected final function outputText(text:String,clear:Boolean=false):void{
			game.outputText(text);
		}
		protected final function combatRoundOver():void{

		}
		/*protected final function combat.cleanupAfterCombat():void
		{
			game.combat.cleanupAfterCombat();
		}*/
		protected static function showStatDown(a:String):void{
			kGAMECLASS.mainView.statsView.showStatDown(a);
		}
		protected final function statScreenRefresh():void {
			game.output.statScreenRefresh();
		}
		protected final function doNext(eventNo:Function):void { //Now typesafe
			game.output.doNext(eventNo);
		}
		/*protected final function combatMiss():Boolean {
			return game.combat.combatMiss();
		}*/
		protected final function combatAvoidDamage(def:*):Object{
			def.attacker = this;
			def.defender = player;
			return game.combat.combatAvoidDamage(def);
		}
		protected final function combatBlock(doFatigue:Boolean = false):Boolean {
			return game.combat.combatBlock(this,player,doFatigue);
		}
		protected function get consumables():ConsumableLib{
			return game.consumables;
		}
		protected function get useables():UseableLib{
			return game.useables;
		}
		protected function get weapons():WeaponLib{
			return game.weapons;
		}
		protected function get shields():ShieldLib{
			return game.shields;
		}
		protected function get armors():ArmorLib{
			return game.armors;
		}
		protected function get jewelries():JewelryLib{
			return game.jewelries;
		}
		protected function get undergarments():UndergarmentLib{
			return game.undergarments;
		}

		protected function get images():ImageManager
		{
			return game.images;
		}

		protected function set images(val:ImageManager):void
		{
			game.images = val;
		}
		///For enemies
		public var currTarget:int //oh god this went terribly wrong;
		public var neverAct:Boolean = false;
		public var tookAction:Boolean = false; //used to mark if a monster already acted.
		public var bonusHP:Number = 0;
		public var bonusLust:Number = 0;
		public var prefersRanged:Boolean = false; //if true, will allow the player to distance itself.
		//public var monsterCounters:MonsterCounters = null;
		public var ignoreLust:Boolean = false //used to mark whether or not a monster should act even at max lust.
		public var ignoreHP:Boolean = false //used to mark whether or not a monster should act even at 0 HP.
		public var temporary:Boolean = false//used to mark whether or not a monster should vanish when his HP reaches 0 or its lust reaches max.
		public var canBlock:Boolean = false;
		private var _long:String = "<b>You have encountered an uninitialized  Please report this as a bug</b>.";
		public function get long():String
		{
			return _long;
		}
		public function set long(value:String):void
		{
			initsCalled.long = true;
			_long = value;
		}

		//Is a creature a 'plural' encounter - mob, etc.
		public var plural:Boolean = false;
		public var unitHP:Number = 0;//useful when making a dynamic horde that decreases in power as you "defeat" it.
		public var unitAmount:Number = 0;//same
		public var imageName:String = "";

		//Lust vulnerability
		public var lustVuln:Number = 1;

		public static const TEMPERMENT_AVOID_GRAPPLES:int = 0;
		public static const TEMPERMENT_LUSTY_GRAPPLES:int = 1;
		public static const TEMPERMENT_RANDOM_GRAPPLES:int = 2;
		public static const TEMPERMENT_LOVE_GRAPPLES:int = 3;
		/**
		 * temperment - used for determining grapple behaviors
		 * 0 - avoid grapples/break grapple
		 * 1 - lust determines > 50 grapple
		 * 2 - random
		 * 3 - love grapples
		*/
		public var temperment:Number = TEMPERMENT_AVOID_GRAPPLES;

		//Used for special attacks.
		public var special1:Function = null;
		public var special2:Function = null;
		public var special3:Function = null;

		//Assign tags that can be checked elsewhere, e.g. a demon tag on all demon enemies so abilities or items can give bonuses when fighting demons
		public var tagList:Array = [];
		public function hasTag(tag:String):Boolean {
			return tagList.indexOf(tag) >= 0;
		}

		///he
		public var pronoun1:String = "";
		public function get Pronoun1():String{
			if (pronoun1=="") return "";
			return pronoun1.substr(0,1).toUpperCase()+pronoun1.substr(1);
		}
		///him
		public var pronoun2:String = "";
		public function get Pronoun2():String{
			if (pronoun2=="") return "";
			return pronoun2.substr(0,1).toUpperCase()+pronoun2.substr(1);
		}
		///3: Possessive his
		public var pronoun3:String = "";
		public function get Pronoun3():String{
			if (pronoun3=="") return "";
			return pronoun3.substr(0,1).toUpperCase()+pronoun3.substr(1);
		}

		private var _drop:RandomDrop = new ChainedDrop();
		public function get drop():RandomDrop { return _drop; }
		public function set drop(value:RandomDrop):void
		{
			_drop = value;
			initedDrop = true;
		}

		public function scaleToLevel(levelDelta:int = 0):void{
			if(levelDelta == 0) levelDelta = player.level - this.level;
			if (levelDelta <= 0) return;
			this.str *= 1 + levelDelta * 0.025;
			this.inte *= 1 + levelDelta * 0.05;
			this.spe *= 1 + levelDelta * 0.05;
			this.tou *= 1 + levelDelta * 0.05;
			this.weaponAttack *= 1 + levelDelta * 0.025;
			this.bonusHP += this.maxHP() * (1 + levelDelta * 0.0125);
			this.level = player.level;
		}

		public override function maxHP():Number
		{
			//Base HP
			var temp:Number = super.maxHP() + this.bonusHP;
			//Apply NG+, NG++, NG+++, etc.
			if (flags[kFLAGS.ASCENSIONING] == 0){
				if (short === "doppelganger" || short === "pod" || short === "sand trap" || short === "sand tarp") {
					temp += 200 * player.newGamePlusMod();
				}
				else if (short === "Lethice") {
					temp += 1200 * player.newGamePlusMod();
				}
				else if (short === "Marae") {
					temp += 2500 * player.newGamePlusMod();
				}
				else if (this is AkbalUnsealed) {
					temp += 1500 * player.newGamePlusMod();
				}
				else {
					temp += 1000 * player.newGamePlusMod();
				}
			}
			if (flags[kFLAGS.ASCENSIONING] == 1){
				if (short == "doppelganger" || short == "pod" || short == "sand trap" || short == "sand tarp") {
					temp += 10 * player.newGamePlusMod();
				}
				else if (short == "Lethice") {
					temp += 80 * player.newGamePlusMod();
				}
				else if (short == "Marae") {
					temp += 100 * player.newGamePlusMod();
				}
				else if (this is AkbalUnsealed) {
					temp += 100 * player.newGamePlusMod();
				}
				else {
					temp += 10 * player.newGamePlusMod();
				}
			}
			//if (hasStatusEffect(StatusEffects.Apotheosis)) temp = temp/Math.pow(2, statusEffectv1(StatusEffects.Apotheosis));
			//Apply difficulty
			if (flags[kFLAGS.GAME_DIFFICULTY] <= 0) temp *= 1.0;
			else if (flags[kFLAGS.GAME_DIFFICULTY] === 1) temp *= 1.25;
			else if (flags[kFLAGS.GAME_DIFFICULTY] === 2) temp *= 1.5;
			else temp *= 2.0;
			//Volcanic Golem has persistent HP
			if (short == "Volcanic Golem") temp = flags[kFLAGS.VOLCANICGOLEMHP];
			temp = Math.round(temp);
			return temp;
		}

		override public function maxLust():Number {
			//Base Lust
			var temp:Number = 100 + this.bonusLust;
			if (findPerk(PerkLib.ImprovedSelfControl) >= 0) temp += 20;
			return temp;
		}
		public function addHP(hp:Number):void {
			HPChange(hp,false);
		}

		/**
		 * @return damage not reduced by player stats
		 */
		public function eBaseDamage():Number {
			var weaponDamage:Number =  getTotalStat(BonusDerivedStats.weaponDamage,weaponAttack);
			var retv:Number = getTotalStat(BonusDerivedStats.physDmg,str + weaponDamage)
			return retv;
		}

		/**
		 * @return randomized damageDealt reduced by player stats
		 */
		public function calcDamage():int{
			if (player.hasStatusEffect(StatusEffects.CounterAB)){
				if(attackCountered(player)) return 0;
			}
			return player.reduceDamage(eBaseDamage(),this);
		}

		public function totalXP(playerLevel:Number=-1):Number
		{
			var multiplier:Number = 1;
			multiplier += game.player.perkv1(PerkLib.AscensionWisdom) * 0.1;
			if (playerLevel === -1) playerLevel = game.player.level;
			//
			// 1) Nerf xp gains by 20% per level after first two level difference
			// 2) No bonuses for underlevel!
			// 3) Super high level folks (over 10 levels) only get 1 xp!
			var difference:Number = playerLevel - this.level;
			if (difference <= 2) difference = 0;
			else difference -= 2;
			if (difference > 4) difference = 4;
			difference = (5 - difference) * 20.0 / 100.0;
			if (playerLevel - this.level > 10) return 1;
			return Math.round(this.additionalXP + (this.baseXP() + this.bonusXP()) * difference * multiplier);
		}
		protected function baseXP():Number
		{
			return[200, 10, 20, 30, 40, 50, 55, 60, 66, 75,//0-9
				83, 85, 92, 100, 107, 115, 118, 121, 128, 135,//10-19
				145][Math.round(level)] || 200;
		}
		protected function bonusXP():Number
		{
			return rand([200,10,20,30,40,50,55,58,66,75,
					83,85,85,86,92,94,96,98,99,101,
					107][Math.round(this.level)] || 130);
		}

		public function Monster()
		{
			// trace("Generic Monster Constructor!");

			//// INSTRUCTIONS
			//// Copy-paste remaining code to the new monster constructor
			//// Uncomment and replace placeholder values with your own
			//// See existing monsters for examples

			// super(mainClassPtr);

			//// INIITIALIZERS
			//// If you want to skip something that is REQUIRED, you shoud set corresponding
			//// this.initedXXX property to true, e.g. this.initedGenitals = true;

			//// 1. Names and plural/singular
			///*REQUIRED*/ this.a = "a";
			///*REQUIRED*/ this.short = "short";
			///*OPTIONAL*/ // this.imageName = "imageName"; // default ""
			///*REQUIRED*/ this.long = "long";
			///*OPTIONAL*/ //this.plural = true|false; // default false

			//// 2. Gender, genitals, and pronouns (also see "note for 2." below)
			//// 2.1. Male
			///*REQUIRED*/ this.createCock(length,thickness,type); // defaults 5.5,1,human; could be called multiple times
			///*OPTIONAL*/ //this.balls = numberOfBalls; // default 0
			///*OPTIONAL*/ //this.ballSize = ; // default 0. should be set if balls>0
			///*OPTIONAL*/ //this.cumMultiplier = ; // default 1
			///*OPTIONAL*/ //this.hoursSinceCum = ; // default 0
			//// 2.2. Female
			///*REQUIRED*/ this.createVagina(virgin=true|false,Vagina.WETNESS_,Vagina.); // default true,normal,tight
			///*OPTIONAL*/ //this.createStatusEffect(StatusEffects.BonusVCapacity, bonus, 0, 0, 0);
			//// 2.3. Hermaphrodite
			//// Just create cocks and vaginas. Last call determines pronouns.
			//// 2.4. Genderless
			///*REQUIRED*/ initGenderless(); // this functions removes genitals!

			//// Note for 2.: during initialization pronouns are set in:
			//// * createCock: he/him/his
			//// * createVagina: she/her/her
			//// * initGenderless: it/it/its
			//// If plural=true, they are replaced with: they/them/their
			//// If you want to customize pronouns:
			///*OPTIONAL*/ //this.pronoun1 = "he";
			///*OPTIONAL*/ //this.pronoun2 = "him";
			///*OPTIONAL*/ //this.pronoun3 = "his";
			//// Another note for 2.: gender is automatically calculated in createCock,
			//// createVagina, initGenderless. If you want to change it, set this.gender
			//// after these method calls.

			//// 3. Breasts
			///*REQUIRED*/ this.createBreastRow(size,nipplesPerBreast); // default 0,1
			//// Repeat for multiple breast rows
			//// You can call just `this.createBreastRow();` for flat breasts
			//// Note useful method: this.createBreastRow(Appearance.breastCupInverse("C")); // "C" -> 3

			//// 4. Ass
			///*OPTIONAL*/ //this.ass.analLooseness = Ass.LOOSENESS_; // default TIGHT
			///*OPTIONAL*/ //this.ass.analWetness = Ass.WETNESS_; // default DRY
			///*OPTIONAL*/ //this.createStatusEffect(StatusEffects.BonusACapacity, bonus, 0, 0, 0);
			//// 5. Body
			///*REQUIRED*/ this.tallness = ;
			///*OPTIONAL*/ //this.hips.rating = Hips.RATING_; // default boyish
			///*OPTIONAL*/ //this.butt.rating = Butt.RATING_; // default buttless
			///*OPTIONAL*/ //this.lowerBody.typePart.type = LOWER_BODY_; //default human
			///*OPTIONAL*/ //this.arms.type = Arms.; // default human

			//// 6. Skin
			///*OPTIONAL*/ //this.skin.tone = ".skin.tone"; // default "albino"
			///*OPTIONAL*/ //this.skin.type = Skin.; // default PLAIN
			///*OPTIONAL*/ //this.skin.desc = "skinDesc"; // default "skin" if this.skin.type is not set, else Appearance.DEFAULT_SKIN_DESCS[skinType]
			///*OPTIONAL*/ //this.skin.adj = "skinAdj"; // default ""

			//// 7. Hair
			///*OPTIONAL*/ //this.hair.color = ; // default "no"
			///*OPTIONAL*/ //this.hair.length = ; // default 0
			///*OPTIONAL*/ //this.hair.type = Hair.; // default NORMAL

			//// 8. Face
			///*OPTIONAL*/ //this.face.type = Face.; // default HUMAN
			///*OPTIONAL*/ //this.horns.type= Ears.; // default HUMAN
			///*OPTIONAL*/ //this.tongue.type = Tongue.; // default HUMAN
			///*OPTIONAL*/ //this.eyes.type = Eyes.; // default HUMAN

			//// 9. Primary stats.
			///*REQUIRED*/ initStrTouSpeInte(,,,);
			///*REQUIRED*/ initLibSensCor(,,);

			//// 10. Weapon
			///*REQUIRED*/ this.weaponName = "weaponName";
			///*REQUIRED*/ this.weaponVerb = "weaponVerb";
			///*OPTIONAL*/ //this.weaponAttack = ; // default 0
			///*OPTIONAL*/ //this.weaponPerk = "weaponPerk"; // default ""
			///*OPTIONAL*/ //this.weaponValue = ; // default 0

			//// 11. Armor
			///*REQUIRED*/ this.armorName = "armorName";
			///*OPTIONAL*/ //this.armorDef = ; // default 0
			///*OPTIONAL*/ //this.armorPerk = "armorPerk"; // default ""
			///*OPTIONAL*/ //this.armorValue = ; // default 0

			//// 12. Combat
			///*OPTIONAL*/ //this.bonusHP = ; // default 0
			///*OPTIONAL*/ //this.lust = ; // default 0
			///*OPTIONAL*/ //this.lustVuln = ; // default 1
			///*OPTIONAL*/ //this.temperment = TEMPERMENT; // default AVOID_GRAPPLES
			///*OPTIONAL*/ //this.fatigue = ; // default 0

			//// 13. Level
			///*REQUIRED*/ this.level = ;
			///*REQUIRED*/ this.gems = ;
			///*OPTIONAL*/ //this.additionalXP = ; // default 0

			//// 14. Drop
			//// 14.1. No drop
			///*REQUIRED*/ this.drop = NO_DROP;
			//// 14.2. Fixed drop
			///*REQUIRED*/ this.drop = new WeightedDrop(dropItemType);
			//// 14.3. Random weighted drop
			///*REQUIRED*/ this.drop = new WeightedDrop()...
			//// Append with calls like:
			//// .add(itemType,itemWeight)
			//// .addMany(itemWeight,itemType1,itemType2,...)
			//// Example:
			//// this.drop = new WeightedDrop()
			//// 		.add(A,2)
			//// 		.add(B,10)
			//// 		.add(C,1)
			//// 	will drop B 10 times more often than C, and 5 times more often than A.
 			//// 	To be precise, \forall add(A_i,w_i): P(A_i)=w_i/\sum_j w_j
			//// 14.4. Random chained check drop
			///*REQUIRED*/ this.drop = new ChainedDrop(optional defaultDrop)...
			//// Append with calls like:
			//// .add(itemType,chance)
			//// .elseDrop(defaultDropItem)
			////
			//// Example 1:
			//// init14ChainedDrop(A)
			//// 		.add(B,0.01)
			//// 		.add(C,0.5)
			//// 	will FIRST check B vs 0.01 chance,
			//// 	if it fails, C vs 0.5 chance,
			//// 	else A
			////
			//// 	Example 2:
			//// 	init14ChainedDrop()
			//// 		.add(B,0.01)
			//// 		.add(C,0.5)
			//// 		.elseDrop(A)
			//// 	for same result

			//// 15. Special attacks. No need to set them if the monster has custom AI.
			//// Values are either combat event numbers (5000+) or function references
			///*OPTIONAL*/ //this.special1 = ; //default 0
			///*OPTIONAL*/ //this.special2 = ; //default 0
			///*OPTIONAL*/ //this.special3 = ; //default 0

			//// 16. Tail
			///*OPTIONAL*/ //this.tail.type = Tail.; // default NONE
			///*OPTIONAL*/ //this.tail.venom = ; // default 0
			///*OPTIONAL*/ //this.tail.recharge = ; // default 5

			//// 17. Horns
			///*OPTIONAL*/ //this.hornsPart.type = Horns.; // default NONE
			///*OPTIONAL*/ //this.hornsPart.value = numberOfHorns; // default 0

			//// 18. Wings
			///*OPTIONAL*/ //this.wings.type = Wings.; // default NONE
			///*OPTIONAL*/ //this.wingDesc = ; // default Appearance.DEFAULT_WING_DESCS[wingType]

			//// 19. Antennae
			///*OPTIONAL*/ //this.antennaePart.type = Antennae.; // default NONE

			//// 20. Tags
			///*OPTIONAL*/ //this.tagList = []; // default empty

			//// REQUIRED !!!
			//// In debug mode will throw an error for uninitialized monster
			//checkMonster();
		}

		private var _checkCalled:Boolean = false;
		public function get checkCalled():Boolean { return _checkCalled; }
		public var checkError:String = "";
		public var initsCalled:Object = {
			a:false,
			short:false,
			long:false,
			genitals:false,
			breasts:false,
			tallness:false,
			str_tou_spe_inte:false,
			lib_sens_cor:false,
			drop:false
		};
		// MONSTER INITIALIZATION HELPER FUNCTIONS
		protected function set initedGenitals(value:Boolean):void{
			initsCalled.genitals = value;
		}
		protected function set initedBreasts(value:Boolean):void{
			initsCalled.breasts = value;
		}
		protected function set initedDrop(value:Boolean):void{
			initsCalled.drop = value;
		}
		protected function set initedStrTouSpeInte(value:Boolean):void{
			initsCalled.str_tou_spe_inte = value;
		}
		protected function set initedLibSensCor(value:Boolean):void{
			initsCalled.lib_sens_cor = value;
		}
		protected const NO_DROP:WeightedDrop = new WeightedDrop();

		public function isFullyInit():Boolean {
			for each (var phase:Object in initsCalled) {
				if (phase is Boolean && phase === false) return false;
			}
			return true;
		}
		public function missingInits():String{
			var result:String = "";
			for (var phase:String in initsCalled){
				if (initsCalled[phase] is Boolean && initsCalled[phase] === false){
					if (result === "") result = phase;
					else result+=", "+phase;
				}
			}
			return result;
		}

		override public function set a(value:String):void {
			initsCalled.a = true;
			super.a = value;
		}

		override public function set short(value:String):void {
			initsCalled.short = true;
			super.short = value;
		}

		override public function createCock(clength:Number = 5.5, cthickness:Number = 1, ctype:CockTypesEnum = null):Boolean
		{
			initedGenitals = true;
			if (!_checkCalled) {
				if (plural) {
					this.pronoun1 = "they";
					this.pronoun2 = "them";
					this.pronoun3 = "their";
				} else {
					this.pronoun1 = "he";
					this.pronoun2 = "him";
					this.pronoun3 = "his";
				}
			}
			var result:Boolean = super.createCock(clength, cthickness, ctype);
			return result;
		}

		override public function createVagina(virgin:Boolean = true, vaginalWetness:Number = 1, vaginalLooseness:Number = 0):Boolean
		{
			initedGenitals = true;
			if (!_checkCalled) {
				if (plural) {
					this.pronoun1 = "they";
					this.pronoun2 = "them";
					this.pronoun3 = "their";
				} else {
					this.pronoun1 = "she";
					this.pronoun2 = "her";
					this.pronoun3 = "her";
				}
			}
			var result:Boolean = super.createVagina(virgin, vaginalWetness, vaginalLooseness);
			return result;
		}

		protected function initGenderless():void
		{
			this.cocks = new Vector.<Cock>();
			this.vaginas = new Vector.<Vagina>();
			initedGenitals = true;
			if (plural) {
				this.pronoun1 = "they";
				this.pronoun2 = "them";
				this.pronoun3 = "their";
			} else {
				this.pronoun1 = "it";
				this.pronoun2 = "it";
				this.pronoun3 = "its";
			}
		}

		override public function createBreastRow(size:Number = 0, nipplesPerBreast:Number = 1):Boolean
		{
			initedBreasts = true;
			return super.createBreastRow(size, nipplesPerBreast);
		}

		override public function set tallness(value:Number):void
		{
			initsCalled.tallness = true;
			super.tallness = value;
		}

		protected function initStrTouSpeInte(str:Number, tou:Number, spe:Number, inte:Number):void
		{
			this.str = str;
			this.tou = tou;
			this.spe = spe;
			this.inte = inte;
			initedStrTouSpeInte = true;
		}

		protected function initLibSensCor(lib:Number, sens:Number, cor:Number):void
		{
			this.lib = lib;
			this.sens = sens;
			this.cor = cor;
			initedLibSensCor = true;
		}

		override public function validate():String
		{
			var error:String = "";
			// 1. Required fields must be set
			if (!isFullyInit()) {
				error += "Missing phases: "+missingInits()+". ";
			}
			if(flags[kFLAGS.OTHERCOCANON_SURVIVALTWEAK] & 8) this.scaleToLevel();
			this.HP = maxHP();
			this.XP = totalXP();
			error += super.validate();
			error += Utils.validateNonNegativeNumberFields(this, "Monster.validate",[
					"lustVuln", "temperment"
			]);
			return error;
		}

		public function checkMonster():Boolean
		{
			_checkCalled = true;
			checkError = validate();
			if (checkError.length>0) CoC_Settings.error("Monster not initialized:"+checkError);
			return checkError.length === 0;
		}

		/**
		 * try to hit, apply damageDealt
		 * @return damage
		 */
		public function eOneAttack():int
		{
			//Determine damageDealt - str modified by enemy toughness!
			var damage:int = calcDamage();
			if (damage > 0) damage = player.takeDamage(damage);
			return damage;
		}

		/**
		 * return true if we land a hit
		 */
		protected function attackSucceeded():Boolean
		{
			var attack:Boolean = true;
			attack &&= !playerAvoidDamage({});
			return attack;
		}

		public function eAttack():void {
			var attacks:int = statusEffectv1(StatusEffects.Attacks);
			if (attacks === 0) attacks = 1;
			while (attacks>0){
				if (attackSucceeded()){
				    var damage:int = eOneAttack();
					outputAttack(damage);
					postAttack(damage);
					game.output.statScreenRefresh();
					outputText("\n");
				}
				if (statusEffectv1(StatusEffects.Attacks) >= 0) {
					addStatusValue(StatusEffects.Attacks, 1, -1);
				}
				attacks--;
			}
			removeStatusEffect(StatusEffects.Attacks);
			if (hasPerk(PerkLib.ChargingSwings)) game.combatAttackData.closeDistance(game.monster);
			  //The doNext here was not required
		}

		/**
		 * Called no matter of success of the attack
		 * @param damage damageDealt received by player
		 */
		protected function postAttack(damage:int):void
		{
			if (player.statusEffectv1(StatusEffects.CounterAB) == 1 && distance != DISTANCE_DISTANT){
				game.combat.performRegularAttack(0);
				player.addStatusValue(StatusEffects.CounterAB, 1, -1);
			}
			if (damage > 0) {
				if (lustVuln > 0 && player.armorName === "barely-decent bondage straps") {
					if (!plural) outputText("\n" + capitalA + short + " brushes against your exposed skin and jerks back in surprise, coloring slightly from seeing so much of you revealed.");
					else outputText("\n" + capitalA + short + " brush against your exposed skin and jerk back in surprise, coloring slightly from seeing so much of you revealed.");
					lust += 5 * lustVuln;
				}
			if (player.armorName == "Obsidian golem full-plate armor" || player.hasStatusEffect(StatusEffects.TFMoltenPlate)) {
					var golemArmor:Boolean = player.armorName == "Obsidian golem full-plate armor";
					var moltenPlate:Boolean = player.hasStatusEffect(StatusEffects.TFMoltenPlate);
					outputText("\nYour armor reacts against the damage and expels lava against your attacker!");
					if (!plural) outputText("\n" + this.capitalA + this.short + " is burned by the lava.");
					else outputText("\n" + this.capitalA + this.short + " are burned by the lava.");
					var thornsDamage:Number = 0;
					if (golemArmor) thornsDamage += rand(20) + 15;
					if (moltenPlate) thornsDamage += game.combat.combatAbilities.tfMoltenPlateCalc();
					this.HP -= thornsDamage;
					outputText(" <b>(<font color=\"#ff8d29\">" + thornsDamage + "</font>)</b>");
					if (moltenPlate) {
						outputText("\nUnfortunately the lava burns you as well. ");
						player.takeDamage(game.combat.combatAbilities.tfMoltenPlateCalc("self"), true);
					}
				}
				if (player.armor.id == armors.VINARMR.id && armors.VINARMR.saveContent.armorStage > 2) {
					outputText("\nThe vines react to the impact, immediately expelling wicked thorns from within their fleshy stalks at the attacker.");
					var thornsDamage:Number = this.reduceDamage(rand(20) + 15, player);
					damage = game.combat.doDamage(thornsDamage, true);
					if (rand(5) == 0)
						if(this.bleed(player)) outputText("");
				}
			}
		}

		public function outputAttack(damage:int):void
		{

			if (damage <= 0) {
				//Due to toughness or amor...
				if (player.statusEffectv1(StatusEffects.CounterAB) == 1) outputText("You parry and counter the enemy's attack!");
				else if (rand(player.armorDef + player.tou) < player.armorDef) outputText("You absorb and deflect every " + weaponVerb + " with your " + (player.armor != ArmorLib.NOTHING ? player.armor.name : player.armorName) + ".");
				else {
					if (plural) outputText("You deflect and block every " + weaponVerb + " " + a + short + " throw at you. ");
					else outputText("You deflect and block every " + weaponVerb + " " + a + short + " throws at you. ");
				}
			}
			else if (damage < 6) outputText("You are struck a glancing blow by " + a + short + "! ");
			else if (damage < 11) {
				outputText(capitalA + short + " wound");
				if (!plural) outputText("s");
				outputText(" you! ");
			}
			else if (damage < 21) {
				outputText(capitalA + short + " stagger");
				if (!plural) outputText("s");
				outputText(" you with the force of " + pronoun3 + " " + weaponVerb + "! ");
			}
			else if (damage > 20) {
				outputText(capitalA + short + " <b>mutilate");
				if (!plural) outputText("s");
				outputText("</b> you with " + pronoun3 + " powerful " + weaponVerb + "! ");
			}
			if (damage > 0) {
				if (flags[kFLAGS.ENEMY_CRITICAL] > 0) outputText("<b>Critical hit! </b>");
				outputText("<b>(<font color=\"#800000\">" + damage + "</font>)</b>");
			}
			else outputText("<b>(<font color=\"#000080\">" + damage + "</font>)</b>");
		}

		/**
		 * @return true if continue with attack
		 */
		protected function handleBlind():Boolean
		{
			if (rand(3) < 2) {
				if (weaponVerb === "tongue-slap") outputText(capitalA + short + " completely misses you with a thrust from "+pronoun3+" tongue!\n");
				else outputText(capitalA + short + " completely misses you with a blind attack!\n");
				return false;
			}
			return true;
		}

		/**
		 * print something about how we miss the player
		 */
		protected function outputPlayerDodged(dodge:int):void
		{
			if (dodge==1) outputText("You narrowly avoid " + a + short + "'s " + weaponVerb + "!\n");
			else if (dodge==2) outputText("You dodge " + a + short + "'s " + weaponVerb + " with superior quickness!\n");
			else {
				outputText("You deftly avoid " + a + short);
				if (plural) outputText("'");
				else outputText("'s");
				outputText(" slow " + weaponVerb + ".\n");
			}
		}

		public var evasionResult:Object = {
			counter:false,
			dodge: null,
			parry: false,
			block: false

		};
		/**
		 * Generic function that both checks for a player dodge/parry/block and outputs text on every possible avoidance case. Perfect for lazy people.
		 * @param	doDodge
		 * @param	doParry
		 * @param	doBlock
		 * @param	doFatigue
		 * @param	toHitChance
		 * @param   customReactions an array with custom reactions for each possible avoidance case. Tag each string accordingly with [EVADE],[SPEED],[MISDIRECTION],[UNHANDLEDDODGE],[BLOCK],[PARRY], etc.
		 * @return
		 */
		public function playerAvoidDamage(def:*,customReactions:Array = null):Boolean
		{

			//Determine if dodged!
			evasionResult = combatAvoidDamage(def);
			var SPEEDRESULT:String = "";
			var EVADERESULT:String = "";
			var MISDIRECTIONRESULT:String = "";
			var FLEXIBILITYRESULT:String = "";
			var BLINDRESULT:String = "";
			var UNHANDLEDRESULT:String = "";
			var PARRYRESULT:String = "";
			var BLOCKRESULT:String = "";
            var COUNTERRESULT:String = "";
			if(customReactions != null) for each(var result:String in customReactions){
				if (result.indexOf("[SPEED]") != -1) SPEEDRESULT = result.replace("[SPEED]", "");
				if (result.indexOf("[EVADE]") != -1) EVADERESULT = result.replace("[EVADE]", "");
				if (result.indexOf("[MISDIRECTION]") != -1) MISDIRECTIONRESULT = result.replace("[MISDIRECTION]", "");
				if (result.indexOf("[UNHANDLED]") != -1) UNHANDLEDRESULT = result.replace("[UNHANDLED]", "");
				if (result.indexOf("[BLOCK]") != -1) BLOCKRESULT = result.replace("[BLOCK]", "");
				if (result.indexOf("[PARRY]") != -1) PARRYRESULT = result.replace("[PARRY]", "");
				if (result.indexOf("[FLEXIBILITY]") != -1) FLEXIBILITYRESULT = result.replace("[FLEXIBILITY]", "");
				if (result.indexOf("[BLIND]") != -1) BLINDRESULT = result.replace("[BLIND]", "");
                if (result.indexOf("[COUNTER]") != -1) COUNTERRESULT = result.replace("[COUNTER]", "");
			}

			if(evasionResult.counter){
                if (COUNTERRESULT.length == 0) outputText("You parry and counter the enemy's attack!");
                else outputText(COUNTERRESULT);
				return true;
			}
			if (evasionResult.dodge == EVASION_SPEED) {
				if (SPEEDRESULT.length == 0) outputPlayerDodged(rand(3));
				else outputText(SPEEDRESULT);
				return true;
			}
			if (evasionResult.dodge == EVASION_EVADE) {
				if (EVADERESULT.length == 0){
					outputText("Using your skills at evading attacks, you anticipate and sidestep " + a + short + "'");
					if (!plural) outputText("s");
					outputText(" attack.\n");
				}else outputText(EVADERESULT);
				return true;
			}
			//("Misdirection"
			if (evasionResult.dodge == EVASION_MISDIRECTION) {
				if (MISDIRECTIONRESULT.length == 0){
					outputText("Using Raphael's teachings, you anticipate and sidestep " + a + short + "'");
					if (!plural) outputText("s");
					outputText(" attack.\n");
				}else outputText(MISDIRECTIONRESULT);
				return true;
			}
			//Determine if cat'ed
			if (evasionResult.dodge == EVASION_FLEXIBILITY) {
				if (FLEXIBILITYRESULT.length == 0){
					outputText("With your incredible flexibility, you squeeze out of the way of " + a + short + "");
					if (plural) outputText("' attacks.\n");
					else outputText("'s attack.\n");
				}else outputText(EVADERESULT);
				return true;
			}
			if (evasionResult.dodge == EVASION_BLIND) {
				if (BLINDRESULT.length == 0) outputText(capitalA + short + " misses you wildly with a blind attack.");
				else outputText(BLINDRESULT);
				return true;
			}
			if (evasionResult.dodge != null) { // Failsafe fur unhandled
				if (UNHANDLEDRESULT.length == 0) outputText("Using your superior combat skills you manage to avoid the attack completely.\n");
				else outputText(UNHANDLEDRESULT);
				return true;
			}
			//Parry with weapon
			if (evasionResult.parry) {
				if(PARRYRESULT.length == 0){
				outputText("You manage to block " + a + short + "");
				if (plural) outputText("' attacks ");
				else outputText("'s attack ");
				outputText("with your " + player.weaponName + ".\n");
				}else outputText(PARRYRESULT);
				return true;
			}
			//Block with shield
			if (evasionResult.block) {
				if (BLOCKRESULT.length == 0) outputText("You block " + a + short + "'s " + weaponVerb + " with your " + player.shieldName + "! ");
				else outputText(BLOCKRESULT);
				return true;
			}
			return false;
		}

		public function doAI():void
		{
			if (hasStatusEffect(StatusEffects.Stunned)) {
				if (!handleStun()) return;
			}
			if (hasStatusEffect(StatusEffects.Fear)) {
				if (!handleFear()) return;
			}
			//Exgartuan gets to do stuff!
			if (game.player.hasStatusEffect(StatusEffects.Exgartuan) && game.player.statusEffectv2(StatusEffects.Exgartuan) === 0 && rand(3) === 0) {
				if (game.exgartuan.exgartuanCombatUpdate()) game.outputText("\n\n");
			}
			if (hasStatusEffect(StatusEffects.Constricted)) {
				if (!handleConstricted()) return;
			}
			//If grappling... TODO implement grappling
//			if (game.gameState == 2) {
//				game.gameState = 1;
				//temperment - used for determining grapple behaviors
				//0 - avoid grapples/break grapple
				//1 - lust determines > 50 grapple
				//2 - random
				//3 - love grapples
				/*
				 //		if (temperment == 0) eGrappleRetreat();
				 if (temperment == 1) {
				 //			if (lust < 50) eGrappleRetreat();
				 mainClassPtr.doNext(3);
				 return;
				 }
				 mainClassPtr.outputText("Lust Placeholder!!");
				 mainClassPtr.doNext(3);
				 return;*/
//			}
			moveCooldown = Math.max(moveCooldown-1,0);
			performCombatAction();
		}

		/**
		 * Called if monster is constricted. Should return true if constriction is ignored and need to proceed with ai
		 */
		protected function handleConstricted():Boolean
		{
			//Enemy struggles -
			game.outputText("Your prey pushes at your tail, twisting and writhing in an effort to escape from your tail's tight bonds.");
			if (statusEffectv1(StatusEffects.Constricted) <= 0) {
				game.outputText("  " + capitalA + short + " proves to be too much for your tail to handle, breaking free of your tightly bound coils.");
				removeStatusEffect(StatusEffects.Constricted);
			}
			addStatusValue(StatusEffects.Constricted, 1, -1);

			return false;
		}

		/**
		 * Called if monster is under fear. Should return true if fear ignored and need to proceed with ai
		 */
		protected function handleFear():Boolean
		{
			if (hasPerk(PerkLib.FearImmune)){
				game.outputText(capitalA + short + " appears to be immune to your fear.\n\n");
				removeStatusEffect(StatusEffects.Fear);
				return true;
			}

			if (statusEffectv1(StatusEffects.Fear) === 0) {
				if (plural) {
					removeStatusEffect(StatusEffects.Fear);
					game.outputText("Your foes shake free of their fear and ready themselves for battle.");
				}
				else {
					removeStatusEffect(StatusEffects.Fear);
					game.outputText("Your foe shakes free of its fear and readies itself for battle.");
				}
			}
			else {
				addStatusValue(StatusEffects.Fear, 1, -1);
				if (plural) game.outputText(capitalA + short + " are too busy shivering with fear to fight.");
				else game.outputText(capitalA + short + " is too busy shivering with fear to fight.");
			}

			return false;
		}

		/**
		 * Called if monster is stunned. Should return true if stun is ignored and need to proceed with ai.
		 */
		protected function handleStun():Boolean
		{
			if (plural) game.outputText("Your foes are too dazed from your last hit to strike back!");
			else game.outputText("Your foe is too dazed from your last hit to strike back!");
			if (statusEffectv1(StatusEffects.Stunned) <= 0) removeStatusEffect(StatusEffects.Stunned);
			else addStatusValue(StatusEffects.Stunned, 1, -1);
			if (hasStatusEffect(StatusEffects.Uber)) removeStatusEffect(StatusEffects.Uber);

			return false;
		}

		/**
		 * This method is called after all stun/fear/constricted checks.
		 * Default: Equal chance to do physical or special (if any) attack
		 */
		protected function performCombatAction():void
		{
			var actions:Array = [eAttack,special1,special2,special3].filter(
					function(special:Function, idx:int, array:Array):Boolean {
						return special !== null;
					}
			);
			var rando:int = int(Math.random() * (actions.length));
			var action:Function = actions[rando];
			action();
		}

		/**
		 * All branches of this method and all subsequent scenes should end either with
         * 'cleanupAfterCombat', 'awardPlayer' or 'finishCombat'. The latter also displays
		 * default message like "you defeat %s" or "%s falls and starts masturbating"
		 */
		public function defeated(hpVictory:Boolean):void
		{
			game.combat.finishCombat();
		}

		/**
		 * All branches of this method and all subsequent scenes should end with
         * 'cleanupAfterCombat'.
		 */
		public function won(hpVictory:Boolean,pcCameWorms:Boolean = false):void
		{
			clearOutput();
			if (hpVictory){
				player.HP = 1;
				outputText("Your wounds are too great to bear, and you fall unconscious.");
			} else {
				outputText("Your desire reaches uncontrollable levels, and you end up openly masturbating.\n\nThe lust and pleasure cause you to black out for hours on end.");
				player.lust = 0;
			}
			game.inCombat = false;
			game.combat.clearStatuses();
			var temp:Number = rand(10) + 1;
			if (temp > player.gems) temp = player.gems;
			outputText("\n\nYou'll probably wake up in eight hours or so, missing " + temp + " gems.");
			player.gems -= temp;
			player.sleeping = true;
			game.output.doNext(game.camp.returnToCampUseEightHours);
		}

		/**
		 * Function(hpVictory) to call INSTEAD of default defeated(). Call it or finishCombat() manually
		 */
		public var onDefeated:Function = null;
		/**
		 * Function(hpVictory,pcCameWorms) to call INSTEAD of default won(). Call it or finishCombat() manually
		 */
		public var onWon:Function = null;
		/**
		 * Function() to call INSTEAD of common run attempt. Call runAway(false) to perform default run attempt
		 */
		public var _onPcRunAttempt:Function = null;

		public function set onPcRunAttempt(value:Function):void {
			_onPcRunAttempt = value;
		}

		public function get onPcRunAttempt():Function {
			return _onPcRunAttempt;
		}

		/**
		 * Final method to handle hooks before calling overriden method
		 */
		public final function defeated_(hpVictory:Boolean):void
		{
			if (onDefeated !== null) onDefeated(hpVictory);
			else defeated(hpVictory);
		}

		/**
		 * Final method to handle hooks before calling overriden method
		 */
		public final function won_(hpVictory:Boolean,pcCameWorms:Boolean = false):void
		{
			if (onWon !== null) onWon(hpVictory,pcCameWorms);
			else won(hpVictory,pcCameWorms);
		}

		/**
		 * Display tease reaction message. Then call applyTease() to increase lust.
		 * @param lustDelta value to be added to lust (already modified by lustVuln etc)
		 */
		public function teased(lustDelta:Number):void
		{
			outputDefaultTeaseReaction(lustDelta);
			if (lustDelta > 0) {
				//Imp mob uber interrupt!
			  	if (hasStatusEffect(StatusEffects.ImpUber)) { // TODO move to proper class
					outputText("\nThe imps in the back stumble over their spell, their loincloths tenting obviously as your display interrupts their casting.  One of them spontaneously orgasms, having managed to have his spell backfire.  He falls over, weakly twitching as a growing puddle of whiteness surrounds his defeated form.");
					//(-5% of max enemy HP)
					HP -= bonusHP * .05;
					lust -= 15;
					removeStatusEffect(StatusEffects.ImpUber);
					createStatusEffect(StatusEffects.ImpSkip,0,0,0,0);
				}
			}
			applyTease(lustDelta);
		}

		protected function outputDefaultTeaseReaction(lustDelta:Number):void
		{
			if (plural) {
				if (lustDelta === 0) outputText("\n\n" + capitalA + short + " seem unimpressed.");
				if (lustDelta > 0 && lustDelta < 4) outputText("\n" + capitalA + short + " look intrigued by what " + pronoun1 + " see.");
				if (lustDelta >= 4 && lustDelta < 10) outputText("\n" + capitalA + short + " definitely seem to be enjoying the show.");
				if (lustDelta >= 10 && lustDelta < 15) outputText("\n" + capitalA + short + " openly stroke " + pronoun2 + "selves as " + pronoun1 + " watch you.");
				if (lustDelta >= 15 && lustDelta < 20) outputText("\n" + capitalA + short + " flush hotly with desire, " + pronoun3 + " eyes filled with longing.");
				if (lustDelta >= 20) outputText("\n" + capitalA + short + " lick " + pronoun3 + " lips in anticipation, " + pronoun3 + " hands idly stroking " + pronoun3 + " bodies.");
			}
			else {
				if (lustDelta === 0) outputText("\n" + capitalA + short + " seems unimpressed.");
				if (lustDelta > 0 && lustDelta < 4) {
					if (plural) outputText("\n" + capitalA + short + " looks intrigued by what " + pronoun1 + " see.");
					else outputText("\n" + capitalA + short + " looks intrigued by what " + pronoun1 + " sees.");
				}
				if (lustDelta >= 4 && lustDelta < 10) outputText("\n" + capitalA + short + " definitely seems to be enjoying the show.");
				if (lustDelta >= 10 && lustDelta < 15) {
					if (plural) outputText("\n" + capitalA + short + " openly strokes " + pronoun2 + "selves as " + pronoun1 + " watch you.");
					else outputText("\n" + capitalA + short + " openly strokes " + pronoun2 + "self as " + pronoun1 + " watches you.");
				}
				if (lustDelta >= 15 && lustDelta < 20) {
					if (plural) outputText("\n" + capitalA + short + " flush hotly with desire, " + pronoun3 + " eyes filling with longing.");
					else outputText("\n" + capitalA + short + " flushes hotly with desire, " + pronoun3 + " eyes filled with longing.");
				}
				if (lustDelta >= 20) {
					if (plural) outputText("\n" + capitalA + short + " licks " + pronoun3 + " lips in anticipation, " + pronoun3 + " hands idly stroking " + pronoun3 + " own bodies.");
					else outputText("\n" + capitalA + short + " licks " + pronoun3 + " lips in anticipation, " + pronoun3 + " hands idly stroking " + pronoun3 + " own body.");
				}
			}
		}

		protected function applyTease(lustDelta:Number):void{
			lust += lustDelta;
			lustDelta = Math.round(lustDelta * 10)/10;
			outputText(" <b>(<font color=\"#ff00ff\">" + lustDelta + "</font>)</b>");
		}

		public function generateDebugDescription():String{
			var result:String;
			var be:String =plural?"are":"is";
			var have:String = plural ? "have" : "has";
			var Heis:String = Pronoun1+" "+be+" ";
			var Hehas:String = Pronoun1 + " " + have + " ";
			result = "You are inspecting "+a+short+" (imageName='"+imageName+"', class='"+getQualifiedClassName(this)+"'). You are fighting "+pronoun2+".\n\n";
			result += Heis+(Appearance.DEFAULT_GENDER_NAMES[gender]||("gender#"+gender))+
					" with "+numberOfThings(cocks.length,"cock") +
					", "+numberOfThings(vaginas.length,"vagina")+
					" and "+numberOfThings(breastRows.length,"breast row")+".\n\n";
			// APPEARANCE
			result +=Heis+Appearance.inchesAndFeetsAndInches(tallness)+" tall with "+
					Appearance.describeByScale(hips.rating,Appearance.DEFAULT_HIPS_RATING_SCALES,"thinner than","wider than")+" hips and "+
					Appearance.describeByScale(butt.rating,Appearance.DEFAULT_BUTT_RATING_SCALES,"thinner than","wider than")+" butt.\n";
			result +=Pronoun3+" lower body is "+(Appearance.DEFAULT_LOWER_BODY_NAMES[lowerBody.type]||("lowerBody#"+lowerBody.type));
			result += ", "+pronoun3+" arms are "+(Appearance.DEFAULT_ARM_NAMES[arms.type]||("armType#"+arms.type));
			result += ", "+pronoun1+" "+have+" "+skin.tone+" "+skin.adj+" "+skin.desc+" (type "+(Appearance.DEFAULT_SKIN_NAMES[skin.type]||("skinType#"+skin.type))+").\n";
			result += Hehas;
			if (hair.length>0){
				result += hair.color+" "+Appearance.inchesAndFeetsAndInches(hair.length)+" long "+(Appearance.DEFAULT_HAIR_NAMES[hair.type]||("hair.type#"+hair.type))+" hair.\n";
			} else {
				result += "no hair.\n";
			}
			result += Hehas;
			if (beard.length>0){
				result += hair.color+" "+Appearance.inchesAndFeetsAndInches(beard.length)+" long "+(Appearance.DEFAULT_BEARD_NAMES[beard.style]||("beardType#"+beard.style))+".\n";
			} else {
				result += "no beard.\n";
			}
			result += Hehas
					+(Appearance.DEFAULT_FACE_NAMES[face.type]||("face.type#"+face.type))+" face, "
					+(Appearance.DEFAULT_EARS_NAMES[ears.type]||("ears.type#"+ears.type))+" ears, "
					+(Appearance.DEFAULT_TONGUE_NAMES[tongue.type]||("tongueType#"+tongue.type))+" tongue and "
					+(Appearance.DEFAULT_EYES_NAMES[eyes.type]||("eyes.type#"+eyes.type))+" eyes.\n";
			result += Hehas;
			if (tail.type === Tail.NONE) result += "no tail, ";
			else result+=(Appearance.DEFAULT_TAIL_NAMES[tail.type]||("tailType#"+tail.type))+" tail with venom="+tail.venom+" and recharge="+tail.recharge+", ";
			if (horns.type === Horns.NONE) result += "no horns, ";
			else result += horns.value+" "+(Appearance.DEFAULT_HORN_NAMES[horns.type]||("hornsPart.type#"+horns.type))+" horns, ";
			if (wings.type === Wings.NONE) result += "no wings, ";
			else result += Appearance.DEFAULT_WING_DESCS[wings.type]+" wings (type "+(Appearance.DEFAULT_WING_NAMES[wings.type]||("wingType#"+wings.type))+"), ";
			if (antennae.type === Antennae.NONE) result += "no antennae.\n\n";
			else result += (Appearance.DEFAULT_ANTENNAE_NAMES[antennae.type]||("antennaeType#"+antennae.type))+" antennae.\n\n";

			// GENITALS AND BREASTS
			for (var i:int = 0; i<cocks.length; i++){
				var cock:Cock = (cocks[i] as Cock);
				result += Pronoun3+(i>0?(" #"+(i+1)):"")+" "+cock.cockType.toString().toLowerCase()+" cock is ";
				result += Appearance.inchesAndFeetsAndInches(cock.cockLength)+" long and "+cock.cockThickness+"\" thick";
				if (cock.isPierced) result += ", pierced with " + cock.pLongDesc;
				if (cock.knotMultiplier !== Cock.KNOTMULTIPLIER_NO_KNOT) result += ", with knot of size " + cock.knotMultiplier;
				result+=".\n";
			}
			if (balls > 0 || ballSize > 0) result += Hehas + numberOfThings(balls, "ball") + " of size " + ballSize+".\n";
			if (cumMultiplier !== 1 || cocks.length > 0) result += Pronoun1 + " " + have+" cum multiplier " + cumMultiplier + ". ";
			if (hoursSinceCum > 0 || cocks.length > 0) result += "It were " + hoursSinceCum + " hours since " + pronoun1 + " came.\n\n";
			for (i = 0; i < vaginas.length; i++) {
				var vagina:Vagina = (vaginas[i] as Vagina);
				result += Pronoun3+ (i>0?(" #"+(i+1)):"")+" "+(Appearance.DEFAULT_VAGINA_TYPE_NAMES[vagina.type]||("vaginaType#"+vagina.type))+(vagina.virgin?" ":" non-")+"virgin vagina is ";
				result += Appearance.describeByScale(vagina.vaginalLooseness,Appearance.DEFAULT_VAGINA_LOOSENESS_SCALES,"tighter than","looser than");
				result += ", "+Appearance.describeByScale(vagina.vaginalWetness,Appearance.DEFAULT_VAGINA_WETNESS_SCALES,"drier than","wetter than");
				if (vagina.labiaPierced) result += ". Labia are pierced with "+vagina.labiaPLong;
				if (vagina.clitPierced) result += ". Clit is pierced with "+vagina.clitPLong;
				if (statusEffectv1(StatusEffects.BonusVCapacity)>0){
					result+="; vaginal capacity is increased by "+statusEffectv1(StatusEffects.BonusVCapacity);
				}
				result+=".\n";
			}
			if (breastRows.length > 0) {
				var nipple:String = nippleLength+"\" ";
				if (nipplesPierced) nipple+="pierced by "+nipplesPLong;
				for (i = 0; i < breastRows.length; i++) {
					var row:BreastRow = (breastRows[i] as BreastRow);
					result += Pronoun3+(i>0?(" #"+(i+1)):"") + " breast row has " + row.breasts;
					result += " " + row.breastRating.toFixed(2) + "-size (" + Appearance.breastCup(row.breastRating) + ") breasts with ";
					result += numberOfThings(row.nipplesPerBreast, nipple+(row.fuckable ? "fuckable nipple" : "unfuckable nipple")) + " on each.\n";
				}
			}
			result += Pronoun3+" ass is "+Appearance.describeByScale(ass.analLooseness,Appearance.DEFAULT_ANAL_LOOSENESS_SCALES,"tighter than","looser than")+", "+Appearance.describeByScale(ass.analWetness,Appearance.DEFAULT_ANAL_WETNESS_SCALES,"drier than","wetter than");
			if (statusEffectv1(StatusEffects.BonusACapacity)>0){
				result += "; anal capacity is increased by "+statusEffectv1(StatusEffects.BonusACapacity);
			}
			result +=".\n\n";

			// COMBAT AND OTHER STATS
			result += Hehas + "str=" + str + ", tou=" + tou + ", spe=" + spe+", inte=" + inte+", lib=" + lib + ", sens=" + sens + ", cor=" + cor + ".\n";
			result += Pronoun1 + " can " + weaponVerb + " you with  " + weaponPerk + " " + weaponName+" (attack " + weaponAttack + ", value " + weaponValue+").\n";
			result += Pronoun1 + " is guarded with " + armorPerk + " " + armorName+" (defense " + armorDef + ", value " + armorValue+").\n";
			result += Hehas + HP + "/" + maxHP() + " HP, " + lust + "/" + maxLust() + " lust, " + fatigue + "/100 fatigue. " + Pronoun3 + " bonus HP=" + bonusHP + ", and lust vulnerability=" + lustVuln + ".\n";
			result += Heis + "level " + level + " and " + have+" " + gems + " gems. You will be awarded " + XP + " XP.\n";

			var numSpec:int = (special1 !== null ? 1 : 0) + (special2 !== null ? 1 : 0) + (special3 !== null ? 1 : 0);
			if (numSpec > 0) {
				result += Hehas + numSpec + " special attack" + (numSpec > 1 ? "s" : "") + ".\n";
			}
			else {
				result += Hehas + "no special attacks.\n";
			}

			return result;
		}

		protected function clearOutput():void
		{
			game.clearOutput();
		}

		public function dropLoot():ItemType
		{
			return _drop.roll() as ItemType;
		}

		public function combatRoundUpdate():void
		{
			var store:Number = 0;
			if (hasStatusEffect(StatusEffects.MilkyUrta)) {
				game.urtaQuest.milkyUrtaTic();
			}
			//Countdown
			var tcd:StatusEffect = statusEffectByType(StatusEffects.TentacleCoolDown);
			if (tcd!=null) {
				tcd.value1-=1;
				if (tcd.value1 <= 0) {
					removeStatusEffect(StatusEffects.TentacleCoolDown);
				}
			}
			if (hasStatusEffect(StatusEffects.GuardAB)) {
				//Countdown to heal
				addStatusValue(StatusEffects.GuardAB,1,-1);
				//Heal wounds
				if (statusEffectv1(StatusEffects.GuardAB) <= 0) {
					outputText("The " + short + " is no longer guarded!\n\n");
					removeStatusEffect(StatusEffects.GuardAB);
				}
				//Deal damageDealt if still wounded.
				else {
					outputText("The " + short + " is currently being guarded, and is out of your reach.\n\n");
				}
			}
			if (hasStatusEffect(StatusEffects.CoonWhip)) {
				if (statusEffectv2(StatusEffects.CoonWhip) <= 0) {
					armorDef += statusEffectv1(StatusEffects.CoonWhip);
					if (this is VolcanicGolem && armorDef >= 300) armorDef = 300;
					outputText("<b>Tail whip wears off!</b>\n\n");
					removeStatusEffect(StatusEffects.CoonWhip);
				}
				else {
					addStatusValue(StatusEffects.CoonWhip,2,-1);
					outputText("<b>Tail whip is currently reducing your foe");
					if (plural) outputText("s'");
					else outputText("'s");
					outputText(" armor by " + statusEffectv1(StatusEffects.CoonWhip) + ".</b>\n\n")
				}
			}
			if (hasStatusEffect(StatusEffects.Blind)) {
				addStatusValue(StatusEffects.Blind,1,-1);
				if (statusEffectv1(StatusEffects.Blind) <= 0) {
					outputText("<b>" + capitalA + short + (plural ? " are" : " is") + " no longer blind!</b>\n\n");
					removeStatusEffect(StatusEffects.Blind);
				}
				else outputText("<b>" + capitalA + short + (plural ? " are" : " is") + " currently blind!</b>\n\n");
			}
			if (hasStatusEffect(StatusEffects.Earthshield)) {
				outputText("<b>" + capitalA + short + " is protected by a shield of rocks!</b>\n\n");
			}
			if (hasStatusEffect(StatusEffects.Sandstorm)) {
				//Blinded:
				if (player.hasStatusEffect(StatusEffects.Blind)) {
					outputText("<b>You blink the sand from your eyes, but you're sure that more will get you if you don't end it soon!</b>\n\n");
					player.removeStatusEffect(StatusEffects.Blind);
				}
				else {
					if (statusEffectv1(StatusEffects.Sandstorm) === 0 || statusEffectv1(StatusEffects.Sandstorm) % 4 === 0) {
						player.createStatusEffect(StatusEffects.Blind,0,0,0,0);
						outputText("<b>The sand is in your eyes!  You're blinded this turn!</b>\n\n");
					}
					else {
						outputText("<b>The grainy mess cuts at any exposed flesh and gets into every crack and crevice of your armor. ");
						var temp:Number = player.takeDamage(1 + rand(2), true);
						outputText("</b>\n\n");
					}
				}
				addStatusValue(StatusEffects.Sandstorm,1,1);
			}
			if (hasStatusEffect(StatusEffects.Stunned)) {
				outputText("<b>" + capitalA + short +(plural ? " are" : " is")+" still stunned!</b>\n\n");
			}
			if (hasStatusEffect(StatusEffects.Shell)) {
				if (statusEffectv1(StatusEffects.Shell) >= 0) {
					outputText("<b>A wall of many hues shimmers around " + a + short + ".</b>\n\n");
					addStatusValue(StatusEffects.Shell,1,-1);
				}
				else {
					outputText("<b>The magical barrier " + a + short + " erected fades away to nothing at last.</b>\n\n");
					removeStatusEffect(StatusEffects.Shell);
				}
			}
			if(hasStatusEffect(StatusEffects.IzmaBleed)) updateBleed();
			if (hasStatusEffect(StatusEffects.BasiliskCompulsion) && spe > 1) {
				var oldSpeed:Number = spe;
				var speedDiff:Number = 0;
				var bse:BasiliskSlowDebuff = createOrFindStatusEffect(StatusEffects.BasiliskSlow) as BasiliskSlowDebuff;
				bse.applyEffect(statusEffectv1(StatusEffects.BasiliskCompulsion));
				speedDiff = Math.round(oldSpeed - spe);
				if (plural) {
					outputText(capitalA + short + "  still feel the spell of those gray eyes, making " + pronoun3 + " movements slow and difficult,"
					          +" the remembered words tempting " + pronoun2 + " to look into your eyes again. "
					          + Pronoun1 + " need to finish this fight as fast as " + pronoun3 + "  heavy limbs will allow."
					          +" <b>(<font color=\"#800000\">" + Math.round(speedDiff) + "</font>)</b>\n\n");
				} else {
					outputText(capitalA + short + "  still feels the spell of those gray eyes, making " + pronoun3 + " movements slow and difficult,"
					          +" the remembered words tempting " + pronoun2 + " to look into your eyes again. "
					          + Pronoun1 + " needs to finish this fight as fast as " + pronoun3 + "  heavy limbs will allow."
					          +" <b>(<font color=\"#800000\">" + Math.round(speedDiff) + "</font>)</b>\n\n");

				}
			}
			if (hasStatusEffect(StatusEffects.OnFire)) {
				//Countdown to heal
				addStatusValue(StatusEffects.OnFire,1,-1);
				//Heal fire
				if (statusEffectv1(StatusEffects.OnFire) <= 0) {
					outputText("The flames engulfing " + a + short + " finally fades.\n\n");
					removeStatusEffect(StatusEffects.OnFire);
				}
				//Deal damageDealt if still on fire.
				else {
					store = maxHP() * (4 + rand(5)) / 100;
					store = game.combat.doDamage(store);
					if (plural) outputText(capitalA + short + " continue to burn from the flames engulfing " + pronoun2 + ". <b>(<font color=\"#800000\">" + store + "</font>)</b>\n\n");
					else outputText(capitalA + short + " continues to burn from the flames engulfing " + pronoun2 + ". <b>(<font color=\"#800000\">" + store + "</font>)</b>\n\n");
				}
			}
			if (hasStatusEffect(StatusEffects.Timer)) {
				if (statusEffectv1(StatusEffects.Timer) <= 0)
					removeStatusEffect(StatusEffects.Timer);
				addStatusValue(StatusEffects.Timer,1,-1);
			}
			if (hasStatusEffect(StatusEffects.LustStick)) {
				//LoT Effect Messages:
				switch(statusEffectv1(StatusEffects.LustStick)) {
					//First:
					case 1:
						if (plural) outputText("One of " + a + short + " pants and crosses " + mf("his","her") + " eyes for a moment.  " + mf("His","Her") + " dick flexes and bulges, twitching as " + mf("he","she") + " loses himself in a lipstick-fueled fantasy.  When " + mf("he","she") + " recovers, you lick your lips and watch " + mf("his","her") + " blush spread.\n\n");
						else outputText(capitalA + short + " pants and crosses " + pronoun3 + " eyes for a moment.  " + mf("His","Her") + " dick flexes and bulges, twitching as " + pronoun1 + " loses " + mf("himself", "herself") + " in a lipstick-fueled fantasy.  When " + pronoun1 + " recovers, you lick your lips and watch " + mf("his","her") + " blush spread.\n\n");
						break;
					//Second:
					case 2:
						if (plural) outputText(capitalA + short + " moan out loud, " + pronoun3 + " dicks leaking and dribbling while " + pronoun1 + " struggle not to touch " + pronoun2 + ".\n\n");
						else outputText(capitalA + short + " moans out loud, " + pronoun3 + " dick leaking and dribbling while " + pronoun1 + " struggles not to touch it.\n\n");
						break;
					//Third:
					case 3:
						if (plural) outputText(capitalA + short + " pump " + pronoun3 + " hips futilely, air-humping non-existent partners.  Clearly your lipstick is getting to " + pronoun2 + ".\n\n");
						else outputText(capitalA + short + " pumps " + pronoun3 + " hips futilely, air-humping a non-existent partner.  Clearly your lipstick is getting to " + pronoun2 + ".\n\n");
						break;
					//Fourth:
					case 4:
						if (plural) outputText(capitalA + short + " close " + pronoun3 + " eyes and grunt, " + pronoun3 + " cocks twitching, bouncing, and leaking pre-cum.\n\n");
						else outputText(capitalA + short + " closes " + pronoun2 + " eyes and grunts, " + pronoun3 + " cock twitching, bouncing, and leaking pre-cum.\n\n");
						break;
					//Fifth and repeat:
					default:
						if (plural) outputText("Drops of pre-cum roll steadily out of their dicks.  It's a marvel " + pronoun1 + " haven't given in to " + pronoun3 + " lusts yet.\n\n");
						else outputText("Drops of pre-cum roll steadily out of " + a + short + "'s dick.  It's a marvel " + pronoun1 + " hasn't given in to " + pronoun3 + " lust yet.\n\n");
						break;
				}
				addStatusValue(StatusEffects.LustStick,1,1);
				//Damage = 5 + bonus score minus
				//Reduced by lust vuln of course
				lust += Math.round(lustVuln * (5 + statusEffectv2(StatusEffects.LustStick)));
			}
			if (hasStatusEffect(StatusEffects.PCTailTangle)) {
				//when Entwined
				outputText("You are bound tightly in the kitsune's tails.  <b>The only thing you can do is try to struggle free!</b>\n\n");
				outputText("Stimulated by the coils of fur, you find yourself growing more and more aroused...\n\n");
				game.dynStats("lus", 5+player.sens/10);
			}
			if (hasStatusEffect(StatusEffects.QueenBind)) {
				outputText("You're utterly restrained by the Harpy Queen's magical ropes!\n\n");
				if (game.fetishManager.compare(FetishManager.FETISH_BONDAGE)) game.dynStats("lus", 3);
			}
			if (this is SecretarialSuccubus || this is MilkySuccubus) {
				if (player.lust100 < 45) outputText("There is something in the air around your opponent that makes you feel warm.\n\n");
				if (player.lust100 >= 45 && player.lust100 < 70) outputText("You aren't sure why but you have difficulty keeping your eyes off your opponent's lewd form.\n\n");
				if (player.lust100 >= 70 && player.lust100 < 90) outputText("You blush when you catch yourself staring at your foe's rack, watching it wobble with every step she takes.\n\n");
				if (player.lust100 >= 90) outputText("You have trouble keeping your greedy hands away from your groin.  It would be so easy to just lay down and masturbate to the sight of your curvy enemy.  The succubus looks at you with a sexy, knowing expression.\n\n");
				game.dynStats("lus", 1+rand(8));
			}
			//[LUST GAINED PER ROUND] - Omnibus
			if (hasStatusEffect(StatusEffects.LustAura)) {
				if (player.lust100 < 33) outputText("Your groin tingles warmly.  The demon's aura is starting to get to you.\n\n");
		 		if (player.lust100 >= 33 && player.lust100 < 66) outputText("You blush as the demon's aura seeps into you, arousing you more and more.\n\n");
		  		if (player.lust100 >= 66) {
					outputText("You flush bright red with desire as the lust in the air worms its way inside you.  ");
					temp = rand(4);
					if (temp === 0) outputText("You have a hard time not dropping to your knees to service her right now.\n\n");
					if (temp === 2) outputText("The urge to bury your face in her breasts and suckle her pink nipples nearly overwhelms you.\n\n");
					if (temp === 1) outputText("You swoon and lick your lips, tasting the scent of the demon's pussy in the air.\n\n");
					if (temp === 3) outputText("She winks at you and licks her lips, and you can't help but imagine her tongue sliding all over your body.  You regain composure moments before throwing yourself at her.  That was close.\n\n");
				}
				game.dynStats("lus", (3 + int(player.lib/20 + player.cor/30)));
			}
		}

		public function handleAwardItemText(itype:ItemType):void
		{ //New Function, override this function in child classes if you want a monster to output special item drop text
			if (itype !== null) outputText("\nThere is " + itype.longName + " on your defeated opponent.  ");
		}

		public function handleAwardText():void
		{ //New Function, override this function in child classes if you want a monster to output special gem and XP text
			//This function doesn’t add the gems or XP to the player, it just provides the output text
			if (this.gems === 1) outputText("\n\nYou snag a single gem and " + this.XP + " XP as you walk away from your victory.");
			else if (this.gems > 1) outputText("\n\nYou grab " + this.gems + " gems and " + this.XP + " XP from your victory.");
			else if (this.gems === 0) outputText("\n\nYou gain " + this.XP + " XP from the battle.");
		}

		public function handleCombatLossText(inDungeon:Boolean, gemsLost:int):int
		{ //New Function, override this function in child classes if you want a monster to output special text after the player loses in combat
			//This function doesn’t take the gems away from the player, it just provides the output text
			if (game.prison.inPrison) {
				game.prison.doPrisonEscapeFightLoss();
				return 8;
			}
			if (!inDungeon) {
				if (game.prison.trainingFeed.prisonCaptorFeedingQuestTrainingExists()) {
					if (short === "goblin" || short === "goblin assassin" || short === "goblin warrior" || short === "goblin shaman" || short === "imp" || short === "imp lord" || short === "imp warlord" || short === "imp overlord" || //Generic encounter
						short === "tentacle beast" || (short === "kitsune" && hair.color === "red") || short === "Akbal" || short === "Tamani" || //Forest, deepwoods
						short === "goo-girl" || short === "green slime" || short === "fetish cultist" || short === "fetish zealot" || //Lake
						short === "sandtrap" || short === "sand tarp" || short === "naga" || short === "demons" || short === "Cum Witch" || //Desert
						short === "hellhound" || short === "infested hellhound" || short === "minotaur" || short === "minotaur lord" || short === "minotaur gang" || short === "minotaur tribe" || short === "basilisk" || short === "phoenix" || //Mountain, high mountains
						short === "satyr" || short === "gnoll" || short === "gnoll spear-thrower" || short === "female spider-morph" || short === "male spider-morph" || short === "corrupted drider" || //Plains, swamp, bog
						short === "yeti") { //Glacial rift, volcanic crag
						game.prison.trainingFeed.prisonCaptorFeedingQuestTrainingProgress(1, 1);
					}
				}
				outputText("\n\nYou'll probably come to your senses in eight hours or so");
				if (player.gems > 1)
					outputText(", missing " + gemsLost + " gems.");
				else if (player.gems === 1)
					outputText(", missing your only gem.");
				else outputText(".");
			}
			else {
				outputText("\n\nSomehow you came out of that alive");
				if (player.gems > 1)
					outputText(", but after checking your gem pouch, you realize you're missing " + gemsLost + " gems.");
				else if (player.gems === 1)
					outputText(", but after checking your gem pouch, you realize you're missing your only gem.");
				else outputText(".");
			}
			return 8; //This allows different monsters to delay the player by different amounts of time after a combat loss. Normal loss causes an eight hour blackout
		}
        ///Function to allow for monsters to react to several different situations. Returns true if the player's turn should continue, false otherwise.
		///before a regular attack lands.
		public const CON_BEFOREATTACKED:int = 0;
		///The moment a regular  lands.
		public const CON_WHENATTACKED:int = 1;
		///Right after a regular  lands.
		public const CON_AFTERATTACKED:int = 2;
		///Player waited.
		public const CON_PLAYERWAITED:int = 3;
		///After taking damageDealt of any kind.
		public const CON_AFTERDAMAGED:int = 4;
		///When hit by "Blind".
		public const CON_BLINDED:int = 5;
		///When hit by fire damageDealt.
		public const CON_BURNED:int = 6;
		///When the player distances itself.
		public const CON_DISTANCED:int = 7;
		///When the player closes the distance.
		public const CON_APPROACHED:int = 8;
        ///Whenever a turn starts.
        public const CON_TURNSTART:int = 9;
		public function react(context:int):Boolean{
			return true;
		}

		public function struggle():void{

		}

		public function getCurrMonsterIndex():int{
			for(var i:int = 0;i<game.monsterArray.length;i++){
				if(game.monsterArray[i] == this){
					return i;
				}
			}
			return -1;
		}

		override public function updateBleed():void{
			var totalDuration:int = 0;
			for (var i:int = 0; i < statusEffects.length;i++){
				if (statusEffects[i].stype.id == "Izma Bleed") {
				//Countdown to heal
				statusEffects[i].value1 -= 1;
				totalDuration += statusEffects[i].value1;
				if (statusEffects[i].value1 <= 0) {
				statusEffects.splice(i, 1);
				}
			}
			}
			if (totalDuration <= 0){
					game.outputText("The wounds you left on " + a + short + " stop bleeding so profusely.\n\n");
				}else{
					var store:Number = bleedDamage();
					store = game.combat.doDamage(store);
					if (plural) game.outputText(capitalA + short + " bleed profusely from the jagged wounds your weapon left behind. <b>(<font color=\"#800000\">" + store + "</font>)</b>\n\n");
					else game.outputText(capitalA + short + " bleeds profusely from the jagged wounds your weapon left behind. <b>(<font color=\"#800000\">" + store + "</font>)</b>\n\n");
			}
		}

		public function handleDamaged(damage:Number,apply:Boolean = true):Number{//Handles any effect that takes place when damageDealt is dealt, from any source. Use combat.damageType to get the type of damageDealt dealt by the player(melee physical, melee ranged, magical melee, magical ranged) and respond appropriately.
			return damage;
		}

		override public function set HP(value:Number):void {
			super.HP = value;
			game.mainView.monsterStatsView.refreshStats(game);
		}
		override public function set lust(value:Number):void {
			super.lust = value;
			game.mainView.monsterStatsView.refreshStats(game);
		}
		override public function set fatigue(value:Number):void {
			super.fatigue = value;
			game.mainView.monsterStatsView.refreshStats(game);
		}

		public function generateTooltip():String{
			var retv:String = "<b>Corruption:</b>" + (game.player.hasPerk(PerkLib.Awareness) ? cor : "???") + "\n<b>Armor:</b>" + (game.player.hasPerk(PerkLib.Awareness) ? armorDef : "???") + "\n";
			if (hasStatusEffect(StatusEffects.IzmaBleed)) retv += "<b>Bleeding:</b> Target is bleeding and takes <b>(<font color=\"" + game.mainViewManager.colorHpMinus() + "\">" + Math.round(bleedDamage(false,true)) + "-" +Math.round(bleedDamage(true)) +  "</font>)</b> damage each turn.\n";
			if (hasStatusEffect(StatusEffects.Stunned)) retv += "<b>Stunned:</b> Target is stunned, and may not act for " + (statusEffectv1(StatusEffects.Stunned)+1) + " turns.\n";
			if (hasPerk(PerkLib.Invincible)) retv += "<b>INVINCIBLE:</b> Target is invincible, and will take no damage from any attack.\n";
			if (hasPerk(PerkLib.BleedImmune)) retv += "<b>Bleed Immune:</b> Target is immune to bleeding effects.\n";
			if (hasPerk(PerkLib.Resolute)) retv += "<b>Stun Immune:</b> Target is immune to stun effects.\n";
			if (hasStatusEffect(StatusEffects.Blind))  retv += "<b>Blinded:</b> Target is blinded and will miss much more often.\n";
			if (hasStatusEffect(StatusEffects.Fear))  retv += "<b>Frightened:</b> Target is frozen by fear, and cannot attack.\n";
			if (hasStatusEffect(StatusEffects.NagaVenom))  retv += "<b>Poisoned(Naga):</b> Target is continuously losing speed and strength.\n";
			if (hasStatusEffect(StatusEffects.Whispered))  retv += "<b>Whispered:</b> Target is addled by dark whisperings, and cannot attack.\n";
			if (hasStatusEffect(StatusEffects.OnFire))  retv += "<b>Burning:</b> Target is burning, and takes damage every turn for " + statusEffectv1(StatusEffects.OnFire) +" turns.\n";
			if (hasStatusEffect(StatusEffects.Shell))  retv += "<b>Shell:</b> Target is protected by a magical shell for " + statusEffectv1(StatusEffects.Shell) +" turns, and will absorb some magical attacks.\n";
			if (hasStatusEffect(StatusEffects.GuardAB))  retv += "<b>Guarded:</b> Target is guarded, and cannot be attacked directly.\n";
			if (hasPerk(PerkLib.PoisonImmune)) retv += "<b>Poison Immune:</b> Target is immune to poison effects.\n";
			if (hasPerk(PerkLib.PhysicalResistance)) retv += "<b>Physical Resistance:</b> Target is resilient to physical damage.\n";
			if (hasPerk(PerkLib.ExtraDodge)) retv += "<b>Extra Dodgy:</b> Target has extra chance to dodge attacks.\n";
			if (HP <= 0) retv += "<b>This enemy is out of the fight.</b>\n";
			if (lust >= maxLust() && !ignoreLust) retv +=  "<b>This enemy is too aroused to bother fighting.</b>\n";
			if (hasStatusEffect(StatusEffects.GuardAB)) retv +=  "<b>This enemy is being guarded by another, and can't be reached.</b>\n";
			retv += getDistanceDescription();
			if (hasPerk(PerkLib.Flying)) retv += "<b>Flying:</b> This enemy can fly and will execute melee attacks no matter your distance.\n";
			for each(var status:StatusEffect in statusEffects){
				if(status is CombatBuff && (status as CombatBuff).tooltip != ""){
					retv += (status as CombatBuff).tooltip;
				}
			}
			return retv;
		}

		public function getDistanceDescription():String{
			switch(distance){
				case DISTANCE_DISTANT:
						if(extraDistance > 0) return "This enemy is very distant from you. Approaching " + pronoun2 + " would take <b>" + extraDistance + "</b> moves.";
						return "This enemy is <b>distanced</b> from you. Approach or use ranged attacks.\n";
				case DISTANCE_MELEE:
						return "This enemy is in melee range, and can be hit with any attack.\n";
			}
			return "error\n";
		}

		public function reduceDamageMax(damage:Number,armorIgnore:Number = 0,applyWeaponModifiers:Boolean = false):int{
    	    return reduceDamage(damage,player,armorIgnore,false,false,true,false,applyWeaponModifiers);
	    }
        public function reduceDamageMin(damage:Number,armorIgnore:Number = 0,applyWeaponModifiers:Boolean = false):int{
            return reduceDamage(damage,player,armorIgnore,false,false,false,true,applyWeaponModifiers);
        }

		public function reduceDamageCombat(damage:Number,armorIgnore:Number = 0,applyWeaponModifiers:Boolean = false):int{
			return reduceDamage(damage,player,armorIgnore,false,true,false,false,applyWeaponModifiers);
		}
		override public function attackOfOpportunity():void{
			outputText("[Themonster] is quick to react to your movement, attacking you as you escape!\n");
			eAttack();
		}

		public function initiativeValue():int{
			var diff:Number = player.level - this.level;
			diff += 15 * (1 - Math.max(HPRatio(),0.1));
            diff += 10 * LustRatio();
			if(player.spellMod() > 3) diff += 2;
			if (game.combat.calcDamage(false,false) >= maxHP()/4  || (game.combat.calcDamage(false,false) * game.combat.getNumAttacks()*0.7) >= maxHP()/4) diff += 5;
			return Math.round(diff);
		}

		public var moveCooldown:int = 0;
		//Returns whether or not a monster should bother moving, based on a new possible position.
        public function shouldMove(newPos:int,forceAction:Boolean = false):Boolean {
			var takeAction:Boolean = initiativeValue() > 15 || newPos == DISTANCE_MELEE; //Moving to melee generally happens when the monster is disadvantaged at range, so it shouldn't require initiativeValue which is more about being in danger
			var moveToBetterPosition:Boolean = ((newPos == DISTANCE_DISTANT && prefersRanged) || (newPos == DISTANCE_MELEE && !prefersRanged));
			return  (moveToBetterPosition && !hasPerk(PerkLib.Immovable)) &&
					moveCooldown == 0 && !isFlying && (forceAction || takeAction) ;
        }

		/**
		 * Override these to add custom win/loss conditions to a specific monster, and return the function to call when the condition is met. See the basilisk or sand trap for examples.
		 */
		public function playerWinCondition():Function { return null; }
		public function playerLossCondition():Function { return null; }
    }
}


code:
package classes
{
	import classes.BodyParts.*;
	import classes.GlobalFlags.kFLAGS;
	import classes.GlobalFlags.kGAMECLASS;
	import classes.Items.ArmorLib;
	import classes.Items.ConsumableLib;
	import classes.Items.JewelryLib;
	import classes.Items.UseableLib;
	import classes.Items.WeaponLib;
	import classes.Items.ShieldLib;
	import classes.Items.UndergarmentLib;
	import classes.Scenes.Areas.VolcanicCrag.VolcanicGolem;
	import classes.Scenes.Dungeons.Factory.SecretarialSuccubus;
	import classes.Scenes.NPCs.Kiha;
	import classes.Scenes.Quests.UrtaQuest.MilkySuccubus;
	import classes.internals.ChainedDrop;
	//import classes.internals.MonsterCounters;
	import classes.internals.RandomDrop;
	import classes.internals.Utils;
	import classes.internals.WeightedDrop;
	/**
	 * ...
	 * @author ...
	 */
	public class MonsterAbilities extends Monster
	{

		public function get monster():Monster { return game.monster; }

		public function MonsterAbilities()
		{

		}
		public function whitefire():void{
			outputText("[Themonster] narrows [monster.pronoun3] eyes and focuses [monster.pronoun3] mind with deadly intent. [monster.pronoun1caps] snaps [monster.pronoun3] fingers and you are enveloped in a flash of white flames!  ");
			var damage:int = (monster.inte + rand(50))* monster.spellMod();
			if (player.isGoo()) {
				damage *= 1.5;
				outputText("It's super effective! ");
			}
			player.takeDamage(damage, true);
		}

		public function blind():void{
			outputText("[Themonster] glares at you and points at you! A bright flash erupts before you!  ");
			if (rand(player.inte / 5) <= 4) {
				outputText("You are blinded!");
				player.createStatusEffect(StatusEffects.Blind, 1 + rand(3), 0, 0, 0);
			}
			else {
				outputText("You manage to blink in the nick of time!");
			}
		}

		public function arouse():void{
			outputText("[Themonster] makes a series of arcane gestures, drawing on [monster.pronoun3] lust to inflict it upon you! ");
			var lustDmg:int = (monster.inte / 10) + (player.lib / 10) + rand(10)* monster.spellMod();
			player.takeLustDamage(lustDmg, true);
		}

		public function chargeweapon():void{
			outputText("[Themonster] utters word of power, summoning an electrical charge around [monster.pronoun3] "+monster.weaponName+". It looks like" +
					" [monster.pronoun1]'ll deal more physical damage now!");
			monster.createStatusEffect(StatusEffects.ChargeWeapon, 25 * monster.spellMod(), 0, 0, 0);
		}

		public function heal():void{
			outputText("[Themonster] focuses on [monster.pronoun3] body and [monster.pronoun3] desire to end pain, trying to draw on [monster.pronoun3] arousal without enhancing it.");
			var temp:int = int(10 + (monster.inte/2) + rand(monster.inte/3)) * monster.spellMod();
			outputText("[monster.pronoun1caps] flushes with success as [monster.pronoun3] wounds begin to knit! (+" + temp + ").");
			monster.addHP(temp);
		}

		public function might():void{
			outputText("[Themonster] flushes, drawing on [monster.pronoun3] body's desires to empower [monster.pronoun3] muscles and toughen [monster.pronoun3] up.");
			outputText("The rush of success and power flows through [monster.pronoun3] body.  [monster.pronoun1caps] feels like [monster.pronoun1] can do anything!");
			monster.createStatusEffect(StatusEffects.Might, 20 * monster.spellMod(), 20 * monster.spellMod(), 0, 0);
			monster.str += 20 * monster.spellMod();
			monster.tou += 20 * monster.spellMod();
		}

		public function distanceSelf():void{
			monster.moveCooldown = 3;
			game.combat.blockTurn = true;
			outputText("[Themonster] readies [monster.pronoun2]self and dashes back, getting some distance from you!\n");
			if (player.hasStatusEffect(StatusEffects.TFScorch)) {
				outputText("The scorching flames covering the battlefield burn [monster.pronoun2] as [monster.pronoun1] passes through. ");
				game.combat.doDamage(game.combat.combatAbilities.tfScorchCalc(), true, true);
			}
            if(player.canMove()) {
                game.menu();
                game.addButton(0, "Chase", distanceSelfReact, true).hint("Chase after the enemy!");
                game.addButton(1, "Wait", distanceSelfReact, false).hint("Just wait.");
				game.combat.combatAbilities.whipTripFunc.createButton(2);
				game.combat.combatAbilities.vineTripFunc.createButton(2); //Having vine armor overrides wielding a whip
            }else{
                game.combat.blockTurn = false;
				distanceSelfReact(false,false);
			}
		}

		public function distanceSelfReact(chase:Boolean, continueTurn:Boolean = true):void{
            if(chase){
                outputText("\nYou chase after [themonster], trying to deny [monster.pronoun2] from gaining any ground.\n");
                player.changeFatigue(10, FATIGUE_PHYSICAL);
				if (monster.react(monster.CON_APPROACHED)) {
					if (rand(player.spe) + 10 > rand(monster.spe)){
						outputText("You manage to keep up with [themonster], and you both remain at melee range.\n");
					}else{
						outputText("You fail to keep up with [monster.pronoun2], and [monster.pronoun1] manages to distance [monster.pronoun2]self from you!\n");
						game.combatAttackData.distance(monster,false);
					}
				}
				else game.combatAttackData.distance(monster,false,0,false);
            }else{
                outputText("\n\nYou wait, and let [themonster] distance [monster.pronoun2]self.\n");
                game.combatAttackData.distance(monster,false);
            }
            game.outputText("\n");
			if(continueTurn)game.combat.execMonsterAI(game.combat.currMonsterIndex+1);
		}

		public function approach():void{
			game.combat.blockTurn = true;
			outputText("[Themonster] readies [monster.pronoun2]self and dashes towards you, intent on closing the distance!\n");
			if (player.hasStatusEffect(StatusEffects.TFScorch)) {
				outputText("The scorching flames covering the battlefield burn [monster.pronoun2] as [monster.pronoun1] passes through. ");
				game.combat.doDamage(game.combat.combatAbilities.tfScorchCalc(), true, true);
			}
			if(player.canMove()){
                game.menu();
                game.addButton(0, "Distance", approachReact,true).hint("Try to keep yourself distanced!");
                game.addButton(1, "Wait", approachReact,false).hint("Just wait.");
			}else{
                game.combat.blockTurn = false;
				approachReact(false,false);
			}

		}

		public function approachReact(distance:Boolean, continueTurn:Boolean = true):void{
            if(distance){
                outputText("\n\nYou distance yourself from [themonster], trying to deny [monster.pronoun2] from approaching you.\n");
                player.changeFatigue(10, FATIGUE_PHYSICAL);
				if (monster.react(monster.CON_DISTANCED)) {
					if (rand(player.spe) + 10> rand(monster.spe)){
						outputText("You manage to distance yourself from [themonster].");
					}else {
						outputText("You fail to match [monster.pronoun2]'s speed, and [monster.pronoun1] manages to close the gap between you!\n");
						game.combatAttackData.closeDistance(monster);
					}
				}
				else game.combatAttackData.closeDistance(monster);
            }else{
                outputText("\n\nYou wait, and let [themonster] approach you.");
                game.combatAttackData.closeDistance(monster);
            }
			game.outputText("\n");
            if(continueTurn)game.combat.execMonsterAI(game.combat.currMonsterIndex+1);
		}

		public function wait():void{
			outputText("[Themonster] waits.");
			monster.changeFatigue(-10);
		}
	}

}


code:
package classes
{
	/**
	 * ...
	 * @author ...
	 */
	public class MonsterAbilityContainer
	{

		public function MonsterAbilityContainer()
		{

		}

	}

}


code:
package classes.classes
{
	import classes.Character;
	import classes.CoC;

	/**
	 * ...
	 * @author Yoffy
	 */
	public class NonPlayer extends Character
	{

		public function NonPlayer(game:CoC)
		{
			super(game);
		}

	}

}