function AIPlayer::jump(%this) {
	%this.setJumping(1);
	%this.schedule(15, setJumping, 0);
}
function AIPlayer::say(%this, %msg) {
	%personality = %this.personality;
	if(MarcPersonalityData.isPersonality(%personality)) {
		if(strPos(%msg, "#") != -1) {
			for(%i=0;%i<getWordCount(%msg);%i++) {
				%tag  = getWord(%msg, %i);
				if(getSubStr(%tag, 0, 1) !$= "#") continue;
				%word = MarcPersonalityData.getRandomString(%personality, getSubStr(%tag, 1, strLen(%tag)));
				if(%word $= "") continue;
				%msg = setWord(%msg, %i, %word);
			}
		}
	}
	doSubTitleText(%this, "\c3" @ %this.firstName @ "\c6: " @ %msg);
}
function getWordWrap(%str,%index) { return getWord(%str,%index % getWordCount(%str)); }
function wordPos(%str,%word) { for(%i=0;%i<getWordCount(%str);%i++) { if(getWord(%str,%i) !$= %word) continue; return %i; } return -1; }
function AIPlayer::trustsObj(%this, %obj) {
	if(!isObject(%obj)) return 0;
	if(%obj.getClassName() $= "Player") if(wordPos(%this.trustList, %obj.client) == -1) return 0; else return 1;
	else if(%obj.getClassName() $= "AIPlayer") if(wordPos(%this.trustList, %obj) == -1) return 0; else return 1;
	return 0;
}
function AIPlayer::doTrustObj(%this, %obj) {
	if(!isObject(%obj)) return;
	if(%this.trustsObj(%obj)) return;
	if(%obj.getClassName() $= "GameConnection") %this.trustList = trim(%this.trustList SPC %obj);
	else if(%obj.getClassName() $= "AIPlayer") %this.trustList = trim(%this.trustList SPC %obj);
}
function AIPlayer::findClosestPlayer_Priority(%this) {
	// Get the closest thing by priority. If they can kill us in one hand motion, then it's probably a larger threat than someone the same size as us.
	%type = $TypeMasks::PlayerObjectType;
	%pos = %this.getPosition();
	%scale = getWord(%this.getScale(),0);
	initContainerRadiusSearch(%pos,9999999,%type);
	%priTbl = "smaller samesize bigger";
	if(!%this.isNotVorist) %priTbl = "samesize smaller bigger";
	%toRet = "99999999 0 0";
	while((%target = containerSearchNext()) != 0) {
		%target = %target.getID();
		if(%target.getDataBlock().getName() !$= "EmptyArmor" && %this != %target && !%target.inStomach && !%target.isCloaked && %target.getState() !$= "Dead" && !%target.inMouth) {
			if(%target.getClassName() $= "Player" || %target.getClassName() $= "AIPlayer") {
				if(!%target.noTarget && %this.canSeeObject(%target)) {
					%priority = wordPos(%priTbl, %this.sizeDiff(%target));
					if(%this.sizeDiff(%target) $= "bigger" && !%target.isNotVorist && !%this.trustsObj(%target) && !%this.trustsObj(%target.client)) %priority++;
					if($debug == %this) {
						if(%target.getClassName() $= "GameConnection") {
							%target.setShapeName(%this.sizeDiff(%target) SPC %priority, 8564862);
							cancel(%target.debugRevert);
							%target.debugRevert = %target.schedule(1000, setShapeName, %target.getPlayerName(), 8564862);
						} else {
							%target.setShapeName(%this.sizeDiff(%target) SPC %priority, 8564862);
							cancel(%target.debugRevert);
							%target.debugRevert = %target.schedule(1000, setShapeName, %target.firstName SPC %target.lastName, 8564862);
						}
					}
					// If the priority of this object is lower than the already got object and the object is closer to us,
					// ignore it.
					if(((%priority $= %lastPri && getWord(%toRet, 2) == 1 && !(%this.canSeeObject(%target) == 2)) || %priority > %lastPri || (%priority == %lastPri && vectorDist(%this.getTransform(),%target.getTransform()) <= getWord(%toRet, 0)))) {
						if(%this.trustsObj(%dd = %target) || %this.trustsObj(%dd = %target.client)) {
							// We trust this person, so if they move, we should pay attention to them.
							if(getWords(%this.memBank_Movement[%dd],1,4) !$= %target.getPosition()) {
								if(vectorDist(getWords(%this.memBank_Movement[%dd],1,4), %target.getPosition()) < 1*getWord(%target.getScale(),2)) {
									// They aren't moving that fast. Ignore 'em, but pay slight attention to their new position.
									%this.memBank_Movement[%dd] = getWord(%this.memBank_Movement[%dd],0) SPC %target.getPosition();
								} else %this.memBank_Movement[%dd] = getSimTime() SPC %target.getPosition();
							}
							if(getSimTime()-getWord(%this.memBank_Movement[%dd],0) > 2000) continue; // They haven't moved in a few seconds. Ignore 'em.
						}
						%lastPri = %priority;
						%toRet = vectorDist(%this.getTransform(),%target.getTransform()) SPC %target SPC (%this.canSeeObject(%target) == 2);
					}
				}
			}
		}
	}
	return %toRet;
}
function AIPlayer::makeStomachSound(%this, %friend) {
	if(getSimTime()-%this.lastStomachSound >= %this.newDecayTime) {
		%this.lastStomachSound = getSimTime();
		if(%this.digestionAmt >= 200)      %decayTime = getRandom(2000, 3000);
		else if(%this.digestionAmt >= 100) %decayTime = getRandom(3000, 4200);
		else if(%this.digestionAmt < 99)   %decayTime = getRandom(4200, 150000);
		%this.newDecayTime = %decayTime;
		%muffle = getRandomF(2);
		if(%this.digestionAmt >= 200) {
			%soundList = "GROOOOOOAN GURGLE GLORP GLUG GLG GLRP GLP GRP BLP";
		} else if(%this.digestionAmt >= 100) {
			%soundList = "Grooooooooooan~ Grglb Blb Glorp Glrb Slosh Grrrrrr Rmbl Rmmmmmmmbl Grrrroooaan";
		} else if(%this.digestionAmt <= 99 && %this.digestionAmt >= 30) {
			%soundList = "Ruuuumble Rmmmmmble Rumbbble Brbl Grrrrrooooo~";
		} else if(%friend) {
			%soundList = "Rummmmmble... Grooan... Guuurrrgle...";
			%muffle    = 1;
		} else %soundList = "non";
		%random = getWord(%soundList, getRandom(0, getWordCount(%soundList)-1));
		for(%i=0;%i<%this.getMountedObjectCount();%i++) {
			%obje = %this.getMountedObject(%i);
			%slot = %this.getMountedObjectNode(%i);
			if(%slot != 8) continue;
			if(!isObject(%obje.client)) continue;
			%whiteList = trim(%whiteList @ "_" @ %obje.client.getId() @ "_");
		}
		if(%random !$= "non") {
			doSubtitleText(%this, "(" @ %random @ ")", "", "", %muffle, %whiteList);
			if(isObject(%this.phyStomach)) doSubtitleText(%this.phyStomach, "(" @ %random @ ")", "", "", %muffle, %whiteList);
		}
	}
}
function AIPlayer::digestCooldown(%this) {
	if($Stomach::use) return;
	if(%this.digestionAmt > 0) {
		if(getSimTime()-%this.lastDigestDeduction >= 1000) {
			%this.lastDigestDeduction = getSimTime();
			%this.digestionAmt -= (isObject(%this.getMountNodeObject(8)) || isObject(%this.getMountNodeObject(7)) ? -1 : 1);
		}
	} else %this.newDecayTime = 100;
	if(%this.dataBlock.mouth) {
		if(!isObject(%this.getMountNodeObject(8)) || isObject(%this.getMountNodeObject(7))) {
			%this.hideNode("stomach");
			%this.hideNode("DigestGoop0");
			%this.hideNode("DigestGoop1");
			%this.hideNode("DigestGoop2");
		} else %this.unHideNode("stomach");
		%digestAmt = %this.digestionAmt;
		if(%digestAmt >= 200)      %node = "DigestGoop2";
		else if(%digestAmt >= 150) %node = "DigestGoop1";
		else if(%digestAmt >= 100) %node = "DigestGoop0";
		%this.unHideNode(%node);
	}
	
	// Churn the stomach
	if(%this.dataBlock.mouth && (isObject(%this.getMountNodeObject(8)) || isObject(%this.getMountNodeObject(7)))) {
		%stomachChurnStates = 7;
		
		if(%this.digestionAmt >= 70) {
			%delay = 10;
			%state = (%this.stomach_visibleChurnTimer / %delay);
			
			if(!%this.stomach_isVisiblyChurning) {
				if(getRandom(0, 10000) <= 100) {
					%this.stomach_isVisiblyChurning = 1;
					%this.stomach_visibleChurnTimer = 0;
					%this.stomach_churnHidden       = 0;
					%this.stomach_lastChurnNode     = "";
					%this.unhideNode("stomach_churn0");
				}
			} else {
				%this.stomach_visibleChurnTimer++;
				
				%node = "stomach_churn" @ %state;
				
				if(%this.stomach_lastChurnNode !$= %node) {
					%this.stomach_lastChurnNode = %node;
					
					if(%state - 1 >= 0) %this.hideNode("stomach_churn" @ %state - 1);
					%this.unHideNode(%node);
				}
				if(%this.stomach_visibleChurnTimer >= (%delay * (%stomachChurnStates + 1))) {
					%this.stomach_visibleChurnTimer = 0;
					%this.stomach_isVisiblyChurning = 0;
				}
			}
		} else {
			if(!%this.stomach_churnHidden) {
				%this.stomach_churnHidden       = 1;
				%this.stomach_isVisiblyChurning = 0;
				%this.stomach_visibleChurnTimer = 0;
				for(%i=0;%i<%stomachChurnStates;%i++) %this.hideNode("stomach_churn" @ %i);
			}
		}
	}
	
	if(%this.energyDrinkAmt > 0) {
		%this.energyDrinkAmt -= 4;
	}
	
	if(isObject(%this.getMountNodeObject(8)) || isObject(%this.getMountNodeObject(7))) {
		%mod = (%this.digestionAmt >= 200 ? 2 : (%this.energyDrinkAmt > 0 ? 4 : 10));
		if(%this.digestionAmt >= 100 && %this.digestionAmt % %mod == 0) {
			%this.digestionAmt++;
			if(getRandom(0, (%this.energyDrinkAmt > 0 ? 40 : 100)) < 10 && (getSimTime()-%this.stomach_lastChurn >= 15000 || (%this.energyDrinkAmt > 0 && getSimTime()-%this.stomach_lastChurn >= 1000))) {
				for(%i=0;%i<%this.getMountedObjectCount();%i++) {
					%obje = %this.getMountedObject(%i);
					%slot = %this.getMountedObjectNode(%i);
					if(%slot != 8 && %slot != 7) continue;
					%obje.stomach_msgTime   = getSimTime();
					%obje.stomach_message   = "\c3The stomach churns, costing you some struggle points.";
					%obje.stomach_struggle -= getRandom(50,150);
				}
				%this.stomach_lastChurn = getSimTime();
			} else {
				// Digest all players in stomach a bit
				// Hell, digest their tools if they have any out as well.
				for(%i=0;%i<%this.getMountedObjectCount();%i++) {
					%obje = %this.getMountedObject(%i);
					%slot = %this.getMountedObjectNode(%i);
					if(%slot != 8 && %slot != 7) continue;
					if(%obje.currTool != -1 && %obje.tool[%obje.currTool].digestable) {
						if((%obje.toolDigest[%obje.currTool] += getRandom(3, 5)) >= %obje.tool[%obje.currTool].digestThreshold) {
							messageClient(%obje.client, '', "\c6Your " @ %obje.tool[%obje.currTool].uiname @ " was digested!");
							%obje.tool[%obje.currTool].image.onDigest(%this);
							%obje.toolDigest[%obje.currTool] = 0;
							if(!%obje.client.isAdmin) {
								messageClient(%obje.client, 'MsgItemPickup', '', %obje.currTool, 0);
								%obje.playThread(1, "root");
								%obje.unmountImage(%obje.tool[%obje.currTool].image.mountPoint);
								%obje.tool[%obje.currTool] = 0;
								%obje.currTool = -1;
							}
						} else {
							messageClient(%obje.client, '', "\c6Your " @ %obje.tool[%obje.currTool].uiname @ " is being digested (" @ mFloor((%obje.toolDigest[%obje.currTool] / %obje.tool[%obje.currTool].digestThreshold) * 100) @ "%)!");
						}
					}
					if(%obje.invulnerable) {
						%newDmg = %obje.getDamageLevel() + getRandom(3,5);
						if(%newDmg >= %obje.getDataBlock().maxDamage-1) {
							%newDmg = %obje.getDataBlock().maxDamage-1;
						}
						%obje.setDamageLevel(%newDmg);
					} else %obje.setDamageLevel(%obje.getDamageLevel() + getRandom(3,5));
					if(%obje.digestAmt < 200) %obje.stomach_stamina -= getRandom(10, 12);
					else %obje.stomach_stamina -= getRandom(5, 8);
				}
			}
		}
	}
	%this.makeStomachSound();
}

