[help]How to destroy a table of entities?

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
Post Reply
flatline

[help]How to destroy a table of entities?

Post by flatline »

I've been using this for a spell I'm working on, Arrow protection.
In short, it should detect arrows in front of the player and destroy them. Right now, I'm using a script provided by Lark here: viewtopic.php?f=14&t=3985

arrows = findAll(party.level, party.x, party.y, {"arrow"}, "any", false, false, true)

My quetion is:
It should return a table of entities and I want to destroy any entities it returns. What is the right way to do that?

just putting :destroy() at the end, or arrows:destroy() won't work.
User avatar
Komag
Posts: 3659
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: [help]How to destroy a table of entities?

Post by Komag »

maybe something like

Code: Select all

for i=1,#arrows, do
   arrows[i]:destroy
end
but I'm not sure
Finished Dungeons - complete mods to play
User avatar
Lark
Posts: 178
Joined: Wed Sep 19, 2012 4:23 pm
Location: Springfield, MO USA

Re: [help]How to destroy a table of entities?

Post by Lark »

Yes, I it looks like that should work. Here's code that I used to destroy all items found in a square that's similar - you'd want to change ":getWeight" to "arrow" as indeed you've already done:

Code: Select all

      local found = findAll(self.level, self.x, self.y, {":getWeight"})
      for _, item in ipairs(found) do
        item:destroy()
        end
This code assigns the variable "item" to each entity in the table, one at a time, and then destroys it.

Kromag's code iterates an index, "i", over the table and references the entity by its index by using "arrows" and knows how many items are in the table by using the # operator.

Both methods are equivalent except if you have a table with nulls which findAll won't return, so either will work. FYI the # operator will only count non-null entries so for a table like {1, 2, , , 5}, # will return 3 and the code will fail. Iterating over the table using ipairs is safer.

Cheers, -Lark
flatline

Re: [help]How to destroy a table of entities?

Post by flatline »

Here's my current script. A timer runs this approximately 3 times per second as long as the spell is up.
It won't delete any items though and I have no idea why. It is supposed to react to any entity containing the word "arrow" and delete it, but neither mid-air arrows from skeletons nor arrows lying on the ground are deleted. I really appreciate all the help so far. I'm learning a lot here, and it seems arrow deflection isn't far off (the spell will have deflection and effects added once the core principle of detecting oncoming arrows and deleting them works).

Code: Select all

function arrowshield()
    local arrows = findAll(party.level, party.x, party.y, {"arrow"}, "any", true, false, true)
-- Larks solution
for _, item in ipairs(arrows) do
        item:destroy()
        end
--komags solution
--for i=1,#arrows do
   --arrows[i]:destroy()
--end
--prints text to let you know it is running
hudPrint("one loop")
end

---Larks findAll function below this line, nothing changed from here on

function findAll(level, x, y, keys, all, surrounding, facing, facingUs)
  local answers, r, dx, dy, entity, match, _ = {}, 0
  all = all == "all"
  local any = not all
  if surrounding then r = 1 end
  if facing then 
    dx, dy = getForward(self.facing)
    x, y = x + dx, y + dy
    end
  if keys == nil then keys = {"*"} end

  for i = x - r, x + r do
    for j = y - r, y + r do
      if 0 < i and i < 33 and 0 < j and j < 33 then 
        for entity in entitiesAt(level, i, j) do
          
          match = true
          for _, value in ipairs(keys) do
            if value == "*" then pass = true
            elseif string.sub(value, 1, 1) == ":" then pass = entity[(string.sub(value, 2))] ~= nil
            else pass = string.find(entity.name, value) ~= nil end
            
            if all then match = pass and match
            else match = pass end
            if (match and any) or ((not match) and all) then break end
            end
          
          if match then
            dx, dy = getForward(entity.facing)
            if (not facingUs) or (facingUs and entity.x + dx == self.x and entity.y + dy == self.y) or (self.x == entity.x and self.y == entity.y) then 
              answers[# answers + 1] = entity 
              end 
            end
          
          end
        end
      end
    end
  return answers
  end
User avatar
Grimwold
Posts: 511
Joined: Thu Sep 13, 2012 11:45 pm
Location: A Dungeon somewhere in the UK

Re: [help]How to destroy a table of entities?

Post by Grimwold »

Just curious if it would be easier to use the party hook onProjectileHit() which has as it's second variable the projectile that hit the party.

Something like this:

Code: Select all

onProjectileHit = function(champion,projectile)
  if arrow_shield_script.arrowShieldActive() and projectile.name == "arrow" then
    return false
  end
end,
So we test if the spell is active and if the projectile name is "arrow" and if both conditions are met, we return false so the champion takes no damage from the arrow (you would need to modify the check if you want to protect against other types of arrow as well e.g. frost_arrow )
flatline

Re: [help]How to destroy a table of entities?

Post by flatline »

Grimwold wrote:Just curious if it would be easier to use the party hook onProjectileHit() which has as it's second variable the projectile that hit the party.

Something like this:

Code: Select all

onProjectileHit = function(champion,projectile)
  if arrow_shield_script.arrowShieldActive() and projectile.name == "arrow" then
    return false
  end
end,
So we test if the spell is active and if the projectile name is "arrow" and if both conditions are met, we return false so the champion takes no damage from the arrow (you would need to modify the check if you want to protect against other types of arrow as well e.g. frost_arrow )
Definitely easier. I started off with my version as an experiment to see if I could detect and destroy arrows mid-flight. It could make for some neat other spells, I thought. Still haven't figured out if the arrow can be stopped mid-flight.
Post Reply