code:
/**
 * Created by aimozg on 26.03.2017.
 */
package classes.Scenes.API {
public class ComplexEncounter extends GroupEncounter {
	private var _chance:*;

	/**
	 * @param chance Number, Boolean, or function() returning Number|Boolean,
	 * @param components Array of Encounter-s
	 */
	public function ComplexEncounter(name:String,chance:*,components:Array) {
		super(name,components);
		this._chance = chance;
	}

	override public function encounterChance():Number {
		return Encounters.convertChance(_chance);
	}

}
}

license: unknown


code:
/*
 * Created by aimozg on 26.03.2017.
 */
package classes.Scenes.API {
/**
 * An interface for exploration encounters.
 *
 * - For each encounter registered in area, a Encounter.encounterChance() method is called.
 * -- If the chance is Encounters.ALWAYS = Number.POSITIVE_INFINITY, that encounter is executed immediataly
 *    and no further encounter checks are performed.
 * - If there were no such encounter, the weighted (by the returned chance) encounter is executed.
 * The scale is arbitrary as long as it's same in the grouped encounters.
 * - Numbers aroung 100 are easy to read, write, and understand.
 * - (preferred) Scale from 0 to 1 enables multiplication of chances without them going out of scale
 */
public interface Encounter {
	/**
	 * - 1 for "generic",
	 * - 2-4 for varying scales of "often",
	 * - 0.1-0.5 for "rare",
	 * - 0.01-0.1 for "very rare"
	 */
	function encounterChance():Number;
	function execEncounter():void;
	function encounterName():String;
}
}


code:
/**
 * Created by aimozg on 26.03.2017.
 */
package classes.Scenes.API {
import classes.CoC_Settings;
import classes.GlobalFlags.kGAMECLASS;

public class Encounters {

	// =================================================================================================================
	//      ENCOUNTER BUILDERS
	// =================================================================================================================

	/**
	 * A complex() encounter executes one of its components, and has its own chance
	 * Unlike group(), complex() encounter chance does not depend on its components
	 * * an ALWAYS component won't affect the complex encounter own chance
	 * * components can have any scale
	 * complex() should be used to list variations of an encounter; however, the upper level encounter can
	 * be of any type (since its chance isn't taken into account)
	 * @param chance: Number or function():Number
	 * @param components: Array of Encounter's. First component may be this complex encounter name
	 */
	public static function complex(chance:*,...components):ComplexEncounter {
		if (components[0] is String) return new ComplexEncounter(components[0],chance,components.slice(1));
		if (components.length==1) return new ComplexEncounter((components[0] as Encounter).encounterName(),chance,components);
		return new ComplexEncounter("complex{"+components.length+"}",chance,components);
	}

	/**
	 * A group() encounter executes one of its components, and has no own chance
	 * Unlike complex(), a group() encounter chance directly depends on its components (sum of components')
	 * * an ALWAYS component chance will raise group's own chance to ALWAYS
	 * * components should have same scale as the upper level encounter (if any)
	 * group() should be used to union encounters in one place and add them as sub-components at once
	 * @param components Array of Encounter's or build def's. First component may be this group encounter name
	 */
	public static function group(...components):GroupEncounter {
		if (components[0] is String) return new GroupEncounter(components[0],components.slice(1));
		if (components.length==1) return new GroupEncounter((components[0] as Encounter).encounterName(),components);
		return new GroupEncounter("group{"+components.length+"}",components);
	}

	/**
	 * Multiply encounter chance
	 */
	public static function wrap2(encounter:Encounter,chances:Array):Encounter {
		if (chances.length==0) return encounter;
		return new SimpleEncounter(encounter.encounterName(),
				fn.product(chances.concat([function():Number{return encounter.encounterChance();}])),
				function():void{encounter.execEncounter()}// < wrap in case it uses `this`
		);
	}

	// =================================================================================================================
	//      CONDITIONS AND CHANCES HELPER FUNCTIONS
	// =================================================================================================================

	public static const ALWAYS:Number = Number.POSITIVE_INFINITY;
	//noinspection JSUntypedDeclaration
	public static const fn: FnHelpers = FnHelpers.FN;

	// =================================================================================================================
	//      EVERYTHING ELSE
	// =================================================================================================================

	/**
	 * Runs the encounter selection check. DOES NOT call .execute()
	 * Returns null if all encounters have chance <= 0
	 */
	public static function selectOrNull(encounters:Array):Encounter {
		var items:Array = [];
		var sum:Number = 0;
		var strace:String = "selecting from";
		var i:int;
		var name:String;
		for (i=0;i<encounters.length;i++) {
			var e:Encounter            = encounters[i];
			name = e.encounterName() || ("#" + i);
			debug_callsite = name;
			var c:Number               = e.encounterChance();
			debug_callsite             = "";
			strace += " " + name + "=" + ch2str(c);
			if (c >= ALWAYS) {
				//trace(debug_indent + strace);
				//trace(debug_indent + "-> picked encounter " + name + " with chance ALWAYS of total (unknown)");
				return e;
			}
			if (c > 0) {
				sum += c;
				items.push([e, c, i]);
			}
		}
		//trace(debug_indent+strace);

		var random:Number = Math.random()*sum;
		strace = "-> random[0.." + ch2str(sum) + "]=" + ch2str(random);
		while(items.length>0) {
			var eci:Array = items.shift();
			e = eci[0];
			c = eci[1];
			i = eci[2];
			random -= c;
			name = e.encounterName()||("#"+i);
			strace += " -" + name + "=" + ch2str(random);
			if (random<=0) {
				kGAMECLASS.exploration.lastEncounter = e.encounterName();

				return e;
			}
		}
		//trace(strace);
		//trace("WARNING Encounters.selectOrNull found no encounter");
		return null;
	}
	internal static var debug_indent:String = "";
	/**
	 * Runs the encounter selection check. DOES NOT call .execute()
	 * Returns last if all encounters have chance <= 0.
	 * Throws an error if there are 0 encounters
	 */
	public static function select(encounters:Array):Encounter {
		return selectOrNull(encounters) || encounters[encounters.length-1];
	}

	/**
	 * @param def An encounter definition object with properties:
	 * name:string - used for debugging
	 * call:function():void or Encounter - encounter code itself, or encounter to wrap with
	 * chance:Number or function():Number -  weight of the encounter among others. default 1.0.
	 * 0 is "never" and fn.ALWAYS (shortcut for Number.POSITIVE_INFINITY) is "ignore others"
	 * when:function():Boolean - additional requirement. default always true. "false" skips encounter no matter the `chance`
	 * mods: Array of chances - additional multipliers for resulting chance
	 */
	public static function build(def:*):Encounter {
		var name:String = def.name||"";
		var chance:* = def.chance;
		var when:* = def.when;
		var mods:* = def.mods;
		var call:* = def.call;
		if (mods === null || mods === undefined) mods = [];
		if (!(mods is Array)) {
			CoC_Settings.error("Bad def.mods "+(typeof mods)+" in "+name);
			mods = [1];
		}
		if (chance !== null && chance !== undefined) {
			if (!isChance(chance)) {
				CoC_Settings.error("Bad def.chance "+(typeof chance)+" in "+name);
			} else mods.push(chance);
		}
		if (when !== null && when !== undefined) {
			if (!isChance(when)) {
				CoC_Settings.error("Bad def.when "+(typeof when)+" in "+name);
			} else mods.push(when);
		}
		if (call is Encounter) {
			return wrap2(call,mods);
		} else {
			if (!(call is Function)) {
				CoC_Settings.error("Bad def.call " + (typeof call) + " in " + name);
			}
			return new SimpleEncounter(name,fn.product(mods), call);
		}
	}

	/**
	 * Calculates/converts a chance
	 * Number -> returned
	 * Function -> executed, result recursively converted
	 * Boolean -> converted
	 */
	public static function convertChance(chance:*):Number {
		while (!(chance is Number)) {
			if (chance === undefined || chance === null) {
				//trace("WARNING chance is "+chance+(debug_callsite?" at ":debug_callsite)+"; using 1 as default");
				return 1;
			}
			if (chance is Array) {
				CoC_Settings.error("Array chance argument (rest args?)");
				chance = chance[0];
			} else if (chance is Function) chance = chance();
			else if (chance is Boolean) chance = chance?1:0;
			else {
				CoC_Settings.error("Bad chance of type "+typeof chance+(debug_callsite?" at "+debug_callsite:""));
				return 1;
			}
		}
		return chance;
	}
	public static function isChance(chance:*):Boolean {
		return chance is Function || chance is Number || chance is Boolean;
	}
	private static var debug_callsite:String = "";
	internal static function ch2str(n:Number):String {
		if (n == Number.POSITIVE_INFINITY) return "ALWAYS";
		//if (n <= 0) return "0";
		return n.toFixed(3).replace(/\.?0+$/,"");
	}
}}


code:
/**
 * Created by aimozg on 28.03.2017.
 */
