Jump to content

Help with custom NPC not picking up items


Recommended Posts

I am making a mod that adds NPCs who pickup items.  I modeled my code after the perd and monkey.  Everything works without errors except the part where the character picks up the item.  It will walk to the item and stand there.  The DoAction(ACTIONS.PICKUP) is being called but not picking up the item for some reason.

my brain:

Spoiler

require "behaviours/runaway"
require "behaviours/standstill"

local AUTOCHEST_RANGE = 30

--[NEW] Here we create a new brain 
local workerbrain = Class(Brain, function(self, inst)
    Brain._ctor(self, inst)
end)

local function FindNearestAutochest(inst)
  return GetClosestInstWithTag("autochest", inst, AUTOCHEST_RANGE)
end

local function CleanGroundAction(inst)
  local x, y, z = inst.Transform:GetWorldPosition()
  --local tags = inst.components.
  local ents = TheSim:FindEntities(x, y, z, AUTOCHEST_RANGE)
  --local taget = FindEntity(inst, SEE_FOOD_DIST, HasBerry, { "pickable" })
  --print("clear ground")
  for i, item in ipairs(ents) do
    if item.components.inventoryitem ~= nil and
      item.components.inventoryitem.canbepickedup and
      item:IsOnValidGround() and
      not item.components.inventoryitem:IsHeld() and
      inst.components.container:CanTakeItemInSlot(item, 1) and
      item.name == "Log" then
        -- check it's inrange of the autochest
        if GetClosestInstWithTag("autochest", item, AUTOCHEST_RANGE) ~= nil then
          --print("clear ground worked")
          local act = BufferedAction(inst, item, ACTIONS.PICKUP)
          print(act)
          return act
        end
    end
  end
  --print("clear ground failed")
  return nil 
end

function workerbrain:OnStart()

	--[NEW] Some behavior trees have multiple priority nodes.
    local root = PriorityNode(
    {
    	-- in range of autochest?
      WhileNode(function() return FindNearestAutochest(self.inst) ~= nil end, "ready",
        PriorityNode({
          -- pick up ground
          DoAction(self.inst, CleanGroundAction, "clean up", true),
          
          -- replant seeds
          -- cut tree
        }, 1.0)),
      
      
      -- if nothing else stand there like an id10+.
      StandStill(self.inst),
    }, 1.0) --check every X seconds
    
    --[NEW] Now we attach the behaviour tree to our brain.
    self.bt = BT(self.inst, root)
    
end

--[NEW] Register our new brain so that it can later be attached to any creature we create.
return workerbrain

 

my prefab:

Spoiler

local function init_prefab()
	local inst = CreateEntity()
  inst.entity:AddTransform()
  inst.entity:AddAnimState()
  inst.entity:AddSoundEmitter()
  inst.entity:AddDynamicShadow()
  inst.entity:AddMiniMapEntity()
  inst.entity:AddNetwork()
  
  MakeCharacterPhysics(inst, 50, 0)
  
  inst.DynamicShadow:SetSize(1.5, .75)
  
  inst.MiniMapEntity:SetPriority( 4 )
  inst.MiniMapEntity:SetIcon("worker.tex")
  
  inst.Transform:SetFourFaced() -- will now call '*animation*_up', '*_down' and '*_side'
  
  inst.AnimState:SetBank("worker")
  inst.AnimState:SetBuild("worker")
  inst.AnimState:PlayAnimation("idle", true)
  
  inst.entity:SetPristine()

  if not TheWorld.ismastersim then
      return inst
  end
  
  inst:SetStateGraph("SGworker")
  
  inst:SetBrain(brain)
  
  inst:AddComponent("inspectable")
    
  local chestwidget = 
  {
    slotpos = {},
    animbank = "ui_worker_3x1",
    animbuild = "ui_worker_3x1",
    pos = Vector3(0, 150, 0),
    side_align_tip = 160,
  }

  for x = 0, 2 do
    table.insert(chestwidget.slotpos, Vector3(-75 + 75 * x, 40, 0))
    --table.insert(chestwidget.slotpos, Vector3(-75 + 75 * x, 40 - 75, 0))
  end
  
  local chestdata =
  {
    numslots = #chestwidget.slotpos,
    type = "chest",
    widget = chestwidget,
    acceptsstacks = false,
  }
  
  inst:AddComponent("container")
  inst.components.container:WidgetSetup("worker", chestdata)
  inst.components.container.onopenfn = onopen
  inst.components.container.onclosefn = onclose
  
  inst:AddComponent("inventory")
  inst:ListenForEvent("onpickupitem", OnPickup)

  inst:AddComponent("locomotor")
  inst.components.locomotor.runspeed = 4
  
  return inst
end

 

Any help is very appreciated!

Link to comment
Share on other sites

Ok, update for where I am now:

I have found that in the prefabs state graph there must be a call to: 

inst:PerformBufferedAction()

This goes in the timeline of the stategraph.

My problem now is that the timeline events never get called.  The OnEnter method is called, and if I put the "performBufferedAction" there it works.  However this doesn't seem like the correct way to do it, and it bothers me that the timeline is never called.

Anyone have advice about how to find the problem with the stategraph timeline?

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...