Page 1 of 1

Major bug with Monster.addItem().

Posted: Sat Mar 07, 2015 7:59 pm
by MrChoke
I am wondering if this got introduced in the latest beta, not sure. But for there is a problem now. Monster:addItem() is not taking the item off surface components.

I am getting a monster to take an item out of a chest. This is my exact code to do that:

Code: Select all

                    for i, item in chestGO.surface:contents() do
                         for j, id in ipairs(bd.holdableObjects) do
                            if item.go.id == id then
                                print("Monster: "..brain.go.id.." is taking key: "..item.go.id.." out of chest")
                                brain.go.monster:addItem(item)
                            end
                        end
                    end 
Ignore "bd.holdableObjects". The monster is only allowed to take out certain items. The key is in this table and he does take the key (the only key) out of the chest.

Later, he choses to go back to the chest and take anything in there out again. The exact same code executes. What should happen is chestGO.surface:contents() should not be returning any more objects since he already took the key out. But the key is still there. And he takes it again!! The exact same key.

I kill the monster and the game blows up because it tries to put two identical keys on the ground. Its bugged.
Error:

Code: Select all

[string "Map.lua"]:0: entity already added to map
stack traceback:
	[C]: in function 'assert'
	[string "Map.lua"]: in function 'addEntity'
	[string "Monster.lua"]: in function 'dropItem'
	[string "Monster.lua"]: in function 'dropAllItems'
	[string "Monster.lua"]: in function 'die'
	[string "GameMode.lua"]: in function 'keyPressed'
	[string "DungeonEditor.lua"]: in function 'preview'
	[string "DungeonEditor.lua"]: in function 'update'
	[string "Grimrock.lua"]: in main chunk
I am going look for a work around but needless to say I am bummed.

Re: Major bug with Monster.addItem().

Posted: Sat Mar 07, 2015 8:16 pm
by JohnWordsworth
I'm not certain, but I would imagine the problem is that Monster.addItem doesn't remove a reference to the item from the surface when adding it to the monster. I mean, the actual entity/item component is owned by a map/level/game manager object of some sort and surfaces / monsters just hold references to the items.

So, you would probably need to do something like this...

Code: Select all

local itemsToTake = { };

for i, item in chestGO.surface:contents() do
  for j, id in ipairs(bd.holdableObjects) do
    if item.go.id == id then    
      table.insert(itemsToTake, item);     
    end
  end
end

for _,item in ipairs(itemsToTake) do
  print("Monster: "..brain.go.id.." is taking key: "..item.go.id.." out of chest")
  chestGO.surface:removeItem(item);
  brain.go.monster:addItem(item)
end
I don't know what the "remove item" command is for surfaces, but this is a guess at what you might need to do.

Re: Major bug with Monster.addItem().

Posted: Sat Mar 07, 2015 8:30 pm
by MrChoke
So a couple of updates on this.

The first is a problem in and of itself. There is no "removeitem" for a SurfaceComponent. I think there should be. There is for ContainerComponent for example. So John, your solution will not work.

What did work as a work around is using "removeItem()" on the MonsterComponent. I call this right before addItem(). It eliminates the duplicate key creation. Its still bugged because the key needs to be removed from the surface and its not.

A few other things to point out. Monster:addItem() works fine when the monster is picking up objects from the ground. Its only when taking them from a SurfaceComponet that this problem occurs.

Next, when the party take the key out of the chest, it works fine. The surface component no longer has the key.

Lastly and very strange. Even though after the monster takes the key out (and the surface component still has it), the key does not show in the chest! I open the chest and there is no key for the party to take. So its there but it isn't....

Looking forward to an AH reply on this one.
Thanks.

Re: Major bug with Monster.addItem().

Posted: Sat Mar 07, 2015 10:44 pm
by JohnWordsworth
Hmm, only thing I can think of is calling item:destroy() and then respawning the exact same item again. This works if you don't need to track things like charges (on a staff), but it should work fine for a key.

Code: Select all

local itemsToTake = { };

for i, item in chestGO.surface:contents() do
  for j, id in ipairs(bd.holdableObjects) do
    if item.go.id == id then    
      table.insert(itemsToTake, item);     
    end
  end
end

for _,item in ipairs(itemsToTake) do
  print("Monster: "..brain.go.id.." is taking key: "..item.go.id.." out of chest")
  local entityId = item.go.id;
  local entityName = item.go.name;
  -- Could copy stack size too if you need to.

  item:destroy();
  local entityCopy = spawn(entityName, 1, 1, 1, 1, 1, entityId);
  brain.go.monster:addItem(entityCopy)
end
Again, no promises this will work - especially as I'm not sure if item:destroy() is immediate or just occurs before the next tick, but it's a reasonable work around if you just want to move keys and the like around.

Re: Major bug with Monster.addItem().

Posted: Sat Mar 07, 2015 10:59 pm
by MrChoke
JohnWordsworth wrote:Hmm, only thing I can think of is calling item:destroy() and then respawning the exact same item again. This works if you don't need to track things like charges (on a staff), but it should work fine for a key.

Code: Select all

local itemsToTake = { };

for i, item in chestGO.surface:contents() do
  for j, id in ipairs(bd.holdableObjects) do
    if item.go.id == id then    
      table.insert(itemsToTake, item);     
    end
  end
end

for _,item in ipairs(itemsToTake) do
  print("Monster: "..brain.go.id.." is taking key: "..item.go.id.." out of chest")
  local entityId = item.go.id;
  local entityName = item.go.name;
  -- Could copy stack size too if you need to.

  item:destroy();
  local entityCopy = spawn(entityName, 1, 1, 1, 1, 1, entityId);
  brain.go.monster:addItem(entityCopy)
end
Again, no promises this will work - especially as I'm not sure if item:destroy() is immediate or just occurs before the next tick, but it's a reasonable work around if you just want to move keys and the like around.
That looks like it would work. For simple objects like keys where spawning a new one is no big deal it would be ok. Hopefully AH can fix the bug though. My workaround is also working too though I question when I call "removeItem()" on an object held by a monster, where is it going? It doesn't go to the ground. Is it destroyed? Its a question for sure....

Re: Major bug with Monster.addItem().

Posted: Tue Mar 17, 2015 3:30 am
by MrChoke
Just wondering if there is any confirmation on this being a bug or if we are doing something wrong.