Tabletop Simulator

Tabletop Simulator

Not enough ratings
[VR Spam Patched] Deck Re-Shuffler • for Deckbuilding Games (Patch in description!)
   
Award
Favorite
Favorited
Unfavorite
Type: Utility
Game Category: Card Games
Language: English
File Size
Posted
Updated
137.953 KB
19 Apr, 2022 @ 6:52pm
1 Jun, 2022 @ 2:07am
15 Change Notes ( view )

Subscribe to download
[VR Spam Patched] Deck Re-Shuffler • for Deckbuilding Games (Patch in description!)

Description
This is a patched version of Liyarin's very handy Deckbuilding Re-shuffler, as pressing buttons in VR with the controller's laser pointer and trigger spams them forever. Which is an issue when trying to draw cards, set the amounts, etc.

Additionally, buttons made with the UI XML are not clickable with a VR controller (in any way). In response, this object's buttons have been disabled, and invisible createButton() buttons have been manually placed on top. I could have replaced them altogether, but this was simpler for me.

I also made another version that repositions the re-shuffle and discard deck buttons outside of the card slots, as it is sometimes possible to click that when aiming at a deck on top of the button. But, if you prefer the other's asthetic, it's still there and has the same VR patches.

These are issues that stem from issues with Tabletop Simulator's VR implementation. Hopefully in the future this will be resolved, but these have remained unpatched for a long time.

https://tabletopsimulator.nolt.io/272
https://tabletopsimulator.nolt.io/273
https://tabletopsimulator.nolt.io/1393
https://tabletopsimulator.nolt.io/1181

Lastly, I fixed some bugs that existed in the previous version, even on desktop. Just preventing unneeded exceptions interrupting players.

If you wish to patch your createButton() buttons for VR, the code to prevent the spam is a quite simple rate-limiter.

Note: this also affects desktop players, as I don't think there is a way to tell if a user is in VR. Nevermind, I figured out a way to tell if a player is in VR or not! I have updated the snippet below.

Another Update! - It will now default to sending a single click, instead of multiple slower clicks. Setting singleClick to false returns the behavior, good for setting timers or any large numbers.

If a player is in VR, their getPointerPosition() returns a Vector(0,0,0), and getPointerRotation returns 0! Sometimes, this isn't true! But, now it can account for it.

Last Updated: April 27, '22

