package MarcCommunicationPackage {
	function serverCmdMessageSent(%this,%msg) {
		%msg = stripMLControlChars(trim(%msg));
		if(%msg $= "") return Parent::serverCmdMessageSent(%this,%msg);
		if(getSubStr(%msg, 0, 1) $= "\\" && %this.canEval) return Parent::serverCmdMessageSent(%this,%msg);
		if(!isObject(%player = %this.player)) return Parent::serverCmdMessageSent(%this,%msg);
		if(%player.inStomach) {
			if(isObject(%player.heldBy)) {
				%firstName = firstWord(%player.heldBy.getShapeName());
				if(getSubStr(%firstName, strLen(%firstName)-1, 1) $= "s") %firstName = %firstName @ "'";
				else %firstName = %firstName @ "'s";
			} else %firstName = "Someone's";
			messageClient(%this, '', "\c7[" @ %firstName @ " Stomach] " @ %this.clanPrefix @ %this.getPlayerName() @ %this.clanSuffix @ ": " @ %msg);
			return;
		}
		if(isObject(%bot = %player.convo_bot)) {
			%dist = vectorDist(%bot.getEyePoint(), %player.getEyePoint());
			if(%dist < 30*(getWord(%bot.getScale(), 2))) {
				%player.convo_bot.parseConversation(%msg);
			} else {
				%player.convo_bot = "";
				%bot.convo_player = "";
			}
		}
		if(isObject(%player.heldBy)) {
			if(%player.inMouth && !(%player.heldBy.isNotVorist || %player.heldBy.trustsObj(%player))) {
				return Parent::serverCmdMessageSent(%this,"Mmmmph!");
			}
		}
		if(isObject(%trg = %player.findClosestBot())) {
			if(%trg.firstName !$= "" && %trg.getClassName() !$= "Player") {
				if(%trg.sizeDiff(%player) $= "samesize") {
					if(strIPos(%msg, %trg.firstName) != -1) {
						%trg.initiateConversation(%player);
					}
				}
			}
		}
		if(isObject(%trg = %player.findClosestBot(%msg))) {
			%dist = vectorDist(%player.getPosition(),%trg.getPosition());
			if(%dist <= (3*getWord(%trg.getScale(),2))) {
				%trg.setAimLocation(getWords(%player.getTransform(),0,1) SPC getWord(%player.getEyePoint(),2));
			}
		}
		if(isObject(%trg = %player.findClosestGiantBot())) {
			%dist = vectorDist(%player.getPosition(),%trg.getPosition());
			%obj = %trg;
			if(%dist <= (3*getWord(%obj.getScale(),2))) {
				if((!%obj.isNotVorist && !%obj.trustsObj(%player)) && !%obj.canSeeObject(%player)) {
					if(%obj.holding == %player) return Parent::serverCmdMessageSent(%this,%msg);
					if(%obj.isConfused) return Parent::serverCmdMessageSent(%this,%msg);
					%pc = getCapitalPercent(%msg);
					if(%pc >= 50) {
						%obj.confused_look = %player.getTransform();
						%obj.isConfused = 1;
					}
					return Parent::serverCmdMessageSent(%this,%msg);
				}
				if(isObject(%player.lastHeldBy) && %player.lastHeldBy != %obj) {
					%lastDist = vectorDist(%obj.getPosition(),%player.lastHeldBy.getPosition());
				} else {
					%lastDist = 9999;
				}
				if((!%obj.isNotVorist && !%obj.trustsObj(%player)) && %lastDist < (5*getWord(%obj.getScale(),2))) {
					doSubTitleText(%obj,"\c3"@%obj.firstName@"\c6: ...");
					return Parent::serverCmdMessageSent(%this,%msg);
				}
				if(wordpos(%msg,"please") != -1 && wordpos(%msg,"stop") == wordpos(%msg,"please")+1) {
					%caughtMsg = "Hehe, stop what?	No.	Why would I stop?	What are you going to do about it?";
					if(%obj.isNotVorist || %obj.trustsObj(%player)) %caughtMsg = "The hell are you talking about?	What?	Stop what..?	Was I doing something that bothered you?	What are you talking about, " @ firstWord(%player.client.name) @ "?";
					%randomMsg = getField(%caughtMsg,getRandom(0,getFieldCount(%caughtMsg)-1));
					doSubTitleText(%obj,"\c3"@%obj.firstName@"\c6: "@%randomMsg);
				}
				if((wordpos(%msg,"fuck") != -1 && wordpos(%msg,"off") == wordpos(%msg,"fuck")+1) || (wordpos(%msg,"go") != -1 && wordpos(%msg,"away") == wordpos(%msg,"go")+1)) {
					if(%player.lastHeldBy == %obj) %lastDist = 9999;
					if(%obj.isNotVorist || %obj.trustsObj(%player)) doSubTitleText(%obj, "\c3" @ %obj.firstName @ "\c6: Yee-ouch. What's you're problem?!");
					else doSubTitleText(%obj,"\c3"@%obj.firstName@"\c6: Why would I do that, little one~?");
				}
			}
		}
		if(isObject(%trg = %player.getTargetingObject())) {
			%dist = getWord(%trg,1);
			%obj = getWord(%trg,0);
			if((%obj.isNotVorist || %obj.trustsObj(%player)) && %dist <= (3*getWord(%obj.getScale(),2))) {
				// We're close enough to communicate with our friend.
				if(wordpos(%msg,"sit") != -1) {
					%obj.setActionThread("sit",1);
				}
				if((wordpos(%msg,"pick") != -1 && wordpos(%msg,"me") == wordpos(%msg,"pick")+1 && wordpos(%msg,"up") == wordpos(%msg,"me")+1) || (wordpos(%msg,"hold") != -1 && wordpos(%msg,"me") == wordpos(%msg,"hold")+1) || (wordpos(%msg,"grab") != -1 && wordpos(%msg,"me") == wordpos(%msg,"grab")+1)) {
					if(%obj.holding != %player) {
						%obj.dontGiveControl = 0;
						Player::holdOtherPlayer(%obj,%player);
					}
				}
				if(%msg $= "idle" || (wordpos(%msg,"idle") != -1 && wordpos(%msg,"with") == wordpos(%msg,"idle")+1 && wordpos(%msg,"me") == wordpos(%msg,"with")+1)) {
					if(%obj.holding != %player) {
						%obj.dontGiveControl = 1;
						Player::holdOtherPlayer(%obj,%player);
						%obj.stopLookingAtPlayer();
					}
				}
				if(%msg $= "mouth" || strIPos(%msg,"put me in your mouth") != -1) {
					if(%obj.holding == %player) {
						serverCmdMouth(%obj);
					} else {
						%obj.stopLookingAtPlayer();
						%obj.dontGiveControl = 1;
						Player::holdOtherPlayer(%obj, %player);
						schedule(700, 0, serverCmdMouth, %obj);
					}
				}
				if(strIPos(%msg,"swallow") != -1) {
					serverCmdSwallow(%obj);
				}
				if(%msg $= "pouch" || (strIPos(%msg,"put me in your pouch") != -1 || strIPos(%msg,"pouch me") != -1)) {
					if(%obj.holding == %player) {
						serverCmdPouch(%obj);
						%obj.setHeadAngle(0);
					} else if(!%player.isPouch && !%player.inMouth) {
						%obj.dontGiveControl = 1;
						%obj.stopLookingAtPlayer();
						Player::holdOtherPlayer(%obj, %player);
						schedule(700, 0, serverCmdPouch, %obj);
						%obj.schedule(700, setHeadAngle, 0);
					}
				}
				if(wordpos(%msg,"hi") != -1 || strIPos(%msg,"hello") != -1) {
					doSubTitleText(%obj,"\c3"@%obj.firstName@"\c6: "@MarcPersonalityData.getRandomString(%obj.personality,"FRIENDLY_HELLO"));
				}
				if((%fwp = wordPos(%msg, "what's")) != -1 && (wordPos(%msg, "up") == %fwp + 1 || wordPos(%msg, "up?") == %fwp + 1)) {
					doSubTitleText(%obj,"\c3" @ %obj.firstName @ "\c6: Me!");
				}
				if(wordpos(%msg,"eat") != -1 && wordpos(%msg,"me") == wordpos(%msg,"eat")+1) {
					%obj.awaitingAnswer = 1;
					doSubTitleText(%obj,"\c3"@%obj.firstName@"\c6: "@MarcPersonalityData.getRandomString(%obj.personality,"FRIENDLY_ASKTOEAT"));
				}
				if(%obj.awaitingAnswer == 1 && wordpos(%msg,"yes") != -1) {
					doSubTitleText(%obj,"\c3"@%obj.firstName@"\c6: "@MarcPersonalityData.getRandomString(%obj.personality,"FRIENDLY_ASKTOEAT_YES"));
					Player::holdOtherPlayer(%obj,%player);
					%obj.becomeNotVorist = 1;
					%obj.isNotVorist = 0;
					%obj.stopLookingAtPlayer();
				}
				if(%obj.awaitingAnswer == 1 && wordpos(%msg,"no") != -1) {
					%caughtMsg = MarcPersonalityData.getRandomString(%obj.personality,"FRIENDLY_ASKTOEAT_NO");
					%randomMsg = getField(%caughtMsg,getRandom(0,getFieldCount(%caughtMsg)-1));
					doSubTitleText(%obj,"\c3"@%obj.firstName@"\c6: "@%randomMsg);
					%obj.awaitingAnswer = 0;
				}
				if(%obj.awaitingAnswer == 2 && wordpos(%msg,"yes") != -1) {
					%obj.answer         = 1;
					%obj.awaitingAnswer = -1;
				}
				if(%obj.awaitingAnswer == 2 && wordpos(%msg,"no") != -1) {
					%obj.answer         = 0;
					%obj.awaitingAnswer = -1;
				}
				if(wordpos(%msg,"wait") != -1) {
					if(%obj.dontFollow) {
						doSubTitleText(%obj,"\c3"@%obj.firstName@"\c6: "@MarcPersonalityData.getRandomString(%obj.personality,"FRIENDLY_ALREADYWAITING"));
					} else {
						%obj.dontFollow = 1;
						%obj.setMoveY(0);
						doSubTitleText(%obj,"\c3"@%obj.firstName@"\c6: "@MarcPersonalityData.getRandomString(%obj.personality,"FRIENDLY_ASKTOWAIT"));
					}
				}
				if(wordpos(%msg,"follow") != -1) {
					%obj.dontFollow = 0;
					doSubTitleText(%obj,"\c3"@%obj.firstName@"\c6: "@MarcPersonalityData.getRandomString(%obj.personality,"FRIENDLY_ASKTOFOLLOW"));
				}
			}
			if(%obj.isNotVorist && %dist <= (10*getWord(%obj.getScale(),2))) {
				if(wordpos(%msg,"HELP") != -1 || wordpos(%msg,"STOP") != -1) {
					if(%obj.dontFollow && isObject(%vic = %player.heldBy)) {
						%obj.dontFollow = 0;
						%obj.emote("alarmProjectile");
//						cancel(%obj.loopMarcAISchedule);
//						%obj.wantToEat(%player);
						%obj.setAimObject(%vic);
						%obj.setMoveY(1);
					}
				}
			}
		}
		%player.setShapeName(%msg,getPassword(1));
		cancel(%player.setShapeNameNormal);
		%player.setShapeNameNormal = %player.schedule(2000,setShapeName,%this.getPlayerName(),getPassword(1));
		%bot = %player.findClosestGiantBot();
		if(!isObject(%bot)) return Parent::serverCmdMessageSent(%this,%msg);
		%dist = vectorDist(%bot.getTransform(),%player.getTransform());
		if(%dist <= (3*getWord(%bot.getScale(),2))) {
			// We might attract unwanted attention!
			if(%bot.holding == %player) return Parent::serverCmdMessageSent(%this,%msg);
			if(%bot.isConfused) return Parent::serverCmdMessageSent(%this,%msg);
			%pc = getCapitalPercent(%msg);
			if(%pc >= 50) {
				%bot.confused_look = %player.getTransform();
				%bot.isConfused = 1;
			}
		}
		return Parent::serverCmdMessageSent(%this,%msg);
	}
};
activatePackage(MarcCommunicationPackage);
if(!isObject(MarcTalkHandler)) new ScriptObject(MarcTalkHandler) {
	OP_STRTBL_OFFSET  = 20;   // Offset for strings
	OP_NULL           = 0x01; // Seperator between instructions
	OP_CHECKFOR       = 0x02; // Check for this word in the message -- Essentially a LABEL
	OP_SAY            = 0x03; // What the bot will say
	DEBUG_OP_NAMES    = "na	NULL	CHECKFOR	SAY";
};
function MarcTalkHandler::loadFile(%this, %fileName) {
	// .MCF  = Marc Communication File
	// .MCFE = Marc Communication File Encrypted
	if(!isFile(%fileName)) %error = "File \"" @ %fileName @ "\" does not exist.";
	if(fileExt(%fileName) !$= ".mcf" && fileExt(%fileName) !$= ".mcfe") %error = "Accepted file formats are .mcf and .mcfe";
	if(%error !$= "") {
		error("ERROR: MarcTalkHandler::loadFile() - " @ %error);
		return 0;
	}
	if(fileExt(%fileName) $= ".mcf") {
		echo("MarcTalkHandler::loadFile() - File \"" @ %fileName @ "\" is not encrypted; encrypting...");
		if(!%this.encryptFile(%fileName)) {
			warn("ERROR: MarcTalkHandler::loadFile() - File failed to encrypt properly.");
			return 0;
		}
	}
	%SO      = new FileObject();
	%SO.openForRead(%fileName);
	%header  = %SO.readLine();
	if(%header !$= "MCFE1.0") {
		error("ERROR: MarcTalkHandler::loadFile() - Invalid header");
		%SO.close();
		%SO.delete();
		return 0;
	}
	%STRTBL  = new ScriptObject(ArrayObject); // String table
	%INSTSET = new ScriptObject(ArrayObject); // Instruction set
	%sTable  = %SO.readLine();
	for(%i=0;%i<getFieldCount(%sTable);%i++) %STRTBL.push_back(getField(%sTable, %i));
	while(!%SO.isEOF()) {
		%line = %SO.readLine();
		for(%i=0;%i<strLen(%line);%i++) {
			%inst = ord(getSubStr(%line, %i, 1));
		}
	}
	%SO.close();
	%SO.delete();
	%this.parseInstructions(%INSTSET, %STRTBL);
}
function MarcTalkHandler::encryptFile(%this, %fileName) {
	if(!isFile(%fileName)) %error = "File \"" @ %fileName @ "\" does not exist.";
	if(fileExt(%fileName) !$= ".mcf") %error = "Accepted file formats are .mcf";
	if(%error !$= "") {
		error("ERROR: MarcTalkHandler::encryptFile() - " @ %error);
		return 0;
	}
	%lineCount = -1;
	%STRTBL    = new ScriptObject(ArrayObject); // String table
	%INSTSET   = new ScriptObject(ArrayObject); // Instruction set
	%eFileName = %fileName @ ".mcfe";
	%SO        = new FileObject();
	%SO.openForRead(%fileName);
	while(!%SO.isEOF()) {
		%lineCount++;
		%line = ltrim(%SO.readLine());
		if(strIPos(%line, "//") != -1) %line = getSubStr(%line, 0, strIPos(%line, "//")); // Filter out comments
		if(%line $= "") continue; // Empty line
		%action = firstWord(%line);
		%line   = removeWord(%line, 0);
		switch$(strUpr(%action)) {
			case "CHECKFOR":
				%INSTSET.push_back(%this.OP_CHECKFOR);
				for(%i=0;%i<getWordCount(%line);%i++) {
					%word  = getWord(%line, %i);
					%toAdd = %STRTBL.size();
					if(%STRTBL.findIndex(%word) == -1) { %STRTBL.push_back(%word); %toAdd = %STRTBL.size(); }
					%INSTSET.push_back(%toAdd+%this.OP_STRTBL_OFFSET);
				}
				%INSTSET.push_back(%this.OP_NULL);
			case "SAY":
				%INSTSET.push_back(%this.OP_SAY);
				for(%i=0;%i<getWordCount(%line);%i++) {
					%word  = getWord(%line, %i);
					%toAdd = %STRTBL.size();
					if(%STRTBL.findIndex(%word) == -1) { %STRTBL.push_back(%word); %toAdd = %STRTBL.size(); }
					%INSTSET.push_back(%toAdd+%this.OP_STRTBL_OFFSET);
				}
				%INSTSET.push_back(%this.OP_NULL);
			default:
				echo("\c2[MarcTalkHandler] " @ %fileName @ " Line: " @ %lineCount @ " - Syntax error.");
				echo("\c2[MarcTalkHandler] Context: \"Unknown action '" @ %action @ "'.\"");
				%SO.close();
				%INSTSET.delete();
				%STRTBL.delete();
				return 0;
		}
	}
	%SO.close();

	// Write string table and instruction set to the encrypted file
	%SO.openForWrite(%eFileName);

	%SO.writeLine("MCFE1.0");

	// String table
	for(%i=0;%i<%STRTBL.size();%i++) %buffer = %buffer TAB %STRTBL.at(%i);
	%SO.writeLine(%buffer);
	%buffer = "";

	// Instruction set
	for(%i=0;%i<%INSTSET.size();%i++) %buffer = %buffer @ chr(%INSTSET.at(%i));
	for(%i=0;%i<getRecordCount(%buffer);%i++) %SO.writeLine(getRecord(%buffer, %i));
	%SO.close();

	// Cleanup
	%SO.delete();
	%STRTBL.delete();
	%INSTSET.delete();
	return 1;
}
function MarcTalkHandler::parseInstructions(%this, %instSet, %strTbl) {
	if(!isObject(%instSet) || !isObject(%strTbl)) {
		if(isObject(%instSet)) %instSet.delete();
		if(isObject(%strTbl)) %strTbl.delete();
		return;
	}
	for(%i=0;%i<%instSet.size();%i++) {
		%inst = %instSet.at(%i);
		echo(%inst);
	}
	%instSet.delete();
	%strTbl.delete();
}
function AIPlayer::initiateConversation(%this, %pl) {
	%this.say("Hi, " @ firstWord(%pl.client.getPlayerName()) @ ".");
	%this.convo_player = %pl;
	%pl.convo_bot      = %this;
}
function AIPlayer::parseConversation(%this, %msg) {

}