Building the Turret AI
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.
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
- 6
0 Comments
Recommended Comments
There are no comments to display.