package classes.Scenes.API {
import classes.BaseContent;
import classes.GlobalFlags.kFLAGS;
import classes.GlobalFlags.kGAMECLASS;

public class FnHelpers extends BaseContent {
	public static const FN:FnHelpers = new FnHelpers();

	/**
	 * @param chances An array of chances or chance functions
	 * @return A function returning product of chances. If encountered, 0 beats INFINITY
	 */
	public function product(chances:Array):Function {
		var saved:Array = chances.concat([]);
		return function():Number {
			var rslt:Number = 1;
			for (var i:int = 0; i < saved.length; i++) {
				var o:* = Encounters.convertChance(saved[i]);
				if (o <= 0) return 0;
				rslt *= o;
			}
			return rslt;
		}
	}

	/**
	 * @param chance Number | Boolean | Function():Number|Boolean
	 * @return Function returning 0 if `chance` is not 0, 1 otherwise
	 */
	public function not(chance:*):Function {
		return function():Number {
			var c:* = (chance is Function) ? chance() : chance;
			return Encounters.convertChance(c) ? 0 : 1;
		}
	}

	/**
	 * @param chances Array of [Number | Boolean | Function():Number|Boolean]
	 * @return Function returning 1 iff all chances are not 0, 0 if any is 0
	 */
	public function all(...chances):Function {
		return function():Number {
			for each (var chance:Object in chances) {
				var c:* = chance;
				if (c is Function) c = c();
				if (!Encounters.convertChance(c)) return 0;
			}
			return 1;
		}
	}

	/**
	 * @param chances Array of [Number | Boolean | Function():Number|Boolean]
	 * @return Function returning 1 iff all chances are 0, 0 if any is 1
	 */
	public function none(...chances):Function {
		return function():Number {
			for each (var chance:Object in chances) {
				var c:* = chance;
				if (c is Function) c = c();
				if (Encounters.convertChance(c)) return 0;
			}
			return 1;
		}
	}

	/**
	 * @param chances Array of [Number | Boolean | Function():Number|Boolean]
	 * @return Function returning 0 iff all chances are 0, 1 if any is not 0
	 */
	public function any(...chances):Function {
		return function():Number {
			for each (var chance:Object in chances) {
				var c:* = chance;
				if (c is Function) c = c();
				if (Encounters.convertChance(c)) return 1;
			}
			return 0;
		}
	}

	/**
	 * @return Function returning `iftrue` if player is at least `level` or at least `daysPerLevel`*`level` days have passed, `iffalse` otherwise
	 */
	public function ifLevelMin(level:int, daysPerLevel:int = 6, iftrue:* = 1, iffalse:* = 0):Function {
		return function():* {
			return (player.level >= level || time.days >= level * daysPerLevel) ? iftrue : iffalse;
		}
	}

	/**
	 * @return Function returning Number, linearly dependent on player level:
	 * - at levleA: valueA
	 * - at levelB: valueB
	 * - in levelA..levelB: linearly interpolated value
	 * - if bound==true (default), for levels < levelA returns valueA, for levels > levelB returns valueB
	 * - if bound==false, continues the interpolation outside the levelA..levelB interval,
	 * optionally capped between min and max
	 */
	public function lineByLevel(levelA:int,
								levelB:int,
								valueA:Number,
								valueB:Number,
								bound:Boolean = true,
								min:Number    = Number.NEGATIVE_INFINITY,
								max:Number    = Number.POSITIVE_INFINITY):Function {
		return function ():Number {
			return lerp(player.level, levelA, levelB, valueA, valueB, bound, min, max);
		}
	}

	/**
	 * A linear interpolation of values xA..xB to yA..yB
	 * - if bound==true (default), for x < xA returns xA, for x > xB returns xB
	 * - if bound==false, continues the interpolation outside the xA..xB interval,
	 * optionally capped between min and max
	 */
	public function lerp(x:Number, xA:int, xB:int, yA:Number, yB:Number,
						 bound:Boolean = true, min:Number = Number.NEGATIVE_INFINITY, max:Number = Number.POSITIVE_INFINITY):Number {
		if (bound) {
			if (x <= xA) return yA;
			if (x >= xB) return yB;
		}
		if (xA == xB) return (yA + yB) / 2;
		const y:Number = yA + (x - xA) * (yB - yA) / (xB - xA);
		return Math.min(max, Math.max(min, y));
	}

	/**
	 * Solves
	 *   a * ln(x1 - c) + b = y1
	 *   a * ln(x2 - c) + b = y2 = (y3 + y1) / 2
	 *   a * ln(x3 - c) + b = y3
	 * for a,b,c
	 * @return Object{a:Number,b:Number,c:Number}
	 */
	public function buildLogScaleABC(x1:Number, x2:Number, x3:Number, y1:Number, y3:Number):Object {
		const dy:Number = (y3 - y1) / 2;
		/*
		 * subtract one equation from another
		 * y3 - y2 = a * ln[(x3 - c) / (x2 - c)]
		 * y2 - y1 = a * ln[(x2 - c) / (x1 - c)]
		 * (x2 - c) / (x1 - c) = (x3 - c) / (x2 - c) = exp(dy / a)
		 * x & c part reduces into c*(2*x2 - x1 - x3) = x2*x2 - x1*x3
		 */
		const c:Number = (x2 * x2 - x1 * x3) / (2 * x2 - x1 - x3);
		const a:Number = dy / Math.log((x2 - c) / (x1 - c));
		const b:Number = y1 - a*Math.log(x1 - c);
		return {a:a,b:b,c:c};
	}

	/**
	 * @param abc Object{a:Number,b:Number,c:Number}
	 * @return a * ln(x - c) + b, clamped into [min..max]
	 */
	public function logScale(x:Number, abc:Object, min:Number = Number.NEGATIVE_INFINITY, max:Number = Number.POSITIVE_INFINITY):Number {
		const y:Number = abc.a * Math.log(x - abc.c) + abc.b;
		return Math.min(max, Math.max(min, y));
		}

	/**
	 * @return Function returning `iftrue` if current time (in hours) is between `minimum` (0-23, INCLUSIVELY) and `maximum` (0-24, EXCLUSIVELY)
	 */
	public function ifTimeOfDay(minimum:int, maximum:int, iftrue:* = 1, iffalse:* = 0):Function {
		return function():* {
			var hours:Number = time.hours;
			return (hours >= minimum && hours < maximum) ? iftrue : iffalse;
		}
	}

	/**
	 * @return Function returning `iftrue` if NG+ level is at least `minimum`, `iffalse` otherwise
	 */
	public function ifNGplusMin(minimum:int, iftrue:* = 1, iffalse:* = 0):Function {
		return function():* {
			return flags[kFLAGS.NEW_GAME_PLUS_LEVEL] >= minimum ? iftrue : iffalse;
		}
	}

	public function FnHelpers() {
	}

	public function ifPregnantWith(pregnancyType:int, iftrue:* = 1, iffalse:* = 0):Function {
		return function():* {
			return player.pregnancyIncubation > 1 && player.pregnancyType == pregnancyType ? iftrue : iffalse
		}
	}
}
}


code:
/**
 * Created by aimozg on 26.03.2017.
 */
package classes.Scenes.API {
import classes.GlobalFlags.kGAMECLASS;

public class GroupEncounter implements Encounter {
	protected var components:Array;// of Encounter
	protected var name:String;
	public function GroupEncounter(name:String,components:Array) {
		this.name = name;
		this.components = [];
		for each (var c:* in components) {
			add(c);
		}
	}

	public function encounterName():String {
		return name;
	}

	/**
	 * Builds and adds encounters.
	 * Sample usage:
	 * build({
	 *   name: "encounter1", call: function1,
	 *   chance: 0.2, when: Encounters.fn.ifMinLevel(5)
	 * },{
	 *   name: "encounter2",
	 *   call: function():void{},
	 *   chance: function():Number {}, // default 1
	  *  when: function():Boolean {} // default true
	 * })
	 * @param defs Array of defs objects or Encounter-s.
	 * @see Encounters.build
	 */
	public function add(...defs):GroupEncounter {
		for each (var def:* in defs) {
			if (def is Encounter) components.push(def);
			else components.push(Encounters.build(def));
		}
		return this;
	}

	public function execEncounter():void {
		//trace(Encounters.debug_indent+encounterName()+".execEncounter()");
		Encounters.debug_indent += "  ";
		Encounters.select(components).execEncounter();
		Encounters.debug_indent = Encounters.debug_indent.slice(2);
	}

	public function encounterChance():Number {
		var sum:Number = 0;
		for each (var encounter:Encounter in components) sum += encounter.encounterChance();
		return sum;
	}
}
}


code:
package classes.Scenes.API
{
	/**
	 * Interface for explorable areas.
	 */
	public interface IExplorable
	{
		/**
		 * Check if the area has already been discovered.
		 * @return true if the area has been discovered.
		 */
		function isDiscovered():Boolean;
		/**
		 * Discover the area, making it available for future exploration.
		 */
		function discover():void;
		/**
		 * Explore the area, possibly triggering encounters.
		 */
		function explore():void;
	}
}


code:
/**
 * Created by aimozg on 01.04.2017.
 */
