How do i make my entity roll?

**Objective: **I need my Puddle Jumper to roll but AddAngleVelocity just makes it spin out of control
**Error: **No errors but spins out of control
**Code: *[lua]/
Puddle Jumper for GarrysMod10
Copyright © 2009 RononDex

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/
–################# HEADER #################
AddCSLuaFile(“cl_init.lua”);
AddCSLuaFile(“shared.lua”);
include(“shared.lua”);

ENT.Sounds={
Fail={Sound(“buttons/button19.wav”),Sound(“buttons/combine_button2.wav”)},
Cloak=Sound(“npc/strider/striderx_alert4.wav”),
Uncloak=Sound(“npc/turret_floor/die.wav”),
};

–############### Makes it spawn
function ENT:SpawnFunction(pl, tr)
if (!tr.HitWorld) then return end;
local e = ents.Create(“puddle_jumper”);
e:SetPos(tr.HitPos + Vector(0, 10, 50));
e:Spawn();
e:Activate();
return e;
end

–################# Init
function ENT:Initialize()

self.Jumper = {}
self.Jumper.RotorWash = {}
self.Entity:SetUseType( SIMPLE_USE )
self.Rotorwash = false

self.Inflight=false
self.Pilot=false
self.Entity:SetModel("models/Votekick/jumper/jumper_v3.mdl");
self.Entity:PhysicsInit(SOLID_VPHYSICS);
self.Entity:SetMoveType(MOVETYPE_VPHYSICS);
self.Entity:SetSolid(SOLID_VPHYSICS);
self.Entity:StartMotionController()
self.Accel=0
self.reloadtime = (4);
self.Hover = true;
self.Entity:Health( 500 )
self.Target = Vector(0,0,0);
self.DroneMaxSpeed = (8000);
self.AllowAutoTrack = (true);
self.AllowEyeTrack = (false);
self.TrackTime = 1000000;
self.Drones = {};
self.DroneCount = 0;
self.MaxDrones = (10);
self.Track = false;
self.Launched = false;
self.sequence2 = self.Entity:LookupSequence("door_o");
self.door = true	
self.Entity:SetSequence(self.sequence2);
self.Entity:SetPlaybackRate(2.0);

local phys = self.Entity:GetPhysicsObject();
if(phys:IsValid()) then
	phys:Wake();
	phys:SetMass(10000);
end

end

function ENT:OnRemove()
if self.Inflight then
self.Pilot:Spawn(self.Entity:GetPos())
self.Inflight=false
self.Rotorwashent:Remove()
self.Rotorwash = false
else
return end
end

function ENT:Think()

	if self.Pilot and self.Inflight and self.Pilot:IsValid() then
		if self.Pilot:KeyDown(IN_SPEED) then
		
	if(not self.epodo) then
		self.sequence = self.Entity:LookupSequence("open");
			self.epodo = true
			self.Entity:EmitSound("jumper/Drivepods1.mp3", 100, 100 )
		else
			self.sequence = self.Entity:LookupSequence("close")
			self.epodo = false
			self.Entity:EmitSound("jumper/Drivepods2.mp3", 100, 100 )
end
	self.Entity:SetSequence(self.sequence);
end

if self.Pilot and self.Inflight and self.Pilot:IsValid() then

if self.Pilot:KeyDown(IN_SCORE) then
	if(not self.door) then
		self.sequence2 = self.Entity:LookupSequence("door_o");
		self.door = true
	else
		self.sequence2 = self.Entity:LookupSequence("door_c");
		self.door = false
	end
	self.Entity:SetSequence(self.sequence2);
end

if self.Pilot:KeyDown(IN_RELOAD) then
if(not ValidEntity(p)) then return end;
local e = self:FindGate(3000);
if(not ValidEntity(e)) then return end;
if(hook.Call("StarGate.Player.CanDialGate",GAMEMODE,p,e) == false) then return end;
umsg.Start("StarGate.OpenDialMenuDHD",p);
umsg.Entity(e);
umsg.End();

end

if self.Pilot:KeyDown(IN_WALK) then
self:Status(true);
	else
self:Status(false);

end

//if !self.Pilot then return end

if self.Inflight and self.Pilot and self.Pilot:IsValid() then

	self.Pilot:SetPos(self.Entity:GetPos())

if self.Pilot:KeyDown(IN_USE) then

	self.Entity:NextThink(CurTime())
	
	else
	
	self.Entity:NextThink(CurTime() +1)

end

end

local enabled = self:Enabled();

return true;
end
end
if self.Inflight == false then
self.Rotorwash = false
end
end

