if(!isObject(DebugGroup)) new SimGroup(DebugGroup);
if(!isObject(WaypointLine)) datablock StaticShapeData(DebugLine) {
	shapeFile = "add-ons/server_vore/shapes/line.dts";
};
function testModel(%file) {
	%fileP = "Add-Ons/Server_Vore/shapes/" @ %file @ ".dts";
	
	if(!isFile(%fileP)) { error("file \"" @ %file @ ".dts\" doesnt exist"); return; }
	
	if($CACHE::LastTestModelCRC $= getStringCRC(%fileP)) {
		error("This model has the same CRC as when it was last tested.");
		return;
	}
	
	if(!fileCopy(%fileP, %fileNew = (filePath(%fileP) @ "/" @ $CACHE::LastTestModelCRC @ ".dts"))) {
		error("Failed to copy the model file");
		return;
	}
	
	$CACHE::LastTestModelCRC = getStringCRC(%fileP);
	
	$TESTINC++;
	
	%dataName = "TestData" @ $TESTINC;
	
	eval("datablock staticShapeData(" @ %dataName @ ") { shapeFile = \"" @ %fileNew @ "\"; };");
	
	if(!isObject(%dataName)) {
		error("Failed to create object...");
		$TESTINC--;
		return;
	}
	
	schedule(100, 0, fileDelete, %fileNew);
	echo("new test datablock:" @ %dataName);
	return %dataName;
}
function drawLine(%this,%that,%line) {
	if(!isObject(%ref = %line)) %ref = new StaticShape() { dataBlock = "DebugLine"; };
	%a = (isObject(%this) && isFunction(%this.getClassName(), "getPosition") ? %this.getPosition() : %this);
	%b = (isObject(%that) && isFunction(%that.getClassName(), "getPosition") ? %that.getPosition() : %that);
	%vector = VectorNormalize(VectorSub(%b, %a));
	%axis = VectorNormalize(VectorCross("0 1 0", %vector));
	%mag = mACos(VectorDot("0 1 0", %vector)) * -1;
	
	%ref.setTransform(VectorScale(VectorAdd(%a, %b), 0.5) SPC %axis SPC %mag);
	%max = 0.1;
	%middle = brickToMetric(VectorDist(%a, %b));
	%ref.setScale(%max SPC %middle SPC %max);
	DebugGroup.add(%ref);
	return %ref;
}
package TempPackage {
	function fxDTSBrick::killBrick(%this) {
		%this.schedule(1,delete);
	}
};
activatePackage(TempPackage);

function ServerCmdUndoBrick(%client) {
	%line = %client.undoStack.pop();
	%obj = getField(%line,0);
	%player = %client.player;
	if(!isObject(%obj)) return;
	%action = getField(%line,1);
	if(isObject(%player)) %player.playThread(3,undo);
	if(%action !$= "COLORGENERIC") {
		if(!%obj.getType() & $TypeMasks::FxBrickAlwaysObjectType) {
			error("ERROR: ServerCmdUndoBrick(" @ %client @ ") - " @ %obj @ " is not a brick");
			return;
		}
	}
	switch$(%action) {
		case "PLANT":
			if(%obj.getGroup() != %client.brickGroup) return;
			%obj.schedule(1,delete);
			return;
			if(%obj.willCauseChainKill())
				%obj.undoTrustCheck();
			else
				%obj.killBrick();
		case "COLOR":
			if(getTrustLevel(%obj,%client) < $TrustLevel::UndoPaint) {
				%client.sendTrustFailureMessage(%brickGroup);
				return;
			}
			%oldColor = getField(%line,2);
			%obj.setColor(%oldColor);
			if(isObject(%obj.Vehicle)) if(%obj.reColorVehicle) %obj.colorVehicle();
		case "COLORFX":
			if(getTrustLevel(%obj,%client) < $TrustLevel::UndoFXPaint) {
				%client.sendTrustFailureMessage(%brickGroup);
				return;
			}
			%oldColorFX = getField(%line,2);
			%obj.setColorFX(%oldColorFX);
		case "SHAPEFX":
			if(getTrustLevel(%obj,%client) < $TrustLevel::UndoFXPaint) {
				%client.sendTrustFailureMessage(%brickGroup);
				return;
			}
			%oldShapeFX = getField(%line,2);
			%obj.setShapeFX(%oldShapeFX);
		case "PRINT":
			if(getTrustLevel(%obj,%client) < $TrustLevel::UndoPrint) {
				%client.sendTrustFailureMessage(%brickGroup);
				return;
			}
			%oldPrintID = getField(%line,2);
			%obj.setPrint(%oldPrintID);
		case "COLORGENERIC":
			if(%action $= "COLORGENERIC") {
				%oldColor = getField(%line,2);
				%obj.setNodeColor("ALL",%oldColor);
				%obj.color = %oldColor;
			}
		default:
			error("ERROR: ServerCmdUndoBrick() - unknown undo state " @ %line);
	}
}
function hammerImage::onHitObject(%this,%player,%slot,%hitObj,%hitPos,%hitNormal) {
	%client = %player.client;
	ServerPlay3D(hammerHitSound,%hitPos);
	if(!isObject(%client)) return;
	if(%hitObj.getType() & $TypeMasks::FxBrickAlwaysObjectType) {
		if(!isObject(%client)) return;
		%hitObj.schedule(1,delete);
		return;
		if(!%hitObj.willCauseChainKill()) {
			if(getTrustLevel(%player,%hitObj) < $TrustLevel::Hammer) {
				if(%hitObj.stackBL_ID $= "" || %hitObj.stackBL_ID != %client.getBLID()) {
					%client.sendTrustFailureMessage(%hitObj.getGroup());
					return;
				}
			}
			%hitObj.onToolBreak(%client);
			$CurrBrickKiller = %client;
			%hitObj.schedule(1,delete);
		}
	} else {
		if(%hitObj.getClassName() $= "Player") {
			if(miniGameCanDamage(%client,%hitObj) == 1) {
				%hitObj.Damage(%player,%hitPos,hammerProjectile.directDamage,$DamageType::HammerDirect);
			}
		} else {
			if(%hitObj.getClassName() $= "WheeledVehicle" || %hitObj.getClassName() $= "HoverVehicle" || %hitObj.getClassName() $= "FlyingVehicle") {
				return;
				%mount = %player;
				%i = 0;
				while(%i < 100 && %dbg++ < 100) {
					if(%mount == %hitObj) return;
					if(%mount.isMounted()) {
						%mount = %mount.getObjectMount();
						%i = %i + 1;
					}
				}
				%doFlip = 0;
				if(isObject(%hitObj.spawnBrick))
					%vehicleOwner = findClientByBL_ID(%hitObj.spawnBrick.getGroup().bl_id);
				else
					%vehicleOwner = 0;

				if(isObject(%vehicleOwner))
					if(getTrustLevel(%player,%hitObj) >= $TrustLevel::VehicleTurnover) %doFlip = 1;
				else
					%doFlip = 1;

				if(miniGameCanDamage(%player,%hitObj) == 1) %doFlip = 1;
				if(miniGameCanDamage(%player,%hitObj) == 0) %doFlip = 0;
				if(%doFlip) {
					%impulse = VectorNormalize(%vec);
					%impulse = VectorAdd(%impulse,"0 0 1");
					%impulse = VectorNormalize(%impulse);
					%force = %hitObj.getDataBlock().mass * 5;
					%impulse = VectorScale(%impulse,%force);
					%hitObj.applyImpulse(%hitPos,%impulse);
				}
			}
		}
	}
}