package classes.Scenes.API {

/**
 * A lazily initialized (on first access) Encounter wrapper
 */
public class LateinitEncounter implements Encounter {

	protected var _proxied:Encounter = null;
	protected var scope:Object = null;
	protected function get proxied():Encounter {
		return _proxied ||= createEncounter.apply(scope);
	}
	protected var createEncounter:Function;

	public function encounterChance():Number {
		return proxied.encounterChance();
	}

	public function execEncounter():void {
		proxied.execEncounter();
	}

	public function encounterName():String {
		return proxied.encounterName();
	}

	/**
	 *
	 * @param scope: A "this" object that is implicitly or explicitly used in function
	 * @param createEncounterFn: A function that constructs an Encounter.
	 */
	public function LateinitEncounter(scope:Object,createEncounterFn:Function) {
		this.createEncounter = createEncounterFn;
		this.scope = scope;
	}
}
}


code:
/*
 * Created by aimozg on 26.03.2017.
 */
package classes.Scenes.API {
import classes.CoC_Settings;

public class SimpleEncounter implements Encounter {
	private var _weight:*;
	private var name:String;
	private var _body:Function;
	public function SimpleEncounter(name:String,weight:*, body:Function) {
		if (!(weight is Function) && !(weight is Number)) {
			CoC_Settings.error("Encounters.make(weight=" + (typeof weight) + ")");
			weight = 100;
		}
		this.name = name;
		this._weight = weight;
		this._body = body;
	}

	public function encounterChance():Number {
		if (_weight is Function) return _weight();
		return _weight;
	}

	public function execEncounter():void {
		var rslt:* = _body();
		/*if (rslt !== null && rslt !== undefined) {
			trace("WARNING SimpleEncounter returned "+rslt+" ("+(typeof rslt)+"), value ignored")
		}*/
	}

	public function encounterName():String {
		return name;
	}
}
}


code:
package classes.Scenes
{
	import classes.Creature;
	/**
	 * Interface for anal pregnancy.
	 * The class must at least implement a birth scene.
	 */
	public interface AnalPregnancy
	{
		/**
		 * Progresses a active pregnancy. Updates should eventually lead to birth.
		 * @return true if the display output needs to be updated.
		 */
		function updateAnalPregnancy(): Boolean;

		/**
		 * Give birth. Should outout a birth scene.
		 */
		function analBirth(): void;
	}
}


code:
/* Created by aimozg on 06.01.14 */
package classes.Scenes.Areas {
	import classes.*;
	import classes.GlobalFlags.kFLAGS;
	import classes.GlobalFlags.kGAMECLASS;
	import classes.Items.ConsumableLib;
	import classes.Items.Consumables.BeeHoney;
	import classes.Items.Consumables.PhoukaWhiskey;
	import classes.Items.Consumables.RizzaRoot;
import classes.Scenes.API.Encounter;
import classes.Scenes.API.Encounters;
import classes.Scenes.API.FnHelpers;
	import classes.Scenes.API.IExplorable;
import classes.Scenes.Areas.Bog.*;
	import classes.Scenes.PregnancyProgression;
	import classes.internals.GuiOutput;

	use namespace kGAMECLASS;

	public class Bog extends BaseContent implements IExplorable {
		public var frogGirlScene:FrogGirlScene;
		public var chameleonGirlScene:ChameleonGirlScene = new ChameleonGirlScene();
		public var phoukaScene:PhoukaScene;
		public var lizanScene:LizanRogueScene = new LizanRogueScene();
		public var parasiteScene:ParasiteScene = new ParasiteScene();
		public var infestedChameleonGirlScene:InfestedChameleonGirlScene = new InfestedChameleonGirlScene();
		public var anneMarieScene:AnneMarieScene = new AnneMarieScene();
		public function Bog(pregnancyProgression:PregnancyProgression, output: GuiOutput) {
			this.phoukaScene = new PhoukaScene(pregnancyProgression);
			this.frogGirlScene = new FrogGirlScene(pregnancyProgression, output);
		}

		public function isDiscovered():Boolean { return flags[kFLAGS.BOG_EXPLORED] > 0; }
		public function discover():void {
			clearOutput();
			outputText(images.showImage("area-bog"));
			outputText("While exploring the swamps, you find yourself into a particularly dark, humid area of this already fetid biome.  You judge that you could find your way back here pretty easily in the future, if you wanted to.  With your newfound discovery fresh in your mind, you return to camp.\n\n(Bog exploration location unlocked!)");
			flags[kFLAGS.BOG_EXPLORED]++;
			doNext(camp.returnToCampUseOneHour);
		}

		private var _explorationEncounter:Encounter = null;
		public function get explorationEncounter():Encounter {
			const fn:FnHelpers = Encounters.fn;
			if (_explorationEncounter == null) _explorationEncounter =
					Encounters.group(game.commonEncounters, {
						name: "phoukahalloween",
						when: function ():Boolean {
							//Must have met them enough times to know what they're called, have some idea of their normal behaviour
							return isHalloween()
								   && date.fullYear > flags[kFLAGS.TREACLE_MINE_YEAR_DONE] == 0
								   && flags[kFLAGS.PHOUKA_LORE] > 0;
						},
						call: phoukaScene.phoukaHalloween
					}, {
						name  : "chest",
						chance: 0.1,
						when  : function ():Boolean {
							return !player.hasKeyItem("Camp - Murky Chest");
						},
						call  : findMurkyChest
					}, {
						name: "froggirl",
						when: function ():Boolean {
							return player.buttPregnancyIncubation == 0
						},
						call: frogGirlScene.findTheFrogGirl
					}, {
						name: "phouka",
						call: phoukaScene.phoukaEncounter
					}, {
						name: "chameleon",
						call: chameleonGirlScene.encounterChameleon
					}, {
						name: "lizan",
						call: lizanScene.lizanIntro
					}, /*{
						name: "anne",
						chance: 10,
						when: function ():Boolean{
							return !(flags[kFLAGS.ANNEMARIE_STATUS] & 2);
						},
						call: anneMarieScene.encounterAnneMarie
					},*/{
						name  : "parasite",
						when  : function ():Boolean {
							return player.hasStatusEffect(StatusEffects.WormsOn)
								   && !player.hasStatusEffect(StatusEffects.ParasiteSlugMet);
						},
						chance: function ():Number {
							return player.hasStatusEffect(StatusEffects.WormsHalf) ? 0.5 : 1
						},
						call  : parasiteScene.findParasite
					}, {
						name  : "inf_chameleon",
						when  : function ():Boolean {
							return player.hasStatusEffect(StatusEffects.WormsOn)
								   && !player.hasStatusEffect(StatusEffects.ParasiteEel);
						},
						chance: function ():Number {
							return player.hasStatusEffect(StatusEffects.WormsHalf) ? 0.5 : 1
						},
						call  : infestedChameleonGirlScene.encounterChameleon
					}, {
						name  : "sylvia",
						call  : game.sylviaScene
					}, {
						name  : "walk",
						chance: 0.2,
						call  : walk
					});
			return _explorationEncounter;
		}
		public function explore():void {
			clearOutput();
			player.location = "bog";
			flags[kFLAGS.BOG_EXPLORED]++;
			explorationEncounter.execEncounter();
		}

		public function walk():void {
			clearOutput();
			outputText(images.showImage("area-bog"));
			outputText("You wander around through the humid muck, but you don't run into anything interesting.");
			doNext(camp.returnToCampUseOneHour);
		}

		public function findMurkyChest():void {
			var gemsFound:int = 200 + rand(300);
			outputText(images.showImage("item-chest"));
			outputText("While you're minding your own business, you spot a waterlogged chest. You wade in the murky waters until you finally reach the chest. As you open the chest, you find " + String(gemsFound) + " gems inside the chest! You pocket the gems and haul the chest home. It would make a good storage once you clean the inside of the chest.  ");
			player.createKeyItem("Camp - Murky Chest", 0, 0, 0, 0);
			player.gems += gemsFound;
			statScreenRefresh();
			outputText("\n\nYou now have " + num2Text(inventory.itemStorageDirectGet().length) + " storage item slots at camp.");
			doNext(camp.returnToCampUseOneHour);
		}
	}
}


