code:
import classes.FetishManager;
import classes.Scenes.Achievements;
import coc.view.CoCButton;
import coc.view.MainView;
import flash.display.Stage;
import flash.display.StageQuality;
import flash.text.TextField;
import flash.text.TextFormat;

//MainMenu - kicks player out to the main menu
public function mainMenu(e:MouseEvent = undefined):void
{
	stage.focus = (mainView as MainView).mainText;

	if (CONFIG::debug)
	{
		CoC_Settings.debugBuild = true;
	}
	else
	{
		CoC_Settings.debugBuild = false;
	}

	if (mainView.aCb.parent != null)
	{
		mainView.removeChild(mainView.aCb);
	}
	mainViewManager.registerShiftKeys();
	mainView.eventTestInput.x = -10207.5;
	mainView.eventTestInput.y = -1055.1;
	hideStats();
	mainView.background.gotoAndStop(flags[kFLAGS.BACKGROUND_STYLE] + 1);
	mainView.sideBarBG.gotoAndStop(flags[kFLAGS.BACKGROUND_STYLE] + 1);
	mainViewManager.startUpButtons();
	kGAMECLASS.saves.loadPermObject();
	mainViewManager.setTheme();
	//Reset newgame buttons
	mainView.setMenuButton(MainView.MENU_NEW_MAIN, "New Game", charCreation.newGameFromScratch);
	mainView.hideAllMenuButtons();
	mainView.showMenuButton(MainView.MENU_NEW_MAIN);
	mainView.showMenuButton(MainView.MENU_DATA);

	mainView.newGameButton.toolTipText = "Start a new game.";
	mainView.dataButton.toolTipHeader = "New Game";
	mainView.dataButton.toolTipText = "Save or load your files.";
	mainView.dataButton.toolTipHeader = "Data";
	mainView.statsButton.toolTipText = "View your stats.";
	mainView.statsButton.toolTipHeader = "Stats";
	mainView.perksButton.toolTipText = "View your perks.";
	mainView.perksButton.toolTipHeader = "Perks";
	mainView.appearanceButton.toolTipText = "View your appearance.";
	mainView.appearanceButton.toolTipHeader = "Appearance";
	//Sets game state to 3, used for determining back functionality of save/load menu.
	_gameState = 3;
	clearOutput();
	//outputText("\n");
	outputText("Corruption of Champions (" + version + ")", false);

	if (CoC_Settings.debugBuild)
		outputText(" Debug Build");
	else
		outputText(" Release Build");
	//doThatTestingThang();

	startupScreenBody();

	var resume:Function = null;
	if (player.str > 0)  //we're in a game, allow resume.
		resume = playerMenu;

	var achievements:Achievements = new Achievements();

	// I really wanted to only have the "imageCreditsScreen" button if images were found, but it turns out
	// that if you check if any images were found immediately when this screen is shown, you get 0
	// since the images haven't loaded yet.
	// Therefore, the imageCreditScreen will just have to say "No image pack" if you don't have any images

	menu();
	if (resume != null) addButton(0, "Resume", resume, null, null, null, "Get back to gameplay?");
	else addButtonDisabled(0, "Resume", "Please start or load a game first.");
	addButton(1, "Settings", settingsScreenMain, null, null, null, "Configure game settings and enable cheats.");
	addButton(2, "Instructions", howToPlay, null, null, null, "How to play.  Starting tips.  And hotkeys for easy left-handed play...");
	addButton(3, "Achievements", achievements.achievementsScreen, null, null, null, "View all achievements you have unlocked so far.");
	addButton(4, "Mod Thread", openURL, "http://fenoxo.com/forum/index.php?/topic/5-coc-revamp-mod", null, null, "Check the official mod thread on Fenoxo's forum.");

	addButton(5, "Credits", creditsScreen, null, null, null, "See a list of all the cool people who have contributed to content for this game!");
	addButton(6, "Image Credits", imageCreditsScreen, null, null, null, "Check out who contributed to the image pack.");
	addButton(7, "Debug Info", debugPane, null, null, null, "View debug information. You can also input to access any scenes, if you know the function names!");
	addButton(9, "Harambe", openURL, "https://8ch.net/hgg/catalog.html", null, null, "/hgg/ offical source for degenerate mod.");
}

