Hello Facepunch,
I may have really poorly worded the title, so I'll catch you up to speed on what I'm working on.
I am almost finished with my Murder Bots v2.0 release for MechanicalMind's Murder. I currently am working on the knife throwing aspect of the Bots.
What I have is the code used in the secondary attack on the SWEP, what I need is an aiming system. How can I calculate what angle the Bot should be looking (pitch wise) in order for the knife to reach it's target's OBBCenter.
Code for the player meta function:
[CODE]local plymeta = FindMetaTable( "Player" )
function plymeta:throwFullKnife()
local ent = ents.Create("mu_knife")
ent:SetOwner(self)
ent:SetPos(self:GetShootPos())
local knife_ang = Angle(-28,0,0) + self:EyeAngles()
knife_ang:RotateAroundAxis(knife_ang:Right(), -90)
ent:SetAngles(knife_ang)
ent:Spawn()
local phys = ent:GetPhysicsObject()
phys:SetVelocity(self:GetAimVector() * (1000 + 200))
phys:AddAngleVelocity(Vector(0, 1500, 0))
self:StripWeapon("weapon_mu_knife")
end[/CODE]
Thanks!
[code]local direction = targetPos-sourcePos
local angle = direction:Angle()
local pitch = angle.p[/code]
I think he wants to calculate the arc trajectory of the knife, so that it lands on the target.
[QUOTE] for the knife to reach it's target's OBBCenter[/QUOTE]
[QUOTE]local knife_ang = Angle(-28,0,0) + self:EyeAngles()[/QUOTE]
[url]https://en.wikipedia.org/wiki/Trajectory_of_a_projectile#Angle_of_reach[/url]
ooh that looks really helpful.
Let me try that.
[editline]18th June 2016[/editline]
I started porting some code I found that had to do with Angle Of Reach.
I'm getting the error "attempt to perform arithmetic on a string value" at line 45.
What am I doing wrong?
Thanks.
[CODE]local distance = startpos:Distance(endpos)
local initialvelocity = 1200
local gravity = 600
local ydifference = (endpos.y - startpos.y)
print(ydifference)
local determinant = (initialvelocity ^ 4) - (gravity * ((gravity*(distance^2)) + (2*ydifference*(initialvelocity^2))))
local root = math.sqrt(determinant)
local theta = math.atan(((initialvelocity ^ 2)+root)/(gravity*distance))
print("Theta is: " + theta)[/CODE]
[LUA]print("Theta is: " + theta)[/LUA] should be [LUA]print("Theta is: ", theta)[/LUA]
[CODE]function plymeta:calcAngleOfReach(endpos)
local distance = self:GetPos():Distance(endpos)
local initialvelocity = 1200
local gravity = 600
local ydifference = (endpos.y - self:GetPos().y)
print(ydifference)
local determinant = (initialvelocity ^ 4) - (gravity * ((gravity*(distance^2)) + (2*ydifference*(initialvelocity^2))))
local root = math.sqrt(determinant)
local theta = math.atan(((initialvelocity ^ 2)+root)/(gravity*distance))
print("Theta is: ", theta)
-- Find length of opposite side of triangle (height adjustment)
local lengthofopposite = math.tan(theta) * distance;
local lookatpos = endpos + Vector(0,lengthofopposite,0)
print("Height adjustment: " .. lengthofopposite);
print(lookatpos)
local angletobesetat = (self:WorldToLocal( lookatpos ):Angle())
print(angletobesetat)
self:SetEyeAngles(angletobesetat)
end[/CODE]
Why doesn't this work?
I'm running "lua_run Entity(1):calcAngleOfReach(Entity(2):GetPos())" but everything is not quite right.
Can someone take a look at this?
What are the print results you're getting?
[editline]18th June 2016[/editline]
See if this video helps.
[url]https://www.youtube.com/watch?v=6CSHt1-ShL4[/url]
He calculates how much above the target you have to aim, in order to hit the target. Which is perfect for you, since you can add the height to the target vector, then calculate the angle by subtracting the new target vector minus the shoot position.
[QUOTE=McDunkable;50546074]What are the print results you're getting?
[editline]18th June 2016[/editline]
See if this video helps.
[url]https://www.youtube.com/watch?v=6CSHt1-ShL4[/url]
He calculates how much above the target you have to aim, in order to hit the target. Which is perfect for you, since you can add the height to the target vector, then calculate the angle by subtracting the new target vector minus the shoot position.[/QUOTE]
Alright. I'll take a look in a second. I'm an Algebra 2 student, but I'll give it a shot. Will this account for the player's velocity, and the target entity's velocity, or where would I add that?
No, that wouldn't account for that. If your target is moving, you're going to have to predict where it will be by the time the projectile arrives. So I guess measure how long the projectile will take to arrive, then predict where the player will be in t + timeToArrival then calculate the new trajectory.
Alright I have an almost perfect function now. I had remembered that I misconverted the coordinate system I was using. GMod uses Z for it's vertical axis, where the original code used Y.
Here is the code I have now.
[CODE]function plymeta:calcAngleOfReach(endpos, force)
local distance = self:GetPos():Distance(endpos)
local initialvelocity = (force * 1000 + 200)
local gravity = GetConVar("sv_gravity"):GetInt()
local zdifference = (endpos.z - self:GetPos().z)
print(zdifference)
local determinant = (initialvelocity ^ 4) - (gravity * ((gravity*(distance^2)) + (2*zdifference*(initialvelocity^2))))
local root = math.sqrt(determinant)
local theta = math.atan(((initialvelocity ^ 2)+root)/(gravity*distance))
print("Theta is: ", theta)
-- Find length of opposite side of triangle (height adjustment)
local lengthofopposite = math.tan(theta) * distance;
local lookatpos = endpos + Vector(0,0,lengthofopposite)
print("Height adjustment: " .. lengthofopposite);
print(lookatpos)
local angletobesetat = self:WorldToLocal( lookatpos ):Angle()
local fstplpos = endpos -- or Vector(0,0,0)
local ownpos = self:GetPos() -- or Vector(0,0,0)
local xdiff = fstplpos.x - ownpos.x
local ydiff = fstplpos.y - ownpos.y
local zdiff = fstplpos.z - ownpos.z
local xydist = math.Distance(fstplpos.x,fstplpos.y,ownpos.x,ownpos.y)
yaw = math.deg(math.atan2(ydiff,xdiff))
local angletobe = Angle(angletobesetat.p,yaw,0)
print(angletobe)
self:SetEyeAngles(angletobe)
end
function plymeta:throwFullKnife()
local force = 1
local ent = ents.Create("mu_knife")
ent:SetOwner(self)
ent:SetPos(self:GetShootPos())
local knife_ang = Angle(-28,0,0) + self:EyeAngles()
knife_ang:RotateAroundAxis(knife_ang:Right(), -90)
ent:SetAngles(knife_ang)
ent:Spawn()
local phys = ent:GetPhysicsObject()
phys:SetVelocity(self:GetAimVector() * (force * 1000 + 200))
phys:AddAngleVelocity(Vector(0, 1500, 0))
self:StripWeapon("weapon_mu_knife")
end[/CODE]
It works almost perfectly, except the knife falls a little short, and the yaw if slightly off.
Have you taken into consideration air resistance? If I remember correctly, in Gmod, it is directly proportional to the object's mass. That's why an object with 50,000 weight basically ignores air drag, while those with 1 will fall like and slow down like a feather. I also just remember that someone has done this in Gmod already. I don't remember if it's an addon on the workshop, but it shows you the ballistic trajectory of the crossbow bolt. Perhaps you could take a look at the code.
[QUOTE=McDunkable;50546837]Have you taken into consideration air resistance? If I remember correctly, in Gmod, it is directly proportional to the object's mass. That's why an object with 50,000 weight basically ignores air drag, while those with 1 will fall like and slow down like a feather. I also just remember that someone has done this in Gmod already. I don't remember if it's an addon on the workshop, but it shows you the ballistic trajectory of the crossbow bolt. Perhaps you could take a look at the code.[/QUOTE]
Could you please provide a code example? I was just looking into that. That would explain it falling short, but not why my yaw is off.
Make use of this library to get precise values.
[URL]http://wiki.garrysmod.com/page/physenv/GetGravity[/URL]
[URL]http://wiki.garrysmod.com/page/physenv/GetAirDensity[/URL]
Now I don't really know why your yaw would be off. I see you have indeed converted it into degrees, have you tried offsetting it by right angles? For example, if it's shooting to the side, add or take 90 degrees. However, if you think the angles are right, and it's missing by a few degrees, do some tests and see if it's constant or dependent on distance. Your equation might be a bit off then.
[editline]18th June 2016[/editline]
Alternatively, you could make the projectile constantly try to reach it's predetermined target position, by accelerating it towards it, or adjusting it's course. I'm not talking about it being homing towards the player you want to kill, but rather just fix it onto its ballistic trajectory.
[editline]18th June 2016[/editline]
Also, physenv limits how much an entity can accelerate per second. By default, it's 3500 units, perhaps you're launching your projectile faster, therefore your equation is accounting for that speed, when in reality it's going to get clamped to 3500 as soon as it launches.
Ok. With a little trial and error I just accounted for air resistance with 100 less in the initial velocity. Hits the target every time.
Here is the code if anyone is interested before I make it all neat and pretty.
[CODE]function plymeta:calcAngleOfReach(endpos, force)
local distance = self:GetPos():Distance(endpos)
local initialvelocity = (force * 1000 + 100)
local gravity = GetConVar("sv_gravity"):GetInt()
local zdifference = (endpos.z - self:GetPos().z)
print(zdifference)
local determinant = (initialvelocity ^ 4) - (gravity * ((gravity*(distance^2)) + (2*zdifference*(initialvelocity^2))))
local root = math.sqrt(determinant)
local theta = math.atan(((initialvelocity ^ 2)+root)/(gravity*distance))
print("Theta is: ", theta)
-- Find length of opposite side of triangle (height adjustment)
local lengthofopposite = math.tan(theta) * distance;
local lookatpos = endpos + Vector(0,0,lengthofopposite)
print("Height adjustment: " .. lengthofopposite);
print(lookatpos)
local angletobesetat = self:WorldToLocal( lookatpos ):Angle()
local fstplpos = endpos -- or Vector(0,0,0)
local ownpos = self:GetPos() -- or Vector(0,0,0)
local xdiff = fstplpos.x - ownpos.x
local ydiff = fstplpos.y - ownpos.y
local zdiff = fstplpos.z - ownpos.z
local xydist = math.Distance(fstplpos.x,fstplpos.y,ownpos.x,ownpos.y)
local yaw = math.deg(math.atan2(ydiff,xdiff))
local angletobe = Angle(angletobesetat.p,yaw,angletobesetat.r)
print(angletobe)
self:SetEyeAngles(angletobe)
end
[/CODE]
Sorry, you need to Log In to post a reply to this thread.