Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix cards in more situations #96

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

Canonelis
Copy link
Contributor

These additions help keep the codenames game from breaking and help with transferring host in between games/when rewinding.

-in onObjectEnterContainer only delete the container if a codenames card was put in it
-use isDestroyed() object property for a cleaner way to see if this has been run already(it returns true if the object is about to be but is not yet destroyed)
-created dealCardsDelayed() function which can be called many times per second, but will only run dealCards() once 1.5s have passed without any further calls to dealCardsDelayed()
-created onObjectDestroy() which re-deals cards if a game is being played and a codenames card is deleted and no other cards have been deleted in the past 1.5 seconds
"tag" has been replaced with "type" and contains the same data
-Wherever we set the position I set the rotation as well(except for when picking up pre-rotated cards)
-Wherever we pick up or drop cards, I set the angular velocity to 0
remove unused "rotateclues" function
-to prevent onObjectDestroy from being called due to the script deleting something, use the onPlayerAction function to detect deletions
-move onPlayerPickup voting mechanism to onPlayerAction so that the card doesn't move slightly whenever someone votes
-when transferring host after a game has ended, the current cards become blank and need to be deleted based on their face image URL when dealing out cards
clue tiles are very distinct, so delete them based on their properties when starting a new game.
since the list of clue tiles isn't saved when the game is reloaded, this guarantees they are removed upon reset
do not allow picking up word cards at all
@@ -730,11 +730,31 @@ function encodeClue(color, clue)
end
end

function onObjectEnterContainer(deck, card)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function intercepts all objects that enter any container and deletes the container, so I made it more discriminatory.

function isCodenamesCard(obj)
if obj.type == "Card" then
vals = obj.getCustomObject()
if vals.face != nil and string.find(vals.face,"codenames")then
Copy link
Contributor Author

@Canonelis Canonelis Dec 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I made a function that should work for future implementations. If the object is of type "Card" and the face image URL contains "codenames" then it is probably a codenames card. Agents don't have a type of "Card" and currently no other game elements have a card type in your implementation.
The getCustomObject() function never seems to return "nil" and returns an empty array if there are no elements.

-- if the displaced object is a codenames card then delete the container and refresh the cards
if isCodenamesCard(object) then
-- Check whether container is being destroyed so we only do this once for multiple deposited objects
if not container.isDestroyed() then
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The .isDestroyed() is perfect for this situation. It returns true if .destruct() was called on it even if the object hasn't had any frames to be removed from the game yet.

end

function onObjectDestroy(obj)
-- if there is an ongoing game and a card is deleted then refresh the cards
Copy link
Contributor Author

@Canonelis Canonelis Dec 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't review this function too closely. I replace onObjectDestroy(obj) with a section inside onPlayerAction() in a later commit. But the idea is to redeal cards if one of them is deleted.

@@ -997,6 +1017,14 @@ function setupGame()
gameState.firstTurn = true
end

dealCards_WaitId = nil
function dealCardsDelayed()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the nicest way I've found to let the script spam calls to an expensive function, but only have the function be called once everything has settled down(1.5 seconds after the last request to call the function). The only problems with this kind of set-up is if the function triggers itself, or the game is so laggy that 1.5 seconds is not enough time for the calls to the function to stop.

@@ -742,13 +742,6 @@ function onObjectEnterContainer(container, object)
end
end

function onObjectDestroy(obj)
-- if there is an ongoing game and a card is deleted then refresh the cards
Copy link
Contributor Author

@Canonelis Canonelis Dec 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to remove this function as it gets called every time the script destroys an object. We only really care about when a player deletes a card so I put this in "onPlayerAction".

@@ -1019,6 +1012,12 @@ end

-- Deals the cards on the board
function dealCards()
-- check all objects to delete unused codenames cards
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codenames keeps track of card guid's but this doesn't get saved or loaded when a rewind or host change happens. So let's just delete all codename cards that aren't in the tracked card guid list.(I do a similar thing for clue tiles later on when starting a new game)

end
end
elseif agents[object.guid] ~= nil then
-- Prevent picking up of agent tiles from anyone but red or blue
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section isn't ever used since a pickup action on an agent by a non-codemaster is stopped by a return of "false" inside onPlayerAction() when this happens.

function onObjectPickUp(color, object)
-- Clues
if object.type == "Card" and not object.spawning then
for i = 1, 25, 1 do
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this section into onPlayerAction() so that it can add a vote without ever attempting to pick up the card for a frame.

@@ -1471,6 +1444,17 @@ function onPlayerAction(player, action, objects)
if not processAction then
return
end

if action == Player.Action.Delete then
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where I moved the onObjectDestroy() function so that it doesn't run when the script deletes a card.

@@ -1504,6 +1488,17 @@ function onPlayerAction(player, action, objects)
elseif settings.cardTilting and gameState.status == 1 and not gameState.canVote then
errorMessage = "[a020f0]» [da1918]ERROR: [ffffff]You can't vote until you've been given a clue! [a020f0]«"
end
if #objects == 1 and objects[1].type == "Card" and not objects[1].spawning then
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is where I moved the onObjectPickUp() function so that I can use "return false" when a vote is cast.
I edit this in a later commit to entirely disallow picking up cards.(the only downside I see is that if the game physics somehow puts the card somewhere else, it can't easily be put back)

@@ -731,6 +731,16 @@ function isCodenamesCard(obj)
return false
end

function isCodenamesClue(obj)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very discriminatory function to identify clue tiles.

if clueTile then
clueTile.destruct()
end
for _, obj in pairs(getObjects()) do
Copy link
Contributor Author

@Canonelis Canonelis Dec 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codenames keeps track of clue tile guid's but this doesn't get saved or loaded when a rewind or host change happens. So let's just delete all clue tiles when a new game starts. In my experience with puzzles with 5000 pieces, this is still very fast to run.

dealCardsDelayed()
break
obj.destruct()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I take over what gets deleted in a player action. Deleting agents currently requires the game to be reloaded, so I prevent that outright. Deleting cards causes them to be redealt. And then it deletes everything else the player wanted to delete.

@@ -1513,6 +1513,16 @@ function onPlayerAction(player, action, objects)
end
end
end
local hasCards = false
Copy link
Contributor Author

@Canonelis Canonelis Dec 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for any pickup action, it will prevent the pickup from happening if it contains any word cards, similar to before. As a nicety, it removes the cards from the player's selection so that the player can try and pick up the items again without being blocked.

Change detection of clue
add longer delay for deck respawning
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant