package smmCorpsePackage {
	function Armor::onMount(%this, %obj, %mount, %slot) {
		Parent::onMount(%this, %obj, %mount, %slot);

		if (!%obj.isCorpse || %slot != 0) {
			return;
		}

		if (%mount.isCorpseVehicle) {
			%obj.playThread(3, "root");
		}
		else {
			%mount.playThread(3, "ArmReadyBoth");

			%obj.playThread(3, "death1");
			%obj.setTransform("0 0 -100 0 0 -1 -1.5709");
		}
	}

	function Armor::onUnMount(%this, %obj, %mount, %slot) {
		Parent::onUnMount(%this, %obj, %mount, %slot);

		if (!%obj.isCorpse || %slot != 0) {
			return;
		}

		if (%mount.isCorpseVehicle) {
			%mount.setTransform("0 0 -1000");
			return;
		}

		if (!isObject(%obj.corpseVehicle)) {
			%obj.delete();
		}

		%vehicle = %obj.corpseVehicle;

		if (!isObject(%vehicle)) {
			return;
		}

		%vehicle.mountObject(%obj, 0);

		if (isObject(%mount)) {
			%hackPosition = %mount.getHackPosition();
			%forwardVector = %mount.getForwardVector();

			%position = vectorAdd(%hackPosition, vectorScale(%forwardVector, 2));
			%velocity = vectorScale(%forwardVector, 10);
	
			%ray = containerRayCast(%hackPosition, %position, $TypeMasks::FxBrickObjectType);
	
			if (%ray !$= 0) {
				%position = %hackPosition;
				%velocity = "0 0 0";
			}
	
			%vehicle.setTransform(%position SPC getWords(%mount.getTransform(), 3, 6));

			%vehicle.setVelocity(%velocity);
			%vehicle.setAngularVelocity(vectorNormalize(%velocity));
		}
	}

	function WheeledVehicleData::onDriverLeave(%this, %vehicle, %driver) {
		parent::onDriverLeave(%this, %vehicle, %driver);

		if (%vehicle.isCorpseVehicle && !%vehicle.beingPickedUp) {
			%vehicle.delete();
		}
	}

	function Player::delete(%this) {
		%mount = %this.getObjectMount();

		if (%mount.isCorpseVehicle) {
			%client = %mount.getControllingClient();

			if (isObject(%client)) {
				%client.camera.setMode("Corpse", %this);
				%client.setControlObject(%client.camera);
			}
		}

		if (isObject(%this.corpseVehicle)) {
			%this.corpseVehicle.delete();
		}

		Parent::delete(%this);
	}

	function Player::mountImage(%this, %image, %slot) {
		if (!%this.getMountedObject(0).isCorpse) {
			Parent::mountImage(%this, %image, %slot);
		}
	}

	function AIPlayer::setVelocity(%this, %velocity) {
		Parent::setVelocity(%this, %velocity);
		%mount = %this.getObjectMount();

		if (%this.isCorpse && %mount.isCorpseVehicle) {
			%mount.setVelocity(%velocity);
		}
	}

	function AIPlayer::addVelocity(%this, %velocity) {
		Parent::addVelocity(%this, %velocity);
		%mount = %this.getObjectMount();

		if (%this.isCorpse && %mount.isCorpseVehicle) {
			%mount.setVelocity(vectorAdd(%mount.getVelocity(), %velocity));
		}
	}

	function WheeledVehicleData::onAdd(%this, %obj) {
		Parent::onAdd(%this, %obj);

		if (%obj.isCorpseVehicle) {
			%obj.monitorCorpseVelocity(0);
		}
	}

	function WheeledVehicleData::onDriverLeave(%this, %vehicle, %driver) {
		parent::onDriverLeave(%this, %vehicle, %driver);

		if (%vehicle.isCorpseVehicle && !%vehicle.beingPickedUp) {
			%vehicle.delete();
		}
	}
};
activatePackage(smmCorpsePackage);

function gameConnection::createCorpse(%this) {
	if (isObject(%this.corpse)) {
		%this.corpse.delete();
	}

	if (isObject(%this.player)) {
		%this.corpse = new AIPlayer() {
			dataBlock = %this.player.getDataBlock();

			isCorpse = true;
			originalClient = %this;
		};

		if (isObject(%this.corpse)) {
			%player = %this.player;
			%slots = %player.getDataBlock();

			MissionCleanup.add(%this.corpse);

			for (%i = 0; %i < %slots; %i++) {
				%this.corpse.tool[%i] = %player.tool[%i];
				%this.corpse.toolMag[%i] = %player.toolMag[%i];

				%this.corpse.suitcaseTool[%i] = %player.suitcaseTool[%i];
				%this.corpse.papersNote[%i] = %player.papersNote[%i];

				if (%player.tool[%i].ammoType !$= "") {
					%this.corpse.toolAmmo[%player.tool[%i].ammoType] = %player.toolAmmo[%player.tool[%i].ammoType];
				}
			}

			%vehicle = %this.corpse.corpseVehicle = new WheeledVehicle() {
				dataBlock = CorpseVehicle;

				isCorpseVehicle = true;
				corpse = %this.corpse;
			};

			MissionCleanup.add(%vehicle);

			%pos = vectorAdd(%this.player.position, "0 0 0.15");
			%rot = getWords(%this.player.getTransform(), 3, 6);

			%vehicle.setTransform(%pos SPC %rot);
			%vehicle.mountObject(%this.corpse, 0);

			%ang = vectorSub(%this.player.getHackPosition(), %this.player.lastDamagePos);
			%ang = vectorCross("0 0 1", vectorScale(vectorNormalize(setWord(%ang, 2, 0)), 4));

			%vehicle.setVelocity(vectorScale(%this.player.getVelocity(), 1.5));
			%vehicle.setAngularVelocity(%ang);

			%this.player = %this.corpse;

			%this.applyBodyParts();
			%this.applyBodyColors();

			%this.player = %player;

			if (!%this.player.hasBeenUnconscious) {
				%this.corpse.isUnconscious = true;
				%this.corpse.corpseDamageLevel = 0;

				%this.corpse.reviveCorpseTimer(45);
			}
			else {
				%this.play2d(smmDeathMusic);
			}
		}
	}

	%this.setControlObject(%this.camera);

	if (isObject(%this.player)) {
		%this.camera.setMode("Corpse", %this.player);
		%this.player.schedule(0, delete);
	}

	if (isObject(%this.corpse)) {
		%this.camera.setMode("Corpse", %this.corpse);
	}
}

function AIPlayer::reviveCorpseTimer(%this, %seconds, %scheduled) {
	cancel(%this.reviveCorpseTimer);

	if (!isObject(%this.originalClient) || !%this.isUnconscious) {
		%this.revive = "";
		return;
	}

	if (!%scheduled) {
		if (%this.usedRecoveryDevice) {
			%seconds /= 5;
		}
		else {
			%slots = %this.getDataBlock().maxTools;

			for (%i = 0; %i < %slots; %i++) {
				if (%this.tool[%i] == nameToID("RecoveryDeviceItem")) {
					%this.tool[%i] = "";
					%this.usedRecoveryDevice = true;

					%seconds /= 5;
					break;
				}
			}
		}
	}

	%seconds = mFloor(%seconds);
	%carried = !%this.getObjectMount().isCorpseVehicle;

	if (%seconds <= 0) {
		if (%this.isWrapped) {
			%seconds = 0;
			%this.revive = true;
			%this.originalClient.centerPrint("\c6You have been revived, however, your speech is muffled and you can't move!", 1.5);
		}
		else
		if (%carried) {
			%seconds = 0;
		}
		else {
			%this.reviveCorpse();
			return;
		}
	}
	else {
		if (%this.revive) {
			%this.revive = false;
		}
	}

	if (!%carried && !%this.isWrapped || %seconds > 0) {
		%this.originalClient.centerPrint("\c6You will automatically be revived in \c3" @ %seconds SPC "seconds\c6.", 1.5);
	}
	else {
		if (!%this.isWrapped) {
			%this.originalClient.centerPrint("\c6You will automatically be revived when you are dropped.", 1.5);
		}
	}

	%this.reviveCorpseTimer = %this.schedule(1000, reviveCorpseTimer, %seconds--, true);
}

function AIPlayer::reviveCorpse(%this) {
	if (!%this.isUnconscious || !isObject(%this.originalClient)) {
		return false;
	}

	%client = %this.originalClient;

	if (!%this.getObjectMount().isCorpseVehicle) {
		return;
	}

	cancel(%this.reviveCorpseTimer);
	clearCenterPrint(%client);
	%this.revive = "";

	%this.corpseVehicle.beingPickedUp = false;
	%this.unmount();

	%client.createPlayer(%this.getTransform());

	%client.applyBodyParts();
	%client.applyBodyColors();

	%client.player.setShapeNameDistance(0);
	%client.player.fs_velocityCheckTick();

	%client.player.hasBeenUnconscious = true;
	%client.setControlObject(%client.player);

	%slots = %this.getDataBlock();

	for (%i = 0; %i < %slots; %i++) {
		%client.player.tool[%i] = %this.tool[%i];
		%client.player.toolMag[%i] = %this.toolMag[%i];

		%client.player.suitcaseTool[%i] = %this.suitcaseTool[%i];
		%client.player.papersNote[%i] = %this.papersNote[%i];

		messageClient(%client, 'MsgItemPickup', "", %i, %client.player.tool[%i], true);

		if (%this.tool[%i].ammoType !$= "") {
			%client.player.toolAmmo[%this.tool[%i].ammoType] = %this.toolAmmo[%this.tool[%i].ammoType];
		}
	}

	%this.schedule(0, delete);
}

function WheeledVehicle::monitorCorpseVelocity(%this, %lastSpeed) {
	cancel(%this.monitorCorpseVelocity);
	%speed = vectorLen(%this.getVelocity());

	if (isObject(%this.getMountedObject(0)) && %lastSpeed >= 4 && %lastSpeed - %speed >= 1.5) {
		%pos = %this.getWorldBoxCenter();
		%this.getMountedObject(0).doDripBlood(true);

		if (%lastSpeed >= 12) {
			serverPlay3D(CorpseImpactHardSound @ getRandom(1, 3), %pos);
			%damage = %lastSpeed * 4;
			%this.getMountedObject(0).damage(%this.getMountedObject(0), %pos, %damage);
		}
		else {
			serverPlay3D(CorpseImpactSoftSound @ getRandom(1, 3), %pos);
		}
	}

	%this.monitorCorpseVelocity = %this.schedule(50, "monitorCorpseVelocity", %speed);
}