function AIPlayer::curiosity_shiver(%this) {
	%fVect = %this.getForwardVector();
	%side  = vectorCross(%fVect, %this.getUpVector());
	%sideW = (getWord(%this.getWorldBox(), 3) - getWord(%this.getWorldBox(), 0)) / 70;
	
	switch(%this.curi_state) {
		case 0: %this.curi_shiver_offset = %sideW;
		case 1: %this.curi_shiver_offset = 0;
		case 2: %this.curi_shiver_offset = -%sideW;
		case 3: %this.curi_shiver_offset = 0; %this.curi_state = 0;
	}
	%this.curi_state++;
	
	%this.setTransform(vectorAdd(getWords(%this.curi_oriPos, 0, 1) SPC getWord(%this.getPosition(), 2), vectorScale(%side, %this.curi_shiver_offset)) SPC getWords(%this.getTransform(), 3, 6));
}

function AIPlayer::curiosity_reset(%this) {
	%this.curi_alreadySetWaitTime = 0;
	%this.curi_maxWait = 10000;
	%this.curi_resetOnce = 1;
	%this.curi_done = 0;
	%this.curi_shiverGo = 1;
}

function AIPlayer::curiosity_loop(%this, %target) {
	if(!%this.curi_resetOnce) %this.curiosity_reset();
	if(%this.runAway > 0) { %this.curiosity_reset(); return; }
	
	if(!%this.curi_alreadySetWaitTime) {
		%this.curi_alreadySetWaitTime = 1;
		%this.curi_waitTime = getSimTime();
		%this.curi_state    = 0;
		%this.curi_oriPos   = %this.getPosition();
		%this.curi_tarPos   = %target.getPosition();
	}
	
	if(%target.getPosition() !$= %this.curi_tarPos) {
		if(vectorDist(%target.getPosition(), %this.curi_tarPos) <= 0.3) {
			%this.curi_tarPos = %target.getPosition();
		} else {
			%this.backUpFrom = %target;
			%this.backUpCycle = 20;
			%this.curiosity_reset();
			%this.setAimLocation(%target.getEyePoint());
			return;
		}
	}
	
	if(%this.curi_done || getSimTime() - %this.curi_waitTime <= %this.curi_maxWait) {
		if(%this.curi_shiverGo) %this.curiosity_shiver();
		return;
	}
	%this.curi_shiverGo = 0;
	%this.curi_waitTime = getSimTime();
	%this.curi_maxWait  = getRandom(2000, 2500);
	
	if(vectorDist(%this.getEyePoint(), getField(getRaycastFromObject(%this), 1)) <= 0.26) {
		%this.curi_done = 1;
		%this.schedule(1000, setActionThread, "sit", 1, 0);
		%this.curi_shiverGo = 1;
		%this.curi_oriPos   = %this.getPosition();
		return;
	}
	
	%this.setMoveY(0.4);
	cancel(%this.shyMove);
	%this.shyMove = schedule(250, 0, eval, %this.getId() @ ".setMoveY(0);" @ %this.getId() @ ".curi_shiverGo=1;" @ %this.getId() @ ".curi_oriPos=" @ %this.getId() @ ".getPosition();");
}

