• A* Pathfinding Bots: A "Public Project"
    0 replies, posted
Hello everybody. I decided I'd make a "public project" for lack of a better word. Now, I've always wanted deathmatch-oriented bots in Garry's Mod. So, I decided to look into pathfinding and GMod's built-in navmesh functions. The end result so far was this mess: [code] local testnodes = {} for i = 1, #navmesh.GetAllNavAreas() do local area = navmesh.GetNavAreaByID( i ) if area:IsValid() then testnodes[i] = {} testnodes[i].id = i testnodes[i].x = area:GetCenter().x testnodes[i].y = area:GetCenter().y end end function navmesh.FindExclude( excl, pos, radius, stepdown, stepup ) local checked_areas = {} local unchecked_areas = navmesh.Find( pos, radius, stepdown, stepup ) for _, v in pairs(unchecked_areas) do if v ~= excl then checked_areas[#checked_areas + 1] = v end end return checked_areas end nb_bots = {} function nb_bots.GetAStarPath( ply ) local nav_start = navmesh.GetNearestNavArea( ply:GetPos() ) if !nav_start:IsValid() then return "nope" end local nav_goal = table.Random(navmesh.FindExclude( nav_start, Entity(1):GetPos(), 9999, 9999, 9999 )) if !nav_goal:IsValid() then return "nope" end return astar.path( testnodes[nav_start:GetID()], testnodes[nav_goal:GetID()], testnodes, true, function() return true end ) or "nope" end function nb_bots.DecideEnemy( ply ) if ply.Enemy and ply.Enemy:Alive() and ply:Visible(ply.Enemy) then return end local found = {} for not_needed, playr in pairs( player.GetAll() ) do if playr ~= ply and playr:Alive() and ply:Visible( playr ) then found[#found + 1] = playr end end if #found == 0 and ply.Enemy ~= nil then ply.Enemy = nil return end ply.Enemy = table.Random( found ) end function nb_bots.LookatPosXYZ( usercmd, ply, position ) --[[local our_position = ply:GetPos() local distance = our_position:Distance( position ) local pitch = math.atan2( -(position.z - our_position.z), distance ) local yaw = math.deg(math.atan2(position.y - our_position.y, position.x - our_position.x)) ply:SetEyeAngles( Angle( pitch, yaw, 0 ) ) usercmd:SetViewAngles( Angle( pitch, yaw, 0 ) )]] local ang = ((ply:EyePos() - Vector(0,0,10))-(position - Vector(0,0,10))):AngleEx(Vector(0,0,0)) local lClamp = ang + Angle(0,180,0) local ideal = Angle(math.Clamp(-lClamp.p,-180,180),lClamp.y,math.Clamp(lClamp.r,-180,180)) ply:SetEyeAngles(ideal) usercmd:SetViewAngles(ideal) end function nb_bots.LookatPosXY( usercmd, ply, position ) local our_position = ply:GetPos() local distance = our_position:Distance( position ) local pitch = math.atan2( -(position.z - our_position.z), distance ) local yaw = math.deg(math.atan2(position.y - our_position.y, position.x - our_position.x)) ply:SetEyeAngles( Angle( pitch, yaw, 0 ) ) usercmd:SetViewAngles( Angle( pitch, yaw, 0 ) ) end hook.Add( "StartCommand", "Bots_Control", function( ply, cmd ) if not ply:IsBot() then return end cmd:ClearMovement() cmd:ClearButtons() if not ply.AstarPath then ply.AstarPath = nb_bots.GetAStarPath( ply ) ply.CurSegment = 1 end if ply.CurSegment ~= (#ply.AstarPath+1) then if ply.AstarPath == "nope" then return end if math.Dist( ply:GetPos().x, ply:GetPos().y, ply.AstarPath[ply.CurSegment].x, ply.AstarPath[ply.CurSegment].y ) <= 1 then print("moving on!") ply.CurSegment = ply.CurSegment + 1 else cmd:SetForwardMove( 200 ) end if ply.CurSegment ~= #ply.AstarPath+1 then local vec = Vector( ply.AstarPath[ply.CurSegment].x, ply.AstarPath[ply.CurSegment].y, 0 ) nb_bots.LookatPosXY( cmd, ply, vec ) end else ply.CurSegment = 1 end --[[local valid = IsValid(ply:GetActiveWeapon()) if valid and ply:GetActiveWeapon():GetClass() ~= "weapon_ar2" then ply:SelectWeapon("weapon_ar2") end nb_bots.DecideEnemy( ply ) if ply.Enemy then nb_bots.LookatPos(cmd, ply, ply.Enemy:EyePos())--:GetPos()) if ply.Enemy:Alive() and ply:Visible(ply.Enemy) then --if ply:GetPos().z - enemy:GetPos().z <= -30 or ply:GetPos().z - enemy:GetPos().z >= 30 then return end --if valid and ply:GetActiveWeapon():Clip1() == 0 then --cmd:SetButtons( IN_RELOAD ) --return --end cmd:SetSideMove(math.cos(RealTime())*400) if ply:GetPos():Distance(ply.Enemy:GetPos()) < 801 then cmd:SetButtons( IN_ATTACK ) else cmd:SetForwardMove( 200 ) end end --[[if not ply.path then local nav_area = table.Random( navmesh.Find( ply:GetPos(), 9000, 9000, 9000 ) ) ply.path = nav_area:GetRandomPoint() end if ply.path and ply:GetPos():Distance( ply.path ) ~= 0 then nb_bots.Look_at_Position( cmd, ply, ply.path ) cmd:SetForwardMove( 200 ) else ply.CompletedMoving = true end] end]] end )[/code] (with this a* module [url]https://github.com/lattejed/a-star-lua[/url]) Now, I made this thread to bring awareness to it and also to start a discussion about it. I want to see if anyone is willing to help. I'm interested in seeing what we can do with this. [editline]12th January 2016[/editline] If anyone wants to help clean the code up/has any ideas, be sure to post here!
Sorry, you need to Log In to post a reply to this thread.