Index: binaries/data/mods/public/globalscripts/vector.js
===================================================================
--- binaries/data/mods/public/globalscripts/vector.js	(revision 14624)
+++ binaries/data/mods/public/globalscripts/vector.js	(working copy)
@@ -58,12 +58,14 @@
 
 Vector2D.prototype.length = function()
 {
-	return sqrt(this.lengthSquared());
+	return Math.sqrt(this.lengthSquared());
 };
 
 Vector2D.prototype.normalize = function()
 {
 	var mag = this.length();
+	if (!mag)
+		return;
 	
 	this.x /= mag;
 	this.y /= mag;
@@ -127,12 +129,14 @@
 
 Vector3D.prototype.length = function()
 {
-	return sqrt(this.lengthSquared());
+	return Math.sqrt(this.lengthSquared());
 };
 
 Vector3D.prototype.normalize = function()
 {
 	var mag = this.length();
+	if (!mag)
+		return;
 	
 	this.x /= mag;
 	this.y /= mag;
Index: binaries/data/mods/public/maps/random/rmgen/vector.js
===================================================================
--- binaries/data/mods/public/maps/random/rmgen/vector.js	(revision 14624)
+++ binaries/data/mods/public/maps/random/rmgen/vector.js	(working copy)
@@ -1,141 +0,0 @@
-/////////////////////////////////////////////////////////////////////
-//	Vector2D
-//
-//	Class for representing and manipulating 2D vectors
-//
-/////////////////////////////////////////////////////////////////////
-
-// TODO: Type errors if v not instanceof Vector classes
-// TODO: Possibly implement in C++
-
-function Vector2D(x, y)
-{
-	if (arguments.length == 2)
-	{
-		this.set(x, y);
-	}
-	else
-	{
-		this.set(0, 0);
-	}
-}
-
-Vector2D.prototype.set = function(x, y)
-{
-	this.x = x;
-	this.y = y;
-};
-
-Vector2D.prototype.add = function(v)
-{
-	return new Vector2D(this.x + v.x, this.y + v.y);
-};
-
-Vector2D.prototype.sub = function(v)
-{
-	return new Vector2D(this.x - v.x, this.y - v.y);
-};
-
-Vector2D.prototype.mult = function(f)
-{
-	return new Vector2D(this.x * f, this.y * f);
-};
-
-Vector2D.prototype.div = function(f)
-{
-	return new Vector2D(this.x / f, this.y / f);
-};
-
-Vector2D.prototype.dot = function(v)
-{
-	return this.x * v.x + this.y * v.y;
-};
-
-Vector2D.prototype.lengthSquared = function()
-{
-	return this.dot(this);
-};
-
-Vector2D.prototype.length = function()
-{
-	return sqrt(this.lengthSquared());
-};
-
-Vector2D.prototype.normalize = function()
-{
-	var mag = this.length();
-	
-	this.x /= mag;
-	this.y /= mag;
-};
-
-/////////////////////////////////////////////////////////////////////
-//	Vector3D
-//
-//	Class for representing and manipulating 3D vectors
-//
-/////////////////////////////////////////////////////////////////////
-
-function Vector3D(x, y, z)
-{
-	if (arguments.length == 3)
-	{
-		this.set(x, y, y);
-	}
-	else
-	{
-		this.set(0, 0, 0);
-	}
-}
-
-Vector3D.prototype.set = function(x, y, z)
-{
-	this.x = x;
-	this.y = y;
-	this.z = z;
-};
-
-Vector3D.prototype.add = function(v)
-{
-	return new Vector3D(this.x + v.x, this.y + v.y, this.z + v.z);
-};
-
-Vector3D.prototype.sub = function(v)
-{
-	return new Vector3D(this.x - v.x, this.y - v.y, this.z - v.z);
-};
-
-Vector3D.prototype.mult = function(f)
-{
-	return new Vector3D(this.x * f, this.y * f, this.z * f);
-};
-
-Vector3D.prototype.div = function(f)
-{
-	return new Vector3D(this.x / f, this.y / f, this.z / f);
-};
-
-Vector3D.prototype.dot = function(v)
-{
-	return this.x * v.x + this.y * v.y + this.z * v.z;
-};
-
-Vector3D.prototype.lengthSquared = function()
-{
-	return this.dot(this);
-};
-
-Vector3D.prototype.length = function()
-{
-	return sqrt(this.lengthSquared());
-};
-
-Vector3D.prototype.normalize = function()
-{
-	var mag = this.length();
-	
-	this.x /= mag;
-	this.y /= mag;
-	this.z /= mag;
-};
-
Index: binaries/data/mods/public/simulation/components/Attack.js
===================================================================
--- binaries/data/mods/public/simulation/components/Attack.js	(revision 14624)
+++ binaries/data/mods/public/simulation/components/Attack.js	(working copy)
@@ -449,14 +449,14 @@
 			return;
 		var targetPosition = cmpTargetPosition.GetPosition();
 
-		var relativePosition = {"x": targetPosition.x - selfPosition.x, "z": targetPosition.z - selfPosition.z}
+		var relativePosition = new Vector3D(targetPosition.x - selfPosition.x, 0, targetPosition.z - selfPosition.z);
 		var previousTargetPosition = Engine.QueryInterface(target, IID_Position).GetPreviousPosition();
 
-		var targetVelocity = {"x": (targetPosition.x - previousTargetPosition.x) / this.turnLength, "z": (targetPosition.z - previousTargetPosition.z) / this.turnLength}
+		var targetVelocity = new Vector3D((targetPosition.x - previousTargetPosition.x) / this.turnLength, 0, (targetPosition.z - previousTargetPosition.z) / this.turnLength);
 		// the component of the targets velocity radially away from the archer
-		var radialSpeed = Math.VectorDot(relativePosition, targetVelocity) / Math.VectorLength(relativePosition);
+		var radialSpeed = relativePosition.dot(targetVelocity) / relativePosition.length();
 
-		var horizDistance = Math.VectorDistance(targetPosition, selfPosition);
+		var horizDistance = targetPosition.sub(selfPosition).horizontalLength();
 
 		// This is an approximation of the time ot the target, it assumes that the target has a constant radial 
 		// velocity, but since units move in straight lines this is not true.  The exact value would be more 
@@ -475,13 +475,13 @@
 		var distanceModifiedSpread = spread * horizDistance/elevationAdaptedMaxRange;
 
 		var randNorm = this.GetNormalDistribution();
-		var offsetX = randNorm[0] * distanceModifiedSpread * (1 + Math.VectorLength(targetVelocity) / 20);
-		var offsetZ = randNorm[1] * distanceModifiedSpread * (1 + Math.VectorLength(targetVelocity) / 20);
+		var offsetX = randNorm[0] * distanceModifiedSpread * (1 + targetVelocity.length() / 20);
+		var offsetZ = randNorm[1] * distanceModifiedSpread * (1 + targetVelocity.length() / 20);
 
-		var realTargetPosition = { "x": predictedPosition.x + offsetX, "y": targetPosition.y, "z": predictedPosition.z + offsetZ };
+		var realTargetPosition = new Vector3D(predictedPosition.x + offsetX, targetPosition.y,predictedPosition.z + offsetZ);
 
 		// Calculate when the missile will hit the target position
-		var realHorizDistance = Math.VectorDistance(realTargetPosition, selfPosition);
+		var realHorizDistance = selfPosition.sub(realTargetPosition).horizontalLength();
 		var timeToTarget = realHorizDistance / horizSpeed;
 
 		var missileDirection = {"x": (realTargetPosition.x - selfPosition.x) / realHorizDistance, "z": (realTargetPosition.z - selfPosition.z) / realHorizDistance};
@@ -512,8 +512,8 @@
 	var curPos = cmpTargetPosition.GetPosition();
 	var prevPos = cmpTargetPosition.GetPreviousPosition();
 	lateness /= 1000;
-	return {"x": (curPos.x * (this.turnLength - lateness) + prevPos.x * lateness) / this.turnLength,
-	        "z": (curPos.z * (this.turnLength - lateness) + prevPos.z * lateness) / this.turnLength};
+
+	return curPos.mult(this.turnLength - lateness).add(prevPos.mult(lateness)).div(this.turnLength);
 };
 
 // Tests whether it point is inside of ent's footprint
@@ -532,8 +532,8 @@
 
 	if (targetShape.type === 'circle')
 	{
-		// Use VectorDistanceSquared and square targetShape.radius to avoid square roots.
-		return (Math.VectorDistanceSquared(point, targetPosition) < (targetShape.radius * targetShape.radius));
+		// Use lengthSquared and square targetShape.radius to avoid square roots.
+		return targetPosition.sub(point).lengthSquared() < (targetShape.radius * targetShape.radius));
 	}
 	else
 	{
Index: source/scriptinterface/ScriptInterface.cpp
===================================================================
--- source/scriptinterface/ScriptInterface.cpp	(revision 14624)
+++ source/scriptinterface/ScriptInterface.cpp	(working copy)
@@ -1033,7 +1033,6 @@
 	return ok ? true : false;
 }
 
