Results 1 to 24 of 24

Thread: [SOLVED] Locating Objects by Tag in a zone and then destroying them

  1. #1

    [SOLVED] Locating Objects by Tag in a zone and then destroying them

    Hello, I am new to scripting (3 days). I feel like I'm on the verge of it clicking for me but I'm having some trouble. I'm using MrStumps learning lua mod and this is what I have so far.

    function onload()
    self.createButton({
    label="End the Showdown", click_function="CleanUp",
    function_owner=self, position={0,0,2},
    height=200, width=500, font_size=150, color={0,0,0,}, font_color={1,1,1},
    })

    end

    function CleanUp()
    local zone = getObjectFromGUID("600ec5")
    local objectsInZone = zone.getObjects()
    for _, object in ipairs(objectsInZone) do
    if object.tag == "monster" then
    destroyObject(tag, "monster")
    end
    end
    if foundObject == false then
    print("Showdown Board Cleared")
    end
    print("--------------------")
    end

    Is this even possible to destroy by tag? How do I use the destroy() function?

    - - - Updated - - -

    destroyObject(card, tag, "monster)

    ?
    Last edited by maximo1984@ymail.com; 07-23-2017 at 06:27 AM.

  2. #2
    So, in the "for _,object in pairs(objectsInZone)" loop, you're iterating over objects in the zone. Inside that loop, "object" variable is the reference to one of the objects in the zone - that loop repeats for each one. You got the first part right - "object.tag" accesses its tag. When working with object references, you can access some of its variables and some if its member functions (methods) listed on the API/Object page - one of these methods is .destruct() which simply deletes the object. So yeah, doing something like
    Code:
    local zone = getObjectFromGUID("600ec5")
    local objectsInZone = zone.getObjects()
    for _, object in ipairs(objectsInZone) do
        if object.tag == "monster" then
            object.destruct()
        end
    end
    will destroy the object that was in the zone (iterated in the loop) and its tag was "monster" (so it went inside the "if" statement).

    Just make sure that their tag actually is "monster" (I'm not familiar with all possbile types, remember that casing matters!) and it should work

  3. #3
    Ok, so I think I'm confusing "tag" with description that has a list of tags describing it (custom naming conventions), is that the tag its looking for? What if there is more than one tag and I want to single just that out?

  4. #4
    Ok, so I think I'm confusing "tag" with description that has a list of tags describing it (custom naming conventions), is that the tag its looking for? What if there is more than one tag and I want to single just that out?

    latest script change, leaving work, will check back later, thanks for fast reply.

    function CleanUp()
    local zone = getObjectFromGUID("600ec5")
    local objectsInZone = zone.getObjects()
    for k, v in pairs(objectsInZone) do
    if string.find(v.tag,'Monster') then
    destroyObject()
    end
    end

  5. #5
    .tag are things like 'Card', 'Deck", 'Custom' aren't they?

    I think you want to be testing description or the name?

    getDescription() / getName()
    My Boardgame uTube chan - Tragic's Table Top
    BGG Guild of BoardGame uTubers - Tube Tables

  6. #6
    yes, that's what I think you're right, how would the code work?

  7. #7
    --added getDescription()

    function CleanUp()
    local zone = getObjectFromGUID("600ec5")
    local objectsInZone = zone.getObjects()
    local description = getDescription()
    local x = "monster, white lion, showdown, ai, advanced"
    for k, v in pairs(objectsInZone) do
    if string.find(x,'Monster') then
    destroyObject()
    end
    end

  8. #8
    I'm not expert as my slue of stooopid question here will tell you but I think this is what you are looking for... I use zone searches all the time in my mods... but if you change k, v to sometrhing more readable it may make more sesne, a

    Code:
    function CleanUp()
            local zone = getObjectFromGUID("600ec5")
            local objectsInZone = zone.getObjects()
            local findthis = "monster white lion showdown ai advanced"
    
            for _, obj in pairs(objectsInZone) do
    		if string.find(obj.getDescription(), findthis ) ~= nil
                          obj.destruct()
                    end
            end
     end
    I haven't tested, but I think this works..

    • Function name - CleanUp()

    • zone is set to your GUID for the zone

    • you then get a list of all the objects IN that zone (objectsInZone) (Not sure but I think you can go objectsinzone = getgetObjectFromGUID('600ec5').getObjects() to put it in 1 line.. have to test)

    • you make a variable called "findthis" containing a single string of all your keywords you listed (I took out the commas)

    • You then loop over the object list, with ipairs. I set the counter hting to _ as we can ignore it, and set the send one to obj, as this variable IS each object as it comes up in the loop. So you can access all the obj commands form that variable. So loop 1 it is the 1st object it finds, loop 2 it is the 2nd etc etc.

    • Now there is a test, we use search string, on obj.getDescription(). This always returns a NIL value if the sting is NOT found. So if you test for ~= nil (not equal to nil) then it will only execute the code in the IF statement when it DOSE find the key words you assigned.

    • finally, as the if statment is finding the matching objects we can use obj.destruct() to delete them
    Last edited by Tragic; 07-22-2017 at 05:30 PM.
    My Boardgame uTube chan - Tragic's Table Top
    BGG Guild of BoardGame uTubers - Tube Tables

  9. #9
    Join Date
    May 2016
    Posts
    1,072
    Here's the basic script that would work off a description field of the items in a zone.
    Code:
    function cleanUpZone()
        local zone = getObjectFromGUID("guidhere")
        for _, obj in ipairs(zone.getObjects()
        if obj.getDescription() == "Whatever" then
            destroyObject(obj)
        end
    end
    Here is a function I wrote to return objects in a zone by certain tags
    Code:
    --Returns table of objects of given types using their tags
    function getObjectTypesInZone(zone, ...)
        local foundTypes, tagList = {}, {...}
        for _, object in ipairs(zone.getObjects()) do
            for _, tag in ipairs(tagList) do
                if object.tag == tag then
                    table.insert(foundTypes, object)
                    break
                end
            end
        end
        return foundTypes
    end
    You feed it a reference to a scripting zone and then the tags you want to find. It handles any number of different tags. Then it returns a table of objects that had tags matching the ones you were looking for.

    An example of its use
    Code:
    function onload()
        local scriptZone = getObjectFromGUID("######") --guid of the script zone here
        local foundObjects = getObjectTypesInZone(scriptZone , "Dice", "Figurine", "Deck", "Card")
        for _, obj in ipairs(foundObjects) do
            destroyObject(obj)
        end
    end
    
    --Returns table of objects of given types using their tags
    function getObjectTypesInZone(zone, ...)
        local foundTypes, tagList = {}, {...}
        for _, object in ipairs(zone.getObjects()) do
            for _, tag in ipairs(tagList) do
                if object.tag == tag then
                    table.insert(foundTypes, object)
                    break
                end
            end
        end
        return foundTypes
    end
    It goes through every object in the given script zone, and for each item checks if matches any of the given tags. If it finds one, it puts it into the table to return. If there are none, it would return an empty table

  10. #10
    If you want to destroy every object that has something from 'x' in the description, it would look like this:
    Code:
    function CleanUp()
        local zone = getObjectFromGUID("600ec5")
        local objectsInZone = zone.getObjects()
        local x = "monster, white lion, showdown, ai, advanced"
        for k, object in pairs(objectsInZone) do
            local objDescription = object.getDescription()
            if string.find(x, objDescription) then
                object.destruct()
            end
        end 
    end

  11. #11
    Probably should be noted that if you want to search as series of keywords, while you can do it your way by having a single string and then searching that string for patterns. It might be best to use a array of strings...

    So instead of findthis = 'find1 find2 find3 find4 find5" and searching to see if the obj has find2 in the description.... it might be best to make it..

    findthis = {'find1', 'find2', 'find3', 'find4', 'find5'}

    Also when I made my deck builder. I ran into all sorts of problems with searching strings... I'll have to look up the code but I used a trick to make it all lowercase no matter what, and also remove all white spaces and punctuation and special characters before the tests.

    Quote Originally Posted by MrStump View Post
    You feed it a reference to a scripting zone and then the tags you want to find. It handles any number of different tags. Then it returns a table of objects that had tags matching the ones you were looking for.

    Code:
    local scriptZone = getObjectFromGUID("######") --guid of the script zone here
        local foundObjects = getObjectTypesInZone(scriptZone , "Dice", "Figurine", "Deck", "Card")
    awesome! So you do not need to test the tags and FIND them, you can ste up get objects to ONLY make a list OF those tags?
    My Boardgame uTube chan - Tragic's Table Top
    BGG Guild of BoardGame uTubers - Tube Tables

  12. #12
    Join Date
    May 2016
    Posts
    1,072
    Yeah the function will only return objects in a list that have a tag matching one of the ones you used as a parameter.

    I made it for a blackjack table for when I constantly had to find cards and chips and figurines and such. I also like the "string.find" solution, I think both are great

  13. #13
    Thank you for all the replies. I feel like once I can understand locating objects, then I can really start doing some things. I'm modding my Kingdom Death table and the next thing I'm going to try and do is when a player rolls a pefect hit, get a value from a token (whcih will either be 9 or 10), then, search a zone for cards with a name of 'perfect hit', then broadcast to all the description of that card. So for example,

    Mighty Strike: On a perfect hit, gain +2 Strength until the end of this attack.

    The broadcast would say "Perfect Hit! Mighty Strike, gain +2 Str until the end of this attack"

    The problem lies in the heavy book keeping that Kingdom Death demands. And when you play solo controlling 4 survivors at once, there can be upwards of 30-50 cards on the table that you have to keep track of.

    Telling the computer to locate cards in a zone and then do something seems like a powerful tool with possibilities. I imagine the broadcasted color can even be done in the color of the player that rolled the perfect hit?

    I was a little hung up on the details of if something do something and the do command having to be in the format of obj.destroy() instead of just the command destroy()

    What is the purpose of using Return?

    Also what does this mean {...}
    and (zone, ...)
    and for_,

    what does in the ...? Or is that just saying search through the entire table?
    Last edited by maximo1984@ymail.com; 07-23-2017 at 05:43 AM.

  14. #14
    Ok, so this is working

    function CleanUp()
    local zone = getObjectFromGUID("600ec5")
    local objectsInZone = zone.getObjects()
    local x = "monster, white lion, showdown, ai, advanced"
    for k, object in pairs(objectsInZone) do
    local objDescription = object.getDescription()
    if string.find(x, objDescription) then
    object.destruct()
    end
    end

    However, it only destroys those with exact match to x as defined in the function. There are many types of descriptions, here are some examples

    monster, white lion, showdown, hit location
    monster, screaming antelope, showdown, figurine

    etc

    I only want it to find monster within the string and delete any that have that part. Also, is it possible to put more than one click function on a button?

    self.createButton({
    label="End the Showdown", click_function="CleanUp", click_function="name of 2nd function",
    function_owner=self, position={0,0,2},
    height=200, width=500, font_size=150, color={0,0,0,}, font_color={1,1,1},
    })

  15. #15
    **SOLVED **

    function CleanUp()
    local zone = getObjectFromGUID("600ec5")
    local objectsInZone = zone.getObjects()
    for k, object in pairs(objectsInZone) do
    local desc = object.getDescription()
    if string.find(desc, 'monster') then
    object.destruct()
    end
    end

  16. #16
    Good job on getting that to work, BTW there's no direct way of adding a second click_function, but you could simply do that:
    Code:
    self.createButton({
        label="End the Showdown", 
        click_function="callClickFunctions",
        function_owner=self,
        (rest of fields)
    }) 
    
    function callClickFunctions()
        CleanUp()
        MySecondFunctionToCall()
    end

  17. #17
    oh I like that. Thanks. Again, I'm only 3 days into it and its starting to "click" I think I downloaded the click function to my brain.

  18. #18
    so if I set more than one zone, I just call the global table zone so it destroys in all zones? Like this?

    local zone = getObjectFromGUID(zonesDestruct{})

    or is it

    local zone = get.table(zonesDestruct{})

    OR

    local zone = zonesDestruct{}

    after setting zonesDestruct table in global as

    zonesDestruct = {
    zoneShowdown = {guid = 'b7bb89'},
    zoneMonsterboard = {guid = '47751a'},
    zoneSurvivorStatus = {guid = '23e8a5'},
    zoneMonsterResource = {guid ='7efa18'},
    }

  19. #19
    After you define zonesDestruct like that, you access the table with the keys you wrote there (key are 'zoneShowdown', 'zoneMonsterboard') and so on. Additionaly, value of that table entry isn't just GUID (would be "zoneShowdown = 'b7bb89' "), but it is a table with 'guid' key.
    So, you can access it like:

    Code:
    -- Let's get some zones directly
    local someZone = getObjectFromGUID(zoneDestruct.zoneShowdown.guid)               --> gets the object from 'b7bb89' GUID
    local someOtherZone = getObjectFromGUID(zoneDestruct.zoneMonsterResource.guid)   --> gets the object from '7efa18' GUID
    
    -- Let's iterate over every zone in zonesDestruct
    for zoneKey, zoneGUIDtable in pairs(zonesDestruct) do
        -- This will be called for each entry in zonesDestruct
        print('Zone name: ' .. zoneKey)
        local zoneGUID = zoneGUIDtable.guid
        local zone = getObjectFromGUID(zoneGUID)
        -- Do something with the zone
    end
    The first dot indexes the 'zonesDestruct' table with 'zoneShowdown' key, resulting in " {guid = 'b7bb89'} " table. Second dot indexes this smaller table with 'guid' key, so we get 'b7bb89' string. And getObjectFromGUID gets that string and returns whatever object is under it (has that GUID).

  20. #20
    ok

    function cleanUp()

    --what line goes here? feels like its missing something to call the table and then do k, v loop through it, like

    local zone = zonesDestruct{}

    for zoneKey, zoneGUIDtable in pairs(zonesDestruct) do
    local objectsInZone = zone.getObjects()
    for k, object in pairs(objectsInZone) do
    local desc = object.getDescription()
    if string.find(desc, 'monster') then
    object.destruct()
    end
    end

    and is for zoneKey, zoneGUIDtable the same as saying for k, v? And I need an end after every for block of code correct?

  21. #21
    latest

    function cleanUp()
    zonesDestruct = {}
    for k, v in pairs (zonesDestruct) do
    local objectsInZone = zonesDestruct.getObjects()
    for k, object in pairs(objectsInZone) do
    local desc = object.getDescription()
    if string.find(desc, 'monster') then
    object.destruct()
    end
    end

    with table defined in global as

    zonesDestruct = {
    zone1 = {guid = '600ec5'},
    zone2 = {guid = '68de21'},
    }

  22. #22
    Be helpful if you used the CODE BBCODE... just put [ code ]paste code in here[ /code ] (remove the spaces around the brackets)

    Quote Originally Posted by maximo1984@ymail.com View Post
    Code:
    with table defined in global as
    
    zonesDestruct = {
    	zone1 = {guid = '600ec5'},
    	zone2 = {guid = '68de21'},
    }
    Not sure if that would work... maybe.. but there has been a few posted working codes already.. I am not sure that just having a value obj.guid=string would work... but you can get it easy enough...

    Try this? (untested)
    Code:
    zonesDestruct = {'600ec5', '68de21'}
    function cleanUp()
        for i=1, #zonesDestruct , 1 do
            objectsInZone = getObjectFromGUID(zone[i]).getObjects()
            for _, obj in pairs(objectsInZone) do
                local desc = obj.getDescription()
                if string.find(desc, 'monster') then
                    object.destruct()
                end
            end
        end
    end
    • I have defined a table with a list of zone GUIDs, as you have nothing else in there unless you have a reason there is no need to make a nested table, or use descriptive keys as they are all the same. This will equate to zone[1] == '600ec5' and zone[2] == '68de21'.
    • This is a slightly different for loop than a ipairs. Lua enables you to use a bunch. You could still use ipairs but I like this one as it is (for me) very visual. Basically it is saying i=1, then each loop +1 to i (the last value), until it is equal to whatever the middle value is. In this case #zonesDestruct which equals the amount of keys in the table. This is the same as writing, i=1, 2, 1 do
    • Now we have a increment number (i) that can be used to easily grab the keys of zone.. so in the first loop i=1 so zone[1] == '600ec5', 2nd loop i=2 so zone[2] == '68de21'
    • Now, like before you need to get a objectlist for all the stuff in the zone, we can do that with .getObjects. So in a single line we fill the objectsInZone.. by getting the objects form GUID and using zone[i] to tell it what GUID to look for.. so on loop 1 it will be zone[1] and loop two it will be zone[2]
    • finally we loop over objectsInZone using ipairs so we have the obj value, use it to get the .getDescription, do the test and then destroy it.
    My Boardgame uTube chan - Tragic's Table Top
    BGG Guild of BoardGame uTubers - Tube Tables

  23. #23
    thanks, I was wonder how to use the code button for embedding code. I'll have a go at this tonight at work and let you know.

  24. #24
    I've ran into another issue, I'm using the same technique to search an item by name and/or description. I can get the first part to work, but when I put another defined function inside of another, I get an error attempt to index a nil value. Here is what I'm doing.

    On button click, search a players card zone for specific cards by name - set within "if" statements.
    Some of these items will say, you can't depart with this other card also in your zone. So I made another function to also look for that card by description.

    Code:
    -- When you Depart Button
        self.createButton({
                   label="Depart", click_function="whenDepartTrigger",
                   function_owner=self, position={0,0,1.5},
                   height=400, width=2000, font_size=400, color={0,0,0}, font_color={1,1,1}
               })
    
    --Checks for objects in zone with 'when you depart' trigger and broadcasts effects
    
    function whenDepartTrigger()
    
        local zone = getObjectFromGUID('5f6f88')
        local objectsInZone = zone.getObjects()
        for _, object in ipairs(objectsInZone) do
            if object.getName() == "Squeamish" then
                broadcastToAll("Squeamish: You cannot depart with 'stinky' gear.", {1,1,1})
            end
    end
    
    -- Checks for objects in zone that would prevent a player from departing.
    
    function checkCanDepart()
        local zone = getObjectFromGUID('5f6f88')
        local objectsInZone = zone.getObjects()
        for k, object in pairs(objectsInZone) do
            local desc = object.getDescription()
            if string.find(desc, 'monster') then
                broadcastToAll("You have 'stinky' gear in your gear grid.", {1,1,1})
            end
        end
    end
    end
    end
    So when I try to add checkCanDepart() inside the first function I get the error, but it WAS working at one point, I can't figure out how to fix it and it looks right to me.

    Code:
    function whenDepartTrigger()
    
        local zone = getObjectFromGUID('5f6f88')
        local objectsInZone = zone.getObjects()
        for _, object in ipairs(objectsInZone) do
            if object.getName() == "Squeamish" then
                broadcastToAll("Squeamish: You cannot depart with 'stinky' gear.", {1,1,1})
                checkCanDepart()
            end
    end

Similar Threads

  1. Replies: 0
    Last Post: 07-06-2017, 09:28 AM
  2. Replies: 8
    Last Post: 07-02-2017, 09:47 AM
  3. Destroy objects in a zone Error
    By AndyZ in forum Scripting
    Replies: 1
    Last Post: 02-12-2017, 06:23 PM
  4. Replies: 0
    Last Post: 08-08-2016, 05:49 PM
  5. Replies: 0
    Last Post: 01-03-2016, 01:10 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •