-
Notifications
You must be signed in to change notification settings - Fork 16
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
base: master
Are you sure you want to change the base?
Changes from all commits
6eaf9f1
e4cfa70
d123b66
1afe699
a4e82a9
d052236
aae2ba8
d8d5cc3
aba0370
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -659,15 +659,6 @@ function getClueDetails(processedClue) | |
end | ||
end | ||
|
||
function rotateclues() | ||
for cardIndex, cardData in ipairs(cards) do | ||
local card = getObjectFromGUID(cardData.guid) | ||
if card.interactable then | ||
card.setRotation({0, 180, 0}) | ||
end | ||
end | ||
end | ||
|
||
function encodeClue(color, clue) | ||
local finishedClue | ||
local cluePosition | ||
|
@@ -730,11 +721,34 @@ function encodeClue(color, clue) | |
end | ||
end | ||
|
||
function onObjectEnterContainer(deck, card) | ||
-- First to check that we only do this on the first grouping | ||
if #deck.getObjects() == 2 then | ||
deck.destruct() | ||
Wait.frames(function() dealCards() end, 180) | ||
function isCodenamesCard(obj) | ||
if obj.type == "Card" then | ||
vals = obj.getCustomObject() | ||
if vals.face != nil and string.find(vals.face,"codenames")then | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
return true | ||
end | ||
end | ||
return false | ||
end | ||
|
||
function isCodenamesClue(obj) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a very discriminatory function to identify clue tiles. |
||
if obj.type == "Board" then | ||
butts = obj.getButtons() | ||
if butts != nil and (#butts == 1 and butts[1].click_function == "nullFunction" or #butts == 2 and butts[1].click_function == "clue") and butts[1].scale == Vector(2, 2, 1.3333) and butts[1].position == Vector(0,0.2,0) then | ||
return true | ||
end | ||
end | ||
return false | ||
end | ||
|
||
function onObjectEnterContainer(container, object) | ||
-- 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
container.destruct() | ||
dealCardsDelayed() | ||
end | ||
end | ||
end | ||
|
||
|
@@ -924,12 +938,9 @@ function resetGame() | |
end | ||
|
||
-- Delete clue tiles | ||
for _, clueList in ipairs({gameState.redClues, gameState.blueClues}) do | ||
for _, clue in ipairs(clueList) do | ||
local clueTile = getObjectFromGUID(clue) | ||
if clueTile then | ||
clueTile.destruct() | ||
end | ||
for _, obj in pairs(getObjects()) do | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
if isCodenamesClue(obj) then | ||
obj.destruct() | ||
end | ||
end | ||
|
||
|
@@ -976,6 +987,7 @@ function setupGame() | |
|
||
-- Set the correct double card to red | ||
extraCard.setLock(false) | ||
extraCard.setRotation({0, 180, 180}) | ||
extraCard.setPositionSmooth(agents[extraCard.guid].position) | ||
extraCard.interactable = true | ||
agents[extraCard.guid].enabled = true | ||
|
@@ -997,8 +1009,23 @@ function setupGame() | |
gameState.firstTurn = true | ||
end | ||
|
||
dealCards_WaitId = nil | ||
function dealCardsDelayed() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
if dealCards_WaitId != nil then | ||
Wait.stop(dealCards_WaitId) | ||
dealCards_WaitId = nil | ||
end | ||
dealCards_WaitId = Wait.time(dealCards,2.5,1) | ||
end | ||
|
||
-- Deals the cards on the board | ||
function dealCards() | ||
-- check all objects to delete unused codenames cards | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) |
||
for _, obj in pairs(getObjects()) do | ||
if isCodenamesCard(obj) and not isCard(obj.guid) then | ||
obj.destruct() | ||
end | ||
end | ||
for i = 1, 25, 1 do | ||
local cardObject = getObjectFromGUID(cards[i].guid) | ||
if cards[i].guid == nil or cardObject == nil then | ||
|
@@ -1063,14 +1090,17 @@ end | |
|
||
function onObjectDrop(color, agent) | ||
-- Ensure that the dropped object is an agent card | ||
if gameState.status ~= 1 or agent.tag ~= "Tile" or agents[agent.guid] == nil then | ||
if gameState.status ~= 1 or agent.type ~= "Tile" or agents[agent.guid] == nil then | ||
return | ||
end | ||
|
||
-- Find the closest card position to the dropped agent | ||
local cardIndex = findClosestCard(1.65, agent.getPosition()) | ||
if cardIndex == nil or cards[cardIndex].covered then | ||
-- Either no close card found, or card is already covered | ||
agent.setAngularVelocity({0, 0, 0}) | ||
agent.setVelocity({0, 0, 0}) | ||
agent.setRotation({0, 180, 180}) | ||
agent.setPositionSmooth(agents[agent.guid].position) | ||
return | ||
end | ||
|
@@ -1079,6 +1109,9 @@ function onObjectDrop(color, agent) | |
local agentColor = agents[agent.guid].color | ||
local cardColor = cards[cardIndex].color | ||
if cardColor ~= agentColor then | ||
agent.setAngularVelocity({0, 0, 0}) | ||
agent.setVelocity({0, 0, 0}) | ||
agent.setRotation({0, 180, 180}) | ||
agent.setPositionSmooth(agents[agent.guid].position) | ||
Player[color].broadcast("[a020f0]» [da1918]ERROR: [ffffff]An agent has been placed incorrectly. You placed a " .. agentColor .. " agent on a " .. cardColor .. " card. [a020f0]«") | ||
return | ||
|
@@ -1396,30 +1429,6 @@ function votePass(color) | |
playerVote(color, 26) | ||
end | ||
|
||
function onObjectPickUp(color, object) | ||
-- Clues | ||
if object.tag == "Card" and not object.spawning then | ||
for i = 1, 25, 1 do | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
if cards[i].guid == object.guid then | ||
object.setVelocity({0, 0, 0}) | ||
object.drop() | ||
object.setPosition({cards[i].position.x, 1.03, cards[i].position.z}) | ||
if #Player[color].getSelectedObjects() <= 1 then | ||
playerVote(color, i) | ||
end | ||
break | ||
end | ||
end | ||
elseif agents[object.guid] ~= nil then | ||
-- Prevent picking up of agent tiles from anyone but red or blue | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
if color ~= "Red" and color ~= "Blue" then | ||
object.setVelocity({0, 0, 0}) | ||
object.drop() | ||
object.setPosition({agents[object.guid].position.x, 1.01, agents[object.guid].position.z}) | ||
end | ||
end | ||
end | ||
|
||
function onPlayerAction(player, action, objects) | ||
local processAction = false | ||
local actionsToProcess = { | ||
|
@@ -1429,7 +1438,8 @@ function onPlayerAction(player, action, objects) | |
Player.Action.RotateOver, | ||
Player.Action.FlipIncrementalLeft, | ||
Player.Action.FlipIncrementalRight, | ||
Player.Action.FlipOver | ||
Player.Action.FlipOver, | ||
Player.Action.Delete | ||
} | ||
|
||
for _, handledAction in ipairs(actionsToProcess) do | ||
|
@@ -1442,6 +1452,24 @@ function onPlayerAction(player, action, objects) | |
if not processAction then | ||
return | ||
end | ||
|
||
if action == Player.Action.Delete then | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
-- if there is an ongoing game and a card is deleted then refresh the cards | ||
for _, obj in pairs(objects) do | ||
if gameState.status == 1 and isCodenamesCard(obj) then | ||
-- Delete word cards and refresh them | ||
dealCardsDelayed() | ||
obj.destruct() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
elseif agents[obj.guid] ~= nil then | ||
-- Do not delete any agents | ||
else | ||
-- Delete any other objects in the action | ||
obj.destruct() | ||
end | ||
end | ||
-- Prevent deletion of selected objects as we have already delete only what was allowed | ||
return false | ||
end | ||
|
||
local objectIncludesCard = false | ||
local objectIncludesAgent = false | ||
|
@@ -1475,6 +1503,27 @@ 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
object = objects[1] | ||
for i = 1, 25, 1 do | ||
if cards[i].guid == object.guid then | ||
if #player.getSelectedObjects() <= 1 then | ||
playerVote(player.color, i) | ||
end | ||
return false | ||
end | ||
end | ||
end | ||
local hasCards = false | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
for _, obj in pairs(objects) do | ||
if isCard(obj.guid) then | ||
obj.removeFromPlayerSelection(player.color) | ||
hasCards = true | ||
end | ||
end | ||
if hasCards then | ||
return false | ||
end | ||
elseif action == Player.Action.RotateIncrementalLeft or action == Player.Action.RotateIncrementalRight or action == Player.Action.RotateOver then | ||
if objectIncludesCard and not isPlayerTurn then | ||
errorMessage = "[a020f0]» [da1918]ERROR: [ffffff]You can't tilt cards when it's not your turn! [a020f0]«" | ||
|
@@ -2004,4 +2053,5 @@ function api_playerSessionEndCB(responseRaw) | |
analytics.sessions[steamID] = nil | ||
end | ||
end | ||
end | ||
end | ||
|
There was a problem hiding this comment.
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.