code:
package classes.Scenes.Areas.Bog
{
	import classes.*;
	import classes.internals.*;
	import classes.GlobalFlags.kFLAGS;
	import classes.GlobalFlags.kGAMECLASS;
	import classes.BodyParts.*;

	public class AnneMarie extends Monster
	{
		//1 - str
		//2 - tou
		//3 - spe
		//4 - sens
		/*public function blowGun():void {
			if (!combatAvoidDamage({doDodge:true,doParry:false,doBlock:false}).failed) {
				outputText("The lizan flings himself back.  In the air he puts a blowgun to his lips.  You move just in time to avoid the tiny dart.");
			}
			else {
				outputText("The lizan flings himself back.  In the air he puts his blowgun to his lips and fires a single dart into your neck.  As you pull it out your limbs begin to feel like wet noodles, it appears you’ve been poisoned.");
				game.dynStats("str", -5, "spe", -5);
				if (!player.hasStatusEffect(StatusEffects.LizanBlowpipe)) player.createStatusEffect(StatusEffects.LizanBlowpipe, 5, 0, 5, 0);
				else {
					player.addStatusValue(StatusEffects.LizanBlowpipe, 1, 5);
					player.addStatusValue(StatusEffects.LizanBlowpipe, 3, 5);
				}
				if (player.cor > (50 + player.corruptionTolerance())) {
					game.dynStats("str", -5, "spe", -5);
					player.addStatusValue(StatusEffects.LizanBlowpipe, 1, 5);
					player.addStatusValue(StatusEffects.LizanBlowpipe, 3, 5);
				}
			}

		}

		public function immaHurtYouBadly():void {
			if (!combatAvoidDamage({doDodge:true,doParry:false,doBlock:false}).failed) {
				outputText("The lizan Rushes at you.  As you raise your [weapon] to defend yourself he dives to the side, using a blowgun to fire a single dart at you.  You somehow manage to dodge it.");
			}
			else {
				outputText("The lizan rushes at you.  As you raise your [weapon] to defend yourself he dives to the side, using his blowgun to fire a single stinging dart into your neck.  You pull out the dart and your skin begins to feel hypersensitive, you’re going to have trouble defending yourself");
				game.dynStats("tou", -5, "sens", 5);
				if (!player.hasStatusEffect(StatusEffects.LizanBlowpipe)) player.createStatusEffect(StatusEffects.LizanBlowpipe, 0, 5, 0, 5);
				else {
					player.addStatusValue(StatusEffects.LizanBlowpipe, 2, 5);
					player.addStatusValue(StatusEffects.LizanBlowpipe, 4, 5);
				}
				if (player.cor > (50 + player.corruptionTolerance())) {
					game.dynStats("tou", -5, "sens", 5);
					player.addStatusValue(StatusEffects.LizanBlowpipe, 2, 5);
					player.addStatusValue(StatusEffects.LizanBlowpipe, 4, 5);
				}
			}

		}

		public function wingstickThrow():void {
			if (!combatAvoidDamage({doDodge:true,doParry:false,doBlock:false}).failed) {
				outputText("The lizan zips to the side and you hear the whistle of something being thrown. You sidestep just in time to see a wingstick fly past.");
			}
			else {
				outputText("The lizan zips to the side and as you move to follow you feel something sharp cut across your body. He must have thrown something. ");
				var damage:int = 40 + rand(60);
				player.takeDamage(damage, true);
			}

		}

		public function tongueAttack():void {
			if (!combatAvoidDamage({doDodge:true,doParry:false,doBlock:false}).failed) {
				outputText("All you see is a flash of pink and without even thinking you twist out of its way and watch the lizan’s long tongue snap back into his mouth.");
			}
			else {
				outputText("All you see is a flash of pink as the lizan’s long tongue hits your eyes. Some kind of chemical reaction causes your eyes to burn, you’ve been blinded!");
				if (!player.hasStatusEffect(StatusEffects.Blind)) player.createStatusEffect(StatusEffects.Blind, 1 + rand(2), 0, 0, 0)
			}

		}

		protected function chooseBlowpipe():void {
			if (rand(2) == 0) blowGun();
			else immaHurtYouBadly();
		}

		override public function defeated(hpVictory:Boolean):void
		{
			game.bog.lizanScene.winAgainstLizan();
		}

		override public function won(hpVictory:Boolean, pcCameWorms:Boolean = false):void
		{
			//40% chance of getting infected by the bog parasite if fully worms are on. 20% if worms are "half", none if worms are off, the player doesn't have a penis or if he's already infested by something.
			if (player.hasCock() && !player.hasStatusEffect(StatusEffects.ParasiteSlug) && player.findPerk(PerkLib.ParasiteMusk) < 0 && !player.hasStatusEffect(StatusEffects.Infested) && ((player.hasStatusEffect(StatusEffects.WormsOn) && rand(10) < 5)  || (player.hasStatusEffect(StatusEffects.WormsHalf) && rand(10) < 3))) {

				player.createStatusEffect(StatusEffects.ParasiteSlug, 72, 0, 0, 0);
			}
			game.bog.lizanScene.loseToLizan();
		}

		private const SKIN_VARIATIONS:Array = ["emerald", "azure", "scarlet", "violet", "obsidian", "amber", "silver"];

		public function AnneMarie()
		{
			this.a = "";
			this.short = "Anne Marie";
			this.imageName = "annemarie";
			this.long = "S";
			// this.plural = false;
			this.createVagina(true, 1, 1);
			createBreastRow(Appearance.breastCupInverse("B"));
			this.ass.analLooseness = Ass.LOOSENESS_TIGHT;
			this.ass.analWetness = Ass.WETNESS_NORMAL;
			this.tallness = 5*12 + 7;
			this.hips.rating = Hips.RATING_AMPLE;
			this.butt.rating = Butt.RATING_AVERAGE;
			this.skin.tone = "light";
			this.skin.type = Skin.PLAIN;
			this.hair.color = "black";
			this.hair.length= 5;
			initStrTouSpeInte(70, 70, 100, 100);
			initLibSensCor(30, 30, 15);
			this.weaponName = "Final Argument";
			this.weaponVerb="shot";
			this.weaponAttack = 14;
			this.armorName = "Yorham Scout armor";
			this.armorDef = 10;
			this.bonusHP = 380;
			this.lust = 5;
			this.lustVuln = 0.3;
			this.temperment = TEMPERMENT_LUSTY_GRAPPLES;
			this.level = 20;
			this.gems = 30;
			this.drop = new WeightedDrop();
			this.createPerk(PerkLib.ExtraDodge, 30, 0, 0, 0);
			checkMonster();
		}
		*/
	}

}


code:
/**
 * OtherCoCAnon stuff
 */
package classes.Scenes.Areas.Bog
{
	import classes.*;
	import classes.GlobalFlags.*

	public class AnneMarieScene extends BaseContent {

		public function AnneMarieScene()
		{
		}

		public static const MET_ANNE:int = 1;
		public static const RUDE_TO_ANNE:int = 2;

		public function encounterAnneMarie():void{
			clearOutput();
			outputText("You move through the thick marsh as best you can, straining to push yourself through the mud and sharp sawleaves.\n\nSomething catches you attention; a rise in the land that gives way to a patch of much more solid soil. In the center of this small island, something even more interesting; a cabin!");
			outputText("\n\nYou approach the cabin, movement being a lot easier now that the mud isn't slowing you down. You circle the perimeter, wary of any potential ambush, but find nothing suspiscious. Moving in, you notice a smoking fireplace outside the cabin and a series of light footprints heading towards the house; this place is definitely occupied. You slow down, not wanting to attract the attention of the owner of the cabin.");
			outputText("\n\nWith careful, methodical motion, making sure to avoid the windows, you reach for the cabin door and push it open. It creaks as it moves, and you examine the small room inside through the ever increasing gap, hoping to spot the denizen before it spots you.");
			outputText("\n\nThe door hits the wooden wall, and you scratch your head, baffled by the fact that there's nobody inside. You take one step inside and hear a metallic clicking noise over your head. You look up and lose your breath.");
			var continueConv:Function = function():void {
				clearOutput();
				outputText("\n\nJust a few inches from your eyes stands the end of a rifle. And not the good end. Paralyzed with caution, you attempt to examine the wielder of the large gun, that curiously stands upside-down, hanging from the top of the cabin; a dark-gray woman, with short black hair. You can't make out much detail considering the metallic object blocking your vision, but you notice her arms are lean and sinewy, with a thin membrane connecting it to her torso, forming a featherless wing Her neck is covered with a fuzzy bunch of fur that reminds you of a fancy scarf. Her dark leather armor is covered in finely-sewn pockets and holsters, holding an array of weapons, unique devices and bottles with unknown liquids . It has a curious design, to account for her unusual looking arms.");
				outputText("\n\n[say: You. Hands where I can see them. I <b>mean</b> it. Who are you?] - Her raspy voice takes you from your trance and reminds you of your current predicament.");
				outputText("\n\nYou could try to convince her to not shoot you, or try to teach her what happens to people that pull a gun on you.");
				menu();
				addButton(0, "No Harm", encounter2, true).hint("Better to not irritate the person with a loaded, cocked gun to your forehead.");
				addButton(1, "No Miss", encounter2, false).hint("If she fires, she better not miss. You don't take shit from random people like that.");
			};
			doNext(continueConv);
		}

		public function encounter2(kind:Boolean = true):void{
			clearOutput();
			if (kind){
				outputText("You slowly raise your hands, showing the upside-down girl that you don't intend to harm her. [say: I’m [name]. I don’t mean you any harm, I’m just exploring. Save the bullet for someone that matters.]");
				outputText(" You raise your eyebrows, inquisitive about her response. She narrows her eyes, thinking. [say: Alright, [name]. Your curiosity will get the better of you eventually. Put your weapons down and you can enter.]");
				outputText("\n\nYou breathe a sigh of relief as you begin to drop your gear, the barrel of the high-caliber rifle pointed at your head the entire time. When your gear is a safe distance from you, she puts her weapon down and jumps back to the ground, with remarkable dexterity.");
				outputText("\n\nFrom this angle, you can get a better look at her. She's rather short at 5'4\", and you're surprised to see her enormous, steel and wood rifle is almost as tall as she is. Her legs are much wider than her lean arms, though it is all covered in thick leather, much like her thin chest, giving her a distinct \"pear\" shape. Her short hair reaches up to the nape of her neck, and three bangs rest on the sides of her face and her forehead, making out the shape of an \"M\". The long, thin, twitching ears atop her head complete the ensemble and make her nature evident to you; she's a bat-morph.");
				outputText(" You analyze her face, and notice that she seems quite angry, her bright green eyes piercing you with their gaze. She definitely wants you to explain yourself.");
				outputText("\n\n[say: Why are you so on edge?] you ask her.\n\nHer eyelids lower, apparently stupefied at the question. [say: That’s a stupid question. Everything in here either wants to hurt me, rape me, or both. I have to keep watch on every single creature, sentient or not, that wanders into my camp. Being on edge is what keeps me going here.]");
				outputText("\nYou nod in understanding. [say: Understandable. I find it hard to completely relax in my camp too.]");
				outputText("\nHer ears twitch and her eyes widen upon hearing that, causing her to lower her guard for the first time. [say: You have a camp? Where? You’re not from here either?]");
				outputText("\n\n[say: The forest, north of here. A lot less corruption, the denizens aren’t too hostile. The ones that are, well, they’re not as dangerous.]");
				outputText("\n\nShe brings her winged arm to her chin. You notice she only has three useable fingers; the other two \"fingers\" stretch through the membrane, probably to aid in flying.[say: Interesting. Thanks for the information.]");
				outputText("\n\n[say: You’re welcome.]");
				outputText("\n\n[say: ...] She stares at you, wondering why you haven't disappeared from her sight.");
				outputText("\n\nYou cough, and her ears twitch again. [say: You look tense.]");
				outputText("\n\n[say: Very perceptive. Yes. I am. I want you to leave now.]");
				outputText("\n\n[say: Why?] You ask, already being pushed off from her cabin.");
				outputText("\n\n[say: I don’t need to answer that. Leave.] She shuts the door behind you and throws your gear through the window. You grumble while you remove the mud from your equipment. Maybe she'll be a bit more friendly the next time around.");
				flags[kFLAGS.ANNEMARIE_STATUS] = 1;
				doNext(camp.returnToCampUseOneHour);

			}else{
				outputText("You tighten your fist, ready to strike. [say: If you fire that, you better not miss. You won’t get a second shot.]");
				outputText("\n\nShe lets out a short laugh. [say: Thanks for the warning. Not going to.]");
				outputText("\n\nYou attempt to grab the barrel of the rifle and push it away before she can fire. To you own surprise, you're successful, but it proves to be pointless, as the girl had let go of the weapon. She instead picks a dark glass sphere from one of her pockets, filled with a bubbling liquid, and throws it on the floor.");
				outputText("\n\nBefore you can cover your eyes, the sphere cracks, the ambient oxygen reacting to the liquid and causing a massive burst of light that blinds you utterly. You then feel one hit of her rifle's stock to your chest and another to your head, causing you to quickly fall to the ground.");
				outputText("\n\nThe last words you hear before passing out is [say: Fuck. I need to relocate.]");
				doNext(encounter3wakeup);
			}
		}

		public function encounter3wakeup():void{
			clearOutput();
			outputText("You wake up to the feeling of an insect crawling over your face. You groan and lift yourself off the ground. You look around the cabin; it's completely empty. You'll probably not find the hostile girl again.");
			doNext(camp.returnToCampUseFourHours);

		}

		public function mysteriousStranger():void{
			outputText("\nBefore your opponent can react, you see a muzzle flash in the distance.");
			if (rand(9) < 8){
				outputText("\n\nA split second later, your opponent gets hit by something! A projectile pierces cleanly through " + monster.a + monster.short + ", bursting open a wound in a dramatic display and causing " + monster.pronoun2 + " to stagger from the enormous kinetic force.");
				combat.doDamage(monster.reduceDamage(150 + rand(150),player,50),true,true);
			}else{
				outputText("\n\nA split second later, the ground next to your opponent cracks and craters with a violent, smoking impact! Whatever just dashed past " + monster.pronoun2 + " would have caused grievous injury had it hit.");
			}
				outputText("\nYou then hear a tremendous booming sound, like a massive gun - or a cannon - being fired. You may just have a guardian angel watching out for you!\n\n");
		}
	}
}