function AIPlayer::loopMarcAI(%this, %fullName, %scale, %personality, %notvore) {
	%this.digestCooldown();
	if(isObject(%this.spawnBrick)) %this.cache_spawnBrick = %this.spawnBrick;
	if(!isObject(%this.spawnBrick) && %this.cache_spawnBrick !$= "") { %this.schedule(1, delete); return; }
	if(!isEventPending(%this.wantToEat)) if(%this.thread_slot[3] !$= "root") %this.playThread(3, "root");
	if(%this.isEmbarrased) {
		if(%personality $= "") %personality = "General";
		cancel(%this.loopMarcAISchedule);
		%this.loopMarcAISchedule = schedule(100,0,eval,"$Con::logBufferEnabled = 0;"@%this@".loopMarcAI();$Con::logBufferEnabled = 1;");
		return;
	}
	if(%this.inStomach) {
		if(%this.ingestTime $= "") %this.ingestTime = getSimTime();
		if(%this.ingestTime $= "done" || getSimTime() - %this.ingestTime >= getRandom(12000, 16000)) {
			if(%this.ingestTime !$= "done" && %this.ingestTIme !$= "done2") {
				%this.stopLookingAtPlayer();
				%this.setMoveY(0);
				%this.setJumping(0);
				%this.ingestTime = "done";
			} else if(%this.ingestTime $= "done" && %this.getVelocity() $= "0 0 0") {
				%this.setActionThread("sit", 1, 0);
				%this.ingestTime = "done2";
			}
		} else {
			%stm         = %this.heldBy.phyStomach;
			%esoSpawnPos = vectorAdd(%stm.getTransform(), vectorScale("0.00381989 1.38222 6.90997", getWord(%stm.getScale(), 0)));
			%esoSpawnPos = vectorAdd(%esoSpawnPos, "0 0" SPC (getWord(%stm.esoRings.getWorldBox(), 2) - getWord(%stm.esoRings.getWorldBox(), 5)));
			%spawnPos    = Stomach_getOffset(%stm, "0.000743851 1.3466 6.208");
			%jump        = (vectorDist(getWords(%spawnPos, 0, 1), getWords(%this.getPosition(), 0, 1)) <= 0.4);
			%this.setJumping(%jump);
			%this.setAimLocation(%spawnPos);
			%this.setMoveY(2);
			%this.playThread(0, "activate2");
		}
		
		cancel(%this.loopMarcAISchedule);
		%this.loopMarcAISchedule = schedule(100,0,eval,"$Con::logBufferEnabled = 0;"@%this@".loopMarcAI();$Con::logBufferEnabled = 1;");
		return;
	}
	if(removeWord(%this.idleCache, 0) !$= %this.getTransform()) {
		//echo("\"" @ getWords(%this.idleCache,1,6) @ "\" $= \"" @ %this.getPosition() SPC %this.getEyePoint()  @ "\"");
		%this.idleCache = getSimTime() SPC %this.getTransform();
	}
	if(!isObject(%this.heldBy) && !isObject(%this.holding)) {
		if(getSimTime()-getWord(%this.idleCache, 0) >= 5000) {
			//%this.setActionThread(sit, 1, 0);
			%this.wasRelaxing = 1;
		} else {
			if(%this.wasRelaxing) {
				%this.wasRelaxing = 0;
				%this.setActionThread(root, 0,  0);
			}
		}
	}
	if(1 == 0 && isEventPending(%this.wantToEat)) {
		if(%this.isNotVorist) {
			cancel(%this.loopMarcAISchedule);
			%this.loopMarcAISchedule = schedule(100,0,eval,"$Con::logBufferEnabled = 0;"@%this@".loopMarcAI();$Con::logBufferEnabled = 1;");
		}
		return;
	}
	if(%this.movey_speed != 0) %this.movementLogicCheck();
	if(!isObject(%this.holding)) %this.playThread(2, "root");
	%this.lastCheck_CanSeeObject = 0;
	%this.targ_obj = "";
	if(%fullName !$= "") {
		%this.age         = getRandom(18,20);
		%this.isNotVorist = mClamp(%notvore,0,1);
		%this.firstName   = getWord(%fullName,0);
		%this.lastName    = getWord(%fullName,1);
		if(MarcPersonalityData.isPersonality(%personality)) {
			%this.personality = %personality;
		} else {
			%this.personality = "General";
		}
		%this.setShapeName(%this.firstName SPC %this.lastName,"8564862");
	}
	if(%scale !$= "") {
		%this.setScale(%scale);
	}
	// AI
	if(%this.isConfused && !isObject(%this.isFollowing)) {
		if(%this.isConfused == 1) {
			%start = %this.getEyePoint();
			%eyeVec = %this.getEyeVector();
			%vector = VectorScale(%eyeVec, 100);
			%end = VectorAdd(%start, %vector);
			%mask = $TypeMasks::PlayerObjectType;
			%scanTarg = containerRayCast(%start, %end, %mask, %this);
			%pos = posFromRaycast(%scanTarg);
			%this.confused_savedAimLocation = %pos;
			Player::emote(%this,wtfImage);
			%this.clearAim();
			%this.setAimLocation(%this.confused_look);
		}
		if(%this.isConfused++ >= 30) {
			// We don't care anymore.
			%this.setAimLocation(%this.confused_savedAimLocation);
			%this.isConfused = 0;
		}
	}
	if(%this.panic == 1) {
		%this.setMaxForwardSpeed(%this.getDataBlock().maxForwardSpeed+4);
		%this.panic = 2;
		%this.emote(AlarmProjectile);
	}
	if(%this.panic > 0) %this.playThread(3, activate2);
	else if(%this.panic == 0) { %this.setMaxForwardSpeed(%this.getDataBlock().maxForwardSpeed); %this.playThread(3, root); %this.panic = -1; }
	%closestPlayer = %this.findClosestPlayer_Priority();
	%this.lastClosestPlayer = %closestPlayer;
	%safeBehindGlass = (getWord(%closestPlayer, getWordCount(%closestPlayer) - 1) == 1);
	
	if(%this.runAway-- > 0 && %this.backUpCycle <= 0) {
		if(isObject(%this.getObjectMount())) %this.runAway = 0;
		%start = %this.getEyePoint();
		%eyeVec = %this.getEyeVector();
		%vector = VectorScale(%eyeVec, 1);
		%end = VectorAdd(%start, %vector);
		%mask = $TypeMasks::FxBrickAlwaysObjectType;
		%scanTarg = getWord(containerRayCast(%start, %end, %mask, %this),0);
		if(isObject(%scanTarg)) { %this.setJumping(1); %this.schedule(1,setJumping,0); }
		%lastPoint = %this.getPosition();
		if(getWordCount(%this.runningAwayFrom) == 1) {
			if(vectorDist(%this.runningAwayFrom.getPosition(), %this.getPosition()) < (20*getWord(%this.getScale(),2))) {
				%this.runAway++;
				if(%this.panic == -1) %this.panic = 1;
			}
			%point = %this.runningAwayFrom.position;
		} else {
			for(%i=0;%i<getWordCount(%this.runningAwayFrom);%i++) {
				%runFrom = getWord(%this.runningAwayFrom, %i);
				if(!isObject(%runFrom)) {
					%this.runningAwayFrom = removeWord(%this.runningAwayFrom, %i);
					%i--;
					continue;
				}
				if(%point $= "") %point = %runFrom.getPosition();
				if(vectorDist(%runFrom.getPosition(), %this.getPosition()) < (20*getWord(%this.getScale(),2))) {
					%this.runAway++;
					if(%this.panic == -1) %this.panic = 1;
				}
				%cache_p = (getWord(%lastPoint,0)+getWord(%runFrom.getPosition(),0))/2 SPC (getWord(%lastPoint,1)+getWord(%runFrom.getPosition(),1))/2;
				%point = (getWord(%cache_p,0)+getWord(%point,0))/2 SPC (getWord(%cache_p,1)+getWord(%point,1))/2;
			}
		}
		%oldFOVPref = $Pref::CanUseFOV;
		$Pref::CanUseFOV = 0;
		// Let's look for people we trust for saftey!
		for(%i=0;%i<getWordCount(%this.trustList);%i++) {
			%trustedClient = getWord(%this.trustList, %i);
			if(!isObject(%trustedClient)) {
				%this.trustList = removeWord(%this.trustList, %i);
				%i--;
				continue;
			}
			if(%trustedClient.getClassName() $= "GameConnection" && !isObject(%trPl = %trustedClient.player)) continue;
			else if(%trustedClient.getClassName() $= "AIPlayer" && !isObject(%trPl = %trustedClient)) continue;
			if(vectorDist(%this.getPosition(),%trPl.getPosition()) > (80*getWord(%this.getScale(),2))) continue; // They are too far away at the moment.
			if(!%this.canSeeObject(%trPl)) continue; // We can't see them at the moment.
			%point = vectorScale(%trPl.getEyePoint(), -1); // Flip the vector so they run towards this person.
			break;
		}
		$Pref::CanUseFOV = %oldFOVPref;
		%runTo = 0;
		if(isObject(%trustedPlayer = %this.lastHeldBy)) {
			%trustedDist = vectorDist(%trustedPlayer.getPosition(), %this.getPosition());
			if(%this.canSeeObject(%trustedPlayer)) {
				// Hold on; Our trusted player is close enough, so maybe we can run to them!
				if(%trustedDist < (2*getWord(%trustedPlayer.getScale(), 2))) {
					%this.runAway = 0;
				}
				if(%trustedPlayer.sizeDiff(getWord(%closestPlayer,1)) !$= "bigger") {
					// Let's run to our trusted player!
					%point = %trustedPlayer.getPosition();
					%runTo = 1;
				}
			}
		}
		%this.clearAim();
		if(!%runTo) %this.lookAway(%point);
		else %this.setAimLocation(%point);
		%this.setMoveY(1);
	} else {
		if(!%this.alreadyLookedBehind) {
			%lastPoint = %this.getPosition();
			if(getWordCount(%this.runningAwayFrom) == 1) {
				%point = %this.runningAwayFrom.position;
				if(%this.runningAwayFrom.getClassName() $= "AIPlayer" && %this.runningAwayFrom.isNotVorist) {
					%this.isConfused = 1;
					%this.trustList = %this.trustList SPC %this.runningAwayFrom;
				}
			} else {
				for(%i=0;%i<getWordCount(%this.runningAwayFrom);%i++) {
					%runFrom = getWord(%this.runningAwayFrom, %i);
					if(!isObject(%runFrom)) {
						%this.runningAwayFrom = removeWord(%this.runningAwayFrom, %i);
						%i--;
						continue;
					}
					if(%point $= "") %point = %runFrom.getPosition();
					if(vectorDist(%runFrom.getPosition(), %this.getPosition()) < (20*getWord(%this.getScale(),2))) {
						%this.runAway++;
						if(%this.panic == -1) %this.panic = 1;
					}
					%cache_p = (getWord(%lastPoint,0)+getWord(%runFrom.getPosition(),0))/2 SPC (getWord(%lastPoint,1)+getWord(%runFrom.getPosition(),1))/2;
					%point = (getWord(%cache_p,0)+getWord(%point,0))/2 SPC (getWord(%cache_p,1)+getWord(%point,1))/2;
				}
			}
			%this.panic = 0;
			%this.alreadyLookedBehind = 1;
			%this.setMoveY(0);
			%this.setAimLocation(%point);
			%this.runningAwayFrom = "";
		}
	}
	if(!%this.isAsleep && !isObject(%this.heldBy) && isObject(getWord(%closestPlayer,1))) {
		if(getWord(%closestPlayer,0) < (50*getWord(%this.getScale(),2))) {
			%canSeeObject = %this.canSeeObject(getWord(%closestPlayer,1));
			if(%canSeeObject) {
				%zdist = vectorDist("0 0" SPC getWord(%this.getPosition(),2),"0 0" SPC getWord(getWord(%closestPlayer,1).getPosition(),2));
				//if(%zdist > 40) %canSeeObject = 0;
			}
			if(%canSeeObject) {
				if(!isObject(%this.holding) && %this.lastEatObj != getWord(%closestPlayer,1)) {
					%dif_x = getWord(getWord(%closestPlayer,1).getScale(),0)-0.8;
					%dif_y = getWord(getWord(%closestPlayer,1).getScale(),1)-0.8;
					%dif_z = getWord(getWord(%closestPlayer,1).getScale(),2)-0.8;
					if(getWord(%this.getScale(),0) <= %dif_x) {
						if(getWord(%this.getScale(),1) <= %dif_y) {
							if(getWord(%this.getScale(),2) <= %dif_z) {
								%zDist = vectorDist("0 0 " @ getWord(%this.getPosition(),2),"0 0 " @ getWord(getWord(%closestPlayer,1).getPosition(),2));
								if(%this.backUpCycle <= 0 && strIPos(%this.runningAwayFrom,getWord(%closestPlayer,1)) == -1) {
									if((%zDist > 0 || getWord(%closestPlayer,0) > (20*getWord(getWord(%closestPlayer, 1).getScale(),2)))) {
										// They're bigger than us; Let's make sure we want to run first, though...
										if(!%this.trustsObj(getWord(%closestPlayer,1))) {
											// We don't trust this person. Run.
											%runAway = !%safeBehindGlass;
											if(isObject(%trustedPlayer = %this.lastHeldBy)) {
												%trustedDist = vectorDist(%trustedPlayer.getPosition(), %this.getPosition());
												if(%trustedDist < (3*getWord(%trustedPlayer.getScale(), 2))) {
													// Hold on; Our trusted player is close enough, so maybe we're safe?
													%runAway = 0;
													if(%trustedPlayer.sizeDiff(getWord(%closestPlayer,1)) $= "bigger") {
														// Our trusted player is too small to protect us from this thing!
														%runAway = 1;
													}
												}
											}
											if(%runAway) {
												%this.curiosity_reset();
												%this.panic = -1;
												%this.runAway = 50;
												%this.alreadyLookedBehind = 0;
												%this.runningAwayFrom = %this.runningAwayFrom SPC getWord(%closestPlayer,1);
											} else {
												if(%safeBehindGlass) %this.curiosity_loop(getWord(%closestPlayer, 1));
												%this.setAimLocation(getWord(%closestPlayer,1).getEyePoint());
											}
										} else if(%this.runAway < 0) {
											// We trust this guy, but if we're already running, we don't need to waste time looking at them!
											%this.setAimLocation(getWord(%closestPlayer,1).getEyePoint());
											%this.setMoveY(0);
											if(getWord(%closestPlayer,1).getClassName() $= "AIPlayer") {
												// If a bigger player (%closestPlayer) likes us (%this), then...
											} else {
												%this.lookAtPlayer(getWord(%closestPlayer,1));
											}
										}
									} else {
										%this.setMoveY(0);
										%this.setAimObject(getWord(%closestPlayer,1));
									}
								}
								%tooBig = 1;
							}
						}
					}
					if(!%tooBig) {
						%dif_x = getWord(%this.getScale(),0)-0.8;
						%dif_y = getWord(%this.getScale(),1)-0.8;
						%dif_z = getWord(%this.getScale(),2)-0.8;
						if(getWord(getWord(%closestPlayer,1).getScale(),0) <= %dif_x) {
							if(getWord(getWord(%closestPlayer,1).getScale(),1) <= %dif_y) {
								if(getWord(getWord(%closestPlayer,1).getScale(),2) <= %dif_z) {
									if(isObject(%this.randomAI_goToBrick)) {
										%this.randomAI_goToBrick = "";
										%this.clearAim();
										%this.setMoveY(0);
									}
									if(%this.holding.inMouth) serverCmdMouth();
									%this.holdOtherPlayer();
									%this.lastEatObj = getWord(%closestPlayer,1);
									if(!%this.isNotVorist || isObject(getWord(%closestPlayer, 1).client)) %this.wantToEat(getWord(%closestPlayer,1));
									else %this.wantToExamine(getWord(%closestPlayer, 1));
									if(%this.isConfused) {
										Player::emote(%this,alarmProjectile);
										%this.isConfused = 0;
									}
								} else
									%tooBig = 1;
							} else 
								%tooBig = 1;
						} else 
							%tooBig = 1;

						if(%tooBig) {
							// We're the same size.
							if(!isObject(%this.isFollowing) && !isObject(%this.heldBy) && !%this.isEating) {
								%client = getWord(%closestPlayer,1);
								if(%client.getClassName() $= "AIPlayer") {
									if(!isEventPending(%client.wantToEat) && !%client.isEating && !isObject(%client.heldBy) && !isObject(%client.isFollowing)) {
										%vDist = vectorDist(%this.getPosition(),%client.getPosition());
										if(!%client.antiSocial && !%this.antiSocial && %vDist < ((%client.isCrouched() ? 1 : 4)*getWord(%this.getScale(),2))) {
											// close enough to talk to
											if(getWord(%client.lastClosestPlayer,1) != %this) {
												if(getSimTime()-%this.lastConversationTime < 5000) {
													// What are they looking at?
													%this.emote(wtfImage);
													%this.setAimLocation(%client.getAimLocation());
													%code = "if(" @ %this @ ".findClosestPlayer_Priority() !$= \"" @ %closestPlayer @ "\") " @ %this @ ".setAimLocation(\"" @ %client.getEyePoint() @ "\");";
													schedule(100,0,eval,%code);
												} else {
													// Get their attention.
													%client.setAimLocation(%this.getEyePoint());
												}
											} else { %client.setAimLocation(%this.getEyePoint()); %this.lastConversationTime = getSimTime();
											if(!isEventPending(%client.stopTalking) && !isEventPending(%this.stopTalking)) {
												// Let's not interrupt them while they're talking.
				if(getRandom(0,1000) < 500) {
					%this.playThread(3, talk);
					%wait = getRandom(1000,4582);
					%this.stopTalking = %this.schedule(%wait, playThread, 3, root);
					%this.setShapeName("(Chatter, chatter...)", 8564862);
					%this.schedule(%wait-2, setShapeName, %this.firstName SPC %this.lastName, 8564862);
					%client.setShapeName("", 8564862);
					%client.schedule(%wait-2, setShapeName, %client.firstName SPC %client.lastName, 8564862);
				} else if(getRandom(0,1000) > 500) {
					%client.playThread(3, talk);
					%wait = getRandom(1000,4582);
					%client.stopTalking = %client.schedule(%wait, playThread, 3, root);
					%client.setShapeName("(Chatter, chatter...)", 8564862);
					%client.schedule(%wait-2, setShapeName, %client.firstName SPC %client.lastName, 8564862);
					%this.setShapeName("", 8564862);
					%this.schedule(%wait-2, setShapeName, %this.firstName SPC %this.lastName, 8564862);
				} // FOR SAKE OF ACCESSIBILITY -- DONT REMOVE THESE BRACKETS
												}
											}
										}
									}
								}
							}
							if(!%this.isEating && !isObject(%this.heldBy) && isObject(%this.isFollowing)) {
								%client = getWord(%closestPlayer,1);
								%this.setCrouching(%client.isCrouched());
								%this.lastEatObj = 0;
								%this.lookAtPlayer(%this.isFollowing);
								%dist = getWord(%closestPlayer,0);
								%vDist = vectorDist(%this.getPosition(),%this.isFollowing.getPosition());
								if(isEventPending(%this.wantToEat)) cancel(%this.wantToEat);
								if(%vDist < ((%this.isFollowing.isCrouched() ? 1 : 4)*getWord(%this.getScale(),2))) {
									// We're too close. Let's stop a little distance away.
									%this.setMoveY(0);
									if(%vDist < (2*getWord(%this.getScale(),2))) {
										// We don't like how close they are; let's back up.
										%this.setMoveY(-0.7);
									}
								} else
									%this.setMoveY((7*getWord(%this.getScale(),2) ? 0.7 : 1));

							} else if(!%this.isEating && !isObject(%this.held) && %this.isFollowing != -1) {
								%this.isFollowing = -1;
								%this.stopLookingAtPlayer();
								%this.setMoveY(0);
							}
						}
					}
				}
			}
		}
	}
	if(isObject(%this.heldBy)) {
		if(!%this.trustsObj(%this.heldBy)) {
			%this.backUpFrom = %this.heldBy;
			%this.backUpCycle = 20;
			%this.setAimLocation(%this.heldBy.getEyePoint());
		}
	} else {
		if(%this.backUpCycle > 0) {
			%this.backUpCycle--;
			%this.setAimObject(%this.backUpFrom);
			if(%this.backUpCycle > 0)
				%this.setMoveY(-1);
			else
				%this.setMoveY(0);

		}
	}
	if(!isObject(%this.isFollowing) && !isEventPending(%this.wantToEat)) {
		%randomAIBrickTbl = "_ai0 _ai1 _ai2 _ai3 _ai4 _ai5 _ai6 _ai7 _ai8 _ai9 _ai10";
		if(!isObject(%this.randomAI_goToBrick)) {
			if(getRandom(0,1000) <= 500) {
				for(%i=0;%i<getWordCount(%randomAiBrickTbl);%i++) {
					%randomObj = getWord(%randomAIBrickTbl,%i);
					if(!isObject(%randomObj)) continue;
					if(%randomObj == %this.lastRandomGoto) continue;
					if(isObject(%randomObj.getting)) continue;
					%randomTbl = %randomTbl SPC %randomObj;
				}
				%obj = getWord(%randomTbl,getRandom(0,getWordCount(%randomTbl)-1));
				%this.lastRandomGoto = %obj;
				%this.randomAI_goToBrick = %obj;
				%this.randomAI_goToBrick.getting = %obj;
			}
		} else {
			// Goto our random object
			%distaway = vectorDist(%this.getPosition(),%this.randomAI_goToBrick.getPosition());
			if(%distaway >= 2) {
				%this.setAimLocation(getWords(%this.randomAI_goToBrick.getTransform(),0,1) SPC getWord(%this.getEyePoint(),2));
				%this.setMoveY(0.6);
			} else {
				// Let's do what we were going to do here.
				%this.setMoveY(0);
				//%this.setTransform(%this.randomAI_goToBrick.getTransform());
				%this.randomAI_goToBrick.onBotReachBrick(%this);
				%this.randomAI_goToBrick.getting = "";
				%this.randomAI_goToBrick = "";
			}
		}
	}
	// LOOP
	cancel(%this.loopMarcAISchedule);
	if($debugsilent) {
		%this.loopMarcAISchedule = schedule(100,0,eval,"$Con::logBufferEnabled = 0;"@%this@".loopMarcAI();$Con::logBufferEnabled = 1;");
		return;
	}
	%this.loopMarcAISchedule = %this.schedule(100,loopMarcAI);
}
function AIPlayer::lookAway(%obj, %pos) {
	%curPos = %obj.getPosition();
	%pos    = setWord(%pos, 2, getWord(%curPos, 2));
	%b      = VectorDist(%curPos, %pos);
	if( %b == 0 ) return;

	%curRot = getWord(%obj.getTransform(), 6) * getWord(%obj.getTransform(), 5);

	%b_pos = VectorAdd(%curPos, %obj.getForwardVector());
	%a = VectorDist(%pos, %b_pos);
	%c = VectorDist(%curPos, %b_pos);

	%cos_theta = (%b/2) + (1 - (%a*%a)) / (%b * 2);
	if( %cos_theta >= 1 ) {
		%obj.setTransform(%curPos SPC "0 0 1" SPC (%curRot + 3.14159));
		return;
	}
	if( %cos_theta <= -1 ) {
		%obj.setTransform(%curPos SPC "0 0 1" SPC (%curRot + 3.14159));
		%obj.rotate(180);
		return;
	}
	%theta = mAcos(%cos_theta);

	%curx = firstWord(%curPos);
        %cury = getWord(%curPos, 1);
	%posx = firstWord(%pos);
        %posy = getWord(%pos, 1);
	if( %curx < %posx ) %theta *= -1;

	%slope = (%cury - %posy) / (%curx - %posx);
	if(%cury - (%slope * %curx) <  getWord(%b_pos, 1) - (%slope * firstWord(%b_pos)) )
		%theta *= -1;

	%z = 1;
	%newRot = %curRot + %theta;
	if( %newRot < 0 ) {
		%z = -1;
		%newRot *= -1;
	}

	%obj.setTransform(%curPos SPC "0 0" SPC %z SPC %newRot);
	%obj.rotate(180);
}
function AIPlayer::sizeDiff(%this, %obj) {
	// Get if we are larger, same size, or smaller than %obj
	if(!isObject(%obj) || !isFunction(%obj.getClassName(), getScale)) return "none";
	if(getWord(%this.getScale(),0) <= (getWord(%obj.getScale(), 0) - 0.8) && getWord(%this.getScale(),1) <= (getWord(%obj.getScale(), 1) - 0.8) && getWord(%this.getScale(),2) <= (getWord(%obj.getScale(), 2) - 0.8)) return "bigger";
	if(getWord(%obj.getScale(),0) <= (getWord(%this.getScale(), 0) - 0.8) && getWord(%obj.getScale(),1) <= (getWord(%this.getScale(), 1) - 0.8) && getWord(%obj.getScale(),2) <= (getWord(%this.getScale(), 2) - 0.8)) return "smaller";
	return "samesize";
}
function Player::getSizeDifference(%this, %obj) {
	return AIPlayer::sizeDiff(%this, %obj);
}
function Player::sizeDiff(%this, %obj) {
	return AIPlayer::sizeDiff(%this, %obj);
}
function AIPlayer::updateSeenHistory(%this, %obj) {
	return;
	if(wordPos(%this.seenHistory, %obj) != -1) {
		%this.seenHistory = setWord(%this.seenHistory, wordPos(%this.seenHistory, %obj)-1, getSimTime());
		return;
	}
	%this.seenHistory = trim(%this.seenHistory TAB getSimTime() SPC %obj);
}
function AIPlayer::manipulateFOV(%this) {
	%this.fov = 0;
	return;
	if(isObject(%this.holding)) { %this.fov = 0; return; }
	%this.fov = 0.9;
	// Calculate paranoia
	for(%i=0;%i<getFieldCount(%this.seenHistory);%i++) {
		%data  = getField(%this.seenHistory, %i);
		%simtm = getWord(%data, 0);
		%objid = getWord(%data, 1);
		if(!isObject(%objid)) { %data = removeField(%this.seenHistory, %i); %i--; continue; }
		if(getSimTime()-%simtm >= 120000) { %data = removeField(%this.seenHistory, %i); %i--; continue; }
		%this.fov -= 0.05; // Become more paranoid
	}
	%this.fov = mClampF(%this.fov, 0, 1);
}

