Jump to content
SleepingHollow

Created NPC'S can't be killed and other issues

Recommended Posts

Hello there,

 

I have been messing around with Leadwerks and have made new npc's and created new scrips for those npcs and it all works well they move, attack me, and such however I can't seem to kill them. When I try to shoot them, it just goes right through them and I cant seem to figure it out. Second issue, when they come after me they are always looking away, I have the Character angle at 180 but when I turn it to 0, once they get near me they kind of just bounce away not sure why. Any help is much appreciated and thank you.

Share this post


Link to post

Are you using "Point command" to make them ( enemies)point to camera?

 

I'm not sure but I'm guessing that's referring to the scrips for the npcs?

My npc scrips are copies of the original crawler script with a few changes if that helps at all.

Share this post


Link to post

With regards to the bullets going right through? You may need to assign collision types to items in the model tree of your NPC model. It seems even the crawler NPC does not have these set up and they have manually(?) been set up in the FPS Sample AI demo map.

 

My suggestion would be to create a project based on the FPS Sample and take a close look at the crawler setup in the 'AI' map there. in particular, take a look at the collisions setup on the tree of the crawler model.

 

Hope you figure it out.

Share this post


Link to post

Try opening \Scripts\Objects\Weapons\FPSGun.lua and change line 286 to

if self.entity.world:Pick(bullet.position,bullet.position+travel,pickinfo,0,true) then

Share this post


Link to post

Might be helpful if you post your script so we can see what is going on.

 

Otherwise we are only guessing.

 

Your character problem is addressed here.

 

http://www.leadwerks.com/werkspace/topic/13204-wrong-way-round/page__hl__character

 

I've tried that, the npc faces the right way but once it gets close enough to me it kind of bounces away and comes after me again.

 

With regards to the bullets going right through? You may need to assign collision types to items in the model tree of your NPC model. It seems even the crawler NPC does not have these set up and they have manually(?) been set up in the FPS Sample AI demo map.

 

My suggestion would be to create a project based on the FPS Sample and take a close look at the crawler setup in the 'AI' map there. in particular, take a look at the collisions setup on the tree of the crawler model.

 

Hope you figure it out.

 

I've taken a look into the ai map to see how it works and I tried to recreate it with mine but still nothing

 

Here's the code for the npc

 

import "Scripts/AnimationManager.lua"
import "Scripts/Functions/GetEntityNeighbors.lua"
--Public values
Script.health=150--int "Health"
Script.enabled=true--bool "Enabled"
Script.target=nil--entity "Target"
Script.sightradius=30--float "Sight Range"
Script.senseradius=2--float "Hearing Range"
Script.teamid=2--choice "Team" "Neutral,Good,Bad"
Script.attackdelay=350--int "Attack delay"
Script.animspeedrun=0.04--float "Run anim speed"
--Private values
Script.damage=15
Script.attackrange=1.5
Script.updatefrequency=500
Script.lastupdatetime=0
Script.prevtarget=nil
Script.followingtarget=false
Script.maxaccel=15
Script.speed=3.5
Script.lastupdatetargettime=0
Script.attackmode=0
Script.attackbegan=0
Script.attack1sound=""--path "Attack 1 sound" "Wav file (*.wav):wav|Sound"
Script.attack2sound=""--path "Attack 2 sound" "Wav file (*.wav):wav|Sound"
Script.alertsound=""--path "Alert sound" "Wav file (*.wav):wav|Sound"
Script.deathsound=""--path "Death sound" "Wav file (*.wav):wav|Sound"
Script.idlesound=""--path "Idle sound" "Wav file (*.wav):wav|Sound"
function Script:Enable()--in
if self.enabled==false then
 if self.health>0 then
  self.enabled=true
  if self.target~=nil then
   self:SetMode("roam")
  else
   self:SetMode("idle")
  end
 end
end
end
function Script:ChooseTarget()
local entities = GetEntityNeighbors(self.entity,self.sightradius,true)
local k,entity
for k,entity in pairs(entities) do
 if entity.script.teamid~=nil and entity.script.teamid~=0 and entity.script.teamid~=self.teamid then
  if entity.script.health>0 then
   local d = self.entity:GetDistance(entity)
   local pickinfo=PickInfo()
   if self.entity.world:Pick(self.entity:GetPosition()+Vec3(0,1.6,0),entity:GetPosition()+Vec3(0,1.6,0),pickinfo,0,false,Collision.LineOfSight)==false then
 return entity.script
   end
  end
 end
end
end
function Script:DistanceToTarget()
local pos = self.entity:GetPosition()
local targetpos = self.target.entity:GetPosition()
if math.abs(targetpos.y-pos.y)<1.5 then
 return pos:xz():DistanceToPoint(targetpos:xz())
else
 return 100000--if they are on different vertical levels, assume they can't be reached
