if($CACHE::Marc::StomachStruggle::Max $= "") $CACHE::Marc::StomachStruggle::Max = 1300;
package MarcPackageIII {
	function serverPlay3D(%datablock,%pos) {
		Parent::serverPlay3D(%datablock,%pos);
		%badList = "playerMountSound wrenchHitSound";
		if(!isObject(%dataBlock)) return;
		if(wordPos(%badList,%dataBlock.getName()) != -1) return;
		%type = $TypeMasks::PlayerObjectType;
		initContainerRadiusSearch(%pos,9999999,%type);
		while((%target = containerSearchNext()) != 0) {
			if(!isEventPending(%target.loopMarcAI) && !isEventPending(%target.wantToEat)) continue;
			%target = %target.getID();
			if(%target.isCloaked || %target.getState() $= "Dead" || isObject(%target.holding)) continue;
			if(%target.getClassName() !$= "AIPlayer") continue;
			if(vectorDist(%target.getPosition(),%pos) > (3*getWord(%target.getScale(),2))) continue;
			if(isEventPending(%target.stopLookingForSoundSchedule)) continue;
			if(isEventPending(%target.wantToEat)) continue;
			%target.sound_lastLook = "";
			if(%target.getAimLocation() !$= "0 0 0") %target.sound_lastlook = "location" SPC %target.getAimLocation();
			if(%target.getAimObject() != -1) %target.sound_lastlook = "object" SPC %target.getAimLocation();
			if(%target.sound_lastLook $= "") %target.sound_lastlook = "nothing";
			%target.vEmb("wtfImage",1);
			%target.setAimLocation(%pos);
			%target.sound_lastpos = %target.getAimLocation();
			%target.stopLookingForSoundSchedule = %target.schedule(getRandom(1500,2000),"stopLookingForSound");
		}
	}
	function AIPlayer::setAimLocation(%this,%pos) {
		%this.aimLocation = %pos;
		Parent::setAimLocation(%this,%pos);
	}
	function AIPlayer::getAimLocation(%this) {
		if(%this.aimLocation $= "") %this.aimLocation = "0 0 0";
		return %this.aimLocation;
	}
	function AIPlayer::stopLookingAtPlayer(%this) {
		%this.aimLocation = "0 0 0";
		Parent::stopLookingAtPlayer(%this);
	}
	function AIPlayer::setMoveY(%this,%speed) {
		if((%this.movey_speed != 0 && %speed == 0) || %speed != 0) %this.lastStopMove = getSimTime();
		%this.movey_speed = %speed;
		Parent::setMoveY(%this,%speed);
	}
	function Player::changeDatablock(%this,%datablock) {
		Parent::changeDatablock(%this,%datablock);
		%this.defaultForwardSpeed = %this.getMaxForwardSpeed();
		%this.defaultSideSpeed = %this.getMaxSideSpeed();
		%this.defaultBackwardSpeed = %this.getMaxBackwardSpeed();
		if(%dataBlock.getID() != voreInternalPlayerType.getID()) %this.defaultPlayerType = %datablock;
	}
	function AIPlayer::changeDatablock(%this,%datablock) {
		Parent::changeDatablock(%this,%datablock);
		if(%dataBlock.getID() != voreInternalPlayerType.getID()) %this.defaultPlayerType = %datablock;
	}
	function GameConnection::spawnPlayer(%this) {
		Parent::spawnPlayer(%this);
		%this.player.speedModifier = 3;
		%this.player.hudBattery = 100;
		%this.player.defaultForwardSpeed = %this.player.getMaxForwardSpeed();
		%this.player.defaultSideSpeed = %this.player.getMaxSideSpeed();
		%this.player.defaultBackwardSpeed = %this.player.getMaxBackwardSpeed();
		%this.player.loopMarcGui();
		return;
	}
	function AIPlayer::playThread(%this, %slot, %anim) {
		Parent::playThread(%this, %slot, %anim);
		%this.thread_slot[%slot] = %anim;
	}
	function Armor::doDismount(%this,%player) {
		if(%player.inStomach || %player.inMouth) {
			if(!isObject(%player.heldBy)) {
				if(%player.inMouth) {
					%player.setDataBlock((!isObject(%player.defaultPlayerType) ? PlayerStandardArmor : %player.defaultPlayerType));
					%player.unhideNode("headSkin");
					if(%player.getDataBlock().getName() !$= "PlayerStandardArmor") %player.unHideNode("ALL");
					%player.inMouth   = 0;
					%player.inStomach = 0;
					%player.heldBy    = "";
				} else {
					%player.setDataBlock((!isObject(%player.defaultPlayerType) ? PlayerStandardArmor : %player.defaultPlayerType));
					%player.unhideNode("headSkin");
					if(%player.getDataBlock().getName() !$= "PlayerStandardArmor") %player.unHideNode("ALL");
					%player.inMouth   = 0;
					%player.inStomach = 0;
					%player.heldBy    = "";
				}
				return;
			}
		}
		if(isObject(%player.heldBy)) {
			if(%player.heldBy.trustsObj(%player) || %player.heldBy.isNotVorist) {
				%player.heldBy.setHeadAngle(0);
				%player.heldBy.holdDelay = 50;
				if(isObject(%player.client)) if(%player.client.getControlObject() != %player) %player.client.setControlObject(%player);
				Player::holdOtherPlayer(%player.heldBy);
			}
			return;
		}
		Parent::doDismount(%this,%player);
	}
	function Armor::onCollision(%this,%player,%contactObj,%colPos,%idk,%what,%aok) {
		Parent::onCollision(%this,%player,%contactObj,%colPos,%idk,%what,%aok);
		if(%player.getState() $= "Dead") return;
		if(%contactObj.notarget) return;
		if(%player.getClassName() !$= "AIPlayer" && %player.getClassName() !$= "Player") return;
		if(%contactObj.getClassName() !$= "AIPlayer" && %contactObj.getClassName() !$= "Player") return;
		%dif_x = getWord(%player.getScale(),0)-0.8;
		%dif_y = getWord(%player.getScale(),1)-0.8;
		%dif_z = getWord(%player.getScale(),2)-0.8;
		if(getWord(%contactObj.getScale(),0) >= %dif_x) return;
		if(getWord(%contactObj.getScale(),0) >= %dif_y) return;
		if(getWord(%contactObj.getScale(),0) >= %dif_z) return;
		if(isObject(%player.holding)) return;
		if(vectorDist(%contactObj.getPosition(),%player.getEyePoint()) <= 2 && %player.holdDelay < 0) {
			Player::holdOtherPlayer(%player,%contactObj);
			serverCmdMouth(%player);
			if(!%player.isNotVorist && %player.getClassName() $= "AIPlayer") {
				%player.eatDelay = 41;
				// embarrasment
				%player.vEmb();
			}
			if(%player.isNotVorist) {
				if(%player.getClassName() $= "AIPlayer") %player.say("#FRIENDLY_MOUTHSUPRISE");
				%contactObj.swallowDangerLoop = getRandom(0,getMaxSwallowLimit());
			}
			return;
		}
		if(!isObject(%player)) return;
		if(%player.getClassName() $= "Player") return;
		%player.stopLookingAtPlayer();
		%player.setAimLocation(%contactObj.getPosition());
	}
	function Player::activateStuff(%this) {
		Parent::activateStuff(%this);
		if(%this.inStomach) {
			if(%this.stomach_stamina <= 3) {
				%this.stomach_stamina = 3;
				%this.stomach_msgTime = getSimTime(); %this.stomach_message = "<color:ff0000>You need to wait and catch your breath before struggling again!";
			} else {
				%str[-1+%strCount++]  = "You struggle to no avail.";
				%str[-1+%strCount++]  = "You fiercely struggle, to which the stomach responds with an extremely tight contraction.";
				%str[-1+%strCount++]  = "You attempt to struggle, but the stomach stops you by rumbling, throwing you off balance.";
				%str[-1+%strCount++]  = "You attempt to struggle, but slip on gastric acid.";
				%gdd[-1+%goodCount++] = "You fiercely struggle, which causes the stomach to contract. You feel air rush up before the stomach relaxes.";
				%gdd[-1+%goodCount++] = "You shove your hands and feet into the stomach wall, which elicits a cough from your captor.";
				%this.stomach_stamina -= getRandom(5, 10);
				if((%this.energyDrinkAmt > 0 ? getRandom(0, 4) : getRandom(0, 10)) < 3) {
					// Struggled & got a point
					%this.stomach_msgTime   = getSimTime(); %this.stomach_message = "<color:00ff00>" @ %gdd[getRandom(0, %goodCount-1)] @ "<br>(" @ %this.stomach_struggle @ ")";
					%points                 = getRandom(2, 4)*((%this.stomach_stamina/100)*30);
					%this.stomach_struggle += (%this.saveme ? 350 : %points);
					if(%this.stomach_struggle >= $CACHE::Marc::StomachStruggle::Max) {
						%heldBy = %this.heldBy;
						%this.setTransform(%heldBy.getEyePoint());
						centerPrint(%this.client, "<color:ffffff>Your captor puked you out! You escaped!", 3);
						%heldBy.holdDelay = 50;
						%heldBy.schedule(100, vEmb, "", 1);
						// Knock back the other player
						%amt = 5 * getWord(%heldBy.getScale(), 2); // Knockback force multiplier
						%vel = vectorAdd(vectorScale(vectorScale(%heldBy.getForwardVector(), %amt), -1), "0 0 5");
						%heldBy.setVelocity(%vel);
						%this.inStomach = 0;
						%this.inMouth   = 0;
						%this.heldBy    = "";
						%this.disMount();
						if(%heldBy.lastEatObj == %this) %heldBy.lastEatObj = "";
						%heldBy.setAimLocation(%this.getPosition());
						%this.schedule(100, setDataBlock, %this.defaultPlayerType);
						%this.regenerateStamina();
					}
				} else {
					%this.stomach_msgTime = getSimTime(); %this.stomach_message = "<color:ff0000>" @ %str[getRandom(0, %strCount-1)];
				}
			}
		}
		if(isObject(%this.heldBy) && ((%this.inMouth && %this.heldBy.getClassName() !$= "Player") || %this.heldBy.getClassName() $= "Player")) {
			if((!%this.canStruggle && %this.heldBy.eatDelay >= 60) || %this.heldBy.getClassName() $= "Player") {
				%this.canStruggle = 1;
			}
			
			%maxStruggle = 150;
			
			if(%this.canStruggle) {
				%strugglePoints = getRandom(1, 3);
				if(!%this.barOff) %strugglePoints = getRandom(3,9);
				if(%this.hudBroken) %strugglePoints = getRandom(0,2);
				if(%this.saveme) %strugglePoints = getRandom(10,20);
				else if(%this.energyDrinkAmt > 0) %strugglePoints = getRandom(12, 20);
				else {
					%strugglePoints /= getWord(%this.heldBy.getScale(), 2) / 2;
					%strugglePoints *= getWord(%this.getScale(), 2) * 2;
					%strugglePoints  = mFloor(%strugglePoints);
				}
				
				%exhaustLose = (mClamp(getSimTime() - %this.lastStruggleTime, 0, 3000) / 3000) * 0.4;
				%this.struggleExhaustion = mClampF(%this.struggleExhaustion - %exhaustLose, 0, 4000);
				
				%strugglePoints /= (1 + %this.struggleExhaustion);
				%exhaustPoints   = (getRandom() * (1 + (getWord(%this.heldBy.getScale(), 2) - getWord(%this.getScale(), 2)))) / (%this.barOff ? 120 : 250);
				
				%this.stomach_stamina = mClampF(%this.stomach_stamina - %exhaustPoints, 3, 100);
				%this.regenerateStamina();
				
				centerPrint(%this.client, "\c6You struggle.\r\n+" @ %strugglePoints @ " / " @ %maxStruggle @ "\r\n+ " @ %exhaustPoints @ " Exhaustion (" @ %this.struggleExhaustion @ ")", 2);
				%this.struggleExhaustion += %exhaustPoints;
				%this.lastStruggleTime = getSimTime();
				if(%this.heldBy.getClassName() $= "Player") %this.strugglePoints += %strugglePoints;
				else %this.heldBy.eatDelay -= %strugglePoints;
			}
			if((%this.heldBy.getClassName() $= "AIPlayer" && %this.heldBy.eatDelay < 41) || (%this.heldBy.getClassName() $= "Player" && %this.strugglePoints >= %maxStruggle)) {
				%heldBy = %this.heldBy;
				if(%heldBy.getClassName() $= "Player") {
					if(%this.inMouth) serverCmdMouth(%heldBy.client);
					%heldBy.holdOtherPlayer();
					return;
				}
				serverCmdMouth(%heldBy);
				%heldBy.holdDelay = 50;
				%caughtMsg = "Oww, my mouth!!	Agh!	Come back here!";
				if(%heldBy.becomeNotVorist) {
					%heldBy.becomeNotVorist = 0;
					%heldBy.isNotVorist = 1;
					%caughtMsg = "I thought not.	Sorry, I didn't feel you squirming out!	Heh, you taste good!";
				}
				%randomMsg = getField(%caughtMsg,getRandom(0,getFieldCount(%caughtMsg)-1));
				if(!%heldBy.isNotVorist) %heldBy.say(%randomMsg);
				%heldBy.setHeadAngle(0);
				%heldBy.eatDelay = -1;
				%heldBy.schedule(100, vEmb, "", 1);
				Player::holdOtherPlayer(%heldBy);
				// Knock back the other player
				if(!%heldBy.isNotVorist) {
					%amt = 15*getWord(%heldBy.getScale(), 2); // Knockback force multiplier
					%vel = vectorAdd(vectorScale(vectorScale(%heldBy.getForwardVector(), %amt), -1), "0 0 5");
					%heldBy.setVelocity(%vel);
				}
				return;
			}
		}
		%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);
		%vec = VectorSub(%pos,%start);
		%scanTarg = getWord(%scanTarg,0);
		if(isObject(%scanTarg)) {
			if(isObject(%scanTarg.heldBy)) return;
			if(%scanTarg.inMouth) return;
			if(vectorDist(%this.getPosition(),%scanTarg.getPosition()) >= 6*getWord(%this.getScale(),2)) {
				%this.holdOtherPlayer();
				return;
			}
			%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(%scanTarg.getScale(),0) == getWord(%this.getScale(),0)) {
				if(getWord(%scanTarg.getScale(),1) == getWord(%this.getScale(),1)) {
					if(getWord(%scanTarg.getScale(),2) == getWord(%this.getScale(),2)) {
						// If they're holding a tiny that trusts us, let's save them!
						if(isObject(%held = %scanTarg.holding) && %held.trustsObj(%this)) {
							if(%held.inMouth) {
								// They've got our tiny in their mouth! Punch them in the gut.
								%scanTarg.mouthHeldObject();
								%scanTarg.holdOtherPlayer();
								%scanTarg.vEmb(1, 1);
								%held.setTransform(%scanTarg.getEyeTransform());
								%scanTarg.setVelocity(vectorAdd(vectorScale(%fv = %scanTarg.getForwardVector(), -8), "0 0 8"));
								%scanTarg.eatDelay   = 0;
								%scanTarg.lastEatObj = 0;
								%held.setVelocity(vectorAdd(vectorScale(%fv, 8), "0 0 1"));
								return;
							}
							
							%scanTarg.setHeadAngle(0);
							%scanTarg.playThread(0, "activate2");
							%scanTarg.holdOtherPlayer();
							%this.holdOtherPlayer(%held);
							%scanTarg.eatDelay = 0;
							%scanTarg.vEmb(1, 1);
							return;
						}
						
						// Let's give them our tiny if the tiny trusts them.
						if(isObject(%held = %this.holding) && %held.trustsObj(%scanTarg)) {
							%this.holdOtherPlayer();
							%scanTarg.holdOtherPlayer(%held);
							%scanTarg.wantToExamine(%held);
							return;
						}
						
						// Let's get them to follow us!
						if(isObject(%scanTarg.isFollowing))
							%scanTarg.isFollowing = 0;
						else
							%scanTarg.isFollowing = %this;

					}
				}
			}
			if(getWord(%scanTarg.getScale(),0) >= getWord(%this.getScale(),0)) {
				if(getWord(%scanTarg.getScale(),1) >= getWord(%this.getScale(),1)) {
					if(getWord(%scanTarg.getScale(),2) >= getWord(%this.getScale(),2)) {
						if(isObject(%this.heldBy)) return;
						if(%scanTarg.targ_obj != %this) return;
						if(!%scanTarg.isNotVorist && !%scanTarg.trustsObj(%this)) return;
						%scanTarg.schedule(50,holdOtherPlayer,%this);
						return;
					}
				}
			}
			if(getWord(%scanTarg.getScale(),0) >= %dif_x) return;
			if(getWord(%scanTarg.getScale(),0) >= %dif_y) return;
			if(getWord(%scanTarg.getScale(),0) >= %dif_z) return;
			if(isFunction(%scanTarg.getClassName(), "canSeeObject") && %scanTarg.canSeeObject(%this) $= "2") return;
			%this.holdOtherPlayer(%scanTarg);
		} else {
			%brickObj = getField(getRaycastFromObject(%this, $TypeMasks::PlayerObjectType | $TypeMasks::FxBrickAlwaysObjectType), 0);
			if(isObject(%brickObj)) {
				if(%brickObj.getClassName() $= "fxDTSBrick") {
					for(%evIdx=0;%evIdx<=%brickObj.numEvents;%evIdx++) {
						if(%evIdx == %brickObj.numEvents) {
							%this.holdOtherPlayer();
							break;
						}
						if(!%brickObj.eventEnabled[%evIdx]) continue;
						if(%brickObj.eventInput[%evIdx] !$= "onActivate") continue;
						break;
					}
				}
			} else Player::holdOtherPlayer(%this);
		}
	}
	function Player::playThread(%this,%slot,%threadName,%stopSecond) {
		Parent::playThread(%this,%slot,%threadName);
		if(%stopSecond) return;
		if(%slot == 2) { 
			if(isObject(%this.holding) && !%this.holding.inMouth) {
				cancel(%this.holdUpArmReadyLeft);
				%this.holdUpArmReadyLeft = %this.schedule(10,playThread,2,"armReadyLeft",1);
			}
		}
	}
	function serverCmdSit(%this) {
		Parent::serverCmdSit(%this);
		%player = %this.player;
		if(!isObject(%player)) return;
		if(isObject(%player.holding) && %player.holding.inMouth) {
			%player.eatHeldObject();
			messageClient(%this,'',"\c6You swallow.");
		}
	}
	function Player::mountObject(%this,%object,%slot,%bypass) {
		if(!%bypass && %slot == 0 && %this.isEating) return;
		if(%object.getClassName() $= "Player") %object.strugglePoints = 0;
		Parent::mountObject(%this,%object,%slot);
	}
};
activatePackage(MarcPackageIII);