function Movement(oMov, timer){
	this.moveable = moveable.detectMoveable(oMov);
	this.moveable.movement = this;
	this.copy_values();
	this.elem = this.moveable.elem;
	this.stepX = 0;
	this.stepY = 0;
	this.timer = Timer.detectTimer(timer);
	this.STOP_ON_FIRST = true;
	this.refreshCount = 0;
	this.IS_MOVING = false;
	this.onreach = new DOMEvent(this);
	this.onreach.register(
		Movement.defaultOnReach.name,
		Movement.defaultOnReach.func.bind(this)
	);
	this.init();
	if(this.constructor._TO_INSTANCES){
		this.constructor._instances.push(this);
	}
}
Object.extend(Movement.prototype, default_prototype_functions);
Movement.prototype.init = function(){
	this.init_events();
	this.onmove = DOMEvent.cloneEvent(this.moveable.onmove, this);
	if(this.timer._MUTUAL){
		if(this.timer.registerMovement){
			this.timer.registerMovement(this);
		}else{	
			Movement.handleMutualTimer(this.timer);
			this.timer.registerMovement(this);
		}
	}else{
		this.timer.registerEvent(
		{
			name: "Movement",
			func: function(objMoveable){
				objMoveable.moveBy(this.stepX, this.stepY);
			},
			oThis: this,
			args: [this.moveable]
		}
		);
	}
	this.moveable.onmove.register('copy values', this.copy_values.bind(this));
};
Movement.prototype.start = function(){
	this.IS_MOVING = true;
	if(!this.timer._MUTUAL){
		this.timer.start();
	}
};
Movement.prototype.stop = function(){
	this.IS_MOVING = false;
	if(!this.timer._MUTUAL){
		this.timer.clear();
	}
};
Movement.prototype.toggle = function(){
	if(this.IS_MOVING){
		this.stop();
	}else{
		this.start();
	}
};
Movement.prototype.setSteps = function(x, y){
	this.stepX = x ? x : 0;
	this.stepY = y ? y : 0;
};
Movement.prototype.setLimits = function(type, value, startValue){
	this.moveable.setLimits(type, value, startValue);
	var PRESETS = moveable.LIMITS[type];
	this[PRESETS.onless] = DOMEvent.cloneEvent(this.moveable[PRESETS.onless], this);
	this[PRESETS.onmore] = DOMEvent.cloneEvent(this.moveable[PRESETS.onmore], this);
};
Movement.prototype.unsetLimits = function(type){
	this.moveable.unsetLimits(type);
};
Movement.prototype.setMoveSpace = function(X, Y, sX, sY){
	this.moveSpace = this.moveable.setMoveSpace(X, Y, sX, sY);
	if(!this.onmovespacereach){
		this.onmovespacereach = DOMEvent.cloneEvent(this.moveable.onmovespacereach, this);
	}
};
Movement.prototype.moveTo = function(x, y, speed){
	speed = speed ? speed : 3;
	var curLeft = this.moveable.left;
	var curTop = this.moveable.top;
	var nextLeft = x;
	var nextTop = y;
	var distX = nextLeft - curLeft;
	var distY = nextTop - curTop;
	var biggerDist = Math.abs(distX) > Math.abs(distY) ? distX : distY;
	var numOfSteps = Math.abs(Math.round(biggerDist / speed));
	if(numOfSteps == 0){
		numOfSteps = 1;
	}
	var stepX = distX / numOfSteps;
	var stepY = distY / numOfSteps;
	this.mt_stepCount = 0;
	this.mt_numOfSteps = numOfSteps;
	this.distY = distY;
	this.distX = distX;
	this.moveToX = nextLeft;
	this.moveToY = nextTop;
	this.setSteps(stepX, stepY);
	this.X_REACHED = false;
	this.Y_REACHED = false;
	this.moveable.onmove.set_break(this.stopMoveTo.bind(this));
	this._moveTo();

};
Movement.prototype._moveTo = function(){
	this.MOVE_TO = true;
	this.moveable.movedToX = 0;
	this.moveable.movedToY = 0;
	this.moveable.onmove.remove('move-to');
	this.moveable.onmove.register(
		'move-to',
		function(){
			var oM = this.movement;
			if(Math.abs(this.movedToX + this.moveX ) >= Math.abs(oM.distX)){
				var mX = this.moveX;
				this.moveX = Math.floor((Math.abs(oM.distX) - Math.abs(this.movedToX))) * this.moveX.signOf();
				oM.X_REACHED = true;
				this.correctLimit("X", mX);
			}
			if(Math.abs(this.movedToY + this.moveY ) >= Math.abs(oM.distY)){
				var mY = this.moveY;
				this.moveY = Math.floor((Math.abs(oM.distY) - Math.abs(this.movedToY))) * this.moveY.signOf();
				oM.Y_REACHED = true;
				this.correctLimit("Y", mY);
			}
			this.movedToX += this.moveX;
			this.movedToY += this.moveY;
			oM.mt_stepCount++;
			if(oM.X_REACHED && oM.Y_REACHED){
				this.onaftermove.register(
					'move-to-stop',
					function(){
						this.onreach.fire();
					}.bind(oM),
					1
				);
			}
		}.bind(this.moveable, this)
	);
	if(!this.IS_MOVING){
		this.start();
	}
};
Movement.prototype.stopMoveTo = function(){
	this.moveable.onmove.remove('move-to');
	this.stop();
	this.MOVE_TO = false;
};
Movement.prototype.moveDistance = function(distance, direction, numOfSteps){
};
Movement.prototype.copy_values = function(){
	this.startX = this.moveable.startX;
	this.startY = this.moveable.startY;
};
Movement.prototype.toggle = function(){
	if(this.IS_MOVING){
		this.stop();
	}else{
		this.start();
	}
};
Movement.prototype._events = [
	{name: "start", func_name: "start", type: "before"},	
	{name: "stop", func_name: "stop", type: "before"},
	{name: "movetostart", func_name: "_moveTo", type: "before"}
];
Movement.prototype.__name = "Movement";
Movement.prototype.copy_values = function(){
	this.left = this.moveable.left;
	this.top = this.moveable.top;
};
Movement.defaultOnReach = {
	name: 'onreach',
	func: function(){
		this.stopMoveTo();
	}
};
Movement.mutualTimer = null;
Movement.handleMutualTimer = function(oTimer){
	oTimer.movements = [];
	oTimer.registerMovement = function(objMovement){
		this.movements.push(objMovement)
	};
	oTimer.registerEvent(
		{
			name: "Movement",
			func: function(){
				this.movements.each(function(mov){
					if(mov.IS_MOVING){
						mov.moveable.moveBy(mov.stepX, mov.stepY);
					}
				});
			},
			oThis: oTimer,
			args: []
		}
	);	
};
Movement._directions = {
	west: {geo: "W", dir: "left", num: 4},
	north: {geo: "N", dir: "top", num: 1},
	east: {geo: "E", dir: "right", num: 2},
	south: {geo: "S", dir: "bottom", num: 2}
};

