Jump to content
  • entries
    941
  • comments
    5,894
  • views
    866,801

Building the Turret AI


Josh

1,723 views

 Share

In this series of blogs I am going to describe my implementation of AI for a new Workshop Store model, the Leadwerks turret. The model is shown below, without the weapon inserted.

 

blogentry-1-0-65988500-1461465598_thumb.jpg

 

Before writing any code I first decided the main behaviors I wanted this script to involve.

  • The turret should scan the area to identify an enemy (using the team ID to differentiate between enemy types) and choose the closest target. Unlike the soldier AI, the turret AI will not change targets when another enemy attacks it.
  • If the target is lost or occluded, another target will be chosen.
  • The turret will fire a continuous rapid stream of bullets whenever an enemy is in view. We want this to be an obstacle you have to take cover from, or you will quickly be killed.
  • The turret can be killed by either incurring enough damage to bring the health down to zero, or by knocking it over to deactivate it. If the turret is damaged to the point of "death" it will shoot sparks out once and then emit a cloud of smoke. The smoke will be continuous, to clearly indicate the turret is inactive.
  • The turret movement will not use the physics system. The model is relatively small and I can't think of any really useful reasons I would want the motion to interact with physics, so I'm not going to implement this.

 

The first draft of the script uses the World:ForEachEntityInAABB() function to perform a search and find a target enemy within a certain range. I set a breakpoint at line 18 to confirm that the script was successfully finding the player: Notice that a distance check is used so the turret will locate the closest enemy.

Script.target = nil--enemy to shoot
Script.mode = "idle"
Script.lastsearchtime=0
Script.searchfrequency = 500
Script.range = 20

function TurretSearchHook(entity,extra)
   if entity.script~=nil then
       if type(entity.script.health)=="number" then
           if entity.script.health>0 then
               local d = extra:GetDistance(entity)
               if d<extra.script.range then
                   if extra.script.target~=nil then
                       if extra.script:GetDistance(extra.script.target)>d then
                           extra.script.target = entity.script
                       end
                   else
                       extra.script.target = entity.script                    
                   end
               end
           end
       end
   end
end

function Script:UpdateWorld()

   --Search for target
   if self.target==nil then
       local currenttime = Time:GetCurrent()
       if currenttime - self.lastsearchtime > self.searchfrequency then
           self.lastsearchtime = currenttime
           local pos = self.entity:GetPosition(true)
           local aabb = AABB(pos - Vec3(self.range), pos + Vec3(self.range))
           self.entity.world:ForEachEntityInAABBDo(aabb,"TurretSearchHook",self.entity)
       end
   end

end

  • Upvote 6
 Share

0 Comments


Recommended Comments

There are no comments to display.

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...