diff --git a/Helper.lsl b/Helper.lsl new file mode 100644 index 0000000..f9fac58 --- /dev/null +++ b/Helper.lsl @@ -0,0 +1,131 @@ +// === Game Helper Functions Module === + +integer MSG_GET_DICE_TYPE = 1001; +integer MSG_DICE_TYPE_RESULT = 1005; +integer MSG_GET_PICKS_REQUIRED = 1002; +integer MSG_GET_PICKER_INDEX = 1003; +integer MSG_SERIALIZE_GAME_STATE = 1004; +integer MSG_SYNC_GAME_STATE = 107; +integer MSG_SYNC_PICKQUEUE = 2001; + +list lives; +list picksData; +string perilPlayer; +list names; +list pickQueue; + +integer getDiceType(integer playerCount) { + if (playerCount < 1) return 2; + return (integer)(llPow(3.0, (float)(playerCount - 1)) * 2.0); +} + +integer getPicksRequiredFromName(string name) { + integer idx = llListFindList(names, [name]); + if (idx == -1) { + integer i; + for (i = 0; i < llGetListLength(names); i++) { + string testName = llList2String(names, i); + if (llSubStringIndex(testName, name) != -1) { + idx = i; + i = llGetListLength(names); + } + } + } + if (idx == -1) return 0; + integer lifeCount = (integer)llList2String(lives, idx); + if (lifeCount >= 3) return 1; + if (lifeCount == 2) return 2; + return 3; +} + +integer getPickerIndex(string name) { + return llListFindList(pickQueue, [name]); +} + +string serializeGameState() { + return llList2CSV(lives) + "~" + llList2CSV(picksData) + "~" + perilPlayer + "~" + llList2CSV(names); +} + +showPickManager(string player, key id) { + string searchName = player; + if (llSubStringIndex(searchName, "~") != -1) { + list parts = llParseString2List(searchName, ["~"], []); + searchName = llList2String(parts, 1); + } + + integer idx = llListFindList(names, [searchName]); + if (idx == -1) { + integer i; + for (i = 0; i < llGetListLength(names); i++) { + string testName = llList2String(names, i); + if (llSubStringIndex(testName, searchName) != -1) { + idx = i; + llOwnerSay("✅ Matched pick list for: " + testName); + i = llGetListLength(names); + } + } + if (idx == -1) { + llOwnerSay("⚠️ Could not find player: " + player); + return; + } + } + + integer maxPicks = getPicksRequiredFromName(llList2String(names, idx)); + + string currentData = llList2String(picksData, idx); + list parts = llParseString2List(currentData, ["|"], []); + list currentPicks = []; + if (llGetListLength(parts) > 1) { + currentPicks = llParseString2List(llList2String(parts, 1), [","], []); + } + + list buttons = []; + integer i; + for (i = 1; i <= 6; i++) { + string numStr = (string)i; + if (llListFindList(currentPicks, [numStr]) != -1) { + buttons += ["❌ " + numStr]; + } else if (llGetListLength(currentPicks) < maxPicks) { + buttons += ["➕ " + numStr]; + } + } + + llOwnerSay("🛠 Showing pick dialog to: " + (string)id); + llDialog(id, "🛠 Managing picks for: " + searchName + "\nCurrent: " + llList2CSV(currentPicks), buttons, -88888); +} + +default { + link_message(integer sender, integer num, string str, key id) { + if (num == MSG_SYNC_GAME_STATE) { + list parts = llParseString2List(str, ["~"], []); + lives = llCSV2List(llList2String(parts, 0)); + picksData = llCSV2List(llList2String(parts, 1)); + perilPlayer = llList2String(parts, 2); + names = llCSV2List(llList2String(parts, 3)); + } + else if (num == MSG_SYNC_PICKQUEUE) { + pickQueue = llCSV2List(str); + } + else if (num == MSG_GET_DICE_TYPE) { + integer playerCount = (integer)str; + llOwnerSay("📊 playerCount received: " + (string)playerCount); + integer result = getDiceType(playerCount); + llMessageLinked(LINK_THIS, MSG_DICE_TYPE_RESULT, (string)result, NULL_KEY); + } + else if (num == MSG_GET_PICKS_REQUIRED) { + integer result = getPicksRequiredFromName(str); + llMessageLinked(LINK_THIS, MSG_GET_PICKS_REQUIRED, (string)result, NULL_KEY); + } + else if (num == MSG_GET_PICKER_INDEX) { + integer result = getPickerIndex(str); + llMessageLinked(LINK_THIS, MSG_GET_PICKER_INDEX, (string)result, NULL_KEY); + } + else if (num == MSG_SERIALIZE_GAME_STATE) { + llMessageLinked(LINK_THIS, MSG_SERIALIZE_GAME_STATE, serializeGameState(), NULL_KEY); + } + else if (num == 206) { + llOwnerSay("📨 MSG 206 received for: " + str + " from: " + (string)id); + showPickManager(str, id); + } + } +} diff --git a/Main.lsl b/Main.lsl new file mode 100644 index 0000000..8646d2d --- /dev/null +++ b/Main.lsl @@ -0,0 +1,254 @@ +// === Main Peril Dice Controller (Refactored with Game Helpers Integration) === + +// --- Variables --- + +integer syncChannel = -77777; +integer numberPickChannel = -77888; +integer rollDialogChannel = -77999; +integer DIALOG_CHANNEL = -88888; + +list players = []; +list names = []; +list lives = []; +string perilPlayer = ""; +list globalPickedNumbers = []; +list picksData = []; +list readyPlayers = []; + +list pickQueue = []; +integer currentPickerIdx = 0; +integer diceType = 6; + +integer MSG_SHOW_DIALOG = 101; +integer MSG_ROLL_RESULT = 102; +integer MSG_UPDATE_FLOAT = 103; +integer MSG_CLEANUP_FLOAT = 104; +integer MSG_REZ_FLOAT = 105; +integer MSG_REGISTER_PLAYER = 106; +integer MSG_SYNC_GAME_STATE = 107; +integer MSG_SHOW_MENU = 201; +integer MSG_SHOW_ROLL_DIALOG = 301; + +integer MSG_GET_DICE_TYPE = 1001; +integer MSG_GET_PICKS_REQUIRED = 1002; +integer MSG_GET_PICKER_INDEX = 1003; +integer MSG_DICE_TYPE_RESULT = 1005; +integer MSG_SERIALIZE_GAME_STATE = 1004; +integer MSG_SYNC_PICKQUEUE = 2001; + +integer TIMEOUT_SECONDS = 600; +integer timeoutTimer; + +integer warning2min = 120; +integer warning5min = 300; +integer warning9min = 540; +integer lastWarning = 0; + +key currentPicker; + +// Forward game state to helpers when it changes +updateHelpers() { + string serialized = llList2CSV(lives) + "~" + llList2CSV(picksData) + "~" + perilPlayer + "~" + llList2CSV(names); + llMessageLinked(LINK_SET, MSG_SYNC_GAME_STATE, serialized, NULL_KEY); + llMessageLinked(LINK_SET, MSG_SYNC_PICKQUEUE, llList2CSV(pickQueue), NULL_KEY); +} + +// Request helper-calculated values +requestDiceType() { + llMessageLinked(LINK_SET, MSG_GET_DICE_TYPE, (string)llGetListLength(names), NULL_KEY); +} + +requestPicksRequired(integer idx) { + llMessageLinked(LINK_SET, MSG_GET_PICKS_REQUIRED, llList2String(names, idx), NULL_KEY); +} + +requestPickerIndex(string name) { + llMessageLinked(LINK_SET, MSG_GET_PICKER_INDEX, name, NULL_KEY); +} + +string generateSerializedState() { + return llList2CSV(lives) + "~" + llList2CSV(picksData) + "~" + perilPlayer + "~" + llList2CSV(names); +} + +resetGame() { + integer i; + for (i = 0; i < llGetListLength(names); i++) { + integer ch = -777000 + i; + llMessageLinked(LINK_SET, MSG_CLEANUP_FLOAT, (string)ch, NULL_KEY); + } + players = names = lives = picksData = globalPickedNumbers = []; + perilPlayer = ""; + pickQueue = []; + currentPickerIdx = 0; + llSay(syncChannel, "RESET"); + llOwnerSay("🔄 Game reset!"); + llSleep(0.2); + llSetTimerEvent(0); + updateHelpers(); +} + +startNextRound() { + if (llGetListLength(names) == 1) { + llSay(0, "🏆 " + llList2String(names, 0) + " is the last player standing and wins the game!"); + resetGame(); + return; + } + + picksData = []; + globalPickedNumbers = []; + pickQueue = names; + currentPickerIdx = 0; + + integer j; + for (j = 0; j < llGetListLength(names); j++) { + picksData += [llList2String(names, j) + "|"]; + } + + updateHelpers(); + // requestDiceType(); // Removed to avoid recursion loop +} + +showNextPickerDialog() { + string firstName = llList2String(pickQueue, currentPickerIdx); + currentPicker = llList2Key(players, llListFindList(names, [firstName])); + string dialogPayload = firstName + "|" + (string)diceType; + llMessageLinked(LINK_SET, MSG_SHOW_DIALOG, dialogPayload, currentPicker); + timeoutTimer = llGetUnixTime(); + lastWarning = 0; + llSetTimerEvent(60.0); +} + +integer roundStarted = FALSE; + +default { + state_entry() { + llListen(DIALOG_CHANNEL, "", NULL_KEY, ""); + } + + touch_start(integer total_number) { + llOwnerSay("Touched by: " + (string)llDetectedKey(0)); + key toucher = llDetectedKey(0); + integer idx = llListFindList(players, [toucher]); + if (toucher == llGetOwner()) { + llMessageLinked(LINK_SET, MSG_SHOW_MENU, "owner|0", toucher); + } else if (idx != -1) { + integer isStarter = (idx == 0); + llMessageLinked(LINK_SET, MSG_SHOW_MENU, "player|" + (string)isStarter, toucher); + } + } + + link_message(integer sender, integer num, string str, key id) { + if (num == 202 && str == "REQUEST_PLAYER_LIST") { + string namesCSV = llList2CSV(names); + llMessageLinked(LINK_SET, 203, namesCSV, id); + return; + } + if (num == 206) { + string targetName = str; + integer i; + for (i = 0; i < llGetListLength(picksData); i++) { + string rawEntry = llList2String(picksData, i); + list parts = llParseString2List(rawEntry, ["|"], []); + if (llList2String(parts, 0) == targetName) { + llMessageLinked(LINK_SET, 205, targetName + "|" + llList2String(parts, 1), id); + return; + } + } + llMessageLinked(LINK_SET, 205, targetName + "|", id); + return; + } + if (num == 208) { + string playerName = str; + integer idx = llListFindList(names, [playerName]); + if (idx != -1) { + string lifeVal = llList2String(lives, idx); + llMessageLinked(LINK_SET, 208, playerName + "|" + lifeVal, id); + } + return; + } + if (num == MSG_DICE_TYPE_RESULT) { + if (!roundStarted) { + roundStarted = TRUE; + diceType = (integer)str; + llOwnerSay("🎲 Dice type set to: " + str); + showNextPickerDialog(); + } + } + else if (num == MSG_GET_PICKS_REQUIRED) { + integer picksRequired = (integer)str; + llOwnerSay("📌 Picks required: " + str); + } else if (num == MSG_GET_PICKER_INDEX) { + integer pickIndex = (integer)str; + llOwnerSay("🔍 Picker index: " + str); + } else if (num == MSG_SERIALIZE_GAME_STATE) { + string serialized = str; + llOwnerSay("🧾 Serialized game state: " + serialized); + } else if (num == 204) { + list parts = llParseString2List(str, ["~"], []); + string action = llList2String(parts, 0); + list args = llParseString2List(llList2String(parts, 1), ["|"], []); + string name = llList2String(args, 0); + string pick = llList2String(args, 1); + integer i; + for (i = 0; i < llGetListLength(picksData); i++) { + string entry = llList2String(picksData, i); + list pdParts = llParseString2List(entry, ["|"], []); + if (llList2String(pdParts, 0) == name) { + list pickList = []; + string rawPicks = llList2String(pdParts, 1); + if (rawPicks != "") { + pickList = llParseString2List(rawPicks, [","], []); + } + if (action == "ADD_PICK") { + if (llListFindList(pickList, [pick]) == -1) { + pickList += [pick]; + llOwnerSay("➕ Added " + pick + " to " + name); + } + } else if (action == "REMOVE_PICK") { + integer idx = llListFindList(pickList, [pick]); + if (idx != -1) { + pickList = llDeleteSubList(pickList, idx, idx); + llOwnerSay("➖ Removed " + pick + " from " + name); + } + } + picksData = llListReplaceList(picksData, [name + "|" + llList2CSV(pickList)], i, i); + updateHelpers(); + return; + } + } + } + } + + listen(integer channel, string name, key id, string msg) { + if (channel == DIALOG_CHANNEL) { + if (id == llGetOwner()) { + if (msg == "Reset Game") { + resetGame(); + } else if (msg == "Start Game") { + startNextRound(); + requestDiceType(); + } else if (msg == "Dump Players") { + llOwnerSay("📋 Players: " + llList2CSV(names)); + } else if (msg == "Manage Picks") { + llOwnerSay("📋 Fetching list of players for pick management..."); + llMessageLinked(LINK_SET, 202, "REQUEST_PLAYER_LIST", llGetOwner()); + } else if (msg == "Add Test Player") { + string name = "TestBot" + (string)llGetUnixTime(); + key fake = llGenerateKey(); + players += [fake]; + names += [name]; + lives += [3]; + picksData += [name + "|"]; + llMessageLinked(LINK_SET, MSG_REGISTER_PLAYER, name + "|" + (string)fake, NULL_KEY); + llMessageLinked(LINK_SET, MSG_REZ_FLOAT, name, fake); + llSleep(0.2); + updateHelpers(); + llMessageLinked(LINK_SET, MSG_SHOW_MENU, "owner|0", llGetOwner()); + } + } + if (llListFindList(names, [msg]) != -1) { + llMessageLinked(LINK_SET, 206, msg, id); + } + } + } +} diff --git a/DialogHandler.lsl b/Number Picker Dialog Handler.lsl similarity index 100% rename from DialogHandler.lsl rename to Number Picker Dialog Handler.lsl diff --git a/Owner and Player Dialog Handler.lsl b/Owner and Player Dialog Handler.lsl new file mode 100644 index 0000000..5e51d96 --- /dev/null +++ b/Owner and Player Dialog Handler.lsl @@ -0,0 +1,157 @@ +// === Dialog Handler (Owner & Player) === + +integer DIALOG_CHANNEL = -88888; +integer MSG_SHOW_MENU = 201; +integer MSG_PICK_ACTION = 204; +integer MSG_PLAYER_LIST_RESULT = 203; +integer MSG_PICK_LIST_RESULT = 205; +integer MSG_LIFE_LOOKUP = 207; + +list ownerOptions = ["Join Game", "Leave Game", "Add Test Player", "Manage Picks", "Start Game", "Reset Game", "Dump Players"]; +list playerOptions = ["Start", "Ready"]; + +list currentPickList; +string currentPickTarget; +integer currentPickLimit = 3; + +showOwnerMenu(key id) { + llDialog(id, "🔧 Debug Menu", ownerOptions, DIALOG_CHANNEL); +} + +showPlayerMenu(key id, integer isStarter) { + if (isStarter) { + llDialog(id, "You are the game starter. Click Start to begin when all are ready.", playerOptions, DIALOG_CHANNEL); + } else { + llDialog(id, "Click Ready when you are ready to begin.", ["Ready"], DIALOG_CHANNEL); + } +} + +showPickManageMenu(key id, list playerNames) { + list options = []; + integer i; + for (i = 0; i < llGetListLength(playerNames); i++) { + string pname = llList2String(playerNames, i); + options += ["🛠 " + pname]; + } + options += ["⬅️ Back"]; + llDialog(id, "📋 Manage Picks for: ", options, DIALOG_CHANNEL); +} + +showPickListMenu(key id) { + list options = []; + integer i; + for (i = 0; i < llGetListLength(currentPickList); i++) { + string pick = llList2String(currentPickList, i); + if (llStringLength(pick) > 0) { + options += ["REMOVE: " + pick]; + } + } + options += ["Add Pick", "⬅️ Back"]; + llDialog(id, "🛠 Picks for: " + currentPickTarget, options, DIALOG_CHANNEL); +} + +askForNewPick(key id) { + llTextBox(id, "🔢 Enter a number to add for " + currentPickTarget + ":", DIALOG_CHANNEL); +} + +default { + state_entry() { + llListen(DIALOG_CHANNEL, "", NULL_KEY, ""); + } + + link_message(integer sender, integer num, string str, key id) { + if (num == MSG_SHOW_MENU) { + llOwnerSay("📨 Received MSG_SHOW_MENU with: " + str); + list args = llParseString2List(str, ["|"], []); + if (llGetListLength(args) < 2) { + llOwnerSay("⚠️ Invalid message format: " + str); + return; + } + string targetType = llList2String(args, 0); + integer isStarter = (integer)llList2String(args, 1); + + if (targetType == "owner") { + llOwnerSay("👤 Showing owner menu"); + showOwnerMenu(id); + } else if (targetType == "player") { + llOwnerSay("👥 Showing player menu"); + showPlayerMenu(id, isStarter); + } + } + else if (num == MSG_PLAYER_LIST_RESULT) { + list playerNames = llParseString2List(str, [","], []); + llOwnerSay("📋 Fetching list of players for pick management..."); + showPickManageMenu(id, playerNames); + } + else if (num == MSG_PICK_LIST_RESULT) { + list parts = llParseString2List(str, ["|"], []); + string returnedName = llList2String(parts, 0); + string picks = llList2String(parts, 1); + if (llStringTrim(returnedName, STRING_TRIM) == llStringTrim(currentPickTarget, STRING_TRIM)) { + llOwnerSay("✅ Matched pick list for: " + returnedName); + currentPickList = llCSV2List(picks); + llMessageLinked(LINK_THIS, MSG_LIFE_LOOKUP, currentPickTarget, id); + } else { + llOwnerSay("❌ Name mismatch: got " + returnedName + " but expected " + currentPickTarget); + } + } + else if (num == MSG_LIFE_LOOKUP) { + list parts = llParseString2List(str, ["|"], []); + if (llList2String(parts, 0) == currentPickTarget) { + currentPickLimit = (integer)llList2String(parts, 1); + showPickListMenu(id); + } + } + } + + listen(integer channel, string name, key id, string msg) { + if (msg == "Manage Picks") { + llMessageLinked(LINK_THIS, 202, "REQUEST_PLAYER_LIST", id); + } + else if (llSubStringIndex(msg, "🛠 ") == 0) { + currentPickTarget = llStringTrim(llDeleteSubString(msg, 0, 1), STRING_TRIM); + llOwnerSay("🎯 Pick target set to: " + currentPickTarget); + currentPickList = []; + llMessageLinked(LINK_THIS, 206, currentPickTarget, id); + } + else if (msg == "Add Pick") { + askForNewPick(id); + } + else if (msg == "⬅️ Back") { + llMessageLinked(LINK_THIS, 202, "REQUEST_PLAYER_LIST", id); + } + else if (llSubStringIndex(msg, "REMOVE: ") == 0) { + string pick = llGetSubString(msg, 8, -1); + string payload = "REMOVE_PICK~" + currentPickTarget + "|" + pick; + llMessageLinked(LINK_THIS, MSG_PICK_ACTION, payload, id); + llSleep(0.2); + llMessageLinked(LINK_THIS, 206, currentPickTarget, id); + } + else if ((integer)msg > 0) { + if (llGetListLength(currentPickList) >= currentPickLimit) { + llOwnerSay("⚠️ Reached pick limit of " + (string)currentPickLimit + " for " + currentPickTarget); + showPickListMenu(id); + return; + } + + if (llListFindList(currentPickList, [msg]) != -1) { + llOwnerSay("⚠️ Pick already exists: " + msg); + showPickListMenu(id); + return; + } + + integer i; + for (i = 0; i < llGetListLength(currentPickList); i++) { + if (llList2String(currentPickList, i) == msg) { + llOwnerSay("⚠️ Duplicate pick detected."); + return; + } + } + + string payload = "ADD_PICK~" + currentPickTarget + "|" + msg; + llMessageLinked(LINK_THIS, MSG_PICK_ACTION, payload, id); + llSleep(0.2); + llMessageLinked(LINK_THIS, 206, currentPickTarget, id); + } + } +} diff --git a/PerilController.lsl b/PerilController.lsl deleted file mode 100644 index 0c8100b..0000000 --- a/PerilController.lsl +++ /dev/null @@ -1,177 +0,0 @@ -// === Main Peril Dice Controller (Modular) === - -integer syncChannel = -77777; -integer numberPickChannel = -77888; - -list players = []; -list names = []; -list lives = []; -string perilPlayer = ""; -list globalPickedNumbers = []; -list picksData = []; - -list pickQueue = []; -integer currentPickerIdx = 0; -integer diceType = 6; - -integer MSG_SHOW_DIALOG = 101; -integer MSG_ROLL_RESULT = 102; -integer MSG_UPDATE_FLOAT = 103; -integer MSG_CLEANUP_FLOAT = 104; -integer MSG_REZ_FLOAT = 105; -integer MSG_REGISTER_PLAYER = 106; -integer MSG_SYNC_GAME_STATE = 107; - -integer getDiceType(integer playerCount) { - return ((playerCount + 1) / 2) * 6; -} - -integer getPicksRequired(integer lifeCount) { - if (lifeCount == 3) return 1; - if (lifeCount == 2) return 2; - return 3; -} - -string serializeGameState() { - return llList2CSV(lives) + "~" + llList2CSV(picksData) + "~" + perilPlayer + "~" + llList2CSV(names); -} - -resetGame() { - string gameSync; - integer i; - for (i = 0; i < llGetListLength(names); i++) { - integer ch = -777000 + i; - llMessageLinked(LINK_SET, MSG_CLEANUP_FLOAT, (string)ch, NULL_KEY); - } - players = names = lives = picksData = globalPickedNumbers = []; - perilPlayer = ""; - pickQueue = []; - currentPickerIdx = 0; - llSay(syncChannel, "RESET"); - llOwnerSay("🔄 Game reset!"); - llSleep(0.2); -} - -default { - state_entry() { - llListen(0, "", NULL_KEY, ""); - llListen(syncChannel, "", NULL_KEY, ""); - llListen(numberPickChannel, "", NULL_KEY, ""); - llListen(-88888, "", NULL_KEY, ""); - llOwnerSay("🎲 Modular Peril Controller Ready"); - } - - touch_start(integer total_number) { - key toucher = llDetectedKey(0); - string name = llDetectedName(0); - integer idx = llListFindList(players, [toucher]); - if (~idx) { - llDialog(toucher, "❓ You are already in the game. Leave the game?", ["Yes", "No"], -88888); - return; - } - - players += [toucher]; - names += [name]; - lives += [3]; - picksData += [name + "|0"]; // Initialize pick with default "0" - llOwnerSay("✅ " + name + " has joined the game with 3 lives."); - llMessageLinked(LINK_SET, MSG_REGISTER_PLAYER, name + "|" + (string)toucher, NULL_KEY); - llMessageLinked(LINK_SET, MSG_REZ_FLOAT, name, toucher); - llSleep(0.2); - string gameSync = serializeGameState(); - llMessageLinked(LINK_SET, MSG_SYNC_GAME_STATE, gameSync, NULL_KEY); - llSleep(0.2); - llMessageLinked(LINK_SET, MSG_UPDATE_FLOAT, name, toucher); - } - - listen(integer chan, string speakerName, key id, string msg) { - string gameSync; - - if (chan == -88888 && msg == "Yes") { - integer i = llListFindList(players, [id]); - if (i != -1) { - integer ch = -777000 + i; - llMessageLinked(LINK_SET, MSG_CLEANUP_FLOAT, (string)ch, NULL_KEY); - players = llDeleteSubList(players, i, i); - names = llDeleteSubList(names, i, i); - lives = llDeleteSubList(lives, i, i); - picksData = llDeleteSubList(picksData, i, i); - globalPickedNumbers = llDeleteSubList(globalPickedNumbers, i, i); - llOwnerSay("👋 Player left the game: " + llKey2Name(id)); - gameSync = serializeGameState(); - llMessageLinked(LINK_SET, MSG_SYNC_GAME_STATE, gameSync, NULL_KEY); - llSleep(0.2); - } - } - else if (chan == 0 && llToLower(msg) == "/reset" && id == llGetOwner()) { - resetGame(); - } - else if (chan == 0 && llToLower(msg) == "/start" && id == llGetOwner()) { - if (llGetListLength(names) == 0) { - llOwnerSay("⚠️ No players to choose from."); - return; - } - integer r = (integer)llFrand(llGetListLength(names)); - perilPlayer = llList2String(names, r); - picksData = []; - integer j; - for (j = 0; j < llGetListLength(names); j++) { - picksData += [llList2String(names, j) + "|0"]; // Initialize picks with default "0" - } - globalPickedNumbers = []; - diceType = getDiceType(llGetListLength(names)); - pickQueue = names; - currentPickerIdx = 0; - - llSay(syncChannel, "PERIL:" + perilPlayer); - llOwnerSay("🔥 Peril player is: " + perilPlayer); - gameSync = serializeGameState(); - llMessageLinked(LINK_SET, MSG_SYNC_GAME_STATE, gameSync, NULL_KEY); - llSleep(0.2); - - for (j = 0; j < llGetListLength(names); j++) { - llMessageLinked(LINK_SET, MSG_UPDATE_FLOAT, llList2String(names, j), llList2Key(players, j)); - } - - string firstName = llList2String(pickQueue, currentPickerIdx); - key firstKey = llList2Key(players, llListFindList(names, [firstName])); - llMessageLinked(LINK_SET, MSG_SHOW_DIALOG, firstName + "|" + (string)diceType, firstKey); - gameSync = serializeGameState(); - llMessageLinked(LINK_SET, MSG_SYNC_GAME_STATE, gameSync, NULL_KEY); - } - else if (chan == numberPickChannel) { - integer idx = llListFindList(players, [id]); - string playerName = ""; - if (idx != -1) { - playerName = llList2String(names, idx); - string newPick = msg; - integer i; - for (i = 0; i < llGetListLength(picksData); i++) { - string entry = llList2String(picksData, i); - if (llSubStringIndex(entry, playerName + "|") == 0) { - list parts = llParseString2List(entry, ["|"], []); - string pickStr = llList2String(parts, 1); - llOwnerSay("🔍 Existing pick for " + playerName + ": " + pickStr); - - // If the pick is still "0", update it with the new pick - if (pickStr == "0") { - pickStr = newPick; - } else { - pickStr = newPick; // Replacing rather than appending - } - picksData = llListReplaceList(picksData, [playerName + "|" + pickStr], i, i); - llOwnerSay("✅ " + playerName + "'s pick updated to: " + newPick); - - // Immediately send updated data to floats - gameSync = serializeGameState(); - llMessageLinked(LINK_SET, MSG_SYNC_GAME_STATE, gameSync, NULL_KEY); - - // Update the float - llMessageLinked(LINK_SET, MSG_UPDATE_FLOAT, playerName, id); - return; - } - } - } - } - } -} diff --git a/RollConfettiModule.lsl b/Roll Confetti Module.lsl similarity index 82% rename from RollConfettiModule.lsl rename to Roll Confetti Module.lsl index d8ca2f6..043a358 100644 --- a/RollConfettiModule.lsl +++ b/Roll Confetti Module.lsl @@ -1,10 +1,14 @@ -// === Roll and Confetti Module === +// === Roll and Confetti Module (with Roll Dialog Handler) === + integer MSG_SHOW_DIALOG = 101; integer MSG_ROLL_RESULT = 102; integer MSG_UPDATE_FLOAT = 103; integer MSG_CLEANUP_FLOAT = 104; integer MSG_REZ_FLOAT = 105; integer MSG_SYNC_GAME_STATE = 107; +integer MSG_SHOW_ROLL_DIALOG = 301; + +integer rollDialogChannel = -77999; list names = []; list lives = []; @@ -23,7 +27,6 @@ list getPicksFor(string nameInput) { return []; } - integer rollDice(integer diceType) { return 1 + (integer)llFrand(diceType); } @@ -44,8 +47,17 @@ confetti() { } default { + state_entry() { + llListen(rollDialogChannel, "", NULL_KEY, ""); + } + link_message(integer sender, integer num, string str, key id) { - if (num == MSG_ROLL_RESULT) { + if (num == MSG_SHOW_ROLL_DIALOG) { + llOwnerSay("🎲 Prompting " + str + " to roll the dice."); + llDialog(id, "🎲 All picks are in! You're the peril player. Roll the dice?", ["Roll"], rollDialogChannel); + } + + else if (num == MSG_ROLL_RESULT) { integer diceType = (integer)str; integer result = rollDice(diceType); string resultStr = (string)result; @@ -80,10 +92,13 @@ default { } } - // Send updated game state to floats - string gameSync = llList2CSV(lives) + "~" + llList2CSV(picksData) + "~" + perilPlayer; + string gameSync = llList2CSV(lives) + "~" + llList2CSV(picksData) + "~" + perilPlayer + "~" + llList2CSV(names); llMessageLinked(LINK_SET, MSG_SYNC_GAME_STATE, gameSync, NULL_KEY); llSleep(0.2); } } + + listen(integer channel, string name, key id, string msg) { + llMessageLinked(LINK_THIS, channel, msg, id); + } } diff --git a/peril_game_flowchart.png b/peril_game_flowchart.png deleted file mode 100644 index e3aebb2..0000000 Binary files a/peril_game_flowchart.png and /dev/null differ