Movement._TO_INSTANCES = true;
Movement._instances = [];


/*************************************/
// DA NEW SHIT
Movement.prototype.distortSteps = function(x, y, sign, stop_value){
	this.step_distortion = {
		x: x, y: y, stop_value: stop_value, sign: sign || 1
	};
	this.onmove.register('step distortion', function(){
		var sd = this.step_distortion;
		if(sd.x){
			this.stepX = this.stepX + (this.stepX * sd.x * sd.sign);
		}
		if(sd.y){
			this.stepY = this.stepY + (this.stepY * sd.y * sd.sign);
		}
	});
	if(stop_value){
		this.onmove.register('stop on value', function(){
			var sd = this.step_distortion;
			if(sd.sign > 0){
				if(this.stepX >= sd.stop_value && this.stepY >= sd.stop_value){
					this.unsetStepDistortion();
					this.stop();
				}			
			}else{
				if(this.stepX <= sd.stop_value && this.stepY <= sd.stop_value){
					this.unsetStepDistortion();
					this.stop();
				}
			}

		});
	}
};
Movement.prototype.unsetStepDistortion = function(){
	this.onmove.remove('step distortion');
	this.onmove.remove('stop on value');
};
Movement.prototype.getAngle = function(){
	var angle = Nums.to_degree(Math.atan(this.stepY / this.stepX));
	if(this.stepX >= 0 && this.stepY >= 0){
		this.angle = angle;
	}else if(this.stepX < 0 && this.stepY >= 0){
		this.angle = 90 + (90 + angle);
	}else if(this.stepX < 0 && this.stepY < 0){
		this.angle = 180 + angle;
	}else if(this.stepX >= 0 && this.stepY < 0){
		this.angle = 360 + angle;
	}
	return this.angle;
};
Movement.prototype.setSteps2 = function(angle, speed){
	var x = Math.cos(Nums.to_rad(angle)) * speed;
	var y = Math.sin(Nums.to_rad(angle)) * speed;
	this.setSteps(x, y);
};