end
end
function Script:TargetInRange()
local pos = self.entity:GetPosition()
local targetpos = self.target.entity:GetPosition()
if math.abs(targetpos.y-pos.y)<1.5 then
 if pos:xz():DistanceToPoint(targetpos:xz())<self.attackrange then
  return true
 end
end
return false
end
function Script:Start()
self.entity:SetCharacterControllerAngle(0);
self.entity:SetPickMode(Entity.BoxPick,true)
self.entity:SetPickMode(0,false)
self.animationmanager = AnimationManager:Create(self.entity)
if self.enabled then
 if self.target~=nil then
  self:SetMode("roam")
 else
  self:SetMode("idle")
 end
end
self.sound={}
if self.alertsound then self.sound.alert = Sound:Load(self.alertsound) end
self.sound.attack={}
if self.attack1sound then self.sound.attack[1] = Sound:Load(self.attack1sound) end
if self.attack2sound then self.sound.attack[2] = Sound:Load(self.attack2sound) end
if self.idlesound then self.sound.idle = Sound:Load(self.idlesound) end
self.lastidlesoundtime=Time:GetCurrent()+math.random(1,20000)
end
function Script:Hurt(damage,distributorOfPain)
if self.health>0 then
 if self.target==nil then
  self.target=distributorOfPain
  self:SetMode("attack")
 end
 self.health = self.health - damage
 if self.health<=0 then
  self.entity:SetMass(0)
  self.entity:SetCollisionType(0)
  self.entity:SetPhysicsMode(Entity.RigidBodyPhysics)
  self:SetMode("dying")
 end
end
end
function Script:EndDeath()
self:SetMode("dead")
end
function Script:DirectMoveToTarget()
self.entity:Stop()
local targetpos = self.target.entity:GetPosition()
local pos = self.entity:GetPosition()
local dir = Vec2(targetpos.z-pos.z,targetpos.x-pos.x):Normalize()
local angle = -Math:ATan2(dir.y,-dir.x)
self.entity:SetInput(angle,self.speed)
end
function Script:SetMode(mode)
if mode~=self.mode then
 local prevmode=self.mode
 self.mode=mode
 if mode=="idle" then
  self.target=nil
  self.animationmanager:SetAnimationSequence("Idle",0.02)
  self.animationmanager.animations[1].frameoffset = math.random(1,1000)
  self.entity:Stop()--stop following anything
 elseif mode=="roam" then
  if self.target~=nil then
   self.animationmanager:SetAnimationSequence("Run",self.animspeedrun)
   self.entity:GoToPoint(self.target:GetPosition(true),5,5)
  else
   self:SetMode("idle")
  end
 elseif mode=="attack" then
  self:EndAttack()
 elseif mode=="chase" then
  if self.entity:Follow(self.target.entity,self.speed,self.maxaccel) then
   if prevmode~="chase" then
 if self.sound.alert then self.entity:EmitSound(self.sound.alert) end
   end
   self.followingtarget=true
   self.animationmanager:SetAnimationSequence("Run",self.animspeedrun,300)
   if self:DistanceToTarget()<self.attackrange*2 then
 self.followingtarget=false
 self.entity:Stop()
 self:DirectMoveToTarget()
   end
  else
   self.target=nil
   self:SetMode("idle")
   return
  end
 elseif mode=="dying" then
  self.entity:Stop()
  self.animationmanager:SetAnimationSequence("Death",0.04,300,1,self,self.EndDeath)  
 elseif mode=="dead" then
  self.entity:SetCollisionType(0)
  self.entity:SetMass(0)
  self.entity:SetShape(nil)
  self.entity:SetPhysicsMode(Entity.RigidBodyPhysics)
  self.enabled=false
 end
end
end
function Script:EndAttack()
if self.mode=="attack" then
 if self.target.health<=0 then
  self:SetMode("idle")
  return
 end
 local d = self:DistanceToTarget()
 if d>self.attackrange then
  self:SetMode("chase")
  return
 end
 self.entity:Stop()
 self.attackmode = 1-self.attackmode--switch between right and left attack modes
 self.animationmanager:SetAnimationSequence("Attack"..tostring(1+self.attackmode),0.05,300,1,self,self.EndAttack)
 self.attackbegan = Time:GetCurrent()
 if self.sound.attack[self.attackmode+1] then
  if math.random()>0.75 then
   self.entity:EmitSound(self.sound.attack[self.attackmode+1])
  end
 end
end
end
function Script:UpdatePhysics()
if self.enabled==false then return end
local t = Time:GetCurrent()
self.entity:SetInput(self.entity:GetRotation().y,0)

if self.sound.idle then
 if t-self.lastidlesoundtime>0 then
  self.lastidlesoundtime=t+20000*Math:Random(0.75,1.25)
  self.entity:EmitSound(self.sound.idle,20)
 end
end

if self.mode=="idle" then
 if t-self.lastupdatetargettime>250 then
  self.lastupdatetargettime=t
  self.target = self:ChooseTarget()
  if self.target then
   self:SetMode("chase")
  end
 end