public function startupScreenBody():void
{

	// NO FUCKING DECENT MULTI-LINE STRING LITERALS BECAUSE FUCKING STUPID
	// WTF ACTIONSCRIPT YOUR DEV'S ARE ON CRACK
	// Fixed. No more markdown. :)
	outputText("\n(Formerly Unnamed Text Game)");
	//Brief credits
	outputText("\n\nCreated by: Fenoxo"); //The Original Creator
	outputText("\n\nEdited by: "); //Edited By
	outputText("\n\tAshi, SoS, Prisoner416, Zeikfried, et al");
	outputText("\n\nOpen-source contributions by: "); //Contributions
	outputText("\n\taimozg, Amygdala, Cmacleod42, Enterprise2001, Fake-Name, Gedan, Yoffy, et al");
	outputText("\n\nGame Mod by: Kitteh6660"); //Mod Creator
	outputText("\n\nTailored for /hgg/ by: CoCanon, now with tripcodes!");//Anon
	outputText("\n\nHelspawn content by: EllaKreal");
	//Github for Original
	outputText("\n\nOriginal Game Github");
	outputText("\nSource Code: https://github.com/herp-a-derp/Corruption-of-Champions");
	outputText("\nBug Tracker: https://github.com/herp-a-derp/Corruption-of-Champions/issues");
	outputText("\n(requires an account, unfortunately)");
	//Github for Mod
	outputText("\n\nModded Game Github");
	outputText("\nSource Code: https://github.com/Kitteh6660/Corruption-of-Champions");
	outputText("\nBug Tracker: https://github.com/Kitteh6660/Corruption-of-Champions/issues");
	outputText("\n(requires an account too, unfortunately)");
	//Disclaimer
	outputText("\n\nDISCLAIMER");
	outputText("
There are many strange and odd fetishes contained in this flash, especially in this version.  Peruse at own risk.
");
	outputText("
Please be 18 or the legal age to view porn before playing. If not, enable SFW Mode.
");
	outputText("
Try to keep your keyboard clean.  Think of the children!
");
	outputText("
Abandon all hope he who contributes to this code, for I have awoken something I couldn't put to sleep
");
	//Other Info
	outputText("\n\nFor more information see Fenoxo's Blog at fenoxo.com. ")
	outputText("\n\nCheck out Trials in Tainted Space as well!");
	outputText("\n\nAlso go play Nimin by Xadera on furaffinity.");
	outputText("\n\nSee thread on /hgg/ (or make one) for sugestions and complains about the changes CoCanon made.");

	if (debug)
		outputText("\n\nDEBUG MODE ENABLED: ITEMS WILL NOT BE CONSUMED BY USE.");
	if (flags[kFLAGS.SHOW_SPRITES_FLAG])
		outputText("\n\nSprites disabled.");
	if (flags[kFLAGS.EASY_MODE_ENABLE_FLAG])
		outputText("\n\nEasy Mode On: Bad-ends can be ignored.");
	if (flags[kFLAGS.SILLY_MODE_ENABLE_FLAG])
		outputText("\n\nSILLY MODE ENGAGED: Crazy, nonsensical, and possibly hilarious things may occur.");
	if (flags[kFLAGS.ITS_EVERY_DAY])
		outputText("\n\nEternal holiday enabled.");
	if (plains.bunnyGirl.isItEaster())
		outputText("\n\nIt's Easter! Enjoy the eggs!");
	if (valentines.isItValentine())
		outputText("\n\nIt's Valentine's!");
	if (helFollower.isHeliaBirthday())
		outputText("\n\nIt's Helia's Birthday Month!");

}

public function settingsScreenMain():void
{
	saves.savePermObject(false);
	mainView.showMenuButton(MainView.MENU_NEW_MAIN);
	mainView.showMenuButton(MainView.MENU_DATA);
	clearOutput();
	displayHeader("Settings");
	outputText("Here, you can adjust the gameplay and interface settings. Setting flags are saved in a special file so you don't have to re-adjust it each time you load a save file.");
	menu();
	addButton(0, "Gameplay", settingsScreenGameSettings);
	addButton(1, "Interface", settingsScreenInterfaceSettings);
	addButton(3, "Font Size", fontSettingsMenu);
	addButton(4, "Controls", displayControls);

	addButton(14, "Back", mainMenu);

	if (flags[kFLAGS.HARDCORE_MODE] > 0)
	{
		debug = false;
		flags[kFLAGS.EASY_MODE_ENABLE_FLAG] = 0;
		flags[kFLAGS.HYPER_HAPPY] = 0;
		flags[kFLAGS.LOW_STANDARDS_FOR_ALL] = 0;
	}
}

//------------
// GAMEPLAY
//------------
public function settingsScreenGameSettings():void {
	clearOutput();
	displayHeader("Gameplay Settings");

	if (flags[kFLAGS.HARDCORE_MODE] > 0) outputText("Hardcore mode is enabled. Cheats are disabled.\n\n");

	if (debug)
		outputText("Debug Mode: ON\n Items will not be consumed by use, fleeing always succeeds, and bad-ends can be ignored.");
	else
		outputText("Debug Mode: OFF\n Items consumption will occur as normal.");

	outputText("\n\n");
	if (flags[kFLAGS.GAME_DIFFICULTY] <= 0)
	{
		if (flags[kFLAGS.EASY_MODE_ENABLE_FLAG]) outputText("Difficulty: Easy\n Combat is easier and bad-ends can be ignored.");
		else outputText("Difficulty: Normal\n No opponent stats modifiers. You can resume from bad-ends with penalties.");
	}
	else if (flags[kFLAGS.GAME_DIFFICULTY] == 1)
	{
		outputText("Difficulty: Hard\n Opponent has 25% more HP and does 15% more damage. Bad-ends can ruin your game.");
	}
	else if (flags[kFLAGS.GAME_DIFFICULTY] == 2)
	{
		outputText("Difficulty: Nightmare\n Opponent has 50% more HP and does 30% more damage.");
	}
	else if (flags[kFLAGS.GAME_DIFFICULTY] >= 3)
	{
		outputText("Difficulty: Extreme\n Opponent has 100% more HP and does more 50% damage.");
	}

	/*if (flags[kFLAGS.EASY_MODE_ENABLE_FLAG])
		outputText("Easy Mode: ON\n Bad-ends can be ignored and combat is easier.");
	else
		outputText("Easy Mode: OFF\n Bad-ends can ruin your game and combat is challenging.");

	outputText("\n\n");*/
	outputText("\n\n");
	if (flags[kFLAGS.SILLY_MODE_ENABLE_FLAG])
		outputText("Silly Mode: ON\n Crazy, nonsensical, and possibly hilarious things may occur.");
	else
		outputText("Silly Mode: OFF\n You're an incorrigable stick-in-the-mud with no sense of humor.");

	outputText("\n\n");
	outputText("The following flags are not fully implemented yet (e.g. they don't apply in all cases where they could be relevant).\n");
	outputText("Additional note: You must be in a game session (e.g. load your save, hit \"Main Menu\", change the flag settings, and then hit \"Resume\") to change these flags. They're saved into the saveGame file, so if you load a save, it will clear them to the state in that save.");
	outputText("\n\n");

	if (flags[kFLAGS.LOW_STANDARDS_FOR_ALL])
	{
		outputText("Low standards Mode: ON\n NPCs ignore body type preferences.");
		outputText("\n (Not gender preferences though. You still need the right hole.)");
	}
	else
		outputText("Low standards Mode: OFF\n NPCs have body-type preferences.");

	outputText("\n\n");

	if (flags[kFLAGS.HYPER_HAPPY])
	{
		outputText("Hyper Happy Mode: ON\n Only reducto and humus shrink endowments.");
		outputText("\n Incubus draft doesn't affect breasts, and succubi milk doesn't affect cocks.")
	}
	else
		outputText("Hyper Happy Mode: OFF\n Male enhancement potions shrink female endowments, and vice versa.");

	outputText("\n\n");

	if (flags[kFLAGS.SFW_MODE] >= 1)
	{
		outputText("SFW Mode: ON\n Sex scenes are disabled and adult materials are hidden.");
	}
	else
		outputText("SFW Mode: OFF\n Sex scenes are enabled.");

	outputText("\n\n");

	if (flags[kFLAGS.WATERSPORTS_ENABLED] >= 1 && flags[kFLAGS.SFW_MODE] <= 0)
	{
		outputText("Watersports: Enabled\n Watersports scenes are enabled. (You kinky person)");
	}
	else
		outputText("Watersports: Disabled\n Watersports scenes are disabled.");

	outputText("\n\n");

	if (flags[kFLAGS.AUTO_LEVEL] >= 1)
	{
		outputText("Automatic Leveling: ON\n Leveling up is done automatically once you accumulate enough experience.");
	}
	else
		outputText("Automatic Leveling: OFF\n Leveling up is done manually.");

	menu();
	addButton(0, "Toggle Debug", toggleDebug, null, null, null, "Turn on debug mode. Debug mode is intended for testing purposes but can be thought of as a cheat mode.  Items are infinite and combat is easy to escape from.  Weirdness and bugs are to be expected.");
	if (player.str > 0)
		addButton(1, "Difficulty", difficultySelectionMenu, null, null, null, "Adjust the game difficulty to make it easier or harder.");
	else
		addButtonDisabled(1, "Difficulty", "Please start a game session before you can use this.");
	addButton(2, "Silly Toggle", toggleSillyFlag, null, null, null, "Toggles silly mode. Funny, crazy and nonsensical scenes may occur if enabled.");
	addButton(3, "Low Standards", toggleStandards);
	addButton(4, "Hyper Happy", toggleHyperHappy);

	addButton(5, "SFW Toggle", toggleSFW, null, null, null, "Toggles SFW Mode. If enabled, sex scenes are hidden and all adult materials are censored. \n\nCurrently under development, only disables most sex scenes. Soon, it'll disable rape scenes."); //Softcore Mode
	addButton(6, "Auto level", toggleAutoLevel, null, null, null, "Toggles automatic leveling when you accumulate sufficient experience.");
	if (player.str > 0) addButton(8, "Enable Surv", enableSurvivalPrompt, null, null, null, "Enable Survival mode. This will enable hunger. \n\nNote: This is permanent and cannot be turned off!", "Enable Survival Mode");
	if (player.str > 0) addButton(9, "Enable Real", enableRealisticPrompt, null, null, null, "Enable Realistic mode. This will make the game a bit realistic. \n\nNote: This is permanent and cannot be turned off! Do not turn this on if you have hyper endowments.", "Enable Realistic Mode");
	addButton(10, "Fetishes", fetishSubMenu, null, null, null, "Toggle some of the weird fetishes such as watersports and worms.");

	if (flags[kFLAGS.HUNGER_ENABLED] >= 0.5)
	{
		addButtonDisabled(8, "Enable Surv", "This is already enabled.", "Enable Survival Mode");
	}
	if (flags[kFLAGS.HUNGER_ENABLED] >= 1)
	{
		addButtonDisabled(9, "Enable Real", "This is already enabled.", "Enable Realistic Mode");
	}
	if (flags[kFLAGS.HARDCORE_MODE] > 0)
	{
		addButtonDisabled(0, "Debug", "You cannot enable debug in Hardcore Mode. No cheating!");
		addButtonDisabled(1, "Difficulty", "You cannot change difficulty in Hardcore Mode.");
		addButtonDisabled(3, "Low Standards", "You cannot enable Low Standards in Hardcore Mode.");
		addButtonDisabled(4, "Hyper Happy", "You cannot enable Hyper Happy in Hardcore Mode.");
		debug = false;
		flags[kFLAGS.EASY_MODE_ENABLE_FLAG] = 0;
		flags[kFLAGS.HYPER_HAPPY] = 0;
		flags[kFLAGS.LOW_STANDARDS_FOR_ALL] = 0;
	}
	addButton(14, "Back", settingsScreenMain);
}

public function toggleDebug():void
{
	//toggle debug
	if (debug)
		debug = false;
	else
		debug = true;

	mainView.showMenuButton(MainView.MENU_DATA);
	settingsScreenGameSettings();
	return;
}

public function difficultySelectionMenu():void {
	clearOutput();
	outputText("You can choose a difficulty to set how hard battles will be.\n");
	outputText("\nEasy: -50% damage, can ignore bad-ends.");
	outputText("\nNormal: No stats changes.");
	outputText("\nHard: +25% HP, +15% damage.");
	outputText("\nNightmare: +50% HP, +30% damage.");
	outputText("\nExtreme: +100% HP, +50% damage.");
	//outputText("\nUp to Eleven: +150% HP, +75% damage. This is the most cruel difficulty of all.");
	menu();
	addButton(0, "Easy", chooseDifficulty, -1);
	addButton(1, "Normal", chooseDifficulty, 0);
	addButton(2, "Hard", chooseDifficulty, 1);
	addButton(3, "Nightmare", chooseDifficulty, 2);
	addButton(4, "EXTREME", chooseDifficulty, 3);
	addButton(5, "Ascension settings", ascensionSettingsMenu,null,null,null);
	addButton(14, "Back", settingsScreenGameSettings);
}

public function ascensionSettingsMenu():void {
	clearOutput();
	outputText("You can choose whether Ascension resets your character or not.\n");
	menu();
	addButton(0, "Reset", chooseAscension, 1);
	addButton(1, "Don't reset", chooseAscension, 0);

}

public function chooseAscension(mode:int = 0):void{
	flags[kFLAGS.ASCENSION_MODE] = mode;
	settingsScreenGameSettings();
}

public function chooseDifficulty(difficulty:int = 0):void {
	if (difficulty <= -1) {
		flags[kFLAGS.EASY_MODE_ENABLE_FLAG] = 1;
		flags[kFLAGS.GAME_DIFFICULTY] = 0;
	}
	else {
		flags[kFLAGS.EASY_MODE_ENABLE_FLAG] = 0;
		flags[kFLAGS.GAME_DIFFICULTY] = difficulty;
	}
	settingsScreenGameSettings();
}

//Not used anymore as there's difficulty settings.
/*public function toggleEasyModeFlag():void
{
	//toggle easy mode
	if (flags[kFLAGS.EASY_MODE_ENABLE_FLAG] == 0)
		flags[kFLAGS.EASY_MODE_ENABLE_FLAG] = 1;
	else
		flags[kFLAGS.EASY_MODE_ENABLE_FLAG] = 0;
	mainView.showMenuButton(MainView.MENU_DATA);
	settingsScreenGameSettings();
	return;
}*/

public function toggleSillyFlag():void
{
	//toggle silly mode
	if (flags[kFLAGS.SILLY_MODE_ENABLE_FLAG])
		flags[kFLAGS.SILLY_MODE_ENABLE_FLAG] = false;
	else
		flags[kFLAGS.SILLY_MODE_ENABLE_FLAG] = true;
	settingsScreenGameSettings();
	return;

}

public function toggleStandards():void
{
	//toggle low standards
	if (flags[kFLAGS.LOW_STANDARDS_FOR_ALL])
		flags[kFLAGS.LOW_STANDARDS_FOR_ALL] = false;
	else
		flags[kFLAGS.LOW_STANDARDS_FOR_ALL] = true;
	settingsScreenGameSettings();
	return;
}

public function toggleHyperHappy():void
{
	//toggle hyper happy
	if (flags[kFLAGS.HYPER_HAPPY])
		flags[kFLAGS.HYPER_HAPPY] = false;
	else
		flags[kFLAGS.HYPER_HAPPY] = true;
	settingsScreenGameSettings();
	return;
}

public function toggleSFW():void {
	if (flags[kFLAGS.SFW_MODE] < 1) flags[kFLAGS.SFW_MODE] = 1;
	else flags[kFLAGS.SFW_MODE] = 0;
	settingsScreenGameSettings();
}

public function toggleWatersports():void {
	if (flags[kFLAGS.WATERSPORTS_ENABLED] < 1) flags[kFLAGS.WATERSPORTS_ENABLED] = 1;
	else flags[kFLAGS.WATERSPORTS_ENABLED] = 0;
	settingsScreenGameSettings();
}

public function toggleAutoLevel():void {
	if (flags[kFLAGS.AUTO_LEVEL] < 1) flags[kFLAGS.AUTO_LEVEL] = 1;
	else flags[kFLAGS.AUTO_LEVEL] = 0;
	settingsScreenGameSettings();
}

public function fetishSubMenu():void {
	menu();
	addButton(0, "Watersports", toggleWatersports, null, null, null, "Toggles watersports scenes. (Scenes related to urine fetish)"); //Enables watersports.
	if (player.findStatusEffect(StatusEffects.WormsOn) >= 0 || player.findStatusEffect(StatusEffects.WormsOff) >= 0) addButton(1, "Worms", toggleWormsMenu, null, null, null, "Enable or disable worms. This will NOT cure infestation, if you have any.");
	else addButtonDisabled(1, "Worms", "Find the sign depicting the worms in the mountains to unlock this.");
	addButton(4, "Back", settingsScreenGameSettings);
}

private function toggleWormsMenu():void {
	clearOutput();
	if (player.findStatusEffect(StatusEffects.WormsOn) >= 0) {
		outputText("You have chosen to encounter worms as you find the mountains");
		if (player.findStatusEffect(StatusEffects.WormsHalf) >= 0) outputText(" albeit at reduced encounter rate");
		outputText(". You can get infested.");
	}
	if (player.findStatusEffect(StatusEffects.WormsOff) >= 0) {
		outputText("You have chosen to avoid worms. You won't be able to get infested.");
	}
	menu();
	addButton(0, "Enable", setWorms, true, false);
	addButton(1, "Enable (Half)", setWorms, true, true);
	addButton(2, "Disable", setWorms, false, false);
	addButton(4, "Back", fetishSubMenu);
}

private function setWorms(enabled:Boolean, half:Boolean):void {
	//Clear status effects
	if (player.findStatusEffect(StatusEffects.WormsOn) >= 0) player.removeStatusEffect(StatusEffects.WormsOn);
	if (player.findStatusEffect(StatusEffects.WormsHalf) >= 0) player.removeStatusEffect(StatusEffects.WormsHalf);
	if (player.findStatusEffect(StatusEffects.WormsOff) >= 0) player.removeStatusEffect(StatusEffects.WormsOff);
	//Set status effects
	if (enabled) {
		player.createStatusEffect(StatusEffects.WormsOn, 0, 0, 0, 0);
		if (half) player.createStatusEffect(StatusEffects.WormsHalf, 0, 0, 0, 0);
	}
	else {
		player.createStatusEffect(StatusEffects.WormsOff, 0, 0, 0, 0);
	}
	toggleWormsMenu();
}

//Survival Mode
public function enableSurvivalPrompt():void {
	outputText("Are you sure you want to enable Survival Mode?\n\n", true)
	outputText("You will NOT be able to turn it off! (Unless you reload immediately.)")
	doYesNo(enableSurvivalForReal, settingsScreenGameSettings);
}

public function enableSurvivalForReal():void {
	outputText("Survival mode is now enabled.", true)
	player.hunger = 80;
	flags[kFLAGS.HUNGER_ENABLED] = 0.5;
	doNext(settingsScreenGameSettings);
}

//Realistic Mode
public function enableRealisticPrompt():void {
	outputText("Are you sure you want to enable Realistic Mode?\n\n", true)
	outputText("You will NOT be able to turn it off! (Unless you reload immediately.)")
	doYesNo(enableRealisticForReal, settingsScreenGameSettings);
}

public function enableRealisticForReal():void {
	outputText("Realistic mode is now enabled.", true)
	flags[kFLAGS.HUNGER_ENABLED] = 1;
	doNext(settingsScreenGameSettings);
}

//------------
// INTERFACE
//------------
public function settingsScreenInterfaceSettings():void {
	clearOutput();
	displayHeader("Interface Settings");

	/*if (flags[kFLAGS.USE_OLD_INTERFACE] >= 1)
	{
		outputText("Stats Pane Style: Old\n Old stats panel will be used.");
	}
	else
		outputText("Stats Pane Style: New\n New stats panel will be used.");

	outputText("\n\n");*/

	if (flags[kFLAGS.USE_OLD_FONT] >= 1)
	{
		outputText("Font: Lucida Sans Typewriter\n");
	}
	else
		outputText("Font: Palatino Linotype\n");

	outputText("\n\n");

	if (flags[kFLAGS.IMAGEPACK_OFF] == 0)
	{
		outputText("Image Pack: ON\n Image pack is enabled.");
	}
	else
		outputText("Image Pack: OFF\n Image pack is disabled.");

	outputText("\n\n");

	if (flags[kFLAGS.SHOW_SPRITES_FLAG] == 0) {
		outputText("Sprites: ON\n You like to look at pretty pictures.");
		outputText("\n\n");
		if (flags[kFLAGS.SPRITE_STYLE] == 0)
			outputText("Sprite Type: New\n 16-bit sprites will be used.");
		else
			outputText("Sprite Type: Old\n 8-bit sprites will be used.");
	}
	else {
		outputText("Sprites: OFF\n There are only words. Nothing else.");
		outputText("\n\n\n");
	}

	outputText("\n\n");

	if (flags[kFLAGS.USE_12_HOURS] > 0)
		outputText("Time Format: 12 hours\n Time will display in 12 hours format (AM/PM)");
	else
		outputText("Time Format: 24 hours\n Time will display in 24 hours format.");

	outputText("\n\n");

	if (flags[kFLAGS.USE_METRICS] > 0)
		outputText("Measurement: Metric\n Height and cock size will be measured in metres and centimetres.");
	else
		outputText("Measurement: Imperial\n Height and cock size will be measured in feet and inches.");

	outputText("\n\n");

	if (flags[kFLAGS.DISABLE_QUICKLOAD_CONFIRM] == 0)
	{
		outputText("Confirm Quickload: ON (Quickload confirmation dialog is enabled).");
	}
	else
		outputText("Confirm Quickload: OFF (Quickload confirmation dialog is disabled).");

	outputText("\n\n");

	if (flags[kFLAGS.DISABLE_QUICKSAVE_CONFIRM] == 0)
	{
		outputText("Confirm Quicksave: ON (Quicksave confirmation dialog is enabled).");
	}
	else
		outputText("Confirm Quicksave: OFF (Quicksave confirmation dialog is disabled).");

	menu();
	addButton(0, "Side Bar Font", toggleFont, null, null, null, "Toggle between old and new font for side bar.");
	addButton(1, "Main BG", menuMainBackground, null, null, null, "Choose a background for main game interface.");
	addButton(2, "Text BG", menuTextBackground, null, null, null, "Choose a background for text.");
	addButton(3, "Sprites", menuSpriteSelect, null, null, null, "Turn sprites on/off and change sprite style preference.");

	addButton(5, "Toggle Images", toggleImages, null, null, null, "Enable or disable image pack.");
	addButton(6, "Time Format", toggleTimeFormat, null, null, null, "Toggles between 12-hour and 24-hour format.");
	addButton(7, "Measurements", toggleMeasurements, null, null, null, "Switch between imperial and metric measurements.  \n\nNOTE: Only applies to your appearance screen.");

	addButton(10, "Confirm Load", toggleQuickLoadConfirm, null, null, null, "Toggles the confirmation dialog for Quickload.", "Confirm Quickload");
	addButton(11, "Confirm Save", toggleQuickSaveConfirm, null, null, null, "Toggles the confirmation dialog for Quicksave.", "Confirm Quicksave");
	addButton(14, "Back", settingsScreenMain);
}

public function menuMainBackground():void {
	menu();
	addButton(0, "Map (Default)", setMainBackground, 0);
	addButton(1, "Parchment", setMainBackground, 1);
	addButton(2, "Marble", setMainBackground, 2);
	addButton(3, "Obsidian", setMainBackground, 3);
	addButton(4, "Black", setMainBackground, 4);

	addButton(14, "Back", settingsScreenInterfaceSettings);
}

public function menuTextBackground():void {
	menu();
	addButton(0, "Normal", setTextBackground, 0);
	addButton(1, "White", setTextBackground, 1);
	addButton(2, "Tan", setTextBackground, 2);

	addButton(14, "Back", settingsScreenInterfaceSettings);
}

public function menuSpriteSelect():void {
	menu();
	addButton(0, "Off", toggleSpritesFlag, true, 0, null, "Turn off the sprites completely");
	addButton(1, "Old", toggleSpritesFlag, false, 1, null, "Use the 8-bit sprites from older versions of CoC.");
	addButton(2, "New", toggleSpritesFlag, false, 0, null, "Use the 16-bit sprites in current versions of CoC.");

	addButton(14, "Back", settingsScreenInterfaceSettings);
}

public function toggleInterface():void {
	if (flags[kFLAGS.USE_OLD_INTERFACE] < 1) flags[kFLAGS.USE_OLD_INTERFACE] = 1;
	else flags[kFLAGS.USE_OLD_INTERFACE] = 0;
	settingsScreenInterfaceSettings();
}

public function toggleFont():void {
	if (flags[kFLAGS.USE_OLD_FONT] < 1) flags[kFLAGS.USE_OLD_FONT] = 1;
	else flags[kFLAGS.USE_OLD_FONT] = 0;
	settingsScreenInterfaceSettings();
}

public function setMainBackground(type:int):void {
	flags[kFLAGS.BACKGROUND_STYLE] = type;
	mainView.background.gotoAndStop(flags[kFLAGS.BACKGROUND_STYLE] + 1);
	mainView.sideBarBG.gotoAndStop(flags[kFLAGS.BACKGROUND_STYLE] + 1);
	settingsScreenInterfaceSettings();
}

public function setTextBackground(type:int):void {
	mainView.textBGWhite.visible = false;
	mainView.textBGTan.visible = false;
	if (type == 1) mainView.textBGWhite.visible = true;
	if (type == 2) mainView.textBGTan.visible = true;
	settingsScreenInterfaceSettings();
}

public function toggleSpritesFlag(enabled:Boolean, style:int):void
{
	flags[kFLAGS.SHOW_SPRITES_FLAG] = enabled;
	flags[kFLAGS.SPRITE_STYLE] = style;
	settingsScreenInterfaceSettings();
	return;
}

//Needed for keys
public function cycleBackground():void {
	if (!mainView.textBGWhite.visible)
	{
		mainView.textBGWhite.visible = true;
	}
	else if (!mainView.textBGTan.visible)
	{
		mainView.textBGTan.visible = true;
	}
	else
	{
		mainView.textBGWhite.visible = false;
		mainView.textBGTan.visible = false;
	}
}

public function cycleQuality():void {
	if (stage.quality == StageQuality.LOW) stage.quality = StageQuality.MEDIUM;
	else if (stage.quality == StageQuality.MEDIUM) stage.quality = StageQuality.HIGH;
	else if (stage.quality == StageQuality.HIGH) stage.quality = StageQuality.LOW;
	settingsScreenInterfaceSettings();
}

public function toggleImages():void {
	if (flags[kFLAGS.IMAGEPACK_OFF] < 1) flags[kFLAGS.IMAGEPACK_OFF] = 1;
	else flags[kFLAGS.IMAGEPACK_OFF] = 0;
	settingsScreenInterfaceSettings();
}

public function toggleTimeFormat():void {
	if (flags[kFLAGS.USE_12_HOURS] < 1) flags[kFLAGS.USE_12_HOURS] = 1;
	else flags[kFLAGS.USE_12_HOURS] = 0;
	settingsScreenInterfaceSettings();
}

public function toggleQuickLoadConfirm():void {
	flags[kFLAGS.DISABLE_QUICKLOAD_CONFIRM] ^= 1; // Bitwise XOR. Neat trick to toggle between 0 and 1
	settingsScreenInterfaceSettings();
}

public function toggleQuickSaveConfirm():void {
	flags[kFLAGS.DISABLE_QUICKSAVE_CONFIRM] ^= 1; // Bitwise XOR. Neat trick to toggle between 0 and 1
	settingsScreenInterfaceSettings();
}
public function toggleMeasurements():void {
	if (flags[kFLAGS.USE_METRICS] < 1) flags[kFLAGS.USE_METRICS] = 1;
	else flags[kFLAGS.USE_METRICS] = 0;
	settingsScreenInterfaceSettings();
}

//------------
// FONT SETTINGS
//------------
public function fontSettingsMenu():void {
	menu();
	simpleChoices("Smaller Font", decFontSize,
		"Larger Font", incFontSize,
		"Reset Size", resetFontSize,
		"", null,
		"Back", settingsScreenMain);
}

public function incFontSize():void
{
	var fmt:TextFormat = mainView.mainText.getTextFormat();

	if (fmt.size == null) fmt.size = 20;

	fmt.size = (fmt.size as Number) + 1;

	if ((fmt.size as Number) > 32) fmt.size = 32;

	trace("Font size set to: " + (fmt.size as Number));
	mainView.mainText.setTextFormat(fmt);
	flags[kFLAGS.CUSTOM_FONT_SIZE] = fmt.size;
}

public function decFontSize():void
{
	var fmt:TextFormat = mainView.mainText.getTextFormat();

	if (fmt.size == null) fmt.size = 20;

	fmt.size = (fmt.size as Number) - 1;

	if ((fmt.size as Number) < 14) fmt.size = 14;

	trace("Font size set to: " + (fmt.size as Number));
	mainView.mainText.setTextFormat(fmt);
	flags[kFLAGS.CUSTOM_FONT_SIZE] = fmt.size;
}

public function resetFontSize():void {
	var fmt:TextFormat = mainView.mainText.getTextFormat();
	if (fmt.size == null) fmt.size = 20;
	fmt.size = 20;
	mainView.mainText.setTextFormat(fmt);
	flags[kFLAGS.CUSTOM_FONT_SIZE] = 0;
}

//------------
// CREDITS
//------------
public function creditsScreen():void {
	clearOutput();
	displayHeader("Credits");
	outputText("Coding and Main Events:\n");
	outputText("
");
	outputText("
 Fenoxo
\n");
	outputText("
");
	outputText("Game Mod:\n");
	outputText("
");
	outputText("
 Kitteh6660 (Mod Creator)
");
	outputText("
");
	outputText("Game Mod Contributors:\n");
	outputText("
");
	outputText("
 Parth37955 (Pure Jojo anal pitch scene, Behemoth's vaginal catch scene)
");
	outputText("
 Liadri (Manticore and Dragonne suggestions)
");
	outputText("
 Warbird Zero (Replacement Ingnam descriptions)
");
	outputText("
 Matraia (Replacement Cabin construction texts)
");
	outputText("
 Stadler76 (New arm types, Code refactoring)
");
	outputText("
");
	outputText("Game Mod Supplementary Events:\n");
	outputText("
");
	outputText("
 worldofdrakan (Pigtail Truffles & Pig/Boar TFs)
");
	outputText("
 FeiFongWong (Prisoner Mod)
");
	outputText("
 Foxxling (Lizan Rogue, Skin Oils & Body Lotions, Black Cock)
");
	outputText("
 LukaDoc (Bimbo Jojo)
");
	outputText("
 Kitteh6660 (Behemoth, Cabin, Ingnam, Pure Jojo sex scenes. Feel free to help me with quality control.)
");
	outputText("
 Ormael (Salamander TFs)
");
	outputText("
 Coalsack (Anzu the Avian Deity)
");
	outputText("
");
	outputText("Game Mod Bug Reporting:\n");
	outputText("
");
	outputText("
 Wastarce
");
	outputText("
 Sorenant
");
	outputText("
 tadams857
");
	outputText("
 SirWolfie
");
	outputText("
 Atlas1965
");
	outputText("
 Elitist
");
	outputText("
 Bsword
");
	outputText("
 stationpass
");
	outputText("
 JDoraime
");
	outputText("
 Ramses
");
	outputText("
 OPenaz
");
	outputText("
 EternalDragon (github)
");
	outputText("
 PowerOfVoid (github)
");
	outputText("
 kalleangka (github)
");
	outputText("
 sworve (github)
");
	outputText("
 Netys (github)
");
	outputText("
");
	outputText("
");
	outputText("Typo Reporting\n");
	outputText("
");
	outputText("
 SoS
");
	outputText("
 Prisoner416
");
	outputText("
 Chibodee
");
	outputText("");
	outputText("Graphical Prettiness:")
	outputText("
");;
	outputText("
 Dasutin (Background Images)
");
	outputText("
 Invader (Button Graphics, Font, and Other Hawtness)
");
	outputText("
");
	outputText("Supplementary Events:");
	outputText("
");
	outputText("
 Dxasmodeus (Tentacles, Worms, Giacomo)
");
	outputText("
 Kirbster (Christmas Bunny Trap)
");
	outputText("
 nRage (Kami the Christmas Roo)
");
	outputText("
 Abraxas (Alternate Naga Scenes w/Various Monsters, Tamani Anal, Female Shouldra Tongue Licking, Chameleon Girl, Christmas Harpy)
");
	outputText("
 Astronomy (Fetish Cultist Centaur Footjob Scene)
");
	outputText("
 Adjatha (Scylla the Cum Addicted Nun, Vala, Goo-girls, Bimbo Sophie Eggs, Ceraph Urta Roleplay, Gnoll with Balls Scene, Kiha futa scene, Goblin Web Fuck Scene, and 69 Bunny Scene)
");
	outputText("
 ComfyCushion (Muff Wrangler)
");
	outputText("
 B (Brooke)
");
	outputText("
 Quiet Browser (Half of Niamh, Ember, Amily The Mouse-girl Breeder, Katherine, Part of Katherine Employment Expansion, Urta's in-bar Dialogue Trees, some of Izma, Loppe)
");
	outputText("
 Indirect (Alternate Non-Scylla Katherine Recruitment, Part of Katherine Employment Expansion, Phouka, Coding of Bee Girl Expansion)
");
	outputText("
 Schpadoinkle (Victoria Sex)
");
	outputText("
 Donto (Ro'gar the Orc, Polar Pete)
");
	outputText("
 Angel (Additional Amily Scenes)
");
	outputText("
 Firedragon (Additional Amily Scenes)
");
	outputText("
 Danaume (Jojo masturbation texts)
");
	outputText("
 LimitLax (Sand-Witch Bad-End)
");
	outputText("
 KLN (Equinum Bad-End)
");
	outputText("
 TheDarkTemplar11111 (Canine Pepper Bad End)
");
	outputText("
 Silmarion (Canine Pepper Bad End)
");
	outputText("
 Soretu (Original Minotaur Rape)
");
	outputText("
 NinjArt (Small Male on Goblin Rape Variant)
");
	outputText("
 DoubleRedd (\"Too Big\" Corrupt Goblin Fuck)
");
	outputText("
 Nightshade (Additional Minotaur Rape)
");
	outputText("
 JCM (Imp Night Gangbang, Addition Minotaur Loss Rape - Oral)
");
	outputText("
 Xodin (Nipplefucking paragraph of Imp GangBang, Encumbered by Big Genitals Exploration Scene, Big Bits Run Encumbrance, Player Getting Beer Tits, Sand Witch Dungeon Misc Scenes)
");
	outputText("
 Blusox6 (Original Queen Bee Rape)
");
	outputText("
 Thrext (Additional Masturbation Code, Faerie, Ivory Succubus)
");
	outputText("
 XDumort (Genderless Anal Masturbation)
");
	outputText("
 Uldego (Slime Monster)
");
	outputText("
 Noogai, Reaper, and Numbers (Nipple-Fucking Victory vs Imp Rape)
");
	outputText("
 Verse and IAMurow (Bee-Girl MultiCock Rapes)
");
	outputText("
 Sombrero (Additional Imp Lust Loss Scene (Dick insertion ahoy!)
");
	outputText("
 The Dark Master (Marble, Fetish Cultist, Fetish Zealot, Hellhound, Lumi, Some Cat Transformations, LaBova, Ceraph's Cat-Slaves, a Cum Witch Scene, Mouse Dreams, Forced Nursing:Imps&Goblins, Bee Girl Expansion)
");
	outputText("
 Mr. Fleshcage (Cat Transformation/Masturbation)
");
	outputText("
 Spy (Cat Masturbation, Forced Nursing: Minotaur, Bee, & Cultist)
");
	outputText("
 PostNuclearMan (Some Cat TF)
");
	outputText("
 MiscChaos (Forced Nursing: Slime Monster)
");
	outputText("
 Ourakun (Kelt the Centaur)
");
	outputText("
 Rika_star25 (Desert Tribe Bad End)
");
	outputText("
 Versesai (Additional Bee Rape)
");
	outputText("
 Mallowman (Additional Bee Rape)
");
	outputText("
 HypnoKitten (Additional Centaur x Imp Rape)
");
	outputText("
 Ari (Minotaur Gloryhole Scene)
");
	outputText("
 SpectralTime (Aunt Nancy)
");
	outputText("
 Foxxling (Akbal)
");
	outputText("
 Elfensyne (Phylla)
");
	outputText("
 Radar (Dominating Sand Witches, Some Phylla)
");
	outputText("
 Jokester (Sharkgirls, Izma, & Additional Amily Scenes)
");
	outputText("
 Lukadoc (Additional Izma, Ceraph Followers Corrupting Gangbang, Satyrs, Ember)
");
	outputText("
 IxFa (Dildo Scene, Virgin Scene for Deluxe Dildo, Naga Tail Masturbation)
");
	outputText("
 Bob (Additional Izma)
");
	outputText("
 lh84 (Various Typos and Code-Suggestions)
");
	outputText("
 Dextersinister (Gnoll girl in the plains)
");
	outputText("
 ElAcechador, Bandichar, TheParanoidOne, Xoeleox (All Things Naga)
");
	outputText("
 Symphonie (Dominika the Fellatrix, Ceraph RPing as Dominika, Tel'Adre Library)
");
	outputText("
 Soulsemmer (Ifris)
");
	outputText("
 WedgeSkyrocket (Zetsuko, Pure Amily Anal, Kitsunes)
");
	outputText("
 Zeikfried (Anemone, Male Milker Bad End, Kanga TF, Raccoon TF, Minotaur Chef Dialogues, Sheila, and More)
");
	outputText("
 User21 (Additional Centaur/Naga Scenes)
");
	outputText("
 ~M~ (Bimbo + Imp loss scene)
");
	outputText("
 Grype (Raping Hellhounds)
");
	outputText("
 B-Side (Fentendo Entertainment Center Silly-Mode Scene)
");
	outputText("
 Not Important (Face-fucking a defeated minotaur)
");
	outputText("
 Third (Cotton, Rubi, Nieve, Urta Pet-play)
");
	outputText("
 Gurumash (Parts of Nieve)
");
	outputText("
 Kinathis (A Nieve Scene, Sophie Daughter Incest, Minerva)
");
	outputText("
 Jibajabroar (Jasun)
");
	outputText("
 Merauder (Raphael)
");
	outputText("
 EdgeofReality (Gym fucking machine)
");
	outputText("
 Bronycray (Heckel the Hyena)
");
	outputText("
 Sablegryphon (Gnoll spear-thrower)
");
	outputText("
 Nonesuch (Basilisk, Sandtraps, assisted with Owca/Vapula, Whitney Farm Corruption)
");
	outputText("
 Anonymous Individual (Lilium, PC Birthing Driders)
");
	outputText("
 PKD (Owca, Vapula, Fap Arena, Isabella Tentacle Sex, Lottie Tentacle Sex)
");
	outputText("
 Shamblesworth (Half of Niamh, Shouldra the Ghost-Girl, Ceraph Roleplaying As Marble, Yara Sex, Shouldra Follow Expansion)
");
	outputText("
 Kirbu (Exgartuan Expansion, Yara Sex, Shambles's Handler, Shouldra Follow Expansion)
");
	outputText("
 05095 (Shouldra Expansion, Tons of Editing)
");
	outputText("
 Smidgeums (Shouldra + Vala threesome)
");
	outputText("
 FC (Generic Shouldra talk scene)
");
	outputText("
 Oak (Bro + Bimbo TF, Isabella's ProBova Burps)
");
	outputText("
 Space (Victory Anal Sex vs Kiha)
");
	outputText("
 Venithil (LippleLock w/Scylla & Additional Urta Scenes)
");
	outputText("
 Butts McGee (Minotaur Hot-dogging PC loss, Tamani Lesbo Face-ride, Bimbo Sophie Mean/Nice Fucks)
");
	outputText("
 Savin (Hel the Salamander, Valeria, Spanking Drunk Urta, Tower of the Phoenix, Drider Anal Victory, Hel x Isabella 3Some, Centaur Sextoys, Thanksgiving Turkey, Uncorrupt Latexy Recruitment, Assert Path for Direct Feeding Latexy, Sanura the Sphinx)
");
	outputText("
 Gats (Lottie, Spirit & Soldier Xmas Event, Kiha forced masturbation, Goblin Doggystyle, Chicken Harpy Egg Vendor)
");
	outputText("
 Aeron the Demoness (Generic Goblin Anal, Disciplining the Eldest Minotaur)
");
	outputText("
 Gats, Shamblesworth, Symphonie, and Fenoxo (Corrupted Drider)
");
	outputText("
 Bagpuss (Female Thanksgiving Event, Harpy Scissoring, Drider Bondage Fuck)
");
	outputText("
 Frogapus (The Wild Hunt)
");
	outputText("
 Fenoxo (Everything Else)
");
	outputText("
");
	outputText("Oviposition Update Credits - Names in Order Appearance in Oviposition Document");
	outputText("
");
	outputText("
 DCR (Idea, Drider Transformation, and Drider Impreg of: Goblins, Beegirls, Nagas, Harpies, and Basilisks)
");
	outputText("
 Fenoxo (Bee Ovipositor Transformation, Bee Oviposition of Nagas and Jojo, Drider Oviposition of Tamani)
");
	outputText("
 Smokescreen (Bee Oviposition of Basilisks)
");
	outputText("
 Radar (Oviposition of Sand Witches)
");
	outputText("
 OutlawVee (Bee Oviposition of Goo-Girls)
");
	outputText("
 Zeikfried (Editing this mess, Oviposition of Anemones)
");
	outputText("
 Woodrobin (Oviposition of Minotaurs)
");
	outputText("
 Posthuman (Oviposition of Ceraph Follower)
");
	outputText("
 Slywyn (Bee Oviposition of Gigantic PC Dick)
");
	outputText("
 Shaxarok (Drider Oviposition of Large Breasted Nipplecunts)
");
	outputText("
 Quiet Browser (Bee Oviposition of Urta)
");
	outputText("
 Bagpuss (Laying Eggs In Pure Amily)
");
	outputText("
 Eliria (Bee Laying Eggs in Bunny-Girls)
");
	outputText("
 Gardeford (Helia x Bimbo Sophie Threesomes)
");
	outputText("
");
	outputText("\nIf I'm missing anyone, please contact me ASAP!  I have done a terrible job keeping the credits up to date!");
	doNext(mainMenu);
}

//------------
// IMAGE CREDITS
//------------
public function imageCreditsScreen():void
{
	clearOutput();
	displayHeader("Image Credits");
	if (images.getLoadedImageCount() > 0)
	{
		outputText("Bundled Image Credits:\n\n");
		outputText("Yoh-SL");
		outputText("
Bee-Girl Monster Image
");
		outputText("
Goo-Girl Monster Image
");
		outputText("
Ceraph Monster Image
");
		outputText("
Sand-Witch (and sandwich)
");
	}
	else
	{
		outputText("No Image-Pack Found!\n", false);
	}
	doNext(mainMenu);
}

//------------
// INSTRUCTIONS
//------------
public function howToPlay():void {
	clearOutput();
	displayHeader("Instructions");
	outputText("How To Play:\nClick the buttons corresponding to the actions you want to take.  Your 'goal' is to obviously put an end to the demonic corruption around you, but do whatever the hell you want.  There is a story but sometimes it's fun to ignore it.\n\n", false);
	outputText("Exploration:\nThe lake is a safe zone when you start the game.  It's a good place to explore, and Whitney's farm can offer some nice stat boosts to help get you on your feet. Once you feel comfortable, the forest is probably the next safest area, but beware of tentacle monsters.  The desert is the next toughest area, and the mountains offer further challenges.  There are more areas beyond that, but that's a good way to get started.  You'll uncover plenty of new 'places' exploring, which can be accessed from the Places menu.  You'll also find some interesting characters when you try to discover new explorable locations by choosing Explore twice.\n\n", false);
	outputText("Combat:\nCombat is won by raising an opponent's lust to 100 or taking their HP to 0.  You lose if your enemy does the same to you.  Loss isn't game over, but some losses will make it harder in the future by lowering your stats.  Beware.  Don't be afraid to spam the Run option when you're in over your head.\n\n", false);
	outputText("Controls:\nThe game features numerous hot-keys to make playing quicker and easier.\nP key - Perks Menu\nD key - Data Menu\nA key - Appearance Screen\n1 Through 5 - The top row of 'choice' buttons.\n6 Through 0 - The bottom row of 'choice' buttons.\nQ through T - Alternative bottom 'choice' hotkeys.\nSpace Bar - Next/Back/Leave\nHome Key - Toggle text field background.\nS key - Stats Screen\n(Save Hotkeys - May not work in all players)\nF1-F5 - Quicksave to slot 1 through 5.  Only works when Data is visible.\nF6-F0 - Quick Load from slots 1-5.\n\n", false);
	outputText("Save often using the Data Menu - you never know when your journey will come to an end!", false);
	doNext(mainMenu);
}


code:
<?xml version="1.0" encoding="utf-8"?>
<Images>
	<Image id="monster-ceraph">./img/monster-ceraph.jpg</Image>
	<Image id="monster-ceraph">./img/monster-ceraph.jpeg</Image>
	<Image id="monster-ceraph">./img/monster-ceraph.gif</Image>
	<Image id="monster-ceraph">./img/monster-ceraph.png</Image>
</Images>

license: unknown


code:
import sys
import re
import os
import os.path

def getImageIDList():

	r"init01Names\([\"']\w*[\"'], [\"']\w*[\"'], [\"'](\w+)[\"'], [\"']\w?[\"'], plural=false)"

	imgTagRe        = re.compile(r"images\.showImage\([\"']([\w\d-]+)[\"'](?:,.*?)?\)")
	monsterNameRe   = re.compile(r"this\.imageName\s?=\s?[\"'](\w+)[\"'];?")
	ret = set()

	scanPath = "../"
	for root, dirs, files in os.walk(scanPath):
		#print root, dir#, files
		for fileN in files:
			if fileN.endswith(".as"):
				wholePath = os.path.join(root, fileN)
				print "Scanning file: ", wholePath
				with open(wholePath, "r") as fp:
					cont = fp.read()
					items = set(imgTagRe.findall(cont))

					ret.update(items)

					monsterNames = monsterNameRe.findall(cont)
					if monsterNames:
						for name in monsterNames:
							name = "monster-%s" % name
							ret.add(name)

	ret.add("monster-hollispawn")  # Hack because matching this would be a giant pain in the ass

	print "Found %s image IDs" % len(ret)
	return ret

def genFile():

	imageIDs = getImageIDList()
	imageIDs = list(imageIDs)
	imageIDs.sort()

	extensions = ["png", "jpg", "jpeg", "gif"]

	#print imageIDs

	# Crapping out XML using string manipulation because FUCK YOU
	ret = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
	ret += "	<Images>\n"
	for item in imageIDs:
		for extension in extensions:
			itemClean = item.rstrip().lstrip()
			ret += "		<Image id=\"%s\">./img/%s.%s</Image>\n" % (itemClean, itemClean, extension)

	ret += "</Images>"
	#print ret

	ret = ""
	ret += '<?xml version="1.0" encoding="utf-8"?>\n'
	ret += '	<Images>\n'
	ret += '		<ImageList>\n'
	for imId in imageIDs:
		ret += '			<ImageSet id="%s">\n' % imId
		ret += '				<ImageFile>./img/%s</ImageFile>\n' % imId
		ret += '				<ImageFile>./img/%s_1</ImageFile>\n' % imId
		ret += '			</ImageSet>\n'
	ret += '		</ImageList>\n'
	ret += '		<ExtensionList>\n'
	ret += '			<ExtensionType>png</ExtensionType>\n'
	ret += '			<ExtensionType>jpg</ExtensionType>\n'
	ret += '			<ExtensionType>jpeg</ExtensionType>\n'
	ret += '			<ExtensionType>gif</ExtensionType>\n'
	ret += '		</ExtensionList>\n'

	ret += '	</Images>\n'

	with open("images.xml", "w") as fp:
		fp.write(ret)

if __name__ == "__main__":
	genFile()


code:
<?xml version="1.0" encoding="utf-8"?>
<!--This Adobe Flex compiler configuration file was generated by a tool.-->
<!--Any modifications you make may be lost.-->
<flex-config>
  <target-player>10.3</target-player>
  <benchmark>true</benchmark>
  <static-link-runtime-shared-libraries>true</static-link-runtime-shared-libraries>
  <use-network>false</use-network>
  <compiler>
    <define append="true">
      <name>CONFIG::debug</name>
      <value>true</value>
    </define>
    <define append="true">
      <name>CONFIG::release</name>
      <value>false</value>
    </define>
    <define append="true">
      <name>CONFIG::timeStamp</name>
      <value>'11/23/2016'</value>
    </define>
    <define append="true">
      <name>CONFIG::air</name>
      <value>false</value>
    </define>
    <define append="true">
      <name>CONFIG::mobile</name>
      <value>false</value>
    </define>
    <define append="true">
      <name>CONFIG::desktop</name>
      <value>false</value>
    </define>
    <define append="true">
      <name>CONFIG::STANDALONE</name>
      <value>true</value>
    </define>
    <define append="true">
      <name>CONFIG::AIR</name>
      <value>false</value>
    </define>
    <verbose-stacktraces>true</verbose-stacktraces>
    <source-path append="true">
      <path-element>C:\Flash\Corruption-of-Champions-Mod-Deviant\classes</path-element>
      <path-element>C:\Flash\Corruption-of-Champions-Mod-Deviant\lib\bin</path-element>
      <path-element>C:\Program Files (x86)\FlashDevelop\Library\AS3\classes</path-element>
    </source-path>
    <library-path append="true">
      <path-element>C:\Flash\Corruption-of-Champions-Mod-Deviant\lib\bin\MainView.swc</path-element>
      <path-element>C:\Flash\Corruption-of-Champions-Mod-Deviant\lib\bin\ScrollPane.swc</path-element>
    </library-path>
  </compiler>
  <file-specs>
    <path-element>C:\Flash\Corruption-of-Champions-Mod-Deviant\classes\classes\CoC.as</path-element>
  </file-specs>
  <default-background-color>#000000</default-background-color>
  <default-frame-rate>24</default-frame-rate>
  <default-size>
    <width>1000</width>
    <height>800</height>
  </default-size>
</flex-config>


code:
package coc.view {

	/****
		coc.view.CoCButton

		note that although this stores its current tool tip text,
		it does not display the text.  That is taken care of
		by whoever owns this.

		The mouse event handlers are public to facilitate reaction to
		keyboard events.
	****/

	import flash.display.MovieClip;
	import flash.text.TextField;
	import flash.text.TextFormat;

	import flash.events.MouseEvent;

	public class CoCButton extends MovieClip {
		public static const
			// How far down from the top of our registration point the TF is.
			LABEL_FIELD_Y_OFFSET:Number = 9,
			LABEL_FIELD_HEIGHT:Number = 25;

		protected var
			_labelField:TextField,
			_backgroundGraphic:MovieClip,
			_callback:Function;

		public var
			toolTipHeader:String,
			toolTipText:String;

		public function CoCButton(labelField:TextField = null, backgroundGraphic:MovieClip = null):void {
			if (backgroundGraphic) {
				this.x = backgroundGraphic.x;
				this.y = backgroundGraphic.y;
			}

			this.labelField = labelField;
			this.backgroundGraphic = backgroundGraphic;

			this.mouseChildren = true;
			this.buttonMode = true;

			this.addEventListener(MouseEvent.ROLL_OVER, this.hover);
			this.addEventListener(MouseEvent.ROLL_OUT, this.dim);
			this.addEventListener(MouseEvent.CLICK, this.click);
		}

		//////// Mouse Events... ////////

		public function hover(event: MouseEvent = null):void {
			if (this.backgroundGraphic)
				this.backgroundGraphic.alpha = 0.5;
		}

		public function dim(event:MouseEvent = null):void {
			if (this.backgroundGraphic)
				this.backgroundGraphic.alpha = 1;
		}

		public function click(event:MouseEvent = null):void {
			if (this._callback != null)
				this._callback();
		}

		//////// Getters and Setters ////////

		public function get labelField():TextField {
			return this._labelField;
		}

		public function set labelField(value:TextField):void {
			// TODO: Remove previous labelField?

			this._labelField = value;

			if (! this._labelField) return;

			this.addChild(this._labelField);

			//Workaround for formatting
			var fmt:TextFormat = this._labelField.getTextFormat();
			fmt.bold = true;
			this._labelField.defaultTextFormat = fmt;

			this._labelField.mouseEnabled = false;

			this._labelField.x = 0;
			this._labelField.y = LABEL_FIELD_Y_OFFSET;
			this._labelField.width = this.width;
			this._labelField.height = LABEL_FIELD_HEIGHT;
		}

		public function get backgroundGraphic():MovieClip {
			return this._backgroundGraphic;
		}

		public function set backgroundGraphic(value:MovieClip):void {
			// TODO: Remove previous background graphic?

			this._backgroundGraphic = value;

			if (! this._backgroundGraphic) return;

			this.addChildAt(this._backgroundGraphic, 0);

			this._backgroundGraphic.mouseEnabled = true;

			this._backgroundGraphic.x = 0;
			this._backgroundGraphic.y = 0;

			this.width = this._backgroundGraphic.width;
		}

		public function get labelText():String {
			return this.labelField.text;
		}

		public function set labelText(value:String):void {
			this.labelField.text = value;
		}

		public function get callback():Function {
			return this._callback;
		}

		public function set callback(value:Function):void {
			this._callback = value;
		}

		//// Overrides. ////
		override public function get width():Number {
			return this.backgroundGraphic ? this.backgroundGraphic.width: 0;
		}

		override public function set width(value:Number):void {
			if (this.backgroundGraphic)
				this.backgroundGraphic.width = value;

			if (this.labelField)
				this.labelField.width = value;
		}

		override public function get height():Number {
			return this.backgroundGraphic ? this.backgroundGraphic.height: 0;
		}

		override public function set height(value:Number):void {
			if (this.backgroundGraphic)
				this.backgroundGraphic.height = value;
			// TODO: Do anything to the text field?
		}
	}
}


code:
/****
	coc.view.MainView

	I have no real idea yet what eventTestInput is for,
	but its coordinates get tested for in places, and set in others.
	Perhaps some day I'll ask.

	It's for allowing people to test stuff in the parser. It gets moved into view, and you
	can enter stuff in the text window, which then gets fed through the parser.

	That's good to know.  Cheers.
****/

package coc.view {
	import flash.display.MovieClip;
	import flash.display.DisplayObject;
	import flash.display.InteractiveObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.Font;
	import flash.text.TextField;
	import flash.text.TextFieldType;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;

	import fl.controls.ComboBox;
	import fl.data.DataProvider;

    //import coc.model.GameModel;

    import buttonBackground0;
    import buttonBackground1;
    import buttonBackground2;
    import buttonBackground3;
    import buttonBackground4;
    import buttonBackground5;
    import buttonBackground6;
    import buttonBackground7;
    import buttonBackground8;
    import buttonBackground9;

	public class MainView extends MovieClip {
		// Menu button names.
		public static const MENU_NEW_MAIN:String = 'newGame';
		public static const MENU_DATA:String = 'data';
		public static const MENU_STATS:String = 'stats';
		public static const MENU_LEVEL:String = 'level';
		public static const MENU_PERKS:String = 'perks';
		public static const MENU_APPEARANCE:String = 'appearance';

		private static const BOTTOM_BUTTON_COUNT:int = 15;
		private static const BOTTOM_BUTTON_PER_ROW_COUNT:int = 5;

		private static const BUTTON_X_OFFSET:Number = 200;
		private static const BUTTON_Y_OFFSET:Number = 668;
		private static const BUTTON_X_DELTA:Number = 160;
		private static const BUTTON_Y_DELTA:Number = 45;
		private static const BUTTON_REAL_WIDTH:Number = 150;
		private static const BUTTON_REAL_HEIGHT:Number = 40;

		public var aCb:ComboBox;
		public var nameBox:TextField;

		//// Actual buttons.
		public var bottomButtons:Array;
		public var newGameButton:CoCButton;
		public var dataButton:CoCButton;
		public var statsButton:CoCButton;
		public var levelButton:CoCButton;
		public var perksButton:CoCButton;
		public var appearanceButton:CoCButton;

		public var bottomButtonTexts:Array; // <TextField>
		public var bottomButtonBGs:Array; // <MovieClip>
		public var menuButtonTexts:Array;
		public var menuButtonBGs:Array;
		private var currentActiveButtons:Array;

		public var toolTipView:ToolTipView;
		public var statsView:StatsView;

		public var sideBarDecoration:Sprite;

		protected var options:Object;
		// protected var allButtonTexts:Array;
		protected var allButtons:Array;
		protected var callbacks:Object = {}

		//protected var model:GameModel;

		public var
			newGameBG:MovieClip,
			dataBG:MovieClip,
			statsBG:MovieClip,
			levelBG:MovieClip,
			perksBG:MovieClip,
			appearanceBG:MovieClip;

		public function MainView(/*model:GameModel = null, options:Object = null*/):void {
			// Note: Currently we can't touch this on construction
			// due to the code being a mess.  We'll fix that at some point.
			// maybe even get like update events or some shit like real MV*s or something.
			//this.model = model;
			//this.options = options || {} Is this even used?
			super();

			/*if (! model) {
				trace("MainView/constructor: Game model not passed in.  Don't publish MainView.fla with Ctrl-Enter/Cmd-Enter.  Rather, go to File > Publish to build the SWC.");
				throw new ArgumentError("MainView/constructor: MainView must be constructed with a GameModel as its first argument.");
			}*/

			// Init subviews.
			this.statsView = new StatsView(this/*, this.model*/);
			this.statsView.hide();
			this.addChild(this.statsView);

			this.toolTipView = new ToolTipView(this/*, this.model*/);
			this.toolTipView.hide();
			this.addChild(this.toolTipView);

			this.formatMiscItems();

			this.allButtons = [];

			createBottomButtons();
			createMenuButtons();

			// disable interaction for any remaining TFs.
			disableMouseForMostTextFields();

			// hook!
			hookBottomButtons();
			hookAllButtons();
		}

		//////// Initialization methods. /////////

		protected function formatMiscItems():void {
			// this.mainText = this.getChildByName("mainText");

			this.nameBox.maxChars = 54;

			this.sideBarDecoration = getChildByName("statsBarMarker") as Sprite;

			this.aCb = new ComboBox();
			this.aCb.dropdownWidth = 200;
			this.aCb.width = 200;
			this.aCb.scaleY = 1.1;
			this.aCb.move(-1250, -1550);
			this.aCb.prompt = "Choose a perk";
			this.addChild(this.aCb);

			this.hideSprite();
		}

		// Removes the need for some code in input.as and InitializeUI.as.
		protected function disableMouseForMostTextFields():void {
			var ci:int, t:TextField;

			for(ci = 0; ci < this.numChildren; ++ci) {
				t = this.getChildAt(ci) as TextField;

				if (! t) {
					continue;
				}

				switch(t) {
					case this.mainText:
					case this.nameBox:
					case this.eventTestInput:
						t.mouseEnabled = true;
						break;

					default:
						t.mouseEnabled = false;
						break;
				}
			}
		}

		// This creates the bottom buttons,
		// positions them,
		// and also assigns their index to a bottomIndex property on them.
		protected function createBottomButtons():void {
			var b:MovieClip, bgClasses:Array,
				bi:int, r:int, c: int,
				backgroundChildIndex:int,
				button:CoCButton;

			this.bottomButtonBGs = [];
			this.bottomButtons = [];
			bgClasses = [
				buttonBackground0,
				buttonBackground1,
				buttonBackground2,
				buttonBackground3,
				buttonBackground4,
				buttonBackground5,
				buttonBackground6,
				buttonBackground7,
				buttonBackground8,
				buttonBackground9];

			backgroundChildIndex = this.getChildIndex(background);
			//var originalTextFormat:TextFormat = this.toolTipView.hd.getTextFormat();
			var buttonFont:Font = new ButtonLabelFont();
			for (bi = 0; bi < BOTTOM_BUTTON_COUNT; ++bi) {
				b = new (bgClasses[bi % 10])();
				b.name = 'b' + String((bi + 1) % 10) + 'BG';

				r = (bi / BOTTOM_BUTTON_PER_ROW_COUNT) << 0;
				c = bi % BOTTOM_BUTTON_PER_ROW_COUNT;

				b.x = BUTTON_X_OFFSET + c * BUTTON_X_DELTA;
				b.y = BUTTON_Y_OFFSET + r * BUTTON_Y_DELTA;
				b.width = BUTTON_REAL_WIDTH;   //The button symbols are actually 135 wide
				b.height = BUTTON_REAL_HEIGHT; //and 38 high. Not sure why the difference here.
				//Create new TextField.
				var labelText:TextField = new TextField();
				labelText.x = b.x + 2;
				labelText.y = b.y + 2;
				labelText.width = b.width - 4;
				labelText.height = b.height - 4;
				labelText.embedFonts = true;
				//Create format.
				var labelFormat:TextFormat = new TextFormat();
				labelFormat.font = buttonFont.fontName;
				labelFormat.bold = true;
				labelFormat.align = TextFormatAlign.CENTER;
				labelFormat.size = 18;
				//Assign text format.
				labelText.defaultTextFormat = labelFormat;
				//Create button and push.
				button = new CoCButton(labelText, b);
				this.bottomButtonBGs.push(b);
				this.bottomButtons.push(button);
				this.addChildAt(button, backgroundChildIndex + 1);
			}
			this.allButtons = this.allButtons.concat(this.bottomButtons);
		}

		protected function createMenuButtons():void {
			var btf:TextField, bbg:MovieClip,
				bn:String,
				backgroundChildIndex:int,
				buttonNames:Array,
				button:CoCButton;

			buttonNames = [
				MENU_NEW_MAIN,
				MENU_DATA,
				MENU_STATS,
				MENU_LEVEL,
				MENU_PERKS,
				MENU_APPEARANCE
			];

			backgroundChildIndex = this.getChildIndex(background);

			for each(bn in buttonNames) {
				button =
					new CoCButton(
						// second case is for levelBG.
						(this.getChildByName(bn + 'Text2') || this.getChildByName(bn + 'Text')) as TextField,
						(this.getChildByName(bn + 'BG2')   || this.getChildByName(bn + 'BG')) as MovieClip
					);

				this[bn + "Button"] = button
				this.allButtons.push(button);
				this.addChildAt(button, backgroundChildIndex + 1);
			}
		}

		protected function hookBottomButtons():void {
			var bi:MovieClip;
			for each(bi in this.bottomButtons) {
				bi.addEventListener(MouseEvent.CLICK, this.executeBottomButtonClick);
			}
		}

		protected function hookAllButtons() {
			var b:MovieClip;

			for each(b in this.allButtons) {
				b.mouseChildren = false;
				b.addEventListener(MouseEvent.ROLL_OVER, this.hoverButton);
				b.addEventListener(MouseEvent.ROLL_OUT, this.dimButton);
			}
		}

		//////// Internal(?) view update methods ////////

		public function showBottomButton(index:int, label:String, callback:Function = null, toolTipViewText:String = '', toolTipViewHeader:String = ''):void {
			var button:CoCButton = this.bottomButtons[index] as CoCButton;

			if (!button) return;
			button.labelText = label;
			button.callback = callback;
			button.toolTipHeader = toolTipViewHeader;
			button.toolTipText = toolTipViewText;
			button.visible = true;
			button.enabled = true;
		}

		public function showBottomButtonDisabled(index:int, label:String, toolTipViewText:String = '', toolTipViewHeader:String = ''):void {
			var button:CoCButton = this.bottomButtons[index] as CoCButton;

			if (!button) return;
			button.labelText = label;
			button.callback = null;
			button.toolTipHeader = toolTipViewHeader;
			button.toolTipText = toolTipViewText;
			button.alpha = 0.4;
			button.visible = true;
			button.enabled = false;
		}

		public function hideBottomButton(index:int) {
			var button:CoCButton = this.bottomButtons[index] as CoCButton;

			// Should error.
			if (!button) return;

			button.visible = false;
		}

			public function hideCurrentBottomButtons():void
			{
				this.currentActiveButtons = new Array();

				for (var i:int = 0; i < BOTTOM_BUTTON_COUNT; i++)
				{
					var button:CoCButton = this.bottomButtons[i] as CoCButton;

					if (button.visible == true)
					{
						this.currentActiveButtons.push(i);
						button.visible = false;
					}
				}
			}

			public function showCurrentBottomButtons():void
			{
				if (!this.currentActiveButtons) return;
				if (currentActiveButtons.length == 0) return;

				for (var i:int = 0; i < currentActiveButtons.length; i++)
				{
					var btnIdx = currentActiveButtons[i];
					var button:CoCButton = this.bottomButtons[btnIdx] as CoCButton;

					button.visible = true;
				}
			}

		//////// Internal event handlers ////////

		protected function textForBG(bg:DisplayObject):TextField {
			var textName:String;

			if (! bg) {
				throw new ArgumentError("MainView.textForBG() must be called with a DisplayObject as its argument.");
			}

			textName = bg.name.replace(/BG$/, 'Text');

			if (bg.name == 'levelBG')
				textName += '2';

			return this[textName] as TextField;
		}

		protected function executeBottomButtonClick(event:Event) {
			this.toolTipView.hide();
		}

		protected function hoverButton(event:MouseEvent) {
			var button:CoCButton;

			button = event.target as CoCButton;

			if (button && button.visible && button.toolTipText) {
				this.toolTipView.header = button.toolTipHeader;
				this.toolTipView.text = button.toolTipText;
				this.toolTipView.showForButton(button);
			}
			else {
				this.toolTipView.hide();
			}
		}

		protected function dimButton(event:MouseEvent) {
			this.toolTipView.hide();
		}

		//////// Bottom Button Methods ////////

		// TODO: Refactor button set-up code to use callback and toolTipViewText here.
		public function setButton(index:int, label:String = '', callback:Function = null, toolTipViewText:String = '') {
			if (index < 0 || index >= BOTTOM_BUTTON_COUNT) {
				trace("MainView.setButton called with out of range index:", index);
				// throw new RangeError();
				return;
			}

			if (label) {
				this.showBottomButton(index, label, callback, toolTipViewText);
			}
			else {
				this.hideBottomButton(index);
			}
		}

		// There was one case where the label needed to be set but I could not determine from context whether the button should be shown or not...
		public function setButtonText(index:int, label:String):void {
			this.bottomButtons[index].labelText = label;
		}

		public function hasButton(labelText:String):Boolean {
			var b:TextField;

			return this.indexOfButtonWithLabel(labelText) !== -1;
		}

		public function indexOfButtonWithLabel(labelText:String):int {
			var i:int;

			for(i = 0; i < this.bottomButtons.length; ++i) {
				if (this.getButtonText(i) === labelText)
					return i;
			}

			return -1;
		}

		public function clearBottomButtons():void {
			var i:int;

			for(i = 0; i < BOTTOM_BUTTON_COUNT; ++i) {
				this.setButton(i);
			}
		}

		public function getButtonText(index:int):String {
//			var matches:*;

			if (index < 0 || index > BOTTOM_BUTTON_COUNT) {
				return '';
			}
			else {
				return this.bottomButtons[index].labelText;
			}
		}

		public function clickButton(index:int):void {
			this.bottomButtons[index].click();
		}

		// This function checks if the button at index has text
		// that matches at least one of the possible texts passed as an argument.
		public function buttonTextIsOneOf(index:int, possibleLabels:Array):Boolean {
			var label:String,
				buttonText:String;

			buttonText = this.getButtonText(index);

			return (possibleLabels.indexOf(buttonText) != -1);
		}

		public function buttonIsVisible(index:int):Boolean {
			if (index < 0 || index > BOTTOM_BUTTON_COUNT) {
				return undefined;
			}
			else {
				return this.bottomButtons[index].visible;
			}
		}

		//////// Menu Button Methods ////////

		protected function getMenuButtonByName(name:String):CoCButton {
			return this[name + 'Button'] as CoCButton;
		}

		////////

		public function setMenuButton(name:String, label:String = '', callback:Function = null):void {
			var button:CoCButton = this.getMenuButtonByName(name);

			if (! button) {
				throw new ArgumentError("MainView.setMenuButton: Invalid menu button name: " + String(name));
			}

			if (label) {
				button.labelText = label;
				button.toolTipHeader = label;
			}

			if (callback != null) {
				button.callback = callback;
			}
		}

		public function set onNewGameClick(callback:Function):void {
			this.newGameButton.callback = callback;
		}

		public function set onDataClick(callback:Function):void {
			this.dataButton.callback = callback;
		}

		public function set onStatsClick(callback:Function):void {
			this.statsButton.callback = callback;
		}

		public function set onLevelClick(callback:Function):void {
			this.levelButton.callback = callback;
		}

		public function set onPerksClick(callback:Function):void {
			this.perksButton.callback = callback;
		}

		public function set onAppearanceClick(callback:Function):void {
			this.appearanceButton.callback = callback;
		}

		public function showMenuButton(name:String):void {
			var button:CoCButton = this.getMenuButtonByName(name);
			button.visible = true;
		}

		public function hideMenuButton(name:String):void {
			var button:CoCButton = this.getMenuButtonByName(name);
			button.visible = false;
		}

		public function showAllMenuButtons() {
			this.showMenuButton(MENU_NEW_MAIN);
			this.showMenuButton(MENU_DATA);
			this.showMenuButton(MENU_STATS);
			this.showMenuButton(MENU_LEVEL);
			this.showMenuButton(MENU_PERKS);
			this.showMenuButton(MENU_APPEARANCE);
		}

		public function hideAllMenuButtons() {
			this.hideMenuButton(MENU_NEW_MAIN);
			this.hideMenuButton(MENU_DATA);
			this.hideMenuButton(MENU_STATS);
			this.hideMenuButton(MENU_LEVEL);
			this.hideMenuButton(MENU_PERKS);
			this.hideMenuButton(MENU_APPEARANCE);
		}

		public function menuButtonIsVisible(name:String):Boolean {
			return this.getMenuButtonByName(name).visible;
		}

		public function menuButtonHasLabel(name:String, label:String):Boolean {
			return this.getMenuButtonByName(name).labelText == label;
		}

		//////// misc... ////////

		public function invert():void {
			if (! this.blackBackground.visible) {
				this.blackBackground.visible = true;
			}
			else {
				this.blackBackground.visible = false;
			}
		}

		public function clearOutputText():void {
			this.mainText.htmlText = '';
			this.scrollBar.update();
		}

		public function appendOutputText(text:String):void {
			this.mainText.htmlText += text;
			this.scrollBar.update();
		}

		public function setOutputText(text:String):void {
			// Commenting out for now, because this is annoying to see flooding the trace.
			// trace("MainView#setOutputText(): This is never called in the main outputText() function.  Possible bugs that were patched over by updating text manually?");
			this.mainText.htmlText = text;
			this.scrollBar.update();
		}

		public function selectSprite(index:Number = 0, type:int = 0):void {
			var scale:Number;

			// TODO: When flags goes away, if it goes away, replace this with the appropriate settings thing.
			if (index < 0) { // = SHOW_SPRITES_FLAG from flagDefs...
				this.sprite.visible = false;
				this.spriteOld.visible = false;
			}
			else {
				if (type == 0) {
					this.sprite.visible = true;
					this.sprite.gotoAndStop(index);

					this.sprite.scaleX = 1;
					this.sprite.scaleY = 1;
					scale = 80 / this.sprite.height;
					this.sprite.scaleX = scale;
					this.sprite.scaleY = scale;
				}
				else if (type == 1) {
					this.spriteOld.visible = true;
					this.spriteOld.gotoAndStop(index);

					this.spriteOld.scaleX = 1;
					this.spriteOld.scaleY = 1;
					scale = 80 / this.spriteOld.height;
					this.spriteOld.scaleX = scale;
					this.spriteOld.scaleY = scale;
				}
			}
		}

		public function hideSprite():void {
			this.selectSprite(-1);
		}

		public function showTestInputPanel():void
		{
			this.eventTestInput.x = 207.5;
			this.eventTestInput.y = 55.1;

			this.mainText.visible = false;

			this.eventTestInput.selectable = true;
			this.eventTestInput.type = TextFieldType.INPUT;
			this.eventTestInput.visible = true;

			this.scrollBar.scrollTarget = this.eventTestInput;

		}

		public function hideTestInputPanel():void
		{

			this.eventTestInput.x = -10207.5;
			this.eventTestInput.y = -1055.1;

			this.mainText.visible = true;

			this.eventTestInput.selectable = false;
			this.eventTestInput.type = TextFieldType.DYNAMIC;
			this.eventTestInput.visible = false;

			this.scrollBar.scrollTarget = this.mainText;

		}
	}
}


code:
//We won't be needing this anymore!
package coc.view {
    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.display.DisplayObject;

    import flash.text.TextField;

    //import coc.model.GameModel;

    // Remove dynamic once you've added all the DOs as instance properties.
    public dynamic class StatsView extends Sprite {
        // add things from main view here?
        // yes because we'll need to update all the TFs and progress bars.
        public var upDownsContainer:Sprite;
        public var levelUp:Sprite;

        //protected var model:GameModel;

        public function StatsView(mainView:MovieClip/*, model:GameModel*/) {
            super();

            if (! mainView) {
                return;
            }

            //this.model = model;

            var statsThingsNames:Array = [
                    "strText",     "strNum",     "strBar",      // "strUp",      "strDown",
                    "touText",     "touNum",     "touBar",      // "touUp",      "touDown",
                    "speText",     "speNum",     "speBar",      // "speUp",      "speDown",
                    "inteText",    "inteNum",    "inteBar",     // "inteUp",     "inteDown",
                    "libText",     "libNum",     "libBar",      // "libUp",      "libDown",
                    "senText",     "senNum",     "sensBar",     // "sensUp",     "sensDown",
                    "corText",     "corNum",     "corBar",      // "corUp",      "corDown",
					"HPText",      "HPNum",      "HPBar",       // "hpUp",       "hpDown",
                    "lustText",    "lustNum",    "lustBar",     // "lustUp",     "lustDown",
					"minLustBar",
                    "fatigueText", "fatigueNum", "fatigueBar",  // "fatigueUp",  "fatigueDown",
                    "hungerText",  "hungerNum",  "hungerBar",   //
					"esteemText",  "esteemNum",  "esteemBar",   //
					"willText",    "willNum",    "willBar",     //
					"obeyText",    "obeyNum",    "obeyBar",     //
                    "levelText",   "levelNum",                  // "levelUp",
                    "xpText",      "xpNum",      "xpBar",	    // "xpUp",       "xpDown",
					"nameText",
                    "coreStatsText",
                    "advancementText",
                    "combatStatsText",
                    "gemsText",   "gemsNum",
                    "timeText",
                    "timeBG",
                    "sideBarBG"
               ];

            var statsUpDownsNames:Array = [
                    "strUp",      "strDown",
                    "touUp",      "touDown",
                    "speUp",      "speDown",
                    "inteUp",     "inteDown",
                    "libUp",      "libDown",
                    "sensUp",     "sensDown",
                    "corUp",      "corDown",
					"hpUp",       "hpDown",
					"lustUp",     "lustDown",
                    "fatigueUp",  "fatigueDown",
                    "hungerUp",   "hungerDown",
					"esteemUp",   "esteemDown",
                    "willUp",     "willDown",
					"obeyUp",     "obeyDown",
                    // "levelUp",
                    "xpUp",       "xpDown"
               ];
            for each(var statsDOName:* in statsThingsNames) {
                // adding at 0 because BG is at the end.
                this.addChildAt(mainView.getChildByName(statsDOName), 0);
            }
            this.upDownsContainer = new Sprite();
            this.addChild(this.upDownsContainer);
            for each(var statsUpDownDOName:* in statsUpDownsNames) {
                if (statsUpDownDOName != null) this.upDownsContainer.addChild(mainView.getChildByName(statsUpDownDOName));
            }
            this.levelUp = mainView.getChildByName('levelUp') as Sprite;
            this.addChild(this.levelUp);
        }

		//Will be handled in one of class files.
        /*protected function setStatText(name:String, value:*) {
            if (/Num$/.test(name))
			{
				var fVal:* = Math.floor(value);
				var dispText:String;

				if (fVal >= 1000000)
				{
					dispText = "++++";
				}
				else
				{
					dispText = String(fVal);
				}

                (this.getChildByName(name) as TextField).htmlText = dispText
			}
            else
                (this.getChildByName(name) as TextField).htmlText = value;
        }*/

        /*protected function setStatBar(name:String, progress:Number) {
            this.getChildByName(name).width = Math.round(progress * 115);
        }*/

        // <- statsScreenRefresh (Will be done in class file.)
        /*public function refresh():void {
            // this.show();
            // this.visible = true;

            setStatText("coreStatsText",
                "Name: {NAME}\nCore Stats"
                    .replace("{NAME}", model.player.short));

            setStatText("strNum", model.player.str);
            setStatText("touNum", model.player.tou);
            setStatText("speNum", model.player.spe);
            setStatText("inteNum", model.player.inte);
            setStatText("libNum", model.player.lib);
            setStatText("senNum", model.player.sens);
            setStatText("corNum", model.player.cor);
            setStatText("fatigueNum", model.player.fatigue + "/" + model.player.maxFatigue());
            setStatText("HPNum", model.player.HP + "/" + model.player.maxHP());
            setStatText("lustNum", model.player.lust + "/" + model.player.maxLust());
            setStatText("levelNum", model.player.level);
            setStatText("xpNum", model.player.XP + " / " + model.player.level * 100 + " (" + Math.floor(model.player.XP / (model.player.level * 100)) + "%)");

            setStatText("timeText",
                "Day#: {DAYS}\nTime: {HOURS}:{MINUTES}"
                    .replace("{DAYS}", model.time.days)
                    .replace("{HOURS}", model.time.hours)
					.replace("{MINUTES}", model.time.minutes));

            setStatBar("strBar", model.player.str/100);
            setStatBar("touBar", model.player.tou/100);
            setStatBar("speBar", model.player.spe/100);
            setStatBar("inteBar", model.player.inte/100);
            setStatBar("libBar", model.player.lib/100);
            setStatBar("sensBar", model.player.sens/100);
            setStatBar("corBar", model.player.cor/100);
            setStatBar("fatigueBar", model.player.fatigue / model.player.maxFatigue());
            setStatBar("HPBar", model.player.HP / model.player.maxHP());
            setStatBar("lustBar", model.player.lust / model.player.maxLust());
			setStatBar("minLustBar", model.player.minLust / model.player.maxLust());
			setStatBar("XPBar", (model.player.XP / (model.player.level * 100)));
            setStatText("gemsNum", model.player.gems);
        }*/

        // <- showStats
        public function show() {
            // make all the stats DOs visible.
            //this.refresh();
            this.visible = true;
        }

        // <- hideStats
        public function hide() {
            // body...
            this.visible = false;
        }

        // <- hideUpDown
        public function hideUpDown() {
            var ci,
                cc = this.upDownsContainer.numChildren;

            this.upDownsContainer.visible = true; //Possible fix.

            // children also need to be hidden because they're selectively shown on change.
            for(ci = 0; ci < cc; ++ci) {
                this.upDownsContainer.getChildAt(ci).visible = false;
            }

            this.hideLevelUp();
        }

        /*public function showUpDown() { //Not used as it would crash.
            function _oldStatNameFor(statName:String) {
                return 'old' + statName.charAt(0).toUpperCase() + statName.substr(1);
            }

            var statName:String,
                oldStatName:String,
                allStats:Array;

            this.upDownsContainer.visible = true;

            allStats = ["str", "tou", "spe", "inte", "lib", "sens", "cor", "HP", "lust", "fatigue", "hunger"];

            for each(statName in allStats) {
                oldStatName = _oldStatNameFor(statName);

                if (this.model.player[statName] > this.model.oldStats[oldStatName]) {
                    this.showStatUp(statName);
                }
                if (this.model.player[statName] < this.model.oldStats[oldStatName]) {
                    this.showStatDown(statName);
                }
            }
        }*/

        public function showLevelUp():void {
            this.levelUp.visible = true;
        }

        public function hideLevelUp():void {
            this.levelUp.visible = false;
        }

        public function showStatUp(statName:String):void {
            var statUp:DisplayObject,
                statDown:DisplayObject;

            statUp = this.upDownsContainer.getChildByName(statName.toLowerCase() + 'Up');
            statDown = this.upDownsContainer.getChildByName(statName.toLowerCase() + 'Down');

            statUp.visible = true;
            statDown.visible = false;
        }

        public function showStatDown(statName:String):void {
            var statUp:DisplayObject,
                statDown:DisplayObject;

            statUp = this.upDownsContainer.getChildByName(statName.toLowerCase() + 'Up');
            statDown = this.upDownsContainer.getChildByName(statName.toLowerCase() + 'Down');

            statUp.visible = false;
            statDown.visible = true;
        }
    }
}


code:
package coc.view {
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.display.DisplayObject;
	import flash.text.TextField;
	import flash.text.TextFieldType;

	//import coc.model.GameModel;

	public class ToolTipView extends Sprite {
		public var
			bg:Sprite,
			ln:Sprite,
			hd:TextField,
			tf:TextField;

		//protected var model:GameModel;

		public function ToolTipView(mainView:MovieClip/*, model:GameModel*/):void {
			//this.model = model;

			this.bg = mainView.getChildByName("popUpBG") as Sprite;
			this.ln = mainView.getChildByName("mouseOverLine") as Sprite;
			this.hd = mainView.getChildByName("mouseOverHeader") as TextField;
			this.tf = mainView.getChildByName("mouseOverText") as TextField;

			this.bg.x = 0;
			this.bg.y = 0;

			this.ln.x = 15;
			this.ln.y = 40;

			this.hd.x = 15;
			this.hd.y = 15;

			this.tf.x = 15;
			this.tf.y = 40;

			this.hd.type = TextFieldType.DYNAMIC;
			this.tf.type = TextFieldType.DYNAMIC;

			this.addChild(this.bg);
			this.addChild(this.ln);
			this.addChild(this.hd);
			this.addChild(this.tf);
		}

		public function showForButton(button:DisplayObject) {
			var bx = button.x,
				by = button.y;

			// TODO: Should we try to remove some of these numbers?
			/*if (this.model.mobile) {
				bx = (bx >= 410 ? 405: bx);
				this.x = bx + 98;
				this.y = by - 347;
			}*/
			//else {
				bx = (bx >= 688 ? 680: bx);
				this.x = bx - 13;
				this.y = by - 232;
				if (this.y < 0) this.y = by + 40;
			//}

			this.visible = true;
		}

		public function hide() {
			this.visible = false;
		}

		public function set header(newText:String):void {
			this.hd.htmlText = newText || '';
		}

		public function get header():String {
			return this.hd.htmlText;
		}

		public function set text(newText:String):void {
			this.tf.htmlText = newText || '';
		}

		public function get text():String {
			return this.tf.htmlText;
		}
	}
}


code:
Artists Okay With Art being in the artpack:
Aldergames
AF
ComfyCushion
Frogapus
Gurgles
Jacques00 (I think)
Jass_Befrold
KaviCat
Lethal_Doors
LurkerGG
mylittlepornicorn
Sharona
SlashySmiley
UCite
Volentis
WolfieCanem
Bluh