function ENT:Use(ply,caller,ent)

if self.Inflight then

self.Pilot:UnSpectate()
		self.Pilot:DrawViewModel(true)
		self.Pilot:DrawWorldModel(true)
		self.Pilot:Spawn()
		self.Pilot:SetNetworkedBool("isDrivePJ",false)
		self.Pilot:SetPos(self.Entity:GetPos()+Vector(0,0,-30))
		self.sequence2 = self.Entity:LookupSequence("door_o");
		self.door = true
		self.sequence = self.Entity:LookupSequence("close");
		self.epodo = false

		self.Entity:SetSequence(self.sequence)
		self.Entity:SetSequence(self.sequence2);

		self.Accel=0
		self.Inflight=false
		self.Rotorwash = false
		self.Rotorwashent:Remove()

else

	self.Entity:GetPhysicsObject():Wake()
	self.Entity:GetPhysicsObject():EnableMotion(true)
	self.Inflight=true
	self.Pilot=ply
	
	local rotorent = ents.Create("env_rotorwash_emitter")
	rotorent:SetPos(self.Entity:GetPos())
	rotorent:Spawn()
	rotorent:Activate()
	rotorent:SetParent(self.Entity)
	self.Rotorwashent = rotorent
	self.Rotorwash = true
	
	ply:Spectate( OBS_MODE_CHASE )
	ply:DrawViewModel(false)
	ply:DrawWorldModel(false)
	ply:StripWeapons()
	ply:SetNetworkedBool("isDrivePJ",true)
	ply:SetNetworkedEntity("PJ",self.Entity)
	if( self.door == true ) then
	self.sequence2 = self.Entity:LookupSequence("door_c");
	self.door = false
else
	return end		
	self.Entity:SetSequence(self.sequence2);
end

end

function ENT:PhysicsSimulate( phys, deltatime )

if self.Pilot and self.Pilot:IsValid() then

	if self.Inflight then
	local num=0
	
	if( self.epodo == true ) and self.Pilot:KeyDown(IN_FORWARD) then
		num=1500
	elseif self.Pilot:KeyDown(IN_FORWARD) then
		num=1000
	elseif self.epodo == false and self.Pilot:KeyDown(IN_MOVELEFT) then
		num=500
	elseif self.epodo == false and self.Pilot:KeyDown(IN_MOVERIGHT) then
		num=500
	elseif self.Pilot:KeyDown(IN_BACK) then
		num=-500
end


	phys:Wake()
		self.Accel=math.Approach(self.Accel,num,10)
		if not self.Hover then
		if self.Accel>-200 and self.Accel < 200 then return end --with out this you float
		end
			if self.epodo == true and self.Pilot:KeyDown(IN_MOVELEFT) then
phys:AddAngleVelocity(phys:GetAngleVelocity()+Angle(0,0,-1))

elseif self.epodo == true and self.Pilot:KeyDown(IN_MOVERIGHT) then
phys:AddAngleVelocity(phys:GetAngleVelocity()+Angle(0,0,1))
end
	local pr={}
		pr.secondstoarrive	= 1
		if  self.Pilot:KeyDown( IN_DUCK ) then 
			pr.pos = self.Entity:GetPos()+self.Entity:GetUp()*-200
		elseif  self.Pilot:KeyDown( IN_JUMP ) then 
			pr.pos = self.Entity:GetPos()+self.Entity:GetUp()*300
		elseif self.Pilot:KeyDown( IN_MOVERIGHT ) then 
			pr.pos = self.Entity:GetPos()+self.Entity:GetRight()*400
		elseif self.Pilot:KeyDown( IN_MOVELEFT ) then 
			pr.pos = self.Entity:GetPos()+self.Entity:GetRight()*-400
		else 
			pr.pos = self.Entity:GetPos()+self.Entity:GetForward()*self.Accel
		end
		pr.maxangular		= 5000
		pr.maxangulardamp	= 10000
		pr.maxspeed			= 1000000
		pr.maxspeeddamp		= 10000
		pr.dampfactor		= 0.8
		pr.teleportdistance	= 5000
		pr.angle		= self.Pilot:GetAimVector():Angle()
		
		pr.deltatime		= deltatime
	phys:ComputeShadowControl(pr)
		end



local pos = self.Entity:GetPos();