code:
package classes.Scenes.Areas.Bog
{
	import classes.*;
	import classes.BodyParts.*;
	import classes.internals.*;
	import classes.GlobalFlags.kFLAGS;
	import classes.GlobalFlags.kGAMECLASS;
	import classes.StatusEffects.Combat.DeafeningBuzz;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFormat;
	public class Batgirl extends Monster
	{
		//1 - str
		//2 - tou
		//3 - spe
		//4 - sens
		public var fed:Boolean = false;
		public var dragonShoutUsed:Boolean = false;
		public var type:int = 0;
		public const imp:int = 1;
		public const demon:int = 2;
		public const mino:int = 3;
		public const salamander:int = 4;
		public const sheep:int = 5;
		public const dragon:int = 6;
		public const bimbo:int = 7;
		public const cat:int = 8;
		public const kitsune:int = 9;

		override protected function performCombatAction():void{
			var choices:Array;
			var actionChoices:MonsterAI = new MonsterAI()
				.add(eAttack,    30);
			setHP();
			if (player.hasStatusEffect(StatusEffects.IzmaBleed) && player.statusEffectv1(StatusEffects.IzmaBleed) >= 3 && !fed) actionChoices.add(theThirst, 40);
			if (fatigue <= 90 && hasFatigue(10,FATIGUE_PHYSICAL)) actionChoices.add(openVein, 40);
			if (!player.hasStatusEffect(StatusEffects.Deafeningbuzz) && hasFatigue(10,FATIGUE_PHYSICAL)) actionChoices.add(deafeningBuzz, 40);
			if (type == demon) actionChoices.add(energizedTease, 40);
			if (type == salamander && !hasStatusEffect(StatusEffects.Lustzerking)) actionChoices.add(lustzerk, 40);
			if (type == dragon && !dragonShoutUsed && hasFatigue(15,FATIGUE_MAGICAL)) actionChoices.add(dragonBreath, 40);
			if (type == kitsune && hasFatigue(15,FATIGUE_MAGICAL)) actionChoices.add(kitsuneFire, 40);
			if (type == bimbo) actionChoices.add(bimboTease, 40);

			actionChoices.exec();
		}

		public function deafeningBuzz():void{
			outputText("[Themonster] takes flight and dashes towards you with incredible speed! You prepare to counter and attack, but notice she's not aiming for you. Instead, she zooms to your side and unleashes a deafening screech!");
			if (rand(player.spe) < rand(spe)){
				outputText("\nShe continues to dash around you in circles, attempting to daze you with her screeches. You prove fast enough, however, and manage to catch her with an glancing blow from your [weapon]!");
				HPChange(-(15 + rand(15)), true);
			}else{
				outputText("\nDespite your best attempts to catch her, she continues to fly in circles around you. The screeching increases in intensity and frequency, and soon becomes absolutely deafening!\n She flies away, satisfied. You did not suffer any major damage, but this hellish noise will prevent you from focusing your spells for a while!");
				player.addStatusEffect(new DeafeningBuzz(3));
			}
			changeFatigue(10, FATIGUE_PHYSICAL);
		}

		public function kitsuneFire():void{
			outputText("Smiling mischievously, [themonster] lifts two fingers and kisses them softly, causing a pale blue flame to appear over them. She whips her arm back and throws the flame towards you!");
			var customOutput:Array = [
			"[BLIND]" + capitalA + short + " misses you, unable to aim properly due to her blindness.\n",
			"[SPEED]You're quick enough to dash away from the blue flames.\n",
			"[EVADE]Using your skills at evading attacks, you anticipate and sidestep " + a + short + "'s attack.\n",
			"[MISDIRECTION]Using Raphael's teachings and the movement afforded by your bodysuit, you anticipate and sidestep " + a + short + "'s attack.\n",
			"[FLEXIBILITY]With your incredible flexibility, you squeeze out of the way of the fireball, a bit too close for comfort.",
			"[UNHANDLED]You manage to dodge her fireball."];
			if (!playerAvoidDamage({doDodge:true, doParry:false, doBlock:false, doFatigue:false}, customOutput)){
				outputText("\nYou're hit by the magic fireball, suffering grievous burns!");
				player.takeDamage(inte + rand(50), true);
				outputText(" After the attack, you feel warmer and more sensitive. Your [genitals] twitch with need, teased by some magical force.");
				player.takeLustDamage(10 + rand(10));
			}
			changeFatigue(15, FATIGUE_MAGICAL);
		}

		private function setHP():void {
			this.HP = parseInt(game.mainView.nameBox.text);
		}

		public function dragonBreath():void{
			outputText("Your opponent dashes back, staying out of range for a moment. She inhales deeply, tightens her muscles, and whips herself forward as she opens her mouth, unleashing a massive wave of fire and force that scorches and cracks the earth!");
			outputText("\nThe sheer size and force of the attack makes any defense pointless, and you can only brace yourself and hope for the best!");
			if (player.stun(2, 50)){
				outputText("\nYou're hit in full by the fierce blast of fire, and the accompanying shockwave leaves you stunned");
			}else{
				outputText("\nYou're hit in full by the fierce blast of fire! Luckily, you manage to stand your ground and avoid being stunned by the shockwave.");
			}
			player.takeDamage(inte * 1.5 + player.reduceDamage(str * 1.5), true);
			dragonShoutUsed = true;
			changeFatigue(15, FATIGUE_MAGICAL);
		}

		public function lustzerk():void{
			outputText("[say: I don't understand... I don't want blood, I just want to fight! Fight you, fuck you, and then fight you again! Let's go! Now!] [Themonster] screams, entering a frenzy of lusty rage!");
			createStatusEffect(StatusEffects.Lustzerking, 0, 0, 0, 0);
		}

		public function bimboTease():void{
			outputText("It's pretty evident that the girl that was once focused in the fight and in your blood has other interests in mind now. She stops attacking, entranced by her own, heaving breasts. She brings a hand to her left breasts and squeezes it, teasing a moaning giggle out of her, while her other hand is busy feeling her newly acquired curves.");
			outputText("\nThe hand on her breast slides down to her thighs and then her crotch. She sticks a finger inside her drooling pussy and pulls it" +
					" out, marveling at the now copious lubrication she produces. She sucks her finger and giggles again, smiling lasciviously at you.");
			outputText("\nYou shake your head and attempt to focus on the fight. But part of you wonders... should you?");
			player.takeLustDamage(15 + rand(15));
			takeLustDamage(15 + rand(15));
		}

		public function morphStats():void{
			if (player.impScore() >= 5){
				this.lib += 15;
				this.cor += 15;
				this.lustVuln += 0.1;
				type = imp;
				this.skin.tone = "red";
				return;
			}
			if (player.demonScore() >= 5){
				this.cor += 20;
				this.lib += 15;
				this.bonusLust += 25;
				type = demon;
				this.skin.tone = "pale blue";
				return;
			}
			if (player.minoScore() >= 3 || player.cowScore() >= 3){
				this.lib += 10;
				this.tou += 20;
				this.str += 15;
				this.bonusHP += 300;
				this.HPChange(300,false);
				type = mino;
				this.horns.type = Horns.COW_MINOTAUR;
				this.horns.value = 12;
				this.tallness += 6;
				return;
			}
			if (player.catScore() >= 4){
				this.spe += 10;
				this.str -= 10;
				this.createPerk(PerkLib.Flexibility,0,0,0,0);
				type = cat;
				return;
			}
			if (player.kitsuneScore() >= 5){
				this.str -= 15;
				this.tou -= 10;
				this.inte += 25;
				type = kitsune;
				this.tail.type = Tail.FOX;
				this.tail.venom = 2;
				this.long += "\n\nAfter sucking your blood, [themonster] can't keep a mischievous smile from plastering her face. She seems to be planning some kind of trickery; one that will likely end with a lot of sex.";
				return;
			}
			if (player.dragonScore() >= 8){
				this.str += 15;
				this.tou += 15;
				this.spe += 15;
				this.inte += 15;
				type = dragon;
				this.long += "\n\nAfter sucking your blood, [themonster]'s pose has turned much more regal, her skin red with small patches of scales around her face. If she has absorbed some of the powers of your dragon blood, then she has become a fearsome enemy indeed!";
				this.skin.tone = "red";
				return;
			}
			if (player.bimboScore() >= 10){
				this.breastRows[0].breastRating = Appearance.breastCupInverse("H-cup");
				this.vaginas[0].vaginalWetness = Vagina.WETNESS_DROOLING;
				this.inte -= 20;
				this.lustVuln += 0.3;
				type = bimbo;
				this.long += "\n\nAfter sucking your blood, [themonster] has become much more voluptuous, and her vagina is positively drooling. This will likely be an easy fight, if you bother winning at all.";
				return;
			}
			if (player.salamanderScore() >= 4){
				this.str += 15;
				this.spe += 15;
				this.lib += 15;
				this.fatigue = 0;
				type = salamander;
				this.tallness += 5;
				this.skin.tone = "red";
				this.long += "\n\nAfter sucking your blood, [themonster]'s skin turned a fiery red, and she seems much more active and energetic. She'll probably be a tougher opponent if she inherited some of the salamander people's strength.";
				return;
			}
			if (player.sheepScore() >= 4){
				this.lustVuln -= 0.2;
				type = sheep;
				this.cor -= 20;
				this.lib -= 10;
				this.skin.furColor = "white";
				this.long += "\n\nAfter sucking your blood, [themonster]'s fur turned white, and much fluffier. She has likely inherited some of the innate purity of the sheep folk.";
				return;
			}

		}

		public function openVein():void {
			outputText("[Themonster] launches herself towards you at incredible speed, arms and teeth ready to tear into your flesh!\n\n");
			var customOutput:Array = [
			"[BLIND]" + capitalA + short + " misses you, unable to aim properly due to her blindness.\n",
			"[SPEED]You're quick enough to dash away from her attack, as fast as it was.\n",
			"[EVADE]Using your skills at evading attacks, you anticipate and sidestep " + a + short + "'s attack.\n",
			"[MISDIRECTION]Using Raphael's teachings and the movement afforded by your bodysuit, you anticipate and sidestep " + a + short + "'s attack.\n",
			"[FLEXIBILITY]With your incredible flexibility, you squeeze out of the way of " + a + short + "'s claws, suffering nothing but a harmless scratch.",
			"[BLOCK]You raise your shield in time and manage to meet her attacks!",
			"[UNHANDLED]You manage to dodge her claws."];
			if(!playerAvoidDamage({doDodge:true, doParry:false, doBlock:true, doFatigue:false}, customOutput)){
				//YOU GOT HIT SON
				outputText("You're too slow to react to her charge, and get hit several times by her claws!");
				if (player.bleed(this)){
					outputText(" Despite the frenzied nature of her moves, you notice she struck arteries and veins with surgical precision. You're bleeding!");
				}
				var damage:Number = player.reduceDamage(str / 2 + weaponAttack);
				player.takeDamage(damage, true);
			}
			changeFatigue(10, FATIGUE_PHYSICAL);

		}

		public function energizedTease():void{
			outputText("[say: I feel so alive! So energized! So sexy!] [Themonster] lifts her arms over her head, lifting her now perky breasts, covered by her wings. She slowly spreads her arms, revealing her boobs and hardening nipples, poking out and straining against the fabric of her tattered clothes." +
		    "\nBefore you can attack her, she flies away and returns to a combat stance, though her eyes are definitely filled with lust.\nYou can't help but be affected by her display.");
			player.takeLustDamage(10 + rand(20));
		}

		public function theThirst():void {
			outputText("[Themonster] quickly dashes out of your field of view! You turn and attempt to track her, but despite your best efforts, she has apparently disappeared.\n\n");
			outputText("Suddenly, you feel movement behind you. You turn around as fast as you can; she's preparing a sneak attack!");

			if (rand(player.spe+30) < rand(spe)){
				outputText("\nYou manage to turn around in time, and you see her just before you, mid pounce!\nYou attack before she finishes, and she uses her wings to change directions and avoid your attack.");
			}else{
				player.purgeBleed();
				outputText("You attempt to turn around, but it's too late; she lands on your back and attacks!");
				outputText("\nShe attacks in a flash, biting deep into your flesh with razor sharp teeth. You struggle, but the blood loss is too strong on your body. [say: Stop resisting, sweet blood. Lend yourself to us.] You're soon too weak to stand.");
				outputText("\nAfter a few seconds of feverish blood sucking, you regain enough strength to raise yourself and push her off. She jumps back, surprised at your endurance.");
				outputText("\n\n[say: Your blood is sweet, and energizing. We need more of you. Of your essence!]");
				outputText("\nYou notice the girl is now significantly more voluptuous, with a much more sensual and upright posture. She is no longer as agile, but she is much stronger and resilient!");
				fed = true;
				player.takeDamage(player.reduceDamage(str * 3), true);
				player.createStatusEffect(StatusEffects.MosquitoNumb, 30, 0, 0, 0);
				armorDef = 60;
				str = 80;
				this.hips.rating = Hips.RATING_CURVY;
				this.butt.rating = Hips.RATING_CURVY;
				morphStats();
				this.breastRows[0].breastRating = Appearance.breastCupInverse("DD-cup");
				removePerk(PerkLib.ExtraDodge);
			}

		}

		override public function defeated(hpVictory:Boolean):void
		{
			game.bog.lizanScene.winAgainstLizan();
		}

		override public function won(hpVictory:Boolean, pcCameWorms:Boolean = false):void
		{
			//40% chance of getting infected by the bog parasite if fully worms are on. 20% if worms are "half", none if worms are off, the player doesn't have a penis or if he's already infested by something.
			if (player.hasCock() && !player.hasStatusEffect(StatusEffects.ParasiteSlug) && player.findPerk(PerkLib.ParasiteMusk) < 0 && !player.hasStatusEffect(StatusEffects.Infested) && ((player.hasStatusEffect(StatusEffects.WormsOn) && rand(10) < 5)  || (player.hasStatusEffect(StatusEffects.WormsHalf) && rand(10) < 3))) {

				player.createStatusEffect(StatusEffects.ParasiteSlug, 72, 0, 0, 0);
			}
			game.bog.lizanScene.loseToLizan();
		}

		private var hairColors:Array = ["brown", "black", "blonde", "red"];

		public function Batgirl()
		{
			this.skin.tone = "light brown";
			this.a = "a ";
			this.short = "bat girl";
			this.imageName = "batgirl";
			this.hair.color = hairColors[rand(hairColors.length)];
			this.skin.furColor = "white and brown";
			this.long = "A pale female humanoid stands before you, covered in minimal, ragged gray clothes. She has a lithe, thin body, somewhat obscured by her long furry bat wings that stretch throughout her arms and fingers. Her torso is human and hairless, though her legs are digitigrade, furry mid-thigh and downwards.  You can't tell much about her face aside from the fact she has smooth, shoulder length " + hair.color+ " hair, large mouse-like ears and a patch of thick fur around her neck. She's covering most of her face with her wings and claws, positioned to attack at a moment's notice.";
			// this.plural = false;
			createBreastRow(Appearance.breastCupInverse("B-cup"));
			this.createVagina(false, Vagina.WETNESS_SLICK, Vagina.LOOSENESS_LOOSE);
			this.ass.analLooseness = Ass.LOOSENESS_TIGHT;
			this.ass.analWetness = Ass.WETNESS_MOIST;
			this.tallness = 55 + rand(10);
			this.hips.rating = Hips.RATING_AVERAGE;
			this.butt.rating = Butt.RATING_AVERAGE;
			this.skin.desc = "skin";
			this.hair.length = 20;
			initStrTouSpeInte(40, 70, 100, 55);
			initLibSensCor(20, 10, 50);
			this.weaponName = "claws";
			this.weaponVerb="claw";
			this.weaponAttack = 55;
			this.armorName = "tattered clothes";
			this.armorDef = 8;
			this.bonusHP = 350;
			this.lust = 20;
			this.lustVuln = .2;
			this.temperment = TEMPERMENT_LOVE_GRAPPLES;
			this.level = 16;
			this.gems = 10 + rand(50);
			this.drop = new WeightedDrop().add(consumables.REPTLUM, 5)
					.add(consumables.SMALL_EGGS, 2)
					.add(consumables.OVIELIX,2)
					.add(consumables.W_STICK,1);
			this.createPerk(PerkLib.Evade, 0, 0, 0, 0);
			this.createPerk(PerkLib.ExtraDodge, 25, 0, 0, 0);
			this.createPerk(PerkLib.AntiCoagulant, 0, 0, 0, 0);
			this.ears.type = Ears.MOUSE;
			this.wings.type = Wings.BAT_LIKE_LARGE;
			this.tail.type = Tail.MOUSE;
			checkMonster();
		}

	}

}