-
 bool ScriptInterface::Eval(const char* code)
 {
 	jsval rval;
Index: source/simulation2/scripting/EngineScriptConversions.cpp
===================================================================
--- source/simulation2/scripting/EngineScriptConversions.cpp	(revision 14624)
+++ source/simulation2/scripting/EngineScriptConversions.cpp	(working copy)
@@ -163,7 +163,25 @@
 
 template<> jsval ScriptInterface::ToJSVal<CFixedVector3D>(JSContext* cx, const CFixedVector3D& val)
 {
-	JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
+	// apply the Vector3D prototype to the return value;
+	jsval vector;
+	JSObject* obj;
+	bool success = false;
+	if (JS_GetProperty(cx, JS_GetGlobalObject(cx), "Vector3D", &vector))
+	{
+		jsval proto;
+		if (JS_GetProperty(cx, JSVAL_TO_OBJECT(vector), "prototype", &proto))
+		{
+			success = true;
+			obj = JS_NewObject(cx, NULL, JSVAL_TO_OBJECT(proto), NULL);
+		}
+	}
+	if (!success)
+	{
+		LOGWARNING(L"Vector3D global script not loaded");
+		obj = JS_NewObject(cx, NULL, NULL, NULL);
+	}
+
 	if (!obj)
 		return JSVAL_VOID;
 
@@ -197,7 +215,25 @@
 
 template<> jsval ScriptInterface::ToJSVal<CFixedVector2D>(JSContext* cx, const CFixedVector2D& val)
 {
-	JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
+	// apply the Vector2D prototype to the return value
+	jsval vector;
+	JSObject* obj;
+	bool success = false;
+	if (JS_GetProperty(cx, JS_GetGlobalObject(cx), "Vector2D", &vector))
+	{
+		jsval proto;
+		if (JS_GetProperty(cx, JSVAL_TO_OBJECT(vector), "prototype", &proto))
+		{
+			success = true;
+			obj = JS_NewObject(cx, NULL, JSVAL_TO_OBJECT(proto), NULL);
+		}
+	}
+	if (!success)
+	{
+		LOGWARNING(L"Vector3D global script not loaded");
+		obj = JS_NewObject(cx, NULL, NULL, NULL);
+	}
+
 	if (!obj)
 		return JSVAL_VOID;
 