if self.epodo == true then
if (self.Inflight and self.DroneCount < 10) then

		if self.Pilot:KeyDown(IN_ATTACK) then 
			local vel = self.Entity:GetVelocity();
			local up = self.Entity:GetUp();
			-- calculate the drone's position offset. Otherwise it might collide with the launcher
			local offset = StarGate.VelocityOffset({Velocity=vel,Direction=up,BoundingMax=self.Entity:OBBMaxs().z});
			local e = ents.Create("drone");
			e.Parent = self.Entity;
			e:SetPos(pos+offset);
			e:SetAngles(self.Entity:GetForward():Angle()+Angle(math.random(-2,2),math.random(-2,2),math.random(-2,2)));
			e:SetOwner(self.Entity); -- Don't collide with this thing here please
			e.Owner = self.Entity.Owner;
			e:Spawn();
			e:SetVelocity(vel);
			self.DroneCount = self.DroneCount + 1;
			self.Drones[e] = true;
			-- This is necessary to make the drone not collide and explode with the cannon when it's moving
			e.CurrentVelocity = math.Clamp(vel:Length(),0,self.DroneMaxSpeed-500)+500;
			e.CannonVeloctiy = vel;
		end
end

if self.Inflight then
	self.Track = false
		if self.Pilot:KeyDown(IN_ATTACK2) then
		self.Track = true
		end 
	end
end

end
end

function ENT:ShowOutput()

end

function ENT:StargateCheck() --Check if we are near a dialing stargate.
local gate = self:FindGate(800)
self.NearValidStargate = false
if ValidEntity(gate) then
if gate.IsStargate then
if gate.Outbound then
self.NearValidStargate = true
end
end
end
end

function ENT:OpenDHD§ --thank you avon
if(not ValidEntity§) then return end;
local e = self:FindGate(3000);
if(not ValidEntity(e)) then return end;
if(hook.Call(“StarGate.Player.CanDialGate”,GAMEMODE,p,e) == false) then return end;
umsg.Start(“StarGate.OpenDialMenuDHD”,p);
umsg.Entity(e);
umsg.End();
end

function ENT:FindGate(dist)
local gate;
local pos = self.Entity:GetPos();
for ,v in pairs(ents.FindByClass("stargate*")) do
local sg_dist = (pos - v:GetPos()):Length();
if(dist >= sg_dist) then
dist = sg_dist;
gate = v;
end
end
return gate;
end

function ENT:Status(b,nosound)
if(b) then
if(not self:Enabled()) then
local e = ents.Create(“cloaking”);
e.Size = 200;
e:SetPos(self.Entity:GetPos());
e:SetAngles(self.Entity:GetAngles());
e:SetParent(self.Entity);
e:Spawn();
if(not nosound) then
self:EmitSound(self.Sounds.Cloak,80,math.random(80,100));
end
if(e and e:IsValid() and not e.Disable) then – When our new cloak mentioned, that there is already a cloak
self.Cloak = e;

				return;
			end
		
	end
else
	if(self:Enabled()) then
		self.Cloak:Remove();
		self.Cloak = nil;
		-- Give back the energy, we took when it was enagaged
		if(not nosound) then
			self:EmitSound(self.Sounds.Uncloak,80,math.random(90,110));
		end
	end
	return;
end

-- Fail animation

end

function ENT:Enabled()
return (self.Cloak and self.Cloak:IsValid());
end

–Add explosions
function ENT:Health()

if self.Entity:Health() < 1 then
local explode = ents.Create( “env_explosion” )
explode:Spawn()
explode:SetKeyValue( “iMagnitude”, “220” )
explode:Fire( “Explode”, 0, 0 )
explode:EmitSound( “weapon_AWP.Single”, 400, 400 )
end
end
[/lua]
Any help would be brilliant

Thanks

Can we see your code?

Added to OP

Do this instead:

[lua]
self.lin = Vector(0,0,0)
self.ang = Vector(0,0,0)
local forcelinear, forceangular = phys:CalculateForceOffset(self:GetUp() * 20, self:GetPos() + self:GetRight() * 20) //First arguement is the vector force, second is the origin of the force.

//self.lin = forcelinear + self.lin Dont apply linear you just want it to roll
self.ang = forceangular + self.ang

return self.ang, self.lin, SIM_GLOBAL_ACCELERATION
[/lua]

If you want to make the ship move forwards with this method then do this:

[lua]
local forcelinear, forceangular = phys:CalculateForceOffset(self:GetForwawrd() * 20, self:GetPos())

self.lin = forcelinear + self.lin
//self.ang = forceangular + self.ang On this occasion we DO want to apply linear force but not turn.
[/lua]

Inside your physics simulate function where you want to make it roll left. To make it roll right change the origin to the left and do the same without returning the angular and linear vectors.

Yeah i don’t understand what your doing there

[editline]02:51PM[/editline]

I’ve fixed it now, now rolls perfectly