From bf1b9c82b510a55a9e40b1deeae9cb19a37f9301 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Tue, 9 Jan 2024 13:51:24 +0100 Subject: [PATCH 1/5] added seat switching hotkey --- src/core/GameKeyHandler.ttslua | 61 ++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/src/core/GameKeyHandler.ttslua b/src/core/GameKeyHandler.ttslua index 83e719b0..650fbf4c 100644 --- a/src/core/GameKeyHandler.ttslua +++ b/src/core/GameKeyHandler.ttslua @@ -6,12 +6,14 @@ local searchLib = require("util/SearchLib") local victoryDisplayApi = require("core/VictoryDisplayApi") function onLoad() - addHotkey("Add Doom to Agenda", addDoomToAgenda) - addHotkey("Bless/Curse Status", showBlessCurseStatus) - addHotkey("Discard Object", discardObject) + addHotkey("Add doom to agenda", addDoomToAgenda) + addHotkey("Discard object", discardObject) addHotkey("Discard top card", discardTopDeck) + addHotkey("Display Bless/Curse status", showBlessCurseStatus) addHotkey("Move card to Victory Display", moveCardToVictoryDisplay) addHotkey("Remove a use", removeOneUse) + addHotkey("Switch seat clockwise", switchSeatClockwise) + addHotkey("Switch seat counter-clockwise", switchSeatCounterClockwise) addHotkey("Take clue from location", takeClueFromLocation) addHotkey("Upkeep", triggerUpkeep) addHotkey("Upkeep (Multi-handed)", triggerUpkeepMultihanded) @@ -200,6 +202,59 @@ function removeOneUse(playerColor, hoveredObject) playmatApi.discardListOfObjects(discardForMatColor, { targetObject }) end +-- switches the triggering player to the next seat (clockwise) +function switchSeatClockwise(playerColor) + switchSeat(playerColor, "clockwise") +end + +-- switches the triggering player to the next seat (counter-clockwise) +function switchSeatCounterClockwise(playerColor) + switchSeat(playerColor, "counter-clockwise") +end + +-- handles seat switching in the given direction +function switchSeat(playerColor, direction) + if playerColor == "Black" or playerColor == "Grey" then + broadcastToColor("This hotkey is only available to seated players.", playerColor, "Orange") + return + end + + -- get legal colors + local seatList = Player.getAvailableColors() + + -- sort colors on hand position (Green, White, Orange, Red) + local function sortByHandPosition(color1, color2) + local pos1 = Player[color1].getHandTransform().position + local pos2 = Player[color2].getHandTransform().position + return pos1.z > pos2.z + end + table.sort(seatList, sortByHandPosition) + + -- get current seat index + local index + for i, color in ipairs(seatList) do + if color == playerColor then + index = i + break + end + end + if not index then + broadcastToColor("Couldn't find position of seated color.", playerColor, "Orange") + return + end + + -- get next color + index = index + ((direction == "clockwise") and -1 or 1) + if index == 0 then + index = #seatList + elseif index > #seatList then + index = 1 + end + + -- swap color + Player[playerColor].changeColor(seatList[index]) +end + -- takes a clue from a location, player needs to hover the clue directly or the location function takeClueFromLocation(playerColor, hoveredObject) local cardName, clue From 3beb85d633ec83fd9213fca5130d81eea98ac97e Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Tue, 9 Jan 2024 14:25:22 +0100 Subject: [PATCH 2/5] add number typing handling --- src/core/Global.ttslua | 34 +++++++++++++++++++++++++++++++++ src/playermat/PlaymatApi.ttslua | 9 +++++++++ 2 files changed, 43 insertions(+) diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index a8e95e80..c854529f 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -200,6 +200,40 @@ function onObjectEnterZone(zone, enteringObj) end end +-- handle card drawing via number typing for multihanded gameplay +-- (and additionally allow Norman Withers to draw multiple cards via number) +function onObjectNumberTyped(hoveredObject, playerColor, number) + -- only continue for decks or cards + if hoveredObject.type ~= "Deck" and hoveredObject.type ~= "Card" then return end + + -- get playmat colors with an investigator card + local localInvestigatorPosition = { x = -1.17, y = 1, z = -0.01 } + local matColors = { "White", "Orange", "Green", "Red" } + local legalColors = {} + + for _, color in ipairs(matColors) do + local mat = guidReferenceApi.getObjectByOwnerAndType(color, "Playermat") + if mat ~= nil then + local searchPos = mat.positionToWorld(localInvestigatorPosition) + local searchResult = searchLib.atPosition(searchPos, "isCardOrDeck") + + if #searchResult > 0 then + table.insert(legalColors, color) + end + end + end + if #legalColors == 0 then return end + + -- check whether the hovered object is part of a players draw objects + for _, color in ipairs(legalColors) do + local deckAreaObjects = playmatApi.getDeckAreaObjects(color) + if deckAreaObjects.topCard == hoveredObject or deckAreaObjects.draw == hoveredObject then + playmatApi.drawCardsWithReshuffle(color, number) + return true + end + end +end + --------------------------------------------------------- -- chaos token drawing --------------------------------------------------------- diff --git a/src/playermat/PlaymatApi.ttslua b/src/playermat/PlaymatApi.ttslua index 8ac011e9..26a07391 100644 --- a/src/playermat/PlaymatApi.ttslua +++ b/src/playermat/PlaymatApi.ttslua @@ -180,6 +180,15 @@ do end end + -- triggers the draw function for the specified playmat + ---@param matColor String Color of the playmat - White, Orange, Green, Red or All + ---@param number Number Amount of cards to draw + PlaymatApi.drawCardsWithReshuffle = function(matColor, number) + for _, mat in pairs(getMatForColor(matColor)) do + mat.call("drawCardsWithReshuffle", number) + end + end + -- returns the resource counter amount ---@param matColor String Color of the playmat - White, Orange, Green or Red (does not support "All") ---@param type String Counter to target From 76e5d3e5f66b9cd044b42fd5faf5768536f93490 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Tue, 9 Jan 2024 15:07:40 +0100 Subject: [PATCH 3/5] code improvement by api addition --- src/core/GameKeyHandler.ttslua | 22 ++++++++++++---------- src/core/Global.ttslua | 20 +------------------- src/playermat/PlaymatApi.ttslua | 17 +++++++++++++++++ 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/src/core/GameKeyHandler.ttslua b/src/core/GameKeyHandler.ttslua index 650fbf4c..cc64d9f1 100644 --- a/src/core/GameKeyHandler.ttslua +++ b/src/core/GameKeyHandler.ttslua @@ -219,40 +219,42 @@ function switchSeat(playerColor, direction) return end - -- get legal colors - local seatList = Player.getAvailableColors() - - -- sort colors on hand position (Green, White, Orange, Red) + -- sort function for matcolors based on hand position (Green, White, Orange, Red) local function sortByHandPosition(color1, color2) local pos1 = Player[color1].getHandTransform().position local pos2 = Player[color2].getHandTransform().position return pos1.z > pos2.z end - table.sort(seatList, sortByHandPosition) + + -- get used playermats + local usedColors = playmatApi.getUsedMatColors() + table.sort(usedColors, sortByHandPosition) -- get current seat index local index - for i, color in ipairs(seatList) do + for i, color in ipairs(usedColors) do if color == playerColor then index = i break end end if not index then - broadcastToColor("Couldn't find position of seated color.", playerColor, "Orange") + broadcastToColor("Couldn't detect investigator.", playerColor, "Orange") return end -- get next color index = index + ((direction == "clockwise") and -1 or 1) if index == 0 then - index = #seatList - elseif index > #seatList then + index = #usedColors + elseif index > #usedColors then index = 1 end -- swap color - Player[playerColor].changeColor(seatList[index]) + local newMatColor = usedColors[index] + local newHandColor = playmatApi.getMatColorByPosition(Player[newMatColor].getHandTransform().position) + Player[playerColor].changeColor(newHandColor) end -- takes a clue from a location, player needs to hover the clue directly or the location diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index c854529f..441c04a8 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -206,26 +206,8 @@ function onObjectNumberTyped(hoveredObject, playerColor, number) -- only continue for decks or cards if hoveredObject.type ~= "Deck" and hoveredObject.type ~= "Card" then return end - -- get playmat colors with an investigator card - local localInvestigatorPosition = { x = -1.17, y = 1, z = -0.01 } - local matColors = { "White", "Orange", "Green", "Red" } - local legalColors = {} - - for _, color in ipairs(matColors) do - local mat = guidReferenceApi.getObjectByOwnerAndType(color, "Playermat") - if mat ~= nil then - local searchPos = mat.positionToWorld(localInvestigatorPosition) - local searchResult = searchLib.atPosition(searchPos, "isCardOrDeck") - - if #searchResult > 0 then - table.insert(legalColors, color) - end - end - end - if #legalColors == 0 then return end - -- check whether the hovered object is part of a players draw objects - for _, color in ipairs(legalColors) do + for _, color in ipairs(playmatApi.getUsedMatColors()) do local deckAreaObjects = playmatApi.getDeckAreaObjects(color) if deckAreaObjects.topCard == hoveredObject or deckAreaObjects.draw == hoveredObject then playmatApi.drawCardsWithReshuffle(color, number) diff --git a/src/playermat/PlaymatApi.ttslua b/src/playermat/PlaymatApi.ttslua index 26a07391..1e067bc7 100644 --- a/src/playermat/PlaymatApi.ttslua +++ b/src/playermat/PlaymatApi.ttslua @@ -1,6 +1,7 @@ do local PlaymatApi = {} local guidReferenceApi = require("core/GUIDReferenceApi") + local searchLib = require("util/SearchLib") -- Convenience function to look up a mat's object by color, or get all mats. ---@param matColor String Color of the playmat - White, Orange, Green, Red or All @@ -198,6 +199,22 @@ do end end + -- returns a list of mat colors that have an investigator placed + PlaymatApi.getUsedMatColors = function() + local localInvestigatorPosition = { x = -1.17, y = 1, z = -0.01 } + local usedColors = {} + + for matColor, mat in pairs(getMatForColor("All")) do + local searchPos = mat.positionToWorld(localInvestigatorPosition) + local searchResult = searchLib.atPosition(searchPos, "isCardOrDeck") + + if #searchResult > 0 then + table.insert(usedColors, matColor) + end + end + return usedColors + end + -- resets the specified skill tracker to "1, 1, 1, 1" ---@param matColor String Color of the playmat - White, Orange, Green, Red or All PlaymatApi.resetSkillTracker = function(matColor) From 3faa95966085ca105cfe1ba47008b6d586e20725 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Wed, 10 Jan 2024 11:44:18 +0100 Subject: [PATCH 4/5] code improvement + bugfix --- src/playermat/InvestigatorSkillTracker.ttslua | 62 +++++++++---------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/src/playermat/InvestigatorSkillTracker.ttslua b/src/playermat/InvestigatorSkillTracker.ttslua index 5abf7b19..1f20685c 100644 --- a/src/playermat/InvestigatorSkillTracker.ttslua +++ b/src/playermat/InvestigatorSkillTracker.ttslua @@ -1,62 +1,56 @@ -local BUTTON_PARAMETERS = {} -BUTTON_PARAMETERS.function_owner = self -BUTTON_PARAMETERS.height = 650 -BUTTON_PARAMETERS.width = 700 -BUTTON_PARAMETERS.position = { x = -4.775, y = 0.1, z = -0.03 } -BUTTON_PARAMETERS.color = { 0, 0, 0, 0 } -BUTTON_PARAMETERS.font_color = { 0, 0, 0, 100 } -BUTTON_PARAMETERS.font_size = 450 +local buttonParameters = {} +buttonParameters.function_owner = self +buttonParameters.height = 650 +buttonParameters.width = 700 +buttonParameters.position = { x = -4.775, y = 0.1, z = -0.03 } +buttonParameters.color = { 0, 0, 0, 0 } +buttonParameters.font_color = { 0, 0, 0, 100 } +buttonParameters.font_size = 450 function onSave() return JSON.encode(stats) end -- load stats and make buttons (left to right) -function onLoad(saved_data) - stats = JSON.decode(saved_data) or { 1, 1, 1, 1 } +function onLoad(savedData) + stats = JSON.decode(savedData) or { 1, 1, 1, 1 } - for i = 1, 4 do - BUTTON_PARAMETERS.label = stats[i] .. " " - BUTTON_PARAMETERS.position.x = BUTTON_PARAMETERS.position.x + 1.91 - BUTTON_PARAMETERS.click_function = attachIndex("button_click", i) - self.createButton(BUTTON_PARAMETERS) + for index = 1, 4 do + local fnName = "buttonClick" .. index + _G[fnName] = function(_, _, isRightClick) buttonClick(isRightClick, index) end + buttonParameters.click_function = fnName + buttonParameters.position.x = buttonParameters.position.x + 1.91 + self.createButton(buttonParameters) + updateButtonLabel(index) end self.addContextMenuItem("Reset to 1s", function() updateStats({ 1, 1, 1, 1 }) end) end --- helper function to carry index -function attachIndex(click_function, index) - local fn_name = click_function .. index - _G[fn_name] = function(obj, player_color, isRightClick) - _G[click_function](obj, player_color, isRightClick, index) - end - return fn_name -end - -function button_click(_, _, isRightClick, index) +function buttonClick(isRightClick, index) stats[index] = math.min(math.max(stats[index] + (isRightClick and -1 or 1), 0), 99) - changeButton(index) + updateButtonLabel(index) end -function changeButton(index) - local font_size = BUTTON_PARAMETERS.font_size +-- sync the button label to the internal value +function updateButtonLabel(index) + local fontSize = buttonParameters.font_size local whitespace = " " if stats[index] > 9 then - font_size = BUTTON_PARAMETERS.font_size * 0.65 + fontSize = buttonParameters.font_size * 0.65 whitespace = " " end - self.editButton({ index = index - 1, label = stats[index] .. whitespace, font_size = font_size }) + self.editButton({ index = index - 1, label = stats[index] .. whitespace, font_size = fontSize }) end --- formatting of "newStats": {Willpower, Intellect, Fight, Agility} +-- update the stats to the provided values +---@param newStats Table Contains the new values for the stats: {Willpower, Intellect, Fight, Agility} function updateStats(newStats) if newStats and #newStats == 4 then stats = newStats + + for i = 1, 4 do updateButtonLabel(i) end elseif newStats then printToAll("Provided new stats are incomplete or incorrectly formatted.", "Red") - return end - - for i = 1, 4 do changeButton(i) end end From 04d9878fd1e1cf96e6c62fa0a87a5f97a39277ff Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Wed, 10 Jan 2024 20:20:06 +0100 Subject: [PATCH 5/5] added camera movement to swapping --- src/core/GameKeyHandler.ttslua | 5 ++-- src/core/NavigationOverlayApi.ttslua | 10 ++++++++ src/core/NavigationOverlayHandler.ttslua | 29 ++++++++++++++++++++---- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/core/GameKeyHandler.ttslua b/src/core/GameKeyHandler.ttslua index cc64d9f1..8dcb4528 100644 --- a/src/core/GameKeyHandler.ttslua +++ b/src/core/GameKeyHandler.ttslua @@ -1,5 +1,6 @@ local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi") local guidReferenceApi = require("core/GUIDReferenceApi") +local navigationOverlayApi = require("core/NavigationOverlayApi") local optionPanelApi = require("core/OptionPanelApi") local playmatApi = require("playermat/PlaymatApi") local searchLib = require("util/SearchLib") @@ -252,9 +253,7 @@ function switchSeat(playerColor, direction) end -- swap color - local newMatColor = usedColors[index] - local newHandColor = playmatApi.getMatColorByPosition(Player[newMatColor].getHandTransform().position) - Player[playerColor].changeColor(newHandColor) + navigationOverlayApi.loadCamera(playerColor, usedColors[index]) end -- takes a clue from a location, player needs to hover the clue directly or the location diff --git a/src/core/NavigationOverlayApi.ttslua b/src/core/NavigationOverlayApi.ttslua index a39b0879..9a94d04e 100644 --- a/src/core/NavigationOverlayApi.ttslua +++ b/src/core/NavigationOverlayApi.ttslua @@ -22,5 +22,15 @@ do getNOHandler().call("cycleVisibility", playerColor) end + -- loads the specified camera for a player + ---@param player TTSPlayerInstance Player whose camera should be moved + ---@param camera Variant If number: Index of the camera view to load | If string: Color of the playermat to swap to + NavigationOverlayApi.loadCamera = function(playerColor, camera) + getNOHandler().call("loadCameraFromApi", { + playerColor = playerColor, + camera = camera + }) + end + return NavigationOverlayApi end diff --git a/src/core/NavigationOverlayHandler.ttslua b/src/core/NavigationOverlayHandler.ttslua index 6283a815..55f2de16 100644 --- a/src/core/NavigationOverlayHandler.ttslua +++ b/src/core/NavigationOverlayHandler.ttslua @@ -291,9 +291,30 @@ function getDynamicViewBounds(objList) return totalBounds end +function loadCameraFromApi(params) + loadCamera(Player[params.playerColor], params.camera) +end + -- loads the specified camera for a player -function loadCamera(player, index) - local lookHere +---@param player TTSPlayerInstance Player whose camera should be moved +---@param camera Variant If number: Index of the camera view to load | If string: Color of the playermat to swap to +function loadCamera(player, camera) + local lookHere, index, matColor + local matColorList = { "White", "Orange", "Green", "Red" } + local indexList = { + White = 3, + Orange = 4, + Green = 5, + Red = 6 + } + + if tonumber(camera) then + index = tonumber(camera) + matColor = matColorList[index - 2] -- mat index 1 - 4 + else + index = indexList[camera] + matColor = camera + end -- dynamic view of the play area if index == 2 then @@ -307,9 +328,6 @@ function loadCamera(player, index) } -- dynamic view of the clicked play mat elseif index >= 3 and index <= 6 then - local matColorList = { "White", "Orange", "Green", "Red" } - local matColor = matColorList[index - 2] -- mat index 1 - 4 - -- check if anyone (except for yourself) has claimed this color local isClaimed = false @@ -325,6 +343,7 @@ function loadCamera(player, index) local newPlayerColor = playmatApi.getPlayerColor(matColor) copyVisibility({ startColor = player.color, targetColor = newPlayerColor }) player.changeColor(newPlayerColor) + player = Player[newPlayerColor] end -- search on the playmat for objects