// sine (sin) = up/down
// cosine (cos) = left/right

function Player::getRightVector(%this) {
	return vectorNormalize(vectorCross(%this.getForwardVector(), %this.getUpVector()));
}

function AIPlayer::stopLookingAtPlayer(%this) {
	cancel(%this.lookAtPlayer);
	%this.clearAim();
}

function AIPlayer::lookAtPlayer(%this, %pl, %loop) {
	if(!isObject(%pl)) return;
	%curPos = %this.getPosition();
	%pos    = setWord(%pl.getEyePoint(), 2, getWord(%curPos, 2));
	%b      = VectorDist(%curPos, %pos);
	
	if(%b == 0) {
		cancel(%this.lookAtPlayer);
		%this.lookAtPlayer = %this.schedule(32, lookAtPlayer, %pl, 1);
		return;
	}
	
	if(isEventPending(%this.lookAtPlayer)) %this.turning = 0;
	else if(!%loop) { %this.setAimLocation(%pos); }

	%curRot = getWord(%this.getTransform(), 6) * getWord(%this.getTransform(), 5);

	%b_pos = VectorAdd(%curPos, %this.getForwardVector());
	%a = VectorDist(%pos, %b_pos);
	%c = VectorDist(%curPos, %b_pos);

	%cos_theta = (%b / 2) + (1 - (%a * %a)) / (%b * 2);
	if( %cos_theta >= 1) {
		%this.setTransform(%curPos SPC "0 0 1" SPC (%curRot + (3.14159 * 2)));
	} else if( %cos_theta <= -1) {
		%this.setTransform(%curPos SPC "0 0 1" SPC (%curRot + 3.14159));
		%this.turning = "";
	} else {
		%theta = mAcos(%cos_theta);
	
		%curx = firstWord(%curPos);
	        %cury = getWord(%curPos, 1);
		%posx = firstWord(%pos);
	        %posy = getWord(%pos, 1);
		if( %curx < %posx ) %theta *= -1;
	
		%slope = (%cury - %posy) / (%curx - %posx);
		if(%cury - (%slope * %curx) <  getWord(%b_pos, 1) - (%slope * firstWord(%b_pos)) )
			%theta *= -1;
	
		%z = 1;
		%newRot = %curRot + mClampF(%theta, -0.2, 0.2);
		if( %newRot < 0 ) {
			%z = -1;
			%newRot *= -1;
		}
		
		%turnThresh = ($PI / 3);
		%headTurnAmt = (%theta / (%turnThresh / ($PI / 2))) * %turnThresh;
		
		if(%this.turning || (mClampF(%theta, -0.5, 0.5) !$= -0.5 && mClampF(%theta, -0.5, 0.5) !$= 0.5)) %this.lastTurnTime = getSimTime();
		
		if(!%this.turning && getSimTime() - %this.lastTurnTime >= 1000) {
			%this.lastTurnTime = getSimTime();
			%this.turning = 1;
			%this.setAimLocation(%pl.getEyePoint());
			%this.setTransform(%curPos SPC "0 0" SPC %z SPC %newRot);
			%this.setHeadAngle(0);
		}
		
		if(%this.movey_speed != 0) {
			%this.setAimObject(%pl);
			%this.setHeadAngle(0);
		} else {
			if(%this.turning || %theta >= %turnThresh || %theta <= -%turnThresh) {
				%this.turning = !(mFloatLength(%theta, 1) == 0);
				%this.setAimLocation(%pl.getEyePoint());
				%this.setTransform(%curPos SPC "0 0" SPC %z SPC %newRot);
			} else %this.setAimLocation(getWords(%this.getAimLocation(), 0, 1) SPC getWord(%pl.getEyePoint(), 2));
			%this.setHeadAngle(%headTurnAmt);
		}
	}
	
	cancel(%this.lookAtPlayer);
	%this.lookAtPlayer = %this.schedule(32, lookAtPlayer, %pl, 1);
}