code:
/**
 * Created by aimozg on 03.01.14.
 */
package classes.Scenes.Areas.Bog
{
	import classes.*;
	import classes.GlobalFlags.kFLAGS;
	import classes.display.SpriteDb;
	import classes.internals.*;

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

		public function batDown():void{
			clearOutput();
			outputText("The bat girl falls to the sodden ground, too "+ monster.HP <= 0 ? "wounded":"aroused" +" to continue fighting. She hurriedly" +
					" attempts to reach flight and flee, but you quickly catch her and throw her to the ground again, ending on top of her. She still" +
					" attempts some meager resistance, but quickly gives up due to her weakness.\n\n" +
					"Her gaze dashes to meet your and then quickly to some point in the distance, back and forth, her breath and pulse extremely quick. It's" +
					" clear she's terrified of her current situation.");
			outputText("[say: Let me go, won't kill, just need blood, please?], she hastily says.");
			outputText("\nHer interest in your blood was quite evident from your fight. You ask her why she needs your blood so much.");
			outputText("\n[say: Blood is life! Your essence! She reads you blood, makes more life!] " +
					"\nYou tell her you're not in the mood for riddles, and she shouldn't be either, considering her situation. Her eyes widen immediately." +
					" [say: No riddle! No riddle! All I know!]");
			outputText("\n\nYou lighten your hold on her, and consider your options.");
			menu();
			addButton(0,"Let her go",letBatGo).hint("Let her go.");
			addButton(1,"Give blood",giveBatBlood).hint("Give her some of your blood, as painful as it might be.");
			addButton(2,"Trade",tradeBatBloodDick).hint("Get her to work for her blood in a fun way, for both of you.");

		}

		private function tradeBatBloodVagina():void{
            clearOutput();
            outputText("You tell her you're willing to give some of your blood, and her ears perk up, shifting towards you in surprise.\n\n" +
                    "[say: Yes! Good! Thanks!] she says, shuffling to leave your hold of her. You tighten a bit more and tell her you want a trade: Your" +
                    " blood for something everyone in Mareth wants. She narrows her eyebrows, thinking.\n\nShe thinks for a long time.\n\nWhen you're almost" +
                    " giving up, she perks up in an epiphany. [say: Oh! Sex!], she says, smiling.\n\n" +
                    " A moment of silence passes, the two of you just staring at each other. She then blushes and averts her gaze, suddenly aware of how close" +
                    " the two of you were through the whole exchange. You take the time to" +
                    " appreciate her form; The messy black hair partially covering her face, her surprisingly soft, pale skin, her delicate neck and" +
					" your gaze reaches her face again," +
                    " your eyes meet hers, and she no longer seems to be ashamed at all, her eyes inviting you to start.");
			outputText("\n\nYou lean in to grab her breasts, but are stopped by a sudden groping at your crotch. She gently pushes you off of her, and her" +
					" face turns inquisitive, curious.\n[say:" +
					" You... you don't have a dick!] She says, in a surprised way. [say: Or is it hidden?]" +
					"\n\nYou're surprised at how inexperienced she is, considering where she lives. You scratch your head and tell her that, yes, two girls <i>can</i> have sex. She kneels, both ears perking up and facing towards you," +
					" utterly curious over this new bit of information. ");
			outputText("\n\nYou lift a finger towards her ")
		}
        private function tradeBatBloodDick():void {
			clearOutput();
			outputText("You tell her you're willing to give some of your blood, and her ears perk up, shifting towards you in surprise.\n\n" +
					"[say: Yes! Good! Thanks!] she says, shuffling to leave your hold of her. You tighten a bit more and tell her you want a trade: Your" +
					" blood for something everyone in Mareth wants. She narrows her eyebrows, thinking.\n\nShe thinks for a long time.\n\nWhen you're almost" +
					" giving up, she perks up in an epiphany. [say: Oh! Sex!], she says, smiling.\n\n" +
					" A moment of silence passes, the two of you just staring at each other. She then blushes and averts her gaze, suddenly aware of how close" +
					" the two of you were through the whole exchange. You take the time to" +
					" appreciate her form; The messy black hair partially covering her face, her surprisingly soft, pale skin, her delicate neck and" +
					" collarbones, leading to perky c-cup breasts and softly defined abs, her breath slower down now that she's calmer. She's definitely" +
					" thinner than the" +
					" average marethian, but still retaining a feminine form.\n\nWhen your gaze reaches her face again," +
					" your eyes meet hers, and she no longer seems to be ashamed at all, her eyes inviting you to start.");
			outputText("\n\nYou stare at her body again and bring a hand to her hips, drawing a silent sigh from her lips. You slide your hand upwards and" +
					" cup one of her breasts, your fingers feeling her nipples slowly perking as you massage it.\nYou feel something poking around your" +
					" crotch; one of her feet, [if (isnakedlower) stroking your hardening [cock]|pushing your [armor] down to reveal your hardening [cock]]." +
					" She grabs your chest with both hands and pushes" +
					" down on your cock with her foot, guiding the head towards her now wet vagina. You smoothly push your hips forward, sliding your cock" +
					" on her labia, ever so slightly pushing it in, tasting her folds, teasing her.\n\n She moans, and you notice her hips pushing back" +
					" against yours.");
			outputText(" She continues to grind on your cock, twisting her hips sideways and covering it in her juices. You look at her again, and her" +
					" blushing, panting face shows you she's eager to be penetrated.\n\n" +
					" You pull yourself back a bit, a string of lube stretching from her engorged lips and your cock, her hips jerking reflexively," +
					" painfully deprived of its previous stimulation. You line up yourself against her pussy again and slide your cock inside, a long," +
					" soothing moan escaping her as you" +
					" spread her completely, her raised foot curling in pleasure and her nails lightly digging into your skin.\n\n You move your hand off" +
					" of her breast, and put both on the ground over her shoulders  for support. \nYou slowly slide your cock back, leaving only the head" +
					" inside, and swiftly push it back in, your thrust causing her perky breasts to bounce firmly. You pick up the pace, thrusting faster" +
					" and faster, her moans becoming more frequent and sharper as pleasure strikes her. She puts her raised leg down and squeezes her" +
					" thighs together, tightening the walls around her pussy so much you can't help but moan as well.\n\nHer hands slide up from your chest" +
					" towards your head, and she softly rotates your face to stare directly into hers. Her striking ember eyes, blushing and panting face" +
					" and bouncing breasts rouse more lust within you, and you thrust faster, making her close her eyes and bite her lips."+
					" Overwhelmed by lust, she pulls your face towards her bosom, and you instinctively bite on one of her perky nipples, her desperate" +
					" moan voiced directly in your ears. You continue to thrust as you tease her breasts, her pussy clenching tightly around your" +
					" member every time you hilt yourself on her, begging for your cum.\n\nIt soon" +
					" becomes too much for you to bear, and you thrust one final time, fully pushing yourself and climaxing inside her. She raises her" +
					" legs again" +
					" and puts them" +
					" around you, locking her hips against yours as she reaches her own orgasm, squirting on your crotch and milking your cock with several" +
					" powerful clenches. She fully hugs you and keeps your head between her breasts, her wings spreading and covering your upper body," +
					" isolating your senses from the outside world.\n\nWithin her wings, you can only feel" +
					" her heat and can only hear her husky breath. It's suffocating, but wonderful. Your arms fail you, and you gently fall on top of her," +
					" your [cock] spurting a few last drops of cum as you lay your head on her shoulder.");
			outputText("\n\nThe last thing you feel before falling intro a deep sleep is a sharp bite on your neck.");
			player.orgasm('dick');
			doNext(camp.returnToCampUseOneHour);
        }

        private function giveBatBlood():void {

        }

        private function letBatGo():void {

        }
	}
}


