Page 1 of 2 12 LastLast
Results 1 to 25 of 32

Thread: takeObject() doesn't take last card from deck

  1. #1

    takeObject() doesn't take last card from deck

    Code:
        -- o is a deck
        local cards = o.getObjects()
    
        for i=#cards, 2, -1 do
            o.takeObject({ guid = cards[i].guid })
        end
    
        local c = o.takeObject()
        print(c)  -- prints nil
    When taking cards from a deck via their guid, I can't take the last card. The release notes for 6.8 say, that this should work. Is this a regression or am I doing something wrong?

  2. #2
    I haven't done a lot of deck handling on previous versions, but ran into the same issue kinda recently and had to do some ugly hacks to get around it. Looks like at the moment taking the second-from-last card deletes the deck object and spawns the remaining card in the former place of the deck (so that's a moment to try and intercept its spawn). Or maybe there's some specific way to have it working but never heard of it.

    Maybe you'll be able to cannibalize something from this spaghetti if you want, took the last card reliably (lines 25 and ahead)
    https://gist.github.com/tjakubo2/472...9b592469159532

  3. #3
    The deck object still exists. It just doesn't return the last card. I consider this a bug now, since the release notes state clearly that this should work.

  4. #4
    If you have a 5 card deck and draw 5+ cards after the patch it will draw all those cards. Though if you only have a single card left then the deck is no longer a deck and it is now a card.. so you need to add code to test for it as a deck or a card 1st, then do what you need.

    This is a code snip I posted a while back that may help
    http://www.berserk-games.com/forums/...9760#post19760

    basically you have a script zone where the deck should be... you test that zone to see what objects are in it... then after you have done that you test the list for tag 'Deck' and 'Card'... if it finds a deck, use the draw commands, if it finds a card then it moves the last card, and possibly other stuff (like shuffeling in the discard) and also you can make it do something if it finds nothing.
    My Boardgame uTube chan - Tragic's Table Top
    BGG Guild of BoardGame uTubers - Tube Tables

  5. #5
    I'm trying to create an all-purpose library. Scripting zones are too much setup for a utility function.

  6. #6
    I worked around it, by putting the cards back on the same deck. It works for my particular problem.

  7. #7
    My friend Kijan wrote the following two functions, should do what you are looking for

    Code:
    function getResources()
    
    -- performs check over multiple zones (resource is a table of zones set in onload for this object)
      for _, res in pairs(resource) do
    
    -- for each zone
      	for k, v in pairs(res.zone.getObjects()) do
      		if string.find(v.tag,'Deck') then
      			getCards(v, true, res.pos.x, res.pos.z, res.pos.offset)
      		elseif string.find(v.tag, 'Card') then
      			getCards(v, false, res.pos.x, res.pos.z, res.pos.offset)
      		end
      	end
      end
    end
    
    function getCards(card, deck, x, z, offset)
    	if not deck then
    		card.setPosition({x, 4.19, z})
                    card.setScale({0.80, 1.00, 0.80})
    	else
    	       for i, v in ipairs(card.getObjects()) do
    		    local moved_card = card.takeObject({position={x +(i-1) * offset, 4.19, z}})
                        moved_card.setScale({0.80, 1.00, 0.80})
    		end
    	end
    end
    The position stuff is unique to what I'm doing here, but hopefully you get the idea.

  8. #8
    Any fix coming to this? Any other workaround? I tried to make a coroutine to wait 1 and then check for the last card, but it can't get to that function because it errors on the last card when pulling the rest.

  9. #9
    there is two solutions already posted... try this link for a working example.

    http://www.berserk-games.com/forums/...9760#post19760
    My Boardgame uTube chan - Tragic's Table Top
    BGG Guild of BoardGame uTubers - Tube Tables

  10. #10
    Hi Tragic, I saw that, I'm just having a hard time adapting it to my situation. Here is a quick rundown and video demonstration. This is for the Arkham Horror LCG. The deck builder first grabs all the cards for the Investigator, and arranges in rows by cost and category.

    Then I copy a token to all cards I want in the deck. Once I'm ready, I'm click 'construct deck' and each token does a physics cast then the collision object is cloned and the tokens removed. This makes the deck. Then as an added feature for deck planning, I want to view the current deck by cost (and later by skill icon). Cost is like the mana curve in Magic the gathering. Here is a look at this code snippet

    Code:
    function display_deck(deck)
      removeCards()
      cost0 = {}
      cost1 = {}
      cost2 = {}
      cost3 = {}
      cost4 = {}
      cost5 = {}
      cost6 = {}
      for _, object in ipairs(zone_card_deck.getObjects()) do
        if object.tag == "Deck" then
          deck = object
          break
        end
      end
      for _, card in ipairs(deck.getObjects()) do
      local desc = card.description
         if string.find(desc, "0cost") then
           table.insert(cost0, deck.takeObject({guid=card.guid, position = {asset_row1_pos.x + #cost0 * 2.26, asset_row1_pos.y, asset_row1_pos.z}}))
         elseif string.find(desc, "1cost") then
             table.insert(cost1, deck.takeObject({guid=card.guid, position = {asset_row2_pos.x + #cost1 * 2.26, asset_row2_pos.y, asset_row2_pos.z}}))
         elseif string.find(desc, "2cost") then
             table.insert(cost2, deck.takeObject({guid=card.guid, position = {asset_row3_pos.x + #cost2 * 2.26, asset_row3_pos.y, asset_row3_pos.z}}))
         elseif string.find(desc, "3cost") then
             table.insert(cost3, deck.takeObject({guid=card.guid, position = {asset_row4_pos.x + #cost3 * 2.26, asset_row4_pos.y, asset_row4_pos.z}}))
         elseif string.find(desc, "4cost") then
             table.insert(cost4, deck.takeObject({guid=card.guid, position = {event_row1_pos.x + #cost4 * 2.26, event_row1_pos.y, event_row1_pos.z}}))
        end
    	end -- end for loop
    end -- end function
    I did a 2nd function and loop for card with

    Code:
    function display_card()
    
      for _, object in ipairs(zone_card_deck.getObjects()) do
      local desc = object.getDescription()
        if string.find(desc, "0cost") then
          table.insert(cost0, object.setPosition({position = {asset_row1_pos.x + #cost0 * 2.26, asset_row1_pos.y, asset_row1_pos.z}}))
        elseif string.find(desc, "1cost") then
            table.insert(cost1, object.setPosition({position = {asset_row2_pos.x + #cost1 * 2.26, asset_row2_pos.y, asset_row2_pos.z}}))
        elseif string.find(desc, "2cost") then
            table.insert(cost2, object.setPosition({position = {asset_row3_pos.x + #cost2 * 2.26, asset_row3_pos.y, asset_row3_pos.z}}))
        elseif string.find(desc, "3cost") then
            table.insert(cost3, object.setPosition({position = {asset_row4_pos.x + #cost3 * 2.26, asset_row4_pos.y, asset_row4_pos.z}}))
        elseif string.find(desc, "4cost") then
            table.insert(cost4, object.setPosition({position = {event_row1_pos.x + #cost4 * 2.26, event_row1_pos.y, event_row1_pos.z}}))
        end
      end
    end
    Then called both with

    Code:
    function view_deck_cost()
      display_deck()
      display_card()
    end
    Because I'm having multiple string.find and positions, I'm not sure how to use the code solution you posted.

    Video



    TLDR - I'm not sure where to start adapting the code you posted.

  11. #11
    I'm no coding expert...

    Interesting idea for a deck builder.. I went a different rout for my CoC mod... BTW.. I would recommend having TTS simply read text outputs from arkhamdb.com...

    Anyway...

    Code:
      for _, object in ipairs(zone_card_deck.getObjects()) do
        if object.tag == "Deck" then
          deck = object
          break
        end
      end
    see this code you used here right? Well that is finding a deck ... so all it needs to do is find the card if there is one instead of a decl... just make a elseif for finding "Card" and that should do it right? This will wither make "object" the "decl" or a single "card"... then if it is deck use take object, if it is a card use setPosition

    something like this maybe?

    Code:
      for _, object in ipairs(zone_card_deck.getObjects()) do
        if object.tag == "Deck" then
          drawFromDeck(object)
        elseif object.tag == "Card" then
          drawLastCard(object)
        end
      end
    
    drawFromDeck(obj)
      --Do stuff
      --obj.takeObject(prams)
    end
    
    drawLastCard(obj)
      --Do stuff
      --obj.setPosition(prams)
    end
    Last edited by Tragic; 11-03-2017 at 03:48 PM.
    My Boardgame uTube chan - Tragic's Table Top
    BGG Guild of BoardGame uTubers - Tube Tables

  12. #12
    Thanks, yeah of course the answer is probably a simple one, lol. I tend to overthink things. I don't know how to make read from cardgameDb?

    I have a lot of custom tags in use here so probably best to go with how I did it, besides, I've already tagged all the cards Have you played Arkham LCG? Maybe I can add you as contributor and you can check out my table sometime. (although it is currently put on hold while I make a 7th continent table > private/friends only of course)

  13. #13
    cool... add me to the 7th continent list lol : )
    My Boardgame uTube chan - Tragic's Table Top
    BGG Guild of BoardGame uTubers - Tube Tables

  14. #14
    Friend request sent

  15. #15
    Join Date
    Apr 2016
    Posts
    174
    Probably said, but this is more clear for others reading this thread: Take object on a "Deck" works till the last "Card". The "Deck" is gone when the last "Card" appears. Simply search for a "Card" instead of a "Deck" (eg: when deck size = last card change code to find last card).

    Ps: Side Note: This also affect any reset() or deck functions you may have because the deck is no longer there.

  16. #16
    I am really struggling with this. I cannot get any of the code examples posted to work.

  17. #17
    Join Date
    May 2016
    Posts
    1,072
    Well, tell ya what, I have a shitty workaround for you perhaps.

    When you take a card, do a print of print(#deck.getObjects()) and it should print the # of cards in the deck prior to you taking a card (do it before you take). When you have 1 card left, my guess is it will say 0. That is because the card is out of the deck but the deck instance sort of lingers for a few frames. I've seen it before at least. Do you experience the same thing? If so, let me know and I'll build you a quick fix example.

    Also, if your answer was yes, tell me if your deck is always in the same position or in different spots.

    Even better, post the json for your game on google drive or somewhere and give us a link so we can look at your table and your code to work out what is happening more easily

  18. #18
    Quote Originally Posted by maximo1984@ymail.com View Post
    I am really struggling with this. I cannot get any of the code examples posted to work.
    I'd like to help. But I've read the thread and am not clear on current status other than you still need help. Why didn't the posted solutions work?

    Do you have a minimal viable example that recreates the error you're encountering? Where can I download it?

  19. #19
    Hi Mr Stump, here is the latest thing I have tried

    Code:
    function return_cards()
      count = 0
      for _, object in ipairs(zone_past.getObjects()) do
        if object.tag == "Deck" then
          deck = object
          break
        end
      end
    
      for _, card in ipairs(deck.getObjects()) do
        --local desc = card.description
        --if desc == "exploration 1" then
          count = count + 1
        --end
      end
    
      for _, card in ipairs(deck.getObjects()) do
        --local desc = card.description
        --if desc == "exploration 1" then
        while count  >= 2 do
            deck.takeObject({position = decks_explore.one, guid = card.guid, flip=true})
            count = count - 1
          --elseif not string.find(desc, "exploration") then
            --deck.takeObject({position = deck_adv_pos, guid = card.guid, flip=true})
          --end
        end
      end
    
    end
    there is disabled code here cause I was trying to get it working bare bones. The deck is always in the same position, but will vary in number of items in it. There will also be multiple locations for the cards to go to from the deck depending on the description. I'd say between 2-5 locations to move to. The code above always only takes 1 card.

    As this is a 7th continent table which I don't want getting "out in the wild" , I will private msg you the link to the .json file

    p.s. yes, after print#deck counts down, then goes from 2 to 0

  20. #20
    Code:
    --[[ Lua code. See documentation: http://berserk-games.com/knowledgebase/scripting/ --]]
    
    --[[ The onLoad event is called after the game save finishes loading. --]]
    function onLoad()
        --[[ print('onLoad!') --]]
        clearTable()
        startLuaCoroutine(Global, 'dealCards')
    end
    
    function clearTable()
      for key, value in pairs(getAllObjects()) do
        value.destruct()
      end
    end
    
    function dealCards()
      local deck = spawnObject({
        type = 'Deck',
        rotation = {0, 0, 180}
      })
    
      while deck.guid == nil do
        coroutine.yield(0)
      end
      print(deck.guid)
    
      --simpleDeal(deck) -- error
      saferDeal(deck)
    
      return 1
    end
    
    function saferDeal(deck)
      local deckObjects = deck.getObjects()
      local deckSize = #deckObjects
      
      for index, carddata in ipairs(deckObjects) do
        if index < deckSize then
          local cardObject = deck.takeObject({ guid = carddata.guid, flip = true })
        else
          local cardObject = deck.takeObject({ flip = true })
        end
      end
    end
    
    function simpleDeal(deck)
      for index, carddata in ipairs(deck.getObjects()) do
        deck.takeObject({ guid = carddata.guid, flip = true })
      end
    end

  21. #21
    Just omitting the guid altogether works.

    Code:
    function simpleDeal(deck)
      for index, carddata in ipairs(deck.getObjects()) do
        deck.takeObject({ flip = true })
      end
    end

  22. #22
    Yeah, but there is multiple categories of cards that need taken. I'd have to use by guid then right?

  23. #23
    All of the code posted so far has been iterating through the cards via deck.getObjects() then doing a deck.takeObject(). Since takeObject() by guid isn't working in this case, we can't do any preprocessing of the deck. But you could takeObject() and then process the card.

  24. #24
    In plain words.

    There is a deck of cards, call it a discard pile. In this deck, there are cards that need returned to their own decks, defined by their descriptions. There could be between 2-5 different destinations.

  25. #25
    getting close, I think I'l have it in a few

Page 1 of 2 12 LastLast

Similar Threads

  1. Replies: 3
    Last Post: 07-06-2017, 12:28 PM
  2. Replies: 1
    Last Post: 03-22-2017, 10:28 AM
  3. Replies: 2
    Last Post: 07-07-2016, 05:15 PM
  4. Replies: 8
    Last Post: 04-18-2016, 07:11 PM
  5. Deck Builder doesn't open saved decks properly
    By Logarek in forum General Discussion
    Replies: 8
    Last Post: 08-18-2015, 11:57 PM

Posting Permissions

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