elseif self.mode=="roam" then
 if self.entity:GetDistance(self.target)<1 then
  self:SetMode("idle")
 end
elseif self.mode=="chase" then
 if self.target.health<=0 then
  self:SetMode("idle")
  return
 end
 if self:TargetInRange() then
  self:SetMode("attack")
 elseif self:DistanceToTarget()<self.attackrange*2 then
  self.followingtarget=false
  self.entity:Stop()
  self:DirectMoveToTarget()
 else
  if self.followingtarget==false then
   if self.entity:Follow(self.target.entity,self.speed,self.maxaccel) then
 self:SetMode("idle")
   end
  end
 end
elseif self.mode=="attack" then
 if self.attackbegan~=nil then
  if t-self.attackbegan>self.attackdelay then
   if self.target.entity:GetDistance(self.entity)<1.5 then
 self.attackbegan=nil
 self.target:Hurt(self.damage)
   end
  end
 end
 local pos = self.entity:GetPosition()
 local targetpos = self.target.entity:GetPosition()
 local dx=targetpos.x-pos.x
 local dz=targetpos.z-pos.z
 self.entity:AlignToVector(-dx,0,-dz)
end
end
function Script:Draw()
if self.enabled==false then return end
self.animationmanager:Update()
end

Share this post


Link to post

The PAC guys experienced this problem recently. I updated the script so it will automatically set the correct collision type for all the limbs. if you opt into the beta branch and then update your project, I believe it will correct your problem. Alternatively, you can set every limb to "prop" collision type.

Share this post


Link to post

The PAC guys experienced this problem recently. I updated the script so it will automatically set the correct collision type for all the limbs. if you opt into the beta branch and then update your project, I believe it will correct your problem. Alternatively, you can set every limb to "prop" collision type.

 

Thank you, the alternative method worked and it's pretty straight forward. Now the only issue I'm having is the npc teleports or bounces away when it gets close to me.

Share this post


Link to post

I've never seen this before. Is it just the standard script? Want to upload your map?

Share this post


Link to post

I've never seen this before. Is it just the standard script? Want to upload your map?

 

Yes it is the standard script with changes to damage, health, and speed only

 

I was just messing around with it and found that it was in the code

 

self.entity:SetCharacterControllerAngle(0);

 

I added that following a link from a comment on this thread but I had it set to 0 cuz when it's at 180 the npc gets close to me and attacks but it's facing the wrong way the enter time.

Share this post


Link to post

Check the mass of the npc. If it's low it can bounce away

 

I've fixed the problem with that, It required me to change in the code

 

self.entity:SetCharacterControllerAngle(0);

 

to

 

self.entity:SetCharacterControllerAngle(180);

 

But now the npc faces the wrong way the entire time

Share this post


Link to post

If you didn't try modifying the mass yet then I would try that. I usually just set player to 10 (but my games are probably not the same as yours so it's not that that is the BEST value or anything). Try the enemy at the same mass as the player and them maybe double it or more if still problems. Just to see what happens. The physics system is really trying to simulate 'simplified' but proper physics, and the relative masses of things can be important.

 

I suggest checking the mass setttings of player and enemy on the FPS Sample.

 

When things bounce away and 'teleport' it is usually because the physics are doing the 'correct' calculation and bouncing away the strangely VERY LIGHT (though very large!) concrete block(!) or whatever.

 

Physics can be a frustrating area so keep at it and I'm sure we'll sort it.

 

Supplying the model and map for Josh will surely do the trick.

Share this post


Link to post

Your model didn't seem to have a script attached, but I added the monster script and set the character angle to zero. It looks like a glitch in the AI script only accounts for characters that are turned 180 degrees away. This should be simple to fix, give me a minute...

AI Glitch.rar

Share this post


Link to post

Okay, here's what I did to make it work.

 

In the function DirectMoveToTarget, find this line of code:

local angle = -Math:ATan2(dir.y,-dir.x)

Change it to this:

local angle = -Math:ATan2(dir.y,-dir.x) + self.entity:GetCharacterControllerAngle() + 180.0

 

And then in the UpdatePhysics function, find this line of code:

self.entity:AlignToVector(-dx,0,-dz)

And change it to this:

if self.entity:GetCharacterControllerAngle()>90.0 then
self.entity:AlignToVector(-dx,0,-dz)
else
self.entity:AlignToVector(dx,0,dz) 
end

Share this post


Link to post

The beta branch has been updated with this script. You need to update your project to get the changes, in the project manager.

Share this post


Link to post

It didn't seem to work for the Scorpion I tested in the workshop. I added this to MonsterAI.lua (that Josh gave us awhile back):

 

In Start() function:

SetCollisionType_(self.entity, Collision.Prop)

 

and then add this:

 

function SetCollisionType_(entity,mode)

entity:SetCollisionType(mode)

local n

for n=0,entity:CountChildren()-1 do

SetCollisionType_(entity:GetChild(n),mode)

end

end

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

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.

×
×
  • Create New...