code:
package classes.Scenes.Areas.Bog
{
	import classes.saves.SelfSaver;

	public class BogTemple extends BaseContent implements SelfSaving {

		public var saveContent:Object = {

		};

		public function get saveName():String {
			return "bogtemple";
		}

		public function get saveVersion():int {
			return 1;
		}

		public function load(version:int, saveObject:Object):void {
			for (var property:String in saveContent) {
				if (saveObject.hasOwnProperty(property)) saveContent[property] = saveObject[property];
			}
		}

		public function reset():void {
		}

		public function onAscend(reset:Boolean):void {
		}

		public function saveToObject():Object {
			return saveContent;
		}

		public function loadFromObject(o:Object, ignoreErrors:Boolean):void {}

		public function BogTemple() {
		}

		public function templeFirstTime():void {

		}
		public function templeFirstEnter():void {

		}
		public function templeFirstLeave():void {

		}
	}

}


code:
package classes.Scenes.Areas.Bog
{
	import classes.*;
	import classes.BodyParts.*;
	import classes.display.SpriteDb;
	import classes.internals.*;

	public class ChameleonGirl extends Monster
	{

		public function chameleonTongueAttack():void
		{
			this.weaponName = "tongue";
			this.weaponVerb = "tongue-slap";
			this.weaponAttack = 10;
			createStatusEffect(StatusEffects.Attacks, 1, 0, 0, 0);
			eAttack();
			this.weaponAttack = 30;
			this.weaponName = "claws";
			this.weaponVerb = "claw";
		}

		//Ignores armor
		public function chameleonClaws():void
		{
			//Blind dodge change
			if (hasStatusEffect(StatusEffects.Blind) && rand(3) < 1) {
				outputText(capitalA + short + " completely misses you with a blind claw-attack!\n");
			}
			//Evade:
			else if (!combatAvoidDamage({doDodge:true, doParry:false, doBlock:false}).failed) outputText("The chameleon girl's claws slash towards you, but you lean away from them and they fly by in a harmless blur.");
			//Get hit
			else {
				var damage:Number = player.reduceDamage(str + weaponAttack,this);
				if (damage > 0) {

					outputText("The chameleon swings her arm at you, catching you with her claws.  You wince as they scratch your skin, leaving thin cuts in their wake. ");
					damage = player.takeDamage(damage, true);
				}
				else outputText("The chameleon swings her arm at you, catching you with her claws.  You defend against the razor sharp attack.");
			}

		}

		//Attack 3:
		public function rollKickClawWhatTheFuckComboIsThisShit():void
		{
			//Blind dodge change
			if (hasStatusEffect(StatusEffects.Blind) && rand(3) < 1) {
				outputText(capitalA + short + " completely misses you with a blind roll-kick!\n");
			}
			//Evade:
			else if (!combatAvoidDamage({doDodge:true, doParry:false, doBlock:false}).failed) {
				var damage2:Number = 1 + rand(10);
				outputText("The chameleon girl leaps in your direction, rolls, and kicks at you.  You sidestep her flying charge and give her a push from below to ensure she lands face-first in the bog. ");
				damage2 = game.combat.doDamage(damage2, true);
				outputText("(" + damage2 + ")");
			}
			//Get hit
			else {
				var damage:Number = player.reduceDamage(str + weaponAttack,this) + 25;
				if (damage > 0) {

					outputText("The chameleon leaps in your direction, rolls, and kicks you square in the shoulder as she ascends, sending you reeling.  You grunt in pain as a set of sharp claws rake across your chest. ");
					damage = player.takeDamage(damage, true);
				}
				else outputText("The chameleon rolls in your direction and kicks up at your chest, but you knock her aside without taking any damage..");
			}

		}

		override protected function performCombatAction():void
		{
			game.spriteSelect(SpriteDb.s_chameleon);
			var actionChoices:MonsterAI = new MonsterAI()
				.add(chameleonClaws, 30,true,0,FATIGUE_NONE,RANGE_MELEE);
			actionChoices.add(rollKickClawWhatTheFuckComboIsThisShit,10,true,0,FATIGUE_NONE,RANGE_MELEE);
			actionChoices.add(chameleonTongueAttack,10,true,0,FATIGUE_NONE,RANGE_RANGED);
			actionChoices.exec();
		}

		override public function defeated(hpVictory:Boolean):void
		{
			game.bog.chameleonGirlScene.defeatChameleonGirl();
		}

		override public function won(hpVictory:Boolean, pcCameWorms:Boolean = false):void
		{
			//40% chance of getting infected by the bog parasite if fully worms are on. 20% if worms are "half", none if worms are off, the player doesn't have a penis or if he's already infested by something.
			if (player.hasCock() && !player.hasStatusEffect(StatusEffects.ParasiteSlug) && player.findPerk(PerkLib.ParasiteMusk) < 0 && !player.hasStatusEffect(StatusEffects.Infested) && ((player.hasStatusEffect(StatusEffects.WormsOn) && rand(10) < 5)  || (player.hasStatusEffect(StatusEffects.WormsHalf) && rand(10) < 3))) {

				player.createStatusEffect(StatusEffects.ParasiteSlug, 72, 0, 0, 0);
			}
			if (pcCameWorms) {
				outputText("\n\nThe chameleon girl recoils.  \"Ew, gross!\" she screeches as she runs away, leaving you to recover from your defeat alone.");
				game.combat.cleanupAfterCombat();
			} else {
				game.bog.chameleonGirlScene.loseToChameleonGirl();
			}
		}

		override protected function outputPlayerDodged(dodge:int):void
		{
			outputText("The chameleon girl whips her head and sends her tongue flying at you, but you hop to the side and manage to avoid it.  The pink blur flies back into her mouth as quickly as it came at you, and she looks more than a bit angry that she didn't find her target.\n");
		}

		override public function outputAttack(damage:int):void
		{
			if (damage <= 0) {
				outputText("The Chameleon Girl lashes out with her tongue, but you deflect the sticky projectile off your arm, successfully defending against it.  She doesn't look happy about it when she slurps the muscle back into her mouth.");
			} else {
				outputText("The chameleon whips her head forward and sends her tongue flying at you.  It catches you in the gut, the incredible force behind it staggering you.  The pink blur flies back into her mouth as quickly as it came at you, and she laughs mockingly as you recover your footing. (" + damage + ")");
			}
		}

		/**
		 * Pairs of skinTone/skinAdj
		 */
		private const SKIN_VARIATIONS:Array = [
			["red", "black"],
			["green", "yellowish"],
			["blue", "lighter blue"],
			["purple", "bright yellow"],
			["orange", "brown"],
			["tan", "white"]
		];

		public function ChameleonGirl()
		{
			var skinToneAdj:Array = randomChoice(SKIN_VARIATIONS);
			this.a = "the ";
			this.short = "chameleon girl";
			this.imageName = "chameleongirl";
			this.long = "You're faced with a tall lizard-like girl with smooth " + skinToneAdj[0] + " skin and long, " + skinToneAdj[1] + " stripes that run along her body from ankle to shoulder.  An abnormally large tail swishes behind her, and her hands are massive for her frame, built for easily climbing the trees.  A pair of small, cute horns grow from her temples, and a pair of perky B-cups push out through her skimpy drapings.  Large, sharp claws cap her fingers, gesturing menacingly at you.";
			this.race = "Chameleon-Morph";
			// this.plural = false;
			this.createVagina(false, Vagina.WETNESS_SLAVERING, Vagina.LOOSENESS_LOOSE);
			createBreastRow(Appearance.breastCupInverse("B"));
			this.ass.analLooseness = Ass.LOOSENESS_NORMAL;
			this.ass.analWetness = Ass.WETNESS_DRY;
			this.tallness = rand(2) + 68;
			this.hips.rating = Hips.RATING_AMPLE + 2;
			this.butt.rating = Butt.RATING_LARGE;
			this.skin.tone = skinToneAdj[0];
			this.skin.type = Skin.PLAIN;
			this.skin.desc = "skin";
			this.skin.adj = skinToneAdj[1];
			this.hair.color = "black";
			this.hair.length = 15;
			initStrTouSpeInte(65, 65, 95, 85);
			initLibSensCor(50, 45, 50);
			this.weaponName = "claws";
			this.weaponVerb="claw";
			this.weaponAttack = 30;
			this.armorName = "skin";
			this.armorDef = 20;
			this.bonusHP = 350;
			this.lust = 30;
			this.lustVuln = .25;
			this.temperment = TEMPERMENT_LOVE_GRAPPLES;
			this.level = 14;
			this.gems = 10 + rand(50);
			this.drop = NO_DROP;
			checkMonster();
		}

	}

}