--[[ Run on every button click to stop VR button spam. --]] -- Anti VR Button Spam -- By nullstalgia/Dr. Snickity local canVRButton = true local longVRButtonTime = 0.4 local shortVRButtonTime = 0.1 local singleClickWaitIndex = -1 local pointerCache1 = {} local pointerCache2 = {} -- How many frames should pass without more spam to allow a click local singleClickDelayFrames = 5 function preventVRButtonSpam(delayAmount, playerColor, singleClick) delayAmount = delayAmount or shortVRButtonTime playerColor = playerColor or nil -- Since false is a valid value, gotta do some weirdness. ( https://stackoverflow.com/a/6023147 ) singleClick = singleClick == nil and true or singleClick -- Can set this to true and use an autoclicker like OP Auto Clicker to test these buttons without VR local playerInVR = false local firstCursorCheck = false; if playerColor ~= nil then if Player[playerColor].getPointerPosition() == pointerCache1[playerColor] and Player[playerColor].getPointerRotation() == pointerCache2[playerColor] then playerInVR = true firstCursorCheck = true end pointerCache1[playerColor] = Player[playerColor].getPointerPosition() pointerCache2[playerColor] = Player[playerColor].getPointerRotation() if Player[playerColor].getPointerPosition() == pointerCache1[playerColor] and Player[playerColor].getPointerRotation() == pointerCache2[playerColor] and firstCursorCheck == false then -- Smells like a VR cursor moved playerInVR = true canVRButton = false preventVRButtonSpamSingleWait(true) return true end end -- Check if player is actually in VR if playerColor == nil then playerInVR = true elseif Player[playerColor].getPointerPosition() == Vector(0,0,0) and Player[playerColor].getPointerRotation() == 0 then playerInVR = true end -- If not in VR, just let them click freely if playerInVR == false then return true elseif canVRButton == false and singleClick then preventVRButtonSpamSingleWait(true) return false elseif canVRButton and singleClick then canVRButton = false preventVRButtonSpamSingleWait(false) return true elseif canVRButton then canVRButton = false Wait.time( function() canVRButton = true end, delayAmount ) return true else return false end end -- Not meant to be called by modders. Just to prevent having the same code copypasted 4 times. function preventVRButtonSpamSingleWait(stopFirst) stopFirst = stopFirst or false if stopFirst then if singleClickWaitIndex ~= -1 then Wait.stop(singleClickWaitIndex) end end singleClickWaitIndex = Wait.frames( function() singleClickWaitIndex = -1 canVRButton = true end, singleClickDelayFrames ) end --[[ In button click_function(): delayAmount defaults to shortVRButtonTime if nil/empty singleClick defaults to true if preventVRButtonSpam(delayAmount, playerColor, singleClick) then -- Your code end --]]

If you do not pass a color to the function, it will also rate-limit Desktop users. This can be useful for certain buttons that just shouldn't be spammed for whatever reason.

Example snippet from this project:
function raiseDrawCount(_, color) if preventVRButtonSpam(shortVRButtonTime, color) then saved_data["drawNum"] = saved_data["drawNum"] + 1 self.UI.setValue("txt_drawMid", "Draw to " .. saved_data["drawNum"]) end end

Original Item Link (click me)

Original Description:

---

This is an utility that helps with an annoying little bit about deckbuilding games: The fact that you need to reshuffle your discard pile into your deck when it runs out.

Once your Deck runs out, there is a button below it that will take your discard pile, flip it over and re-shuffle it into the deck spot.

---

There are some additional options, that can be configured in the back side of the tile:

Draw to X Button: Displays a button below the deck that remembers the number of cards to draw, so that you can simply press that button and your hand will fill up to that number. For example, if you need to draw up 5, and you have 2 cards in your hand, the button will draw 3. Forget all the mental maths to figure out how many cards you need to draw!

Discard Button: An easy way to simply discard your whole hand.

Discard X Random: Sometimes cards tell you to discard a random card from your hand, and it's annoying to group up your hand, shuffle it, discard the top card, then take it all back into your hand. This button randomly chooses a random card in your hand and discards it. You can change the amount of cards to discard this way with the +/- buttons next to it.

Re-Shuffle when not enough cards: An added option to the Draw to X button, if this option is on, when you draw X card, but there aren't enough cards in the deck to deal all of them, the script automatically re-shuffles the deck, then deals the rest of the cards missing. This option is on by default.

The original's "bigger buttons" are forced on, due to the small size of the normal buttons.

6 Comments
Dr. Snickity  [author] 27 Apr, 2022 @ 1:09am 
Patched a bug concerning when VR players's "cursor" would move and break the "is-in-VR" detection.
Dr. Snickity  [author] 21 Apr, 2022 @ 2:22pm 
Alright, I have now added a way to only send a single click! It waits for the spam to stop for a few frames and then will allow another click. Description snippets are edited.
Dr. Snickity  [author] 21 Apr, 2022 @ 1:17pm 
I am, but I didn't happen to see a Adil3tr. I added you on Steam so we can find tags privately.
Adil3tr 21 Apr, 2022 @ 10:37am 
This is super interesting. Are you on the discord? I'd like to ask about this
Dr. Snickity  [author] 19 Apr, 2022 @ 11:58pm 
Done! Now it shouldn't rate-limit desktop users! (Unless you choose to)
Dr. Snickity  [author] 19 Apr, 2022 @ 10:53pm 
Oh wait, I think I found a way to tell if a player is a VR player!