Page 1 of 1

[help]How to destroy a table of entities?

Posted: Fri Nov 16, 2012 9:07 pm
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.

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

Posted: Fri Nov 16, 2012 9:20 pm
by Komag
maybe something like

Code: Select all

for i=1,#arrows, do
   arrows[i]:destroy
end
but I'm not sure

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

Posted: Sat Nov 17, 2012 1:12 am
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

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

Posted: Sat Nov 17, 2012 3:04 am
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

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

Posted: Sat Nov 17, 2012 3:44 am
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 )

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

Posted: Sat Nov 17, 2012 6:36 pm
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.