Jump to content

(Solved) Error in script: Attempt To Index Target - A Nil Value - Leadwerks 4.0


Defranco
 Share

Recommended Posts

Using a enemy AI script made by someone else -

 

Heres part of the code that seems to be the issue for LE 4.0

 

function Script:EndHurt()
if self.mode=="hurt" then
if self.target.health<=0 then
self:SetMode("idle")
return
end
if self.health<=0 then
self:EndDeath()
return
end

 

if self.target.health<=0 then gets a NIL error when certain scenarios happen between GOOD/BAD Npcs killing each other.

 

-- Attempt to index field "target" (A nil value)

 

When I put 1 NPC of each Good and Bad to fight, its fine.

 

As soon as I add 3 or more in a area - it gives the error. If i have separate battles far apart its fine.

Link to comment
Share on other sites

It's possible that NPC's are sharing a target and if one kills the target but the other doesn't then things could get messed up since the target probably get deleted?

 

Before using the target variable check if it's nil or not.

 

if self.target ~= nil then
  if self.target.health <= 0 then
  end
end

Link to comment
Share on other sites

okay I switched it and that specific problem went away -

 

Now I'm getting a new error

 

Unable to find "target" (a nil value) for this line ---- if self.entity:Follow(self.target.entity,self.speed,self.maxaccel) then

 

Seems to have a chain effect - my first thought was to put in another target check

 

Now I fixed it by adding

 

if self.target~=nil then to almost 6 script sections in the entire AI code --- this fixed it. but that seems like a lot of checks...

 

From the code below -

 

function Script:SetMode(mode)
if mode~=self.mode then
 math.randomseed(Time:GetCurrent())
 if self.debugMode then
  System:Print("AI mode set to: " .. mode)
 end
 local prevmode=self.mode
 self.mode=mode
 if mode=="idle" then
  local sound = self.sound.idle[math.random(1, #self.sound.idle)]
  if sound ~= nil then
   self.entity:EmitSound(sound,50,1,1,false)
  end
  self.target=nil
  local animationIndex = self.animation.idle[math.random(1, #self.animation.idle)]
  self.animationmanager:SetAnimationSequence(animationIndex, self.idleAnimationSpeed * Time:GetSpeed())
  self.entity:Stop()--stop following anything
 elseif mode=="patrolling" then
  self.entity:GoToPoint(self.currentWaypoint:GetPosition(true), self.speed, self.maxaccel)
  self.isPatrolling = true
  local animationIndex = self.animation.run[math.random(1, #self.animation.run)]
  self.animationmanager:SetAnimationSequence(animationIndex, self.runAnimationSpeed * Time:GetSpeed(),300)
 elseif mode=="hurt" then
  self:EndHurt()
 elseif mode=="attack" then
  self:EndAttack()
 elseif mode=="chase" then
  System:Print("Now in chase mode")
  if self.entity:Follow(self.target.entity,self.speed,self.maxaccel) then
   System:Print("follow")
   self.followingtarget=true
   local animationIndex = self.animation.run[math.random(1, #self.animation.run)]
   self.animationmanager:SetAnimationSequence(animationIndex, self.runAnimationSpeed * Time:GetSpeed(),300)
  else
   System:Print("no path?")
  end
 elseif mode=="dying" then
  self.entity:Stop()
  local animationIndex = self.animation.die[math.random(1, #self.animation.die)]
  self.animationmanager:SetAnimationSequence(animationIndex, self.attackAnimationSpeed * Time:GetSpeed(),300,1,self,self.EndDeath)  
 elseif mode=="dead" then
  local sound = self.sound.die[math.random(1, #self.sound.die)]
  if sound ~= nil then
   self.entity:EmitSound(sound,50,1,1,false)
  end
  self.entity:SetCollisionType(0)
  self.entity:SetMass(0)
  self.entity:SetShape(nil)
  self.entity:SetPhysicsMode(Entity.RigidBodyPhysics)
  self.enabled=false
 end
end
end

Link to comment
Share on other sites

Yes, ideally the code would be better structured so you could just do that check at the top of a function and if nil return from the function. However, the AI code is fairly messy.

 

I was playing with Behavior Trees (found a lua lib and made it work with LE and extended it a little) and found that although building the tree can be complicated, it really helps break AI processes down into much more manageable code. I might share this at some point if I find time as I think it could be useful for people. Without a UI to build the tree it can seem complicated though as it's a big lua table with nested lua tables and that can get complicated to follow, but it's less spaghetti code and more config than the current AI example.

Link to comment
Share on other sites

I reset it and tried a new approach;; I got it down to only 2 checks by removing the other 4......

 

Seems less messy :/ I'm surprised at myself for understanding else/if now. Thanks Rick! It's nice being able to PRINT stuff in the logs to see where the code is activating.

 

if self.mode=="hurt" then
    if self.target~=nil then
  if self.target.health<=0 then
   self:SetMode("idle")
   return
  end
 else
  if self.target==nil then
   System:Print("!!!!!!")
   self:SetMode("idle")
  end
 end
 if self.health<=0 then
  self:EndDeath()
  return
 end

 

And also

 

elseif mode=="hurt" then
  self:EndHurt()
 elseif mode=="attack" then
  self:EndAttack()
 elseif mode=="chase" then
  if self.target~=nil then
   System:Print("Now in chase mode")
   if self.entity:Follow(self.target.entity,self.speed,self.maxaccel) then
 System:Print("follow")
 self.followingtarget=true
 local animationIndex = self.animation.run[math.random(1, #self.animation.run)]
 self.animationmanager:SetAnimationSequence(animationIndex, self.runAnimationSpeed * Time:GetSpeed(),300)
   else
 System:Print("no path?")
   end
  else
   self:SetMode("idle")
  end

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   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.

 Share

×
×
  • Create New...