From f8d711d3c1dbdd982adc26438abfe1ac9e2dd7bd Mon Sep 17 00:00:00 2001 From: RebeccaNod1 Date: Tue, 5 Aug 2025 21:58:20 -0500 Subject: [PATCH] ## [2.3.0] - 2025-08-05 --- Bot Manager.lsl | 19 + CHANGELOG.md | 52 ++ Debugger.lsl | 7 + Floater Manager.lsl | 34 +- Game_Scoreboard_Manager.lsl | 727 ++++++++++++++++++++++++++++ Helper.lsl | 12 + Leaderboard_Bridge.lsl | 56 +++ Leaderboard_Manager.lsl | 253 ++++++++++ Main.lsl | 331 +++++++++++-- Number Picker Dialog Handler.lsl | 45 +- Owner and Player Dialog Handler.lsl | 75 ++- README.md | 49 +- Roll Confetti Module.lsl | 42 ++ StatFloat.lsl | 52 +- XyzzyText_Debug.lsl | 88 ++++ images/title.png | Bin 0 -> 194577 bytes xytext_master.lsl | 611 +++++++++++++++++++++++ xytext_master_clean.lsl | 521 ++++++++++++++++++++ xytext_master_with_listener.lsl | 540 +++++++++++++++++++++ xytext_slave.lsl | 281 +++++++++++ 20 files changed, 3736 insertions(+), 59 deletions(-) create mode 100644 Game_Scoreboard_Manager.lsl create mode 100644 Leaderboard_Bridge.lsl create mode 100644 Leaderboard_Manager.lsl create mode 100644 XyzzyText_Debug.lsl create mode 100644 images/title.png create mode 100644 xytext_master.lsl create mode 100644 xytext_master_clean.lsl create mode 100644 xytext_master_with_listener.lsl create mode 100644 xytext_slave.lsl diff --git a/Bot Manager.lsl b/Bot Manager.lsl index 97d03e8..3a0eccc 100644 --- a/Bot Manager.lsl +++ b/Bot Manager.lsl @@ -5,6 +5,9 @@ integer LISTEN_CHANNEL = -9999; // Change if needed to match main controller integer MSG_SYNC_GAME_STATE = 107; +// Bot timing configuration to prevent dialog system overload +float BOT_RESPONSE_DELAY = 1.5; // Delay before bot responds to commands + // Track game state to validate bot commands list names = []; list lives = []; @@ -56,6 +59,9 @@ doBotPick(string botName, integer count, integer diceMax, list avoidNumbers) { llOwnerSay("[Bot Manager] āš ļø WARNING: " + botName + " only picked " + (string)llGetListLength(picks) + "/" + (string)count + " numbers after " + (string)attempts + " attempts"); } + // Add delay before responding to prevent dialog system overload + llSleep(BOT_RESPONSE_DELAY); + string pickString = llDumpList2String(picks, ";"); string response = "BOT_PICKED:" + botName + ":" + pickString; llMessageLinked(LINK_SET, -9997, response, NULL_KEY); @@ -81,6 +87,9 @@ doBotRoll(string botName, integer diceMax) { return; } + // Add delay before rolling to prevent dialog system overload + llSleep(BOT_RESPONSE_DELAY); + integer roll = 1 + (integer)(llFrand((float)diceMax)); llRegionSay(LISTEN_CHANNEL, "BOT_ROLL:" + botName + ":" + (string)roll); } @@ -94,6 +103,16 @@ default { } link_message(integer sender, integer num, string str, key id) { + // Handle full reset from main controller + if (num == -99999 && str == "FULL_RESET") { + // Reset bot manager state + names = []; + lives = []; + perilPlayer = ""; + llOwnerSay("[Bot Manager] Reset complete!"); + return; + } + // Handle game state sync to track player eliminations if (num == MSG_SYNC_GAME_STATE) { list parts = llParseString2List(str, ["~"], []); diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d3fc74..4026d28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,58 @@ # Changelog All notable changes to Peril Dice will be documented in this file. +## [2.3.0] - 2025-08-05 + + +### šŸ† Visual Scoreboard System +- **Dynamic Player Grid**: Real-time visual scoreboard displaying all players with profile pictures and heart count +- **Profile Picture Integration**: Automatic fetching of Second Life avatar profile pictures via HTTP requests +- **Heart Texture Display**: Visual life representation using custom heart textures (3, 2, 1, 0 hearts) +- **Bot Profile Support**: Special profile texture for TestBot players +- **Immediate Updates**: Hearts update instantly when lives change, before any dialogs appear + +### šŸŽ­ Enhanced Status Display System +- **Visual Status Actions**: Large action prim displaying current game status with custom textures +- **Specific Status Messages**: + - **Direct Hit**: When peril player picks their own rolled number + - **No Shield**: When nobody picks the rolled number + - **Plot Twist**: When peril switches to a new player + - **Elimination**: When a player is eliminated + - **Victory**: When someone wins the game + - **Peril Selected**: When a new peril player is chosen + - **Title**: Default/idle state + +### ⚔ Perfect Status Timing +- **Protected Display Time**: Each status shows for 8 seconds with automatic clearing +- **Strategic Delays**: 2-second delays after status messages prevent overwriting +- **Sequential Flow**: Elimination → 6.4s delay → Victory → 9s delay → Reset +- **Immediate Visual Feedback**: Hearts and status update instantly, delays protect display time + +### šŸŽÆ Comprehensive Leaderboard +- **Persistent Win Tracking**: Player victories saved across game sessions +- **XyzzyText Integration**: Three-prim text display system for leaderboard +- **Automatic Sorting**: Top players by win count with formatted display +- **Separate Reset Options**: Game reset vs. leaderboard reset vs. complete reset + +### šŸŽ® Enhanced User Interface +- **Categorized Owner Menus**: Organized into Game Control, Player Management, Reset Options, etc. +- **Dialog Recovery**: Players can recover lost dialogs by touching the controller +- **Admin Menu Access**: Owner can access admin functions during gameplay +- **Improved Menu Flow**: Streamlined navigation with clear categorization + +### šŸ”§ Technical Improvements +- **Multi-Object Architecture**: Scoreboard and leaderboard as separate linked objects +- **HTTP Profile Fetching**: Robust system for retrieving avatar profile pictures +- **Texture Caching**: Profile pictures cached to avoid repeated HTTP requests +- **Region-Based Communication**: Cross-object messaging using `llRegionSay` +- **Elimination Sequence**: Visual 0-hearts display before player removal + +### šŸ› Critical Fixes +- **Heart Update Timing**: Fixed hearts not updating until after next-turn dialog +- **Victory Overwriting Elimination**: Added proper delay between elimination and victory status +- **Status Message Conflicts**: All status messages now have protective delays +- **Profile Picture Fallbacks**: Proper handling of failed HTTP requests +- **Scoreboard Reset**: Fixed scoreboard not clearing when game resets ## [2.2.0] - 2025-08-04 diff --git a/Debugger.lsl b/Debugger.lsl index 1fd83c3..ec0008d 100644 --- a/Debugger.lsl +++ b/Debugger.lsl @@ -70,6 +70,13 @@ default { } link_message(integer sender, integer num, string str, key id) { + // Handle full reset from main controller + if (num == -99999 && str == "FULL_RESET") { + // Debugger doesn't maintain state, but acknowledge reset + llOwnerSay("šŸ” Debugger reset!"); + return; + } + if (num == MSG_SYNC_GAME_STATE) { list parts = llParseString2List(str, ["~"], []); if (llGetListLength(parts) < 4) { diff --git a/Floater Manager.lsl b/Floater Manager.lsl index 7c52aff..54a6069 100644 --- a/Floater Manager.lsl +++ b/Floater Manager.lsl @@ -73,6 +73,18 @@ default { } link_message(integer sender, integer num, string str, key id) { + // Handle full reset from main controller + if (num == -99999 && str == "FULL_RESET") { + // Reset all game state + players = []; + names = []; + lives = []; + picksData = []; + perilPlayer = ""; + llOwnerSay("šŸ“¦ Floater Manager reset!"); + return; + } + if (num == MSG_REGISTER_PLAYER) { // Enforce the maximum number of players if (llGetListLength(players) >= MAX_PLAYERS) { @@ -85,6 +97,8 @@ default { key avKey = llList2Key(info, 1); names += [name]; players += [avKey]; + lives += [3]; // Initialize with 3 lives for new players + picksData += [name + "|"]; // Initialize with empty picks llSay(0, "šŸ’€ " + name + " has entered the deadly game! Welcome to your potential doom! šŸ’€"); // Immediately rez the float after registration. This ensures the @@ -118,15 +132,21 @@ default { // Real avatars: rez next to the avatar with the standard offset pos = basePos + <1, 0, 1>; } else { - // Test players: space floats apart along the X axis so they don't overlap. - // Each test player gets an additional 0.5m offset based on their index. - // This uses the current prim's position as the base since there's no - // avatar position available. - pos = basePos + <1 + (float)idx * 0.5, 0, 1>; + // Test players: space floats apart and away from the scoreboard/leaderboard area. + // Move them further away (3-5 meters) and spread them out more. + // This prevents them from spawning directly on the leaderboard. + pos = basePos + <-4.0 - (float)idx * 1.0, 2.0 + (float)idx * 0.8, 1>; } integer ch = -777000 + idx; - llSetObjectDesc(name); llRezObject("StatFloat", pos, ZERO_VECTOR, ZERO_ROTATION, ch); + // Wait a moment then set the description + llSleep(0.2); + // Find the rezzed object and set its description + list nearby = llGetObjectDetails(llGetKey(), [OBJECT_POS]); + if (llGetListLength(nearby) > 0) { + // Use llRegionSay to tell the StatFloat its name + llRegionSay(ch, "SET_NAME:" + name); + } // After rezzing, immediately update the float so it displays the // correct lives, picks and peril status. Use the avatar key as // the id to keep the float tied to the player. This ensures that @@ -159,7 +179,7 @@ default { } string picksDisplay = llList2CSV(picks); - string txt = "šŸŽ² Peril Dice\nšŸ‘¤ " + name + "\nā¤ļø Lives: " + (string)lifeCount + "\n" + perilName + "\nšŸ”¢ Picks: " + picksDisplay; + string txt = "šŸŽ² Peril Dice\nšŸ‘¤ " + name + "\nLives: " + (string)lifeCount + "\n" + perilName + "\nšŸ”¢ Picks: " + picksDisplay; llRegionSay(ch, "FLOAT:" + (string)avKey + "|" + txt); } else if (num == MSG_CLEANUP_FLOAT) { diff --git a/Game_Scoreboard_Manager.lsl b/Game_Scoreboard_Manager.lsl new file mode 100644 index 0000000..58574d4 --- /dev/null +++ b/Game_Scoreboard_Manager.lsl @@ -0,0 +1,727 @@ +// Game Scoreboard Manager - Shows current game players in grid layout +// Each player gets a prim showing profile picture + heart texture (lives) + +// Heart texture UUIDs - REPLACE WITH YOUR ACTUAL TEXTURE UUIDs +integer LEADERBOARD_CHANNEL = -12346; +list playerWins = []; // Store wins data for persistent leaderboard +string TEXTURE_0_HEARTS = "7d8ae121-e171-12ae-f5b6-7cc3c0395c7b"; // 0 hearts (dead) +string TEXTURE_1_HEARTS = "6605d25f-8e2d-2870-eb87-77c58cd47fa9"; // 1 heart +string TEXTURE_2_HEARTS = "7ba6cb1e-f384-25a5-8e88-a90bbd7cc041"; // 2 hearts +string TEXTURE_3_HEARTS = "a5d16715-4648-6526-5582-e8068293f792"; // 3 hearts + +// Default textures - REPLACE WITH YOUR ACTUAL TEXTURE UUIDs +string TEXTURE_DEFAULT_PROFILE = "1ce89375-6c3c-3845-26b1-1dc666bc9169"; // Default avatar +string TEXTURE_BOT_PROFILE = "62f31722-04c1-8c29-c236-398543f2a6ae"; // Bot avatar picture +string BLANK_TEXTURE = "5748decc-f629-461c-9a36-a35a221fe21f"; // White texture UUID +string TEXTURE_BACKGROUND = "5748decc-f629-461c-9a36-a35a221fe21f"; // Background texture (blank + black color) +string TEXTURE_ACTIONS = "6aac8dce-1b83-f931-abe3-286f4f2faa29"; // Punishment texture +string TEXTURE_LEADERBOARD = "5748decc-f629-461c-9a36-a35a221fe21f"; // Leaderboard texture + +// Status textures - REPLACE WITH YOUR ACTUAL TEXTURE UUIDs +string TEXTURE_PERIL = "c5676fec-0c85-5567-3dd8-f939234e21d9"; // Elimination texture +string TEXTURE_PERIL_SELECTED = "a53ff601-3c8a-e312-9e0e-f6fa76f6773a"; // Peril Selected texture +string TEXTURE_VICTORY = "ec5bf10e-4970-fb63-e7bf-751e1dc27a8d"; // Victory texture +string TEXTURE_PUNISHMENT = "acfabed0-84ad-bfd1-cdfc-2ada0aeeaa2f"; // Punishment texture (fallback) +string TEXTURE_DIRECT_HIT = "ecd2dba2-3969-6c39-ad59-319747307f55"; // Direct Hit texture +string TEXTURE_NO_SHIELD = "2440174f-e385-44e2-8016-ac34934f11f5"; // No Shield texture +string TEXTURE_PLOT_TWIST = "ec533379-4f7f-8183-e877-e68af703dcce"; // Plot Twist texture +string TEXTURE_TITLE = "624bb7a7-e856-965c-bae8-94d75226c1bc"; // Title texture + +// Player data - used for BOTH current game display AND leaderboard +list playerNames = []; // Current game players for display +list playerLives = []; // Current game player lives +list playerProfiles = []; // Maps to profile texture UUIDs + +// Leaderboard data (persistent - stored in linkset data) +list leaderboardNames = []; // Loaded from linkset data at startup +list leaderboardWins = []; // Loaded from linkset data at startup + +// HTTP tracking +list profileRequests = []; // Track which profile requests belong to which player +list httpRequests = []; // Track HTTP requests for profile pictures + +// Profile picture extraction constants +string profile_key_prefix = "; + + // Profile prim (left side) + vector profilePos = basePos + <-PRIM_OFFSET, 0.0, 0.0>; + integer profilePrimIndex = FIRST_PLAYER_PRIM + (i * 2); // Prims 4, 6, 8, 10... + + // Hearts prim (right side) + vector heartsPos = basePos + ; + integer heartsPrimIndex = FIRST_PLAYER_PRIM + (i * 2) + 1; // Prims 5, 7, 9, 11... + + // Set profile prim properties + if (profilePrimIndex <= totalPrims) { + llOwnerSay("DEBUG: Setting profile prim " + (string)profilePrimIndex + " for player " + (string)i); + llSetLinkPrimitiveParamsFast(profilePrimIndex, [ + PRIM_POSITION, profilePos, + PRIM_ROTATION, <-0.707107, 0.0, 0.0, 0.707107>, // Back to upright portrait rotation + PRIM_SIZE, , // Swap width/height for landscape + PRIM_TEXTURE, ALL_SIDES, TEXTURE_DEFAULT_PROFILE, <1,1,0>, <0,0,0>, 0.0, // All faces + PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0, // Fully opaque white + PRIM_TEXT, "", <1,1,1>, 0.0 + ]); + } else { + llOwnerSay("DEBUG: Skipping profile prim " + (string)profilePrimIndex + " (exceeds total prims)"); + } + + // Set hearts prim properties + if (heartsPrimIndex <= totalPrims) { + llSetLinkPrimitiveParamsFast(heartsPrimIndex, [ + PRIM_POSITION, heartsPos, + PRIM_ROTATION, <-0.7, 0.0, 0.0, 0.7>, // Back to upright portrait rotation + PRIM_SIZE, , // Swap width/height for landscape + PRIM_TEXTURE, ALL_SIDES, TEXTURE_3_HEARTS, <1,1,0>, <0,0,0>, 0.0, // All faces + PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0, // Fully opaque white + PRIM_TEXT, "", <1,1,1>, 0.0 + ]); + } + } +} + +setupUIPrims() { + // Background prim - centered behind the player grid + vector bgPosition = <0.0, 0.04, -1.6>; + llOwnerSay("DEBUG: Setting background prim " + (string)BACKGROUND_PRIM + " to position " + (string)bgPosition); + llSetLinkPrimitiveParamsFast(BACKGROUND_PRIM, [ + PRIM_POSITION, bgPosition, // Behind the board and higher up + PRIM_ROTATION, <0.0, 0.0, -0.04, 1.0>, // No rotation + PRIM_SIZE, , + PRIM_TEXTURE, ALL_SIDES, TEXTURE_BACKGROUND, <1,1,0>, <0,0,0>, 0.0, + PRIM_COLOR, ALL_SIDES, <0.0, 0.0, 0.0>, 1.0, // Black background color + PRIM_TEXT, "", <1,1,1>, 0.0 + ]); + + // Actions/status prim - rectangle above the player grid + llSetLinkPrimitiveParamsFast(ACTIONS_PRIM, [ + PRIM_POSITION, <0.0, 0.01, -0.3>, // Even higher above the grid + PRIM_ROTATION, <0.0, 0.0, -0.04, 1.0>, // No rotation + PRIM_SIZE, , + PRIM_TEXTURE, ALL_SIDES, TEXTURE_TITLE, <1,1,0>, <0,0,0>, 0.0, // Start with title texture + PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0, // White for texture visibility + PRIM_TEXT, "", <0,0,0>, 0.0 // No floating text + ]); + + // Note: Leaderboard is now a separate object + + llOwnerSay("DEBUG: UI prims setup complete"); +} + +// Update actions prim with appropriate status texture +updateActionsPrim(string status) { + string textureToUse = ""; + + if (status == "Elimination") { + textureToUse = TEXTURE_PERIL; + } else if (status == "Victory") { + textureToUse = TEXTURE_VICTORY; + } else if (status == "Punishment") { + textureToUse = TEXTURE_PUNISHMENT; + } else if (status == "Direct Hit") { + textureToUse = TEXTURE_DIRECT_HIT; + } else if (status == "No Shield") { + textureToUse = TEXTURE_NO_SHIELD; + } else if (status == "Peril Selected") { + textureToUse = TEXTURE_PERIL_SELECTED; + } else if (status == "Plot Twist") { + textureToUse = TEXTURE_PLOT_TWIST; + } else if (status == "Title") { + textureToUse = TEXTURE_TITLE; + } else { + llOwnerSay("DEBUG: Unrecognized status '" + status + "' - keeping current texture"); + return; // Don't change texture for unrecognized statuses + } + + llSetLinkPrimitiveParamsFast(ACTIONS_PRIM, [ + PRIM_TEXTURE, ALL_SIDES, textureToUse, <1,1,0>, <0,0,0>, 0.0, + PRIM_TEXT, "", <0,0,0>, 0.0 // Remove existing floating text + ]); +} + +// XyzzyText Communication Constants +integer DISPLAY_STRING = 204000; +integer DISPLAY_EXTENDED = 204001; + +// Generate leaderboard text for triple XyzzyText display (15 characters per line split across 3 prims) +generateLeaderboardText() { + list sortedData = getSortedLeaderboard(); + integer maxDisplay = llGetListLength(sortedData); + if (maxDisplay > 11) maxDisplay = 11; // Show top 11 entries to fit in display + + // Triple prim approach - split lines between left, middle, and right prims + string leftText = "WINS:"; + string middleText = " "; // 5 spaces to align with left prim + string rightText = " "; // 5 spaces to align with left prim + + integer i; + for (i = 0; i < maxDisplay; i++) { + list playerData = llParseString2List(llList2String(sortedData, i), [":"], []); + string playerName = llList2String(playerData, 0); + string winsText = llList2String(playerData, 1); + + // Create 15-character line: "PlayerNameHere Wins" (player name + padding + wins) + // Truncate name to max 12 characters to leave room for wins + if (llStringLength(playerName) > 12) { + playerName = llGetSubString(playerName, 0, 11); + } + + // Format the complete line (15 chars total) + string fullLine = playerName; + + // Add padding spaces + integer padding = 13 - llStringLength(playerName); // Leave 2 chars for wins + integer j; + for (j = 0; j < padding; j++) { + fullLine += " "; + } + + // Add wins (max 2 digits) + if (llStringLength(winsText) > 2) { + winsText = llGetSubString(winsText, 0, 1); // Truncate to 2 digits + } + fullLine += winsText; + + // Ensure exactly 15 characters + if (llStringLength(fullLine) > 15) { + fullLine = llGetSubString(fullLine, 0, 14); + } else if (llStringLength(fullLine) < 15) { + // Pad with spaces if needed + while (llStringLength(fullLine) < 15) { + fullLine += " "; + } + } + + // Split the 15-character line: 5 chars each to left, middle, right prims + string leftPart = llGetSubString(fullLine, 0, 4); // Characters 0-4 + string middlePart = llGetSubString(fullLine, 5, 9); // Characters 5-9 + string rightPart = llGetSubString(fullLine, 10, 14); // Characters 10-14 + + leftText += "\n" + leftPart; + middleText += "\n" + middlePart; + rightText += "\n" + rightPart; + } + + // If no data, show empty message + if (maxDisplay == 0) { + leftText = "NO "; + middleText = "GAMES"; + rightText = " "; + } + + // Send to separate leaderboard object via chat + llOwnerSay("DEBUG: Sending to LEFT XyzzyText: " + leftText); + llOwnerSay("DEBUG: Sending to MIDDLE XyzzyText: " + middleText); + llOwnerSay("DEBUG: Sending to RIGHT XyzzyText: " + rightText); + + // Send to leaderboard bridge in separate object + llRegionSay(LEADERBOARD_CHANNEL, "LEFT_TEXT|" + leftText); + llRegionSay(LEADERBOARD_CHANNEL, "MIDDLE_TEXT|" + middleText); + llRegionSay(LEADERBOARD_CHANNEL, "RIGHT_TEXT|" + rightText); + + // Also create combined floating text as backup display method + string combinedText = "WINS:\n"; + for (i = 0; i < maxDisplay; i++) { + list playerData = llParseString2List(llList2String(sortedData, i), [":"], []); + string playerName = llList2String(playerData, 0); + string winsText = llList2String(playerData, 1); + + if (llStringLength(playerName) > 12) { + playerName = llGetSubString(playerName, 0, 11); + } + + combinedText += playerName + ": " + winsText + "\n"; + } + + if (maxDisplay == 0) { + combinedText = "No games played yet"; + } + + // Note: Leaderboard is now in separate object - no prim to update here +} + +// Update leaderboard prim with current standings and update persistent data +updateLeaderboard(list topPlayers) { + generateLeaderboardText(); +} + +// Handle game won message +handleGameWon(string winnerName) { + integer playerIndex = llListFindList(leaderboardNames, [winnerName]); + + if (playerIndex == -1) { + leaderboardNames += [winnerName]; + leaderboardWins += [1]; + } else { + integer currentWins = llList2Integer(leaderboardWins, playerIndex); + leaderboardWins = llListReplaceList(leaderboardWins, [currentWins + 1], playerIndex, playerIndex); + } + + saveLeaderboardData(); + updateLeaderboard(leaderboardNames); +} + +// Sort leaderboard by wins +list getSortedLeaderboard() { + list combined = []; + integer i; + + for (i = 0; i < llGetListLength(leaderboardNames); i++) { + string playerName = llList2String(leaderboardNames, i); + integer wins = llList2Integer(leaderboardWins, i); + combined += [playerName + ":" + (string)wins]; + } + + integer n = llGetListLength(combined); + integer swapped = TRUE; + + while (swapped) { + swapped = FALSE; + for (i = 0; i < n - 1; i++) { + list data1 = llParseString2List(llList2String(combined, i), [":"], []); + list data2 = llParseString2List(llList2String(combined, i + 1), [":"], []); + + integer wins1 = (integer)llList2String(data1, 1); + integer wins2 = (integer)llList2String(data2, 1); + + if (wins1 < wins2) { + string temp = llList2String(combined, i); + combined = llListReplaceList(combined, [llList2String(combined, i + 1)], i, i); + combined = llListReplaceList(combined, [temp], i + 1, i + 1); + swapped = TRUE; + } + } + n--; + } + + return combined; +} + +// Save leaderboard data +saveLeaderboardData() { + integer i; + llLinksetDataWrite("lb_count", (string)llGetListLength(leaderboardNames)); + for (i = 0; i < llGetListLength(leaderboardNames); i++) { + string playerName = llList2String(leaderboardNames, i); + integer wins = llList2Integer(leaderboardWins, i); + llLinksetDataWrite("lb_player_" + (string)i, playerName); + llLinksetDataWrite("lb_wins_" + (string)i, (string)wins); + } +} + +// Load leaderboard data +loadLeaderboardData() { + string countStr = llLinksetDataRead("lb_count"); + if (countStr == "") return; + + integer count = (integer)countStr; + leaderboardNames = []; + leaderboardWins = []; + integer i; + for (i = 0; i < count; i++) { + string playerName = llLinksetDataRead("lb_player_" + (string)i); + string winsStr = llLinksetDataRead("lb_wins_" + (string)i); + if (playerName != "" && winsStr != "") { + leaderboardNames += [playerName]; + leaderboardWins += [(integer)winsStr]; + } + } +} + +// Reset leaderboard data +resetLeaderboard() { + leaderboardNames = []; + leaderboardWins = []; + integer i; + for (i = 0; i < 100; i++) { + llLinksetDataDelete("lb_player_" + (string)i); + llLinksetDataDelete("lb_wins_" + (string)i); + } + llLinksetDataDelete("lb_count"); + updateLeaderboard([]); +} + +// Clear all current players from the scoreboard +clearAllPlayers() { + llOwnerSay("DEBUG: Clearing all players from scoreboard"); + + // Clear ONLY current game player data lists (NOT leaderboard data) + playerNames = []; + playerLives = []; + playerProfiles = []; + + // NOTE: leaderboardNames and leaderboardWins are NOT cleared - they persist + + // Clear any pending HTTP requests + httpRequests = []; + profileRequests = []; + + // Reset all player prims to default state + integer i; + for (i = 0; i < 10; i++) { + integer profilePrimIndex = FIRST_PLAYER_PRIM + (i * 2); + integer heartsPrimIndex = FIRST_PLAYER_PRIM + (i * 2) + 1; + + // Reset profile prim to default + llSetLinkPrimitiveParamsFast(profilePrimIndex, [ + PRIM_TEXTURE, ALL_SIDES, TEXTURE_DEFAULT_PROFILE, <1,1,0>, <0,0,0>, 0.0, + PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0, + PRIM_TEXT, "", <1,1,1>, 0.0 + ]); + + // Reset hearts prim to 3 hearts + llSetLinkPrimitiveParamsFast(heartsPrimIndex, [ + PRIM_TEXTURE, ALL_SIDES, TEXTURE_3_HEARTS, <1,1,0>, <0,0,0>, 0.0, + PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0, + PRIM_TEXT, "", <1,1,1>, 0.0 + ]); + } +} + +// Check if a player name indicates it's a bot +integer isBot(string playerName) { + return (llSubStringIndex(playerName, "TestBot") == 0); +} + +string getHeartTexture(integer lives) { + if (lives <= 0) return TEXTURE_0_HEARTS; + else if (lives == 1) return TEXTURE_1_HEARTS; + else if (lives == 2) return TEXTURE_2_HEARTS; + else return TEXTURE_3_HEARTS; // 3 or more +} + +// Update player display on the grid +updatePlayerDisplay(string playerName, integer lives, string profileUUID) { + // Find existing player or add new one + integer playerIndex = llListFindList(playerNames, [playerName]); + + if (playerIndex == -1) { + // New player - find next available slot + playerIndex = llGetListLength(playerNames); + if (playerIndex >= 10) { + llOwnerSay("WARNING: Maximum 10 players supported, ignoring: " + playerName); + return; + } + + // Add to tracking lists + playerNames += [playerName]; + playerLives += [lives]; + playerProfiles += [profileUUID]; + + llOwnerSay("DEBUG: Added new player " + playerName + " at slot " + (string)playerIndex); + } else { + // Update existing player + playerLives = llListReplaceList(playerLives, [lives], playerIndex, playerIndex); + // Don't overwrite cached profile texture with original UUID on updates + // playerProfiles = llListReplaceList(playerProfiles, [profileUUID], playerIndex, playerIndex); + + llOwnerSay("DEBUG: Updated player " + playerName + " at slot " + (string)playerIndex + " with " + (string)lives + " lives"); + } + + // Update the physical prims for this player + integer profilePrimIndex = FIRST_PLAYER_PRIM + (playerIndex * 2); + integer heartsPrimIndex = FIRST_PLAYER_PRIM + (playerIndex * 2) + 1; + + // Update profile prim texture + string profileTexture = profileUUID; + + // Check if we already have a cached profile texture for this player + if (playerIndex < llGetListLength(playerProfiles)) { + string cachedTexture = llList2String(playerProfiles, playerIndex); + if (cachedTexture != "" && cachedTexture != profileUUID && + cachedTexture != TEXTURE_DEFAULT_PROFILE && cachedTexture != TEXTURE_BOT_PROFILE) { + // We have a previously fetched profile picture, use it + profileTexture = cachedTexture; + llOwnerSay("DEBUG: Using cached profile texture for " + playerName); + } + } + + // If no cached texture or using original UUID, determine what to use + if (profileTexture == profileUUID) { + if (isBot(playerName)) { + profileTexture = TEXTURE_BOT_PROFILE; + llOwnerSay("DEBUG: Using bot profile texture for " + playerName); + } else if (profileTexture == "" || profileTexture == "00000000-0000-0000-0000-000000000000") { + profileTexture = TEXTURE_DEFAULT_PROFILE; + llOwnerSay("DEBUG: Using default profile texture for " + playerName); + } else { + // Request profile picture via HTTP (the correct method!) + llOwnerSay("DEBUG: Requesting profile picture via HTTP for avatar UUID: " + profileUUID); + string URL_RESIDENT = "https://world.secondlife.com/resident/"; + key httpRequestID = llHTTPRequest(URL_RESIDENT + profileUUID, [HTTP_METHOD, "GET"], ""); + + // Store the HTTP request mapping: requestID -> playerIndex + httpRequests += [httpRequestID, playerIndex]; + + // For now, use the avatar UUID directly as texture + llOwnerSay("DEBUG: Setting temporary profile texture: " + profileTexture); + } + } + + llSetLinkPrimitiveParamsFast(profilePrimIndex, [ + PRIM_TEXTURE, ALL_SIDES, profileTexture, <1,1,0>, <0,0,0>, 0.0, + PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0, + PRIM_TEXT, "", <1,1,1>, 0.0 // Remove player name text + ]); + + // Update hearts prim texture + string heartTexture = getHeartTexture(lives); + llSetLinkPrimitiveParamsFast(heartsPrimIndex, [ + PRIM_TEXTURE, ALL_SIDES, heartTexture, <1,1,0>, <0,0,0>, 0.0, + PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0, + PRIM_TEXT, "", <1,0,0>, 0.0 // Remove lives text + ]); +} + +default { + state_entry() { + // Clear any old floating text on root prim + llSetText("", <1,1,1>, 0.0); + + // Initialize profile picture extraction constants + profile_key_prefix_length = llStringLength(profile_key_prefix); + profile_img_prefix_length = llStringLength(profile_img_prefix); + + llListen(SCOREBOARD_CHANNEL, "", "", ""); + llListen(LEADERBOARD_CHANNEL, "", "", ""); + loadLeaderboardData(); + setupPlayerGrid(); + + // Generate initial leaderboard texture + llSetTimerEvent(1.0); // Short delay to ensure prims are set up + + llOwnerSay("Game Scoreboard Manager ready - Grid layout initialized"); + llOwnerSay("Touch me to re-run setup."); + } + + timer() { + llSetTimerEvent(0.0); // Stop timer + generateLeaderboardText(); // Generate initial leaderboard + } + + listen(integer channel, string senderName, key id, string message) { + if (channel == SCOREBOARD_CHANNEL) { + if (llSubStringIndex(message, "PLAYER_UPDATE|") == 0) { + // Handle player updates here if needed + // Format: PLAYER_UPDATE|PlayerName|Lives|ProfileUUID + llOwnerSay("DEBUG: Received player update: " + message); + + list parts = llParseString2List(message, ["|"], []); + if (llGetListLength(parts) >= 4) { + string playerName = llList2String(parts, 1); + integer lives = (integer)llList2String(parts, 2); + string profileUUID = llList2String(parts, 3); + + updatePlayerDisplay(playerName, lives, profileUUID); + } + } + else if (message == "CLEAR_GAME") { + // Reset to default state + clearAllPlayers(); // Clear all current players + updateActionsPrim("Title"); // Reset to title instead of "Game Cleared" + generateLeaderboardText(); // Refresh leaderboard display + } + else if (llSubStringIndex(message, "GAME_START|") == 0) { + updateActionsPrim("Title"); + } + else if (llSubStringIndex(message, "GAME_STATUS|") == 0) { + // Format: GAME_STATUS|StatusText + list parts = llParseString2List(message, ["|"], []); + if (llGetListLength(parts) >= 2) { + string status = llList2String(parts, 1); + updateActionsPrim(status); + } + } + else if (llSubStringIndex(message, "LEADERBOARD|") == 0) { + // Format: LEADERBOARD|Player1:Score1|Player2:Score2|... + list parts = llParseString2List(message, ["|"], []); + list playerData = llDeleteSubList(parts, 0, 0); // Remove "LEADERBOARD" + updateLeaderboard(playerData); + } else if (llSubStringIndex(message, "GAME_WON|") == 0) { + list parts = llParseString2List(message, ["|"], []); + if (llGetListLength(parts) >= 2) { + string winnerName = llList2String(parts, 1); + handleGameWon(winnerName); + } + } else if (llSubStringIndex(message, "RESET_LEADERBOARD") == 0) { + resetLeaderboard(); + } + } + } + + touch_start(integer total_number) { + // Owner can touch to manually re-run setup + if (llDetectedKey(0) == llGetOwner()) { + llOwnerSay("Owner touched - re-running setup..."); + setupPlayerGrid(); + } + } + + dataserver(key query_id, string data) { + // Handle profile picture data responses + integer requestIndex = llListFindList(profileRequests, [query_id]); + if (requestIndex != -1) { + // Found the request - get the corresponding player index and data type + integer playerIndex = llList2Integer(profileRequests, requestIndex + 1); + integer dataType = llList2Integer(profileRequests, requestIndex + 2); + + llOwnerSay("DEBUG: Data type " + (string)dataType + " returned: '" + data + "' for player at index " + (string)playerIndex); + + // Check if this looks like a valid texture UUID (36 characters, proper format) + if (llStringLength(data) == 36 && llSubStringIndex(data, "-") != -1) { + llOwnerSay("*** FOUND IT! Data type " + (string)dataType + " returned valid UUID: " + data + " ***"); + + // Update the profile texture for this player + integer profilePrimIndex = FIRST_PLAYER_PRIM + (playerIndex * 2); + + llSetLinkPrimitiveParamsFast(profilePrimIndex, [ + PRIM_TEXTURE, ALL_SIDES, data, <1,1,0>, <0,0,0>, 0.0, + PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0 + ]); + + llOwnerSay("Profile picture updated successfully for " + llList2String(playerNames, playerIndex)); + } else { + // Not a valid UUID, continue testing other data types + llOwnerSay("Data type " + (string)dataType + " did not return valid UUID"); + } + + // Clean up the completed request (3 elements: requestID, playerIndex, dataType) + profileRequests = llDeleteSubList(profileRequests, requestIndex, requestIndex + 2); + } + } + + http_response(key request_id, integer status, list metadata, string body) { + // Handle HTTP response for profile picture requests + integer requestIndex = llListFindList(httpRequests, [request_id]); + if (requestIndex != -1) { + integer playerIndex = llList2Integer(httpRequests, requestIndex + 1); + + llOwnerSay("DEBUG: HTTP response received for player at index " + (string)playerIndex + ", status: " + (string)status); + + if (status == 200) { + // Try to extract profile picture UUID from HTML + integer s1 = llSubStringIndex(body, profile_key_prefix); + integer s1l = profile_key_prefix_length; + + if (s1 == -1) { + // Second try with img tag + s1 = llSubStringIndex(body, profile_img_prefix); + s1l = profile_img_prefix_length; + llOwnerSay("DEBUG: Trying img tag method for profile picture extraction"); + } else { + llOwnerSay("DEBUG: Found meta tag with profile image"); + } + + if (s1 == -1) { + // Still no match - use default texture + llOwnerSay("DEBUG: No profile picture found in HTML for player " + llList2String(playerNames, playerIndex)); + + integer profilePrimIndex = FIRST_PLAYER_PRIM + (playerIndex * 2); + llSetLinkPrimitiveParamsFast(profilePrimIndex, [ + PRIM_TEXTURE, ALL_SIDES, TEXTURE_DEFAULT_PROFILE, <1,1,0>, <0,0,0>, 0.0, + PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0 + ]); + } else { + // Extract the UUID + s1 += s1l; + key profileUUID = llGetSubString(body, s1, s1 + 35); + + if (profileUUID == NULL_KEY) { + llOwnerSay("DEBUG: Extracted NULL_KEY, using default texture"); + integer profilePrimIndex = FIRST_PLAYER_PRIM + (playerIndex * 2); + llSetLinkPrimitiveParamsFast(profilePrimIndex, [ + PRIM_TEXTURE, ALL_SIDES, TEXTURE_DEFAULT_PROFILE, <1,1,0>, <0,0,0>, 0.0, + PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0 + ]); + } else { + llOwnerSay("*** SUCCESS! Found profile picture UUID: " + (string)profileUUID + " for player " + llList2String(playerNames, playerIndex) + " ***"); + + // Cache the profile picture UUID + playerProfiles = llListReplaceList(playerProfiles, [(string)profileUUID], playerIndex, playerIndex); + + // Update the profile texture + integer profilePrimIndex = FIRST_PLAYER_PRIM + (playerIndex * 2); + llSetLinkPrimitiveParamsFast(profilePrimIndex, [ + PRIM_TEXTURE, ALL_SIDES, (string)profileUUID, <1,1,0>, <0,0,0>, 0.0, + PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0 + ]); + } + } + } else { + llOwnerSay("DEBUG: HTTP request failed with status " + (string)status + " for player " + llList2String(playerNames, playerIndex)); + + // Use default texture on HTTP failure + integer profilePrimIndex = FIRST_PLAYER_PRIM + (playerIndex * 2); + llSetLinkPrimitiveParamsFast(profilePrimIndex, [ + PRIM_TEXTURE, ALL_SIDES, TEXTURE_DEFAULT_PROFILE, <1,1,0>, <0,0,0>, 0.0, + PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0 + ]); + } + + // Clean up the completed HTTP request (2 elements: requestID, playerIndex) + httpRequests = llDeleteSubList(httpRequests, requestIndex, requestIndex + 1); + } + } +} diff --git a/Helper.lsl b/Helper.lsl index 9b4b9b6..e90f49b 100644 --- a/Helper.lsl +++ b/Helper.lsl @@ -122,6 +122,18 @@ default { } link_message(integer sender, integer num, string str, key id) { + // Handle full reset from main controller + if (num == -99999 && str == "FULL_RESET") { + // Reset helper state + lives = []; + picksData = []; + perilPlayer = ""; + names = []; + pickQueue = []; + llOwnerSay("🧘 Helper Module reset!"); + return; + } + if (num == MSG_SYNC_GAME_STATE) { list parts = llParseString2List(str, ["~"], []); lives = llCSV2List(llList2String(parts, 0)); diff --git a/Leaderboard_Bridge.lsl b/Leaderboard_Bridge.lsl new file mode 100644 index 0000000..fe7e8af --- /dev/null +++ b/Leaderboard_Bridge.lsl @@ -0,0 +1,56 @@ +// Leaderboard Bridge - Receives text from Game Scoreboard Manager and sends to XyzzyText +// This script goes in the root prim of your leaderboard object (alongside XyzzyText master) + +// Communication channels +integer LEADERBOARD_CHANNEL = -12346; // Listen for messages from scoreboard + +// XyzzyText Communication Constants +integer DISPLAY_STRING = 204000; +integer DISPLAY_EXTENDED = 204001; + +default { + state_entry() { + llListen(LEADERBOARD_CHANNEL, "", "", ""); + llOwnerSay("Leaderboard Bridge ready - listening on channel " + (string)LEADERBOARD_CHANNEL); + + // Send initial blank display to all banks + llMessageLinked(LINK_SET, DISPLAY_STRING, " ", "0"); // Bank 0 (left) + llMessageLinked(LINK_SET, DISPLAY_STRING, " ", "1"); // Bank 1 (middle) + llMessageLinked(LINK_SET, DISPLAY_STRING, " ", "2"); // Bank 2 (right) + } + + listen(integer channel, string name, key id, string message) { + if (channel == LEADERBOARD_CHANNEL) { + llOwnerSay("DEBUG: Received leaderboard message: " + message); + + if (llSubStringIndex(message, "LEFT_TEXT|") == 0) { + // Extract left column text and send to bank 0 + string leftText = llGetSubString(message, 10, -1); // Remove "LEFT_TEXT|" prefix + llOwnerSay("DEBUG: Sending to LEFT bank (0): " + leftText); + llMessageLinked(LINK_SET, DISPLAY_STRING, leftText, "0"); + + } else if (llSubStringIndex(message, "MIDDLE_TEXT|") == 0) { + // Extract middle column text and send to bank 1 + string middleText = llGetSubString(message, 12, -1); // Remove "MIDDLE_TEXT|" prefix + llOwnerSay("DEBUG: Sending to MIDDLE bank (1): " + middleText); + llMessageLinked(LINK_SET, DISPLAY_STRING, middleText, "1"); + + } else if (llSubStringIndex(message, "RIGHT_TEXT|") == 0) { + // Extract right column text and send to bank 2 + string rightText = llGetSubString(message, 11, -1); // Remove "RIGHT_TEXT|" prefix + llOwnerSay("DEBUG: Sending to RIGHT bank (2): " + rightText); + llMessageLinked(LINK_SET, DISPLAY_STRING, rightText, "2"); + + } else if (message == "CLEAR_LEADERBOARD") { + // Clear all displays + llOwnerSay("DEBUG: Clearing all leaderboard displays"); + llMessageLinked(LINK_SET, DISPLAY_STRING, " ", "0"); + llMessageLinked(LINK_SET, DISPLAY_STRING, " ", "1"); + llMessageLinked(LINK_SET, DISPLAY_STRING, " ", "2"); + + } else { + llOwnerSay("DEBUG: Unrecognized leaderboard message: " + message); + } + } + } +} diff --git a/Leaderboard_Manager.lsl b/Leaderboard_Manager.lsl new file mode 100644 index 0000000..1f72245 --- /dev/null +++ b/Leaderboard_Manager.lsl @@ -0,0 +1,253 @@ +// Leaderboard Manager - Shows top 10 players ranked by total wins +// Displays as text on a prim face with persistent win tracking + +// Communication +integer LEADERBOARD_CHANNEL = -12346; +integer MAIN_CHANNEL = -12340; + +// Data storage +list playerNames = []; +list playerWins = []; + +// Display settings +integer DISPLAY_FACE = 0; // Which face to show leaderboard text on +vector TEXT_COLOR = <1.0, 1.0, 0.0>; // Yellow text +float TEXT_ALPHA = 1.0; + +default { + state_entry() { + // Listen for game results and commands + llListen(LEADERBOARD_CHANNEL, "", "", ""); + llListen(MAIN_CHANNEL, "", "", ""); + + // Load persistent data + loadLeaderboardData(); + + // Display current leaderboard + updateLeaderboardDisplay(); + + llOwnerSay("Leaderboard Manager ready - Win tracking active"); + } + + listen(integer channel, string name, key id, string message) { + if (channel == LEADERBOARD_CHANNEL) { + if (llSubStringIndex(message, "GAME_WON|") == 0) { + handleGameWon(message); + } + else if (message == "RESET_LEADERBOARD") { + resetLeaderboard(); + } + else if (message == "SHOW_LEADERBOARD") { + updateLeaderboardDisplay(); + } + } + else if (channel == MAIN_CHANNEL) { + // Listen for game end messages from main controller + if (llSubStringIndex(message, "GAME_ENDED|") == 0) { + handleGameEnded(message); + } + } + } + + touch_start(integer total_number) { + // Allow touching to refresh leaderboard display + updateLeaderboardDisplay(); + llOwnerSay("Leaderboard refreshed"); + } +} + +handleGameWon(string message) { + // Format: "GAME_WON|PlayerName" + list parts = llParseString2List(message, ["|"], []); + if (llGetListLength(parts) < 2) return; + + string winnerName = llList2String(parts, 1); + addWinToPlayer(winnerName); + + llOwnerSay("Win recorded for: " + winnerName); +} + +handleGameEnded(string message) { + // Format: "GAME_ENDED|WinnerName|PlayerList" + list parts = llParseString2List(message, ["|"], []); + if (llGetListLength(parts) >= 2) { + string winnerName = llList2String(parts, 1); + if (winnerName != "NONE" && winnerName != "") { + addWinToPlayer(winnerName); + llOwnerSay("Game ended - Win recorded for: " + winnerName); + } + } +} + +addWinToPlayer(string playerName) { + // Check if player already exists in leaderboard + integer playerIndex = llListFindList(playerNames, [playerName]); + + if (playerIndex == -1) { + // New player - add to lists + playerNames += [playerName]; + playerWins += [1]; + } else { + // Existing player - increment wins + integer currentWins = llList2Integer(playerWins, playerIndex); + playerWins = llListReplaceList(playerWins, [currentWins + 1], playerIndex, playerIndex); + } + + // Save data and update display + saveLeaderboardData(); + updateLeaderboardDisplay(); +} + +updateLeaderboardDisplay() { + // Create sorted list of top 10 players + list sortedData = getSortedLeaderboard(); + + // Build display text + string displayText = "═══ LEADERBOARD ═══\n"; + + integer i; + integer maxDisplay = llGetListLength(sortedData); + if (maxDisplay > 10) maxDisplay = 10; // Show only top 10 + + if (maxDisplay == 0) { + displayText += "No games played yet\n"; + } else { + for (i = 0; i < maxDisplay; i++) { + list playerData = llParseString2List(llList2String(sortedData, i), [":"], []); + string name = llList2String(playerData, 0); + string wins = llList2String(playerData, 1); + + displayText += (string)(i + 1) + ". " + name + " - " + wins + " wins\n"; + } + } + + displayText += "═══════════════════"; + + // Set text on prim face + llSetText("", <0,0,0>, 0.0); // Clear floating text + llSetLinkPrimitiveParamsFast(LINK_THIS, [ + PRIM_TEXT, displayText, TEXT_COLOR, TEXT_ALPHA + ]); + + // Also set as texture text if supported + // Note: This would require creating text textures dynamically + // For now, we use floating text above the prim +} + +list getSortedLeaderboard() { + // Create combined list of "PlayerName:Wins" for sorting + list combined = []; + integer i; + + for (i = 0; i < llGetListLength(playerNames); i++) { + string playerName = llList2String(playerNames, i); + integer wins = llList2Integer(playerWins, i); + combined += [playerName + ":" + (string)wins]; + } + + // Sort by wins (descending) - bubble sort + integer n = llGetListLength(combined); + integer swapped = TRUE; + + while (swapped) { + swapped = FALSE; + for (i = 0; i < n - 1; i++) { + list data1 = llParseString2List(llList2String(combined, i), [":"], []); + list data2 = llParseString2List(llList2String(combined, i + 1), [":"], []); + + integer wins1 = (integer)llList2String(data1, 1); + integer wins2 = (integer)llList2String(data2, 1); + + if (wins1 < wins2) { + // Swap positions + string temp = llList2String(combined, i); + combined = llListReplaceList(combined, [llList2String(combined, i + 1)], i, i); + combined = llListReplaceList(combined, [temp], i + 1, i + 1); + swapped = TRUE; + } + } + n--; + } + + return combined; +} + +saveLeaderboardData() { + // Save to linkset data for persistence + integer i; + + // Save player count + llLinksetDataWrite("lb_count", (string)llGetListLength(playerNames)); + + // Save each player's data + for (i = 0; i < llGetListLength(playerNames); i++) { + string playerName = llList2String(playerNames, i); + integer wins = llList2Integer(playerWins, i); + + llLinksetDataWrite("lb_player_" + (string)i, playerName); + llLinksetDataWrite("lb_wins_" + (string)i, (string)wins); + } +} + +loadLeaderboardData() { + // Load from linkset data + string countStr = llLinksetDataRead("lb_count"); + if (countStr == "") return; // No saved data + + integer count = (integer)countStr; + playerNames = []; + playerWins = []; + + integer i; + for (i = 0; i < count; i++) { + string playerName = llLinksetDataRead("lb_player_" + (string)i); + string winsStr = llLinksetDataRead("lb_wins_" + (string)i); + + if (playerName != "" && winsStr != "") { + playerNames += [playerName]; + playerWins += [(integer)winsStr]; + } + } + + llOwnerSay("Loaded leaderboard data: " + (string)llGetListLength(playerNames) + " players"); +} + +resetLeaderboard() { + // Clear all data + playerNames = []; + playerWins = []; + + // Clear persistent storage + integer i; + for (i = 0; i < 100; i++) { // Clear up to 100 possible entries + llLinksetDataDelete("lb_player_" + (string)i); + llLinksetDataDelete("lb_wins_" + (string)i); + } + llLinksetDataDelete("lb_count"); + + // Update display + updateLeaderboardDisplay(); + + llOwnerSay("Leaderboard reset - all win data cleared"); +} + +// Public function to get current standings (for other scripts) +string getLeaderboardString() { + list sortedData = getSortedLeaderboard(); + string result = ""; + + integer i; + integer maxDisplay = llGetListLength(sortedData); + if (maxDisplay > 10) maxDisplay = 10; + + for (i = 0; i < maxDisplay; i++) { + list playerData = llParseString2List(llList2String(sortedData, i), [":"], []); + string name = llList2String(playerData, 0); + string wins = llList2String(playerData, 1); + + if (i > 0) result += ", "; + result += name + "(" + wins + ")"; + } + + return result; +} diff --git a/Main.lsl b/Main.lsl index 3a5cb0a..3648cd6 100644 --- a/Main.lsl +++ b/Main.lsl @@ -13,6 +13,17 @@ integer numberPickChannel = -77888; integer rollDialogChannel = -77999; integer DIALOG_CHANNEL = -88888; +// Game timing settings to prevent dialog system overload +float BOT_PICK_DELAY = 2.0; // Delay after bot picks before next action +float HUMAN_PICK_DELAY = 1.0; // Delay after human picks before next action +float DIALOG_DELAY = 1.5; // Delay before showing dialogs +integer gameTimer = 0; // Timer for game flow delays + +// Status message timing +float STATUS_DISPLAY_TIME = 8.0; // How long to show status messages on scoreboard +integer statusTimer = 0; // Track when status messages were sent +string lastStatus = ""; // Track last status sent + list players = []; list names = []; list lives = []; @@ -39,6 +50,14 @@ integer MSG_QUERY_READY_STATE = 210; integer MSG_READY_STATE_RESULT = 211; integer MSG_CLEANUP_ALL_FLOATERS = 212; integer MSG_SHOW_ROLL_DIALOG = 301; +integer MSG_GET_CURRENT_DIALOG = 302; +integer MSG_PLAYER_WON = 551; +integer MSG_RESET_LEADERBOARD = 553; // Custom message to reset leaderboard + +// Display configuration +integer CONTROLLER_FACE = 1; // Face to display start image on (front face) +string TEXTURE_START = "title_start"; // Start image texture +string TEXTURE_GAME_ACTIVE = "game_active"; // Optional: different texture during game integer MSG_GET_DICE_TYPE = 1001; integer MSG_GET_PICKS_REQUIRED = 1002; @@ -61,6 +80,17 @@ integer lastWarning = 0; key currentPicker; +// Send status message to scoreboard with timing +sendStatusMessage(string status) { + statusTimer = llGetUnixTime(); + lastStatus = status; + llRegionSay(-12345, "GAME_STATUS|" + status); + llOwnerSay("šŸ“¢ Status: " + status + " (showing for " + (string)STATUS_DISPLAY_TIME + "s)"); + + // Start timer to automatically clear status after display time + llSetTimerEvent(STATUS_DISPLAY_TIME + 1.0); // Add 1 second buffer +} + // Forward game state to helpers when it changes updateHelpers() { // Don't send peril player name if game hasn't started yet @@ -111,6 +141,26 @@ updateHelpers() { "~" + perilForSync + "~" + llList2CSV(names); llMessageLinked(LINK_SET, MSG_SYNC_GAME_STATE, serialized, NULL_KEY); llMessageLinked(LINK_SET, MSG_SYNC_PICKQUEUE, llList2CSV(pickQueue), NULL_KEY); + + // Send a test message first to verify scoreboard communication + llRegionSay(-12345, "GAME_STATUS|Testing communication..."); + llOwnerSay("DEBUG: Sent test message to scoreboard"); + + // Send player updates to scoreboard + integer j; + for (j = 0; j < llGetListLength(names); j++) { + string playerName = llList2String(names, j); + integer playerLives = llList2Integer(lives, j); + key playerKey = llList2Key(players, j); + + // Use the actual player key as the profile UUID + string profileUUID = (string)playerKey; + + // Send PLAYER_UPDATE message to scoreboard + string updateMsg = "PLAYER_UPDATE|" + playerName + "|" + (string)playerLives + "|" + profileUUID; + llOwnerSay("DEBUG: Sending to scoreboard: " + updateMsg); + llRegionSay(-12345, updateMsg); + } } // Request helper-calculated values @@ -148,15 +198,36 @@ resetGame() { llMessageLinked(LINK_SET, MSG_CLEANUP_FLOAT, (string)ch, NULL_KEY); } } + + // Reset all game state variables players = names = lives = picksData = globalPickedNumbers = readyPlayers = []; floaterChannels = []; // Clear the tracked channels perilPlayer = ""; pickQueue = []; currentPickerIdx = 0; roundStarted = FALSE; // Reset round flag + currentPicker = NULL_KEY; // Reset current picker + timeoutTimer = 0; // Reset timeout timer + lastWarning = 0; // Reset warning timer + diceType = 6; // Reset dice type to default + + // Send reset message to all other scripts to clear their state + llMessageLinked(LINK_SET, -99999, "FULL_RESET", NULL_KEY); llSay(syncChannel, "RESET"); - llOwnerSay(" Game reset!"); - llSleep(0.2); + + // Send CLEAR_GAME message to scoreboard to reset display + llRegionSay(-12345, "CLEAR_GAME"); + llOwnerSay("šŸŽ® Game reset! All state cleared (including scoreboard)."); + + // Clear status tracking + statusTimer = 0; + lastStatus = ""; + + // Reset controller display to start image + llSetTexture(TEXTURE_START, CONTROLLER_FACE); + llSetText("šŸŽ® PERIL DICE GAME\nTouch to play!", <1.0, 1.0, 0.0>, 1.0); + + llSleep(0.5); // Give other scripts time to process reset llSetTimerEvent(0); updateHelpers(); } @@ -249,9 +320,17 @@ startNextRound() { return; } // If somehow called with exactly one player, treat them as the winner and reset. - if (llGetListLength(names) == 1) { - llSay(0, "✨ ULTIMATE VICTORY! " + llList2String(names, 0) + " is the Ultimate Survivor!"); - resetGame(); +if (llGetListLength(names) == 1) { +string winner = llList2String(names, 0); +llSay(0, "✨ ULTIMATE VICTORY! " + winner + " is the Ultimate Survivor!"); +// Trigger victory confetti and record win +llMessageLinked(LINK_SET, MSG_PLAYER_WON, winner, NULL_KEY); +llMessageLinked(LINK_SET, 995, "VICTORY_CONFETTI", NULL_KEY); +llRegionSay(-12345, "GAME_WON|" + winner); // Send winner info to scoreboard +sendStatusMessage("Victory"); // Show victory status + // Wait for victory status to display before reset + llSleep(STATUS_DISPLAY_TIME + 1.0); +resetGame(); return; } // DON'T reset round flag during continuation rounds - only reset for brand new games @@ -263,7 +342,12 @@ startNextRound() { integer randomIdx = (integer)llFrand(llGetListLength(names)); perilPlayer = llList2String(names, randomIdx); llSay(0, "šŸŽÆ " + perilPlayer + " has been randomly selected and is now in peril!"); + sendStatusMessage("Peril Selected"); // Show peril selected status when peril player is chosen } else { + // Continue showing peril selected status for existing peril player + sendStatusMessage("Peril Selected"); + // Add delay to allow this status to display before next phase + llSleep(STATUS_DISPLAY_TIME * 0.6); // Wait 60% of status display time (~5 seconds) } picksData = []; globalPickedNumbers = []; @@ -292,6 +376,9 @@ showNextPickerDialog() { string firstName = llList2String(pickQueue, currentPickerIdx); currentPicker = llList2Key(players, llListFindList(names, [firstName])); + // Add delay before showing dialog to prevent system overload + llSleep(DIALOG_DELAY); + // Check if this is a bot (TestBot names) if (llSubStringIndex(firstName, "TestBot") == 0) { // Get number of picks needed based on peril player's lives @@ -335,6 +422,11 @@ default { llOwnerSay("šŸŽ® Main Controller ready!"); llOwnerSay("šŸŽ® Main Controller key: " + (string)llGetKey()); llOwnerSay("šŸŽ® Main Controller position: " + (string)llGetPos()); + + // Set the start image on the controller prim + llSetTexture(TEXTURE_START, CONTROLLER_FACE); + llSetText("šŸŽ® PERIL DICE GAME\nTouch to play!", <1.0, 1.0, 0.0>, 1.0); + llListen(DIALOG_CHANNEL, "", NULL_KEY, ""); llListen(-9999, "", NULL_KEY, ""); // Listen for bot responses llListen(rollDialogChannel, "", NULL_KEY, ""); // Listen for roll dialog responses @@ -344,6 +436,56 @@ default { llOwnerSay("Touched by: " + (string)llDetectedKey(0)); key toucher = llDetectedKey(0); integer idx = llListFindList(players, [toucher]); + +// Check if player has a current dialog they can recover +if (idx != -1 && toucher != llGetOwner() && roundStarted) { + string playerName = llList2String(names, idx); + // Check if this player is the current picker waiting for a dialog + if (currentPicker == toucher) { + llRegionSayTo(toucher, 0, "šŸ”„ Restoring your number picking dialog..."); + llMessageLinked(LINK_SET, MSG_GET_CURRENT_DIALOG, playerName, toucher); + return; + } + // Check if this player is the peril player who might need a roll dialog + else if (playerName == perilPlayer && currentPickerIdx >= llGetListLength(pickQueue)) { + llRegionSayTo(toucher, 0, "šŸ”„ Restoring your roll dialog..."); + llMessageLinked(LINK_SET, MSG_SHOW_ROLL_DIALOG, perilPlayer, toucher); + return; + } +} + +// Special handling for owner during gameplay +if (toucher == llGetOwner() && roundStarted) { + string ownerName = llKey2Name(toucher); + list options = []; + string menuText = "Game in progress. What would you like to do?"; + + // Check if owner has active dialogs they can recover + integer hasActiveDialog = FALSE; + if (currentPicker == toucher) { + options += ["šŸ”„ Recover Pick Dialog"]; + hasActiveDialog = TRUE; + } + if (ownerName == perilPlayer && currentPickerIdx >= llGetListLength(pickQueue)) { + options += ["šŸ”„ Recover Roll Dialog"]; + hasActiveDialog = TRUE; + } + + // Always offer admin menu + options += ["šŸ”§ Admin Menu"]; + + // If no active dialogs, just show admin menu directly + if (!hasActiveDialog) { + llOwnerSay("DEBUG: Sending MSG_SHOW_MENU for owner during gameplay"); + llMessageLinked(LINK_SET, MSG_SHOW_MENU, "owner|0", toucher); + return; + } + + // Show choice dialog + llDialog(toucher, menuText, options, DIALOG_CHANNEL); + return; +} + if (toucher == llGetOwner()) { // Determine if this will be the first registered player (starter) before registration integer isStarter = FALSE; @@ -364,7 +506,7 @@ default { llMessageLinked(LINK_SET, MSG_REGISTER_PLAYER, ownerName + "|" + (string)toucher, NULL_KEY); } else { // Already registered; check if owner is the first human player - string ownerName = llList2String(names, idx); + // Owner is starter if they are at index 0 OR if all players before them are bots isStarter = TRUE; // Default to TRUE for owner integer k; for (k = 0; k < idx && isStarter; k++) { @@ -372,11 +514,17 @@ default { // If there's a human player before the owner, owner is not starter if (llSubStringIndex(existingName, "TestBot") != 0) { isStarter = FALSE; - llOwnerSay("āŒ Found human player before owner, not starter"); + llOwnerSay("DEBUG: Found human player before owner at index " + (string)k + ": " + existingName); } } + // Special case: if owner is at index 0, they are definitely the starter + if (idx == 0) { + isStarter = TRUE; + llOwnerSay("DEBUG: Owner is at index 0, definitely starter"); + } } // Show the owner menu with the appropriate starter flag + llOwnerSay("DEBUG: Sending MSG_SHOW_MENU for owner, isStarter=" + (string)isStarter + ", idx=" + (string)idx); llMessageLinked(LINK_SET, MSG_SHOW_MENU, "owner|" + (string)isStarter, toucher); } else if (idx != -1) { // For non-owner players, check if they're the first human player @@ -390,6 +538,27 @@ default { } } llMessageLinked(LINK_SET, MSG_SHOW_MENU, "player|" + (string)isStarter, toucher); + } else { + // Unregistered non-owner player - register them and show menu + string playerName = llKey2Name(toucher); + if (playerName != "") { + // Send a registration request; Main.lsl will handle adding them and rezzing a float + llMessageLinked(LINK_SET, MSG_REGISTER_PLAYER, playerName + "|" + (string)toucher, NULL_KEY); + // Determine if this will be the first human player (starter) + integer isStarter = TRUE; // Default to TRUE + integer n; + for (n = 0; n < llGetListLength(names) && isStarter; n++) { + string existingName = llList2String(names, n); + // If there's already a human player (not a bot), this player is not starter + if (llSubStringIndex(existingName, "TestBot") != 0) { + isStarter = FALSE; + } + } + // Show the player menu with the appropriate starter flag + llMessageLinked(LINK_SET, MSG_SHOW_MENU, "player|" + (string)isStarter, toucher); + } else { + llOwnerSay("āš ļø Could not get name for toucher: " + (string)toucher); + } } } @@ -523,7 +692,7 @@ default { readyPlayers += [newName]; llSay(0, "šŸ¤– " + newName + " boots up with deadly precision - ready to play! šŸ¤–"); } else { - // Check if this is the first human player (starter - automatically ready) + // Check if this is the first human player (starter - automatically ready only if owner) integer humanCount = 0; integer i; for (i = 0; i < llGetListLength(names); i++) { @@ -533,7 +702,14 @@ default { } } if (humanCount == 1) { // This is the first human player - llSay(0, "šŸ‘‘ " + newName + " steps forward as the game master - automatically ready for the deadly challenge! šŸ‘‘"); + if (newKey == llGetOwner()) { + // Owner is auto-ready as starter + readyPlayers += [newName]; + llSay(0, "šŸ‘‘ " + newName + " steps forward as the game master - automatically ready for the deadly challenge! šŸ‘‘"); + } else { + // Non-owner starter can toggle ready state + llSay(0, "šŸ‘‘ " + newName + " steps forward as the game master! Touch to set your ready status."); + } } } // The float will be rezzed by the Floater Manager after it processes @@ -566,17 +742,30 @@ default { llOwnerSay("šŸ—‘ļø Eliminated " + eliminatedPlayer + ". Remaining players: " + (string)llGetListLength(names)); + // Show elimination status when someone is actually eliminated + sendStatusMessage("Elimination"); + // Update all scripts with the new player lists after elimination updateHelpers(); // Check if game should end (1 or fewer players remaining) if (llGetListLength(names) <= 1) { - if (llGetListLength(names) == 1) { - llSay(0, "✨ ULTIMATE VICTORY! " + llList2String(names, 0) + " is the Ultimate Survivor!"); - // Trigger victory confetti - llMessageLinked(LINK_SET, 995, "VICTORY_CONFETTI", NULL_KEY); +if (llGetListLength(names) == 1) { +string winner = llList2String(names, 0); +llSay(0, "✨ ULTIMATE VICTORY! " + winner + " is the Ultimate Survivor!"); +// Trigger victory confetti and record win +llMessageLinked(LINK_SET, MSG_PLAYER_WON, winner, NULL_KEY); +llMessageLinked(LINK_SET, 995, "VICTORY_CONFETTI", NULL_KEY); +llRegionSay(-12345, "GAME_WON|" + winner); // Send winner info to scoreboard + // Wait for elimination status to display before showing victory + llSleep(STATUS_DISPLAY_TIME * 0.8); // Wait 80% of status display time (~6.4 seconds) +sendStatusMessage("Victory"); // Show victory status + // Wait for victory status to display before reset + llSleep(STATUS_DISPLAY_TIME + 1.0); } else { llSay(0, "šŸ’€ DESPAIR WINS! No Ultimate Survivors remain!"); + // Wait for elimination status to display before reset (elimination already sent above) + llSleep(STATUS_DISPLAY_TIME + 1.0); } resetGame(); return; @@ -625,9 +814,10 @@ default { if (num == 998) { list parts = llParseString2List(str, ["|"], []); if (llList2String(parts, 0) == "GAME_WON") { - string winner = llList2String(parts, 1); - llSleep(2.0); // Let celebration message display - resetGame(); +string winner = llList2String(parts, 1); +llRegionSay(-12346, "GAME_WON|" + winner); // Send winner info to scoreboard +llSleep(2.0); // Let celebration message display +resetGame(); } return; } @@ -758,13 +948,17 @@ default { updateHelpers(); llOwnerSay("šŸ‘‹ " + leavingName + " left the game"); // Check if game should end (less than 2 players) - if (llGetListLength(names) == 1) { - llSay(0, "✨ ULTIMATE VICTORY! " + llList2String(names, 0) + " survives the killing game!"); - // Trigger victory confetti - llMessageLinked(LINK_SET, 995, "VICTORY_CONFETTI", NULL_KEY); - resetGame(); - } else if (llGetListLength(names) == 0) { - resetGame(); +if (llGetListLength(names) == 1) { +string winner = llList2String(names, 0); +llSay(0, "✨ ULTIMATE VICTORY! " + winner + " is the Ultimate Survivor!"); +// Trigger victory confetti and record win +llMessageLinked(LINK_SET, MSG_PLAYER_WON, winner, NULL_KEY); +llMessageLinked(LINK_SET, 995, "VICTORY_CONFETTI", NULL_KEY); +llRegionSay(-12345, "GAME_WON|" + winner); // Send winner info to scoreboard +sendStatusMessage("Victory"); // Show victory status + // Wait for victory status to display before reset + llSleep(STATUS_DISPLAY_TIME + 1.0); +resetGame(); } } } @@ -854,6 +1048,9 @@ default { updateHelpers(); llSay(0, "šŸŽÆ " + playerName + " stakes their life on numbers: " + picksStr + " šŸŽ²"); + // Add delay before moving to next picker to prevent dialog system overload + llSleep(HUMAN_PICK_DELAY); + // Move to next picker currentPickerIdx++; if (currentPickerIdx < llGetListLength(pickQueue)) { @@ -912,6 +1109,9 @@ default { updateHelpers(); llSay(0, "šŸŽÆ " + playerName + " (bot) stakes their digital life on numbers: " + picksStr + " šŸŽ²"); + // Add delay after bot picks to prevent dialog system overload + llSleep(BOT_PICK_DELAY); + // Move to next picker currentPickerIdx++; if (currentPickerIdx < llGetListLength(pickQueue)) { @@ -946,23 +1146,45 @@ default { } if (channel == DIALOG_CHANNEL) { + // Handle owner choice dialog responses during gameplay + if (id == llGetOwner() && roundStarted) { + if (msg == "šŸ”„ Recover Pick Dialog") { + string ownerName = llKey2Name(id); + llRegionSayTo(id, 0, "šŸ”„ Restoring your number picking dialog..."); + llMessageLinked(LINK_SET, MSG_GET_CURRENT_DIALOG, ownerName, id); + return; + } + else if (msg == "šŸ”„ Recover Roll Dialog") { + llRegionSayTo(id, 0, "šŸ”„ Restoring your roll dialog..."); + llMessageLinked(LINK_SET, MSG_SHOW_ROLL_DIALOG, perilPlayer, id); + return; + } + else if (msg == "šŸ”§ Admin Menu") { + llOwnerSay("DEBUG: Sending MSG_SHOW_MENU for owner admin during gameplay"); + llMessageLinked(LINK_SET, MSG_SHOW_MENU, "owner|0", id); + return; + } + } + // Owner-specific commands: only owner messages in the dialog should be processed here. if (id == llGetOwner()) { - if (msg == "Reset Game") { - resetGame(); +if (msg == "Reset Game") { +resetGame(); // Only reset current game, keep leaderboard + return; + } + if (msg == "Reset Leaderboard") { +llRegionSay(-12345, "RESET_LEADERBOARD"); // Reset only leaderboard scores + llOwnerSay("šŸ† Leaderboard scores reset - game wins cleared!"); + return; + } + if (msg == "Reset All") { + resetGame(); // Reset current game +llRegionSay(-12345, "RESET_LEADERBOARD"); // Reset leaderboard scores + llOwnerSay("šŸ”„ Complete reset - game and leaderboard cleared!"); return; } // Note: do not handle "Start Game" here; allow the generic start logic below to apply, // so that minimum player checks are enforced and non-owner starters can initiate the game. - if (msg == "Dump Players") { - llOwnerSay(" Players: " + llList2CSV(names)); - return; - } - if (msg == "Manage Picks") { - llOwnerSay(" Fetching list of players for pick management..."); - llMessageLinked(LINK_SET, 202, "REQUEST_PLAYER_LIST", llGetOwner()); - return; - } if (msg == "Add Test Player") { // Ensure we do not exceed the maximum allowed players if (llGetListLength(players) >= MAX_PLAYERS) { @@ -1034,6 +1256,11 @@ default { // All checks passed, start the game llSay(0, "⚔ ALL PARTICIPANTS READY! THE DEADLY PERIL DICE GAME BEGINS! ⚔"); + + // Change controller display to show game is active + llSetText("šŸŽ® GAME IN PROGRESS\nRound " + (string)(llGetListLength(names)) + " players", <1.0, 0.2, 0.2>, 1.0); + + sendStatusMessage("Title"); // Show title status at game start startNextRound(); requestDiceType(); } @@ -1043,4 +1270,38 @@ default { } } } -} \ No newline at end of file + + timer() { + // Check if we need to clear status message + if (statusTimer > 0 && (llGetUnixTime() - statusTimer) >= STATUS_DISPLAY_TIME) { + // Clear the status and revert to title + statusTimer = 0; + lastStatus = ""; + llRegionSay(-12345, "GAME_STATUS|Title"); + llOwnerSay("šŸ“¢ Status cleared - reverted to Title"); + llSetTimerEvent(0); // Stop timer if no other timing needed + } + + // Handle dialog timeout warnings (existing code) + if (timeoutTimer > 0) { + integer elapsed = llGetUnixTime() - timeoutTimer; + if (elapsed >= TIMEOUT_SECONDS) { + llOwnerSay("ā° Dialog timeout reached!"); + llSetTimerEvent(0); + timeoutTimer = 0; + } else { + integer remaining = TIMEOUT_SECONDS - elapsed; + if (remaining <= warning2min && lastWarning < warning2min) { + llOwnerSay("āš ļø " + (string)(remaining / 60) + " minutes remaining for dialog response"); + lastWarning = warning2min; + } else if (remaining <= warning5min && lastWarning < warning5min) { + llOwnerSay("āš ļø " + (string)(remaining / 60) + " minutes remaining for dialog response"); + lastWarning = warning5min; + } else if (remaining <= warning9min && lastWarning < warning9min) { + llOwnerSay("āš ļø " + (string)(remaining / 60) + " minutes remaining for dialog response"); + lastWarning = warning9min; + } + } + } + } +} diff --git a/Number Picker Dialog Handler.lsl b/Number Picker Dialog Handler.lsl index 520fd49..755067f 100644 --- a/Number Picker Dialog Handler.lsl +++ b/Number Picker Dialog Handler.lsl @@ -1,6 +1,7 @@ // === Dialog Handler (Updated for Peril Dice - Paginated Multiple Picks) === integer MSG_SHOW_DIALOG = 101; +integer MSG_GET_CURRENT_DIALOG = 302; integer numberPickChannel = -77888; // Pagination and picking state @@ -66,11 +67,19 @@ showPickDialog(string name, key id, integer diceType, integer picks) { // Show number selection with pagination options = getNumbersForPage(currentPage, diceType); + // If current page has no numbers, go back to page 0 + if (llGetListLength(options) == 0 && currentPage > 0) { + currentPage = 0; + options = getNumbersForPage(currentPage, diceType); + } + // Calculate total pages based on available numbers, not all numbers integer availableCount = diceType - llGetListLength(globallyPickedNumbers) - llGetListLength(currentPicks); totalPages = (availableCount + NUMBERS_PER_PAGE - 1) / NUMBERS_PER_PAGE; if (totalPages < 1) totalPages = 1; - if (totalPages > 1) { + + // Only show navigation if there are multiple pages AND current page has numbers + if (totalPages > 1 && llGetListLength(options) > 0) { if (currentPage > 0) options += ["ā—€ Prev"]; if (currentPage < totalPages - 1) options += ["Next ā–¶"]; } @@ -107,8 +116,22 @@ default { } link_message(integer sender, integer num, string str, key id) { + // Handle full reset from main controller + if (num == -99999 && str == "FULL_RESET") { + // Reset all dialog state + currentPlayer = ""; + currentPlayerKey = NULL_KEY; + currentDiceType = 0; + picksNeeded = 1; + currentPicks = []; + globallyPickedNumbers = []; + currentPage = 0; + llOwnerSay("šŸŽ® Number Picker Dialog Handler reset!"); + return; + } + if (num == MSG_SHOW_DIALOG) { - list parts = llParseString2List(str, ["|"], []); + list parts = llParseString2List(str, ["|"], []); if (llGetListLength(parts) < 3) { llOwnerSay("āš ļø Malformed MSG_SHOW_DIALOG input: " + str); return; @@ -132,6 +155,18 @@ default { showPickDialog(name, id, diceType, picks); } + + // Handle dialog recovery requests + else if (num == MSG_GET_CURRENT_DIALOG) { + string playerName = str; + // Only show dialog if this player is the current picker + if (currentPlayer == playerName && currentPlayerKey == id) { + llOwnerSay("šŸ”„ Restoring dialog for " + playerName); + showPickDialog(currentPlayer, currentPlayerKey, currentDiceType, picksNeeded); + } else { + llRegionSayTo(id, 0, "āŒ You don't have an active dialog to restore."); + } + } } listen(integer channel, string name, key id, string message) { @@ -145,7 +180,11 @@ default { return; } if (message == "Next ā–¶") { - integer totalPages = (currentDiceType + NUMBERS_PER_PAGE - 1) / NUMBERS_PER_PAGE; + // Calculate total pages based on AVAILABLE numbers, not all dice numbers + integer availableCount = currentDiceType - llGetListLength(globallyPickedNumbers) - llGetListLength(currentPicks); + integer totalPages = (availableCount + NUMBERS_PER_PAGE - 1) / NUMBERS_PER_PAGE; + if (totalPages < 1) totalPages = 1; + if (currentPage < totalPages - 1) { currentPage++; showPickDialog(currentPlayer, currentPlayerKey, currentDiceType, picksNeeded); diff --git a/Owner and Player Dialog Handler.lsl b/Owner and Player Dialog Handler.lsl index c0ca1b5..5a7ff89 100644 --- a/Owner and Player Dialog Handler.lsl +++ b/Owner and Player Dialog Handler.lsl @@ -15,18 +15,42 @@ integer MSG_TOGGLE_READY = 202; integer MSG_QUERY_READY_STATE = 210; integer MSG_READY_STATE_RESULT = 211; integer MSG_CLEANUP_ALL_FLOATERS = 212; +integer MSG_GET_CURRENT_DIALOG = 302; -// Owner-specific options shown when pressing the "Owner" button -list ownerOptions = ["Join Game", "Leave Game", "Add Test Player", "Manage Picks", "Start Game", "Reset Game", "Dump Players", "Cleanup Floaters"]; +// Categorized owner menu system +list mainOwnerOptions = ["šŸŽ® Game Participation", "šŸ‘„ Player Management", "šŸ”„ Reset Options", "šŸ› ļø Troubleshooting", "ā¬…ļø Back to Game"]; + +// Sub-menu options for each category +list gameParticipationOptions = ["Join Game", "Leave Game", "ā¬…ļø Back to Main"]; +list playerManagementOptions = ["Add Test Player", "ā¬…ļø Back to Main"]; +list resetOptions = ["Reset Game", "Reset Leaderboard", "Reset All", "ā¬…ļø Back to Main"]; +list troubleshootingOptions = ["Cleanup Floaters", "ā¬…ļø Back to Main"]; // State tracking for dynamic ready menu key pendingMenuPlayer = NULL_KEY; integer pendingMenuIsStarter = FALSE; integer pendingMenuIsOwner = FALSE; -// Display the debug/owner menu +// Display the main categorized owner menu showOwnerMenu(key id) { - llDialog(id, "šŸ”§ Owner Menu", ownerOptions, DIALOG_CHANNEL); + llDialog(id, "šŸ”§ Owner Menu - Select Category", mainOwnerOptions, DIALOG_CHANNEL); +} + +// Display category sub-menus +showGameParticipationMenu(key id) { + llDialog(id, "šŸŽ® Game Participation", gameParticipationOptions, DIALOG_CHANNEL); +} + +showPlayerManagementMenu(key id) { + llDialog(id, "šŸ‘„ Player Management", playerManagementOptions, DIALOG_CHANNEL); +} + +showResetOptionsMenu(key id) { + llDialog(id, "šŸ”„ Reset Options", resetOptions, DIALOG_CHANNEL); +} + +showTroubleshootingMenu(key id) { + llDialog(id, "šŸ› ļø Troubleshooting", troubleshootingOptions, DIALOG_CHANNEL); } // Display the combined Ready/Leave menu for both players and owners @@ -114,6 +138,19 @@ default { } link_message(integer sender, integer num, string str, key id) { + // Handle full reset from main controller + if (num == -99999 && str == "FULL_RESET") { + // Reset dialog state + pendingMenuPlayer = NULL_KEY; + pendingMenuIsStarter = FALSE; + pendingMenuIsOwner = FALSE; + currentPickList = []; + currentPickTarget = ""; + currentPickLimit = 3; + llOwnerSay("šŸŽ­ Owner and Player Dialog Handler reset!"); + return; + } + if (num == MSG_SHOW_MENU) { llOwnerSay("šŸ“Ø Received MSG_SHOW_MENU with: " + str); list args = llParseString2List(str, ["|"], []); @@ -124,8 +161,11 @@ default { string targetType = llList2String(args, 0); integer isStarter = (integer)llList2String(args, 1); if (targetType == "owner") { + // Both starter and non-starter owners get ready/leave menu with Owner button + llOwnerSay("DEBUG: Owner menu request - isStarter=" + (string)isStarter + ", calling showReadyLeaveMenu"); showReadyLeaveMenu(id, isStarter, TRUE); } else if (targetType == "player") { + llOwnerSay("DEBUG: Player menu request - isStarter=" + (string)isStarter + ", calling showReadyLeaveMenu"); showReadyLeaveMenu(id, isStarter, FALSE); } } @@ -137,11 +177,17 @@ default { integer isReady = (integer)llList2String(parts, 1); integer isBot = (integer)llList2String(parts, 2); + llOwnerSay("DEBUG: Ready state result for " + playerName + ": ready=" + (string)isReady + ", bot=" + (string)isBot); + llOwnerSay("DEBUG: Pending menu - starter=" + (string)pendingMenuIsStarter + ", owner=" + (string)pendingMenuIsOwner); + // Show menu with the current ready state if (pendingMenuPlayer == id) { + llOwnerSay("DEBUG: Calling showReadyLeaveMenuWithState"); showReadyLeaveMenuWithState(pendingMenuPlayer, pendingMenuIsStarter, pendingMenuIsOwner, isReady, isBot); // Reset pending state pendingMenuPlayer = NULL_KEY; + } else { + llOwnerSay("DEBUG: Pending menu player mismatch: expected " + (string)pendingMenuPlayer + ", got " + (string)id); } } return; @@ -177,6 +223,27 @@ default { if (msg == "Owner") { showOwnerMenu(id); } + // Handle category menu navigation + else if (msg == "šŸŽ® Game Participation") { + showGameParticipationMenu(id); + } + else if (msg == "šŸ‘„ Player Management") { + showPlayerManagementMenu(id); + } + else if (msg == "šŸ”„ Reset Options") { + showResetOptionsMenu(id); + } + else if (msg == "šŸ› ļø Troubleshooting") { + showTroubleshootingMenu(id); + } + else if (msg == "ā¬…ļø Back to Main") { + showOwnerMenu(id); + } + else if (msg == "ā¬…ļø Back to Game") { + // Return to the owner's ready/leave menu + // Need to determine if owner is starter + llMessageLinked(LINK_SET, MSG_SHOW_MENU, "owner|1", id); // Assume starter for now, will be corrected by main controller + } // Owner joins the game: register and rez a float for them else if (msg == "Join Game") { // Use the avatar's key as the identifier diff --git a/README.md b/README.md index 4e6049a..1768fbb 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,23 @@ Peril Dice is a multiplayer elimination game where each player selects numbers b ## Key Features +### šŸ† Visual Scoreboard System +- **Real-Time Player Grid**: Visual scoreboard showing all players with profile pictures and hearts +- **Profile Picture Integration**: Automatic avatar profile fetching from Second Life +- **Heart Texture Display**: Visual life representation (3, 2, 1, 0 hearts) +- **Instant Updates**: Hearts change immediately when lives are lost + +### šŸŽ­ Enhanced Status Display +- **Visual Status Actions**: Large status prim with custom textures for each game event +- **Specific Status Types**: Direct Hit, No Shield, Plot Twist, Elimination, Victory, etc. +- **Perfect Timing**: 8-second display time with protective delays to prevent overwriting + +### šŸŽÆ Comprehensive Leaderboard +- **Persistent Win Tracking**: Player victories saved across sessions +- **XyzzyText Display**: Professional 3-prim text system for leaderboard +- **Automatic Sorting**: Top players by win count + +### šŸŽ® Core Game Features - **šŸŽÆ Dynamic Player Management**: Players can join at runtime (owner and other avatars) - **šŸ¤– Bot Support**: Add AI bots for testing and gameplay variety - **šŸ“± Floating HUD Display**: Real-time stats for each player @@ -69,18 +86,34 @@ Dice type is automatically chosen to ensure at least 3 picks per player: | 5–6 | d20 | | 7–10 | d30 | -## Recent Improvements (v2.2.0) +## Recent Improvements (v2.3.0) -- **šŸŽ­ Dramatic Messaging**: All game events now use thematic, immersive language -- **šŸ“¢ Public Announcements**: Players can see all major game events in public chat -- **šŸŽ² Enhanced Dice Messages**: Rolls show both dice type (d6, d8, etc.) and result -- **šŸ”§ Bug Fixes**: Resolved StatFloat duplication and duplicate message handling issues +### šŸ† Visual Scoreboard Revolution +- **Real-Time Visual Display**: Complete visual overhaul with player grid showing profile pictures and hearts +- **Instant Heart Updates**: Hearts change immediately when lives are lost, before any dialogs appear +- **Profile Picture Fetching**: Automatic HTTP requests to get actual Second Life avatar pictures +- **0-Hearts Display**: Shows elimination sequence visually before player removal + +### šŸŽ­ Enhanced Status System +- **Specific Status Types**: Separate textures for Direct Hit, No Shield, Plot Twist, Elimination, Victory +- **Perfect Timing**: 8-second display with 2-second protective delays prevent status overwriting +- **Visual Impact**: Large action prim displays current game status with custom textures + +### šŸŽÆ Comprehensive Leaderboard +- **Persistent Win Tracking**: Player victories saved across game sessions using linkset data +- **Professional Display**: XyzzyText 3-prim system for clean leaderboard presentation +- **Flexible Reset Options**: Separate commands for game reset, leaderboard reset, or complete reset + +### šŸ”§ Critical Fixes +- **Heart Update Timing**: Fixed hearts not updating until after next-turn dialog +- **Status Conflicts**: All status messages now have protective delays to prevent overwriting +- **Victory/Elimination Flow**: Proper 6.4-second delay between elimination and victory status ## Version -**Current Version**: 2.2.0 -**Last Updated**: August 2025 -**Status**: Stable - Enhanced UX with dramatic messaging system +**Current Version**: 2.3.0 +**Last Updated**: August 5, 2025 +**Status**: Stable - Complete visual scoreboard system with enhanced status display --- diff --git a/Roll Confetti Module.lsl b/Roll Confetti Module.lsl index bceb9f3..9cf173b 100644 --- a/Roll Confetti Module.lsl +++ b/Roll Confetti Module.lsl @@ -68,6 +68,19 @@ default { } link_message(integer sender, integer num, string str, key id) { + // Handle full reset from main controller + if (num == -99999 && str == "FULL_RESET") { + // Reset roll confetti module state + names = []; + lives = []; + picksData = []; + perilPlayer = ""; + // Stop any active particles + llParticleSystem([]); + llOwnerSay("šŸŽ† Roll Confetti Module reset!"); + return; + } + // Handle game state sync from main controller if (num == MSG_SYNC_GAME_STATE) { list parts = llParseString2List(str, ["~"], []); @@ -155,6 +168,12 @@ default { if (matched && newPeril != "") { llSay(0, "⚔ PLOT TWIST! " + newPeril + " picked " + resultStr + " (rolled on d" + (string)diceType + ") and is now in ULTIMATE PERIL! ⚔"); perilPlayer = newPeril; + + // Send Plot Twist status to scoreboard + llRegionSay(-12345, "GAME_STATUS|Plot Twist"); + // Add delay to let status display before next phase + llSleep(2.0); + // Update floaters immediately to show correct peril player before sync llMessageLinked(LINK_SET, MSG_UPDATE_FLOAT, newPeril, NULL_KEY); } else { @@ -163,19 +182,42 @@ default { integer currentLives = llList2Integer(lives, pidx); lives = llListReplaceList(lives, [currentLives - 1], pidx, pidx); + // Immediately send updated heart count to scoreboard + integer newLives = currentLives - 1; + key perilKey = NULL_KEY; // We don't have player keys in this module, use NULL_KEY + if (pidx < llGetListLength(names)) { + string updateMsg = "PLAYER_UPDATE|" + perilPlayer + "|" + (string)newLives + "|" + (string)perilKey; + llRegionSay(-12345, updateMsg); + llOwnerSay("šŸ’— Immediate scoreboard update: " + perilPlayer + " now has " + (string)newLives + " lives"); + } + // Check if peril player picked the rolled number list perilPicks = getPicksFor(perilPlayer); integer perilPickedIt = (llListFindList(perilPicks, [resultStr]) != -1); if (perilPickedIt) { llSay(0, "🩸 DIRECT HIT! " + perilPlayer + " picked their own doom - the d" + (string)diceType + " landed on " + resultStr + "! 🩸"); + // Send Direct Hit status to scoreboard + llRegionSay(-12345, "GAME_STATUS|Direct Hit"); + // Add delay to let status display before next phase + llSleep(2.0); } else { llSay(0, "🩸 NO SHIELD! Nobody picked " + resultStr + " - " + perilPlayer + " takes the hit from the d" + (string)diceType + "! 🩸"); + // Send No Shield status to scoreboard + llRegionSay(-12345, "GAME_STATUS|No Shield"); + // Add delay to let status display before next phase + llSleep(2.0); } + llMessageLinked(LINK_SET, MSG_UPDATE_FLOAT, perilPlayer, NULL_KEY); // Check for elimination if (currentLives - 1 <= 0) { + // Show 0 hearts on scoreboard before elimination message + string eliminationUpdateMsg = "PLAYER_UPDATE|" + perilPlayer + "|0|" + (string)NULL_KEY; + llRegionSay(-12345, eliminationUpdateMsg); + llOwnerSay("šŸ’€ Elimination update: " + perilPlayer + " now shows 0 hearts"); + llSay(0, "🐻 PUNISHMENT TIME! " + perilPlayer + " has been ELIMINATED!"); // Remove eliminated player (send message to main controller) llMessageLinked(LINK_SET, 999, "ELIMINATE_PLAYER|" + perilPlayer, NULL_KEY); diff --git a/StatFloat.lsl b/StatFloat.lsl index 4588478..fe6fafe 100644 --- a/StatFloat.lsl +++ b/StatFloat.lsl @@ -40,8 +40,13 @@ default { on_rez(integer start_param) { llListen(start_param, "", NULL_KEY, ""); + // Wait a moment for the description to be set + llSleep(0.1); myName = llGetObjectDesc(); - llOwnerSay("šŸ“± Listening on channel " + (string)start_param + " for " + myName); + if (myName == "" || myName == "(No Description)") { + myName = "UnknownPlayer" + (string)start_param; + } +// StatFloat ready and listening } listen(integer channel, string name, key id, string message) { @@ -50,6 +55,40 @@ default { if (llGetListLength(parts) >= 2) { target = (key)llGetSubString(llList2String(parts, 0), 6, -1); displayText = llList2String(parts, 1); + + // Extract life count from the display text to set heart texture + // Look for "Lives: X" pattern in the text + integer livesPos = llSubStringIndex(displayText, "Lives: "); + if (livesPos != -1) { + string livesStr = llGetSubString(displayText, livesPos + 7, livesPos + 7); + integer lifeCount = (integer)livesStr; + string heartTexture = (string)lifeCount + "_hearts"; + // Set heart texture based on current life count + llSetTexture(heartTexture, 1); // Face 1 (right side) + llSetTexture(heartTexture, 2); // Face 2 (back) + llSetTexture(heartTexture, 3); // Face 3 (left side) + llSetTexture(heartTexture, 4); // Face 4 (front) + // Set white background for all faces to eliminate gaps without tinting + llSetColor(<1.0, 1.0, 1.0>, 1); // White background for right side + llSetColor(<1.0, 1.0, 1.0>, 2); // White background for back + llSetColor(<1.0, 1.0, 1.0>, 3); // White background for left side + llSetColor(<1.0, 1.0, 1.0>, 4); // White background for front + llSetColor(<0.2, 0.2, 0.2>, 0); // Dark gray for top + llSetColor(<0.2, 0.2, 0.2>, 5); // Dark gray for bottom + + // Remove "Lives: X" from display text since hearts show it + list lines = llParseString2List(displayText, ["\n"], []); + list filteredLines = []; + integer i; + for (i = 0; i < llGetListLength(lines); i++) { + string line = llList2String(lines, i); + if (llSubStringIndex(line, "Lives: ") != 0) { + filteredLines += [line]; + } + } + displayText = llDumpList2String(filteredLines, "\n"); + } + llSetText(displayText, <1,1,1>, 1.0); } } @@ -57,6 +96,12 @@ default { llOwnerSay("🪟 Cleaning up..."); llDie(); } + else if (llSubStringIndex(message, "SET_NAME:") == 0) { + myName = llGetSubString(message, 9, -1); + // Name successfully received and set + // Update the object description as well for consistency + llSetObjectDesc(myName); + } } link_message(integer sender, integer num, string str, key id) { @@ -101,7 +146,10 @@ default { string picksDisplay = llList2CSV(picks); - string txt = "šŸŽ² Peril Dice\nšŸ‘¤ " + myName + "\nā¤ļø Lives: " + (string)lifeCount + "\nšŸ¢ Peril: " + perilDisplay + "\nšŸ”¢ Picks: " + picksDisplay; + // Note: Heart texture is set via listen() path to avoid conflicts + + // Update text display (lives now shown by heart textures) + string txt = "šŸŽ² Peril Dice\nšŸ‘¤ " + myName + "\nšŸ¢ Peril: " + perilDisplay + "\nšŸ”¢ Picks: " + picksDisplay; llSetText(txt, <1,1,1>, 1.0); } } diff --git a/XyzzyText_Debug.lsl b/XyzzyText_Debug.lsl new file mode 100644 index 0000000..ea2ab38 --- /dev/null +++ b/XyzzyText_Debug.lsl @@ -0,0 +1,88 @@ +// XyzzyText Debug Helper +// This script helps debug issues with XyzzyText display + +// Constants for XyzzyText communication +integer DISPLAY_STRING = 204000; +integer DISPLAY_EXTENDED = 204001; +integer RESCAN_LINKSET = 204008; + +// Communication channel from scoreboard +integer LEADERBOARD_CHANNEL = -12346; + +default { + state_entry() { + // Listen for messages from scoreboard + llListen(LEADERBOARD_CHANNEL, "", "", ""); + llOwnerSay("XyzzyText Debug Helper started"); + + // Check linkset info + integer numPrims = llGetNumberOfPrims(); + llOwnerSay("DEBUG: Linkset has " + (string)numPrims + " prims"); + + // List all prim names to verify XyzzyText setup + integer i; + for (i = 1; i <= numPrims; i++) { + string primName = llGetLinkName(i); + llOwnerSay("DEBUG: Prim " + (string)i + " name: '" + primName + "'"); + } + + // Trigger a rescan of the linkset for XyzzyText + llOwnerSay("DEBUG: Triggering XyzzyText rescan"); + llMessageLinked(LINK_SET, RESCAN_LINKSET, "", ""); + + // Send test text to each bank + llSleep(1.0); // Wait for rescan to complete + llOwnerSay("DEBUG: Sending test text to banks"); + llMessageLinked(LINK_SET, DISPLAY_STRING, "TEST0", "0"); // Bank 0 (left) + llMessageLinked(LINK_SET, DISPLAY_STRING, "TEST1", "1"); // Bank 1 (middle) + llMessageLinked(LINK_SET, DISPLAY_STRING, "TEST2", "2"); // Bank 2 (right) + } + + listen(integer channel, string name, key id, string message) { + if (channel == LEADERBOARD_CHANNEL) { + llOwnerSay("DEBUG: Received message on channel " + (string)channel + ": " + message); + + if (llSubStringIndex(message, "LEFT_TEXT|") == 0) { + string leftText = llGetSubString(message, 10, -1); + llOwnerSay("DEBUG: Got LEFT text: " + leftText); + llMessageLinked(LINK_SET, DISPLAY_STRING, leftText, "0"); + } + else if (llSubStringIndex(message, "MIDDLE_TEXT|") == 0) { + string middleText = llGetSubString(message, 12, -1); + llOwnerSay("DEBUG: Got MIDDLE text: " + middleText); + llMessageLinked(LINK_SET, DISPLAY_STRING, middleText, "1"); + } + else if (llSubStringIndex(message, "RIGHT_TEXT|") == 0) { + string rightText = llGetSubString(message, 11, -1); + llOwnerSay("DEBUG: Got RIGHT text: " + rightText); + llMessageLinked(LINK_SET, DISPLAY_STRING, rightText, "2"); + } + } + } + + touch_start(integer total_number) { + // When touched, refresh debug info and test displays + llOwnerSay("--- XyzzyText Debug Refresh ---"); + + // Check linkset info + integer numPrims = llGetNumberOfPrims(); + llOwnerSay("DEBUG: Linkset has " + (string)numPrims + " prims"); + + // List all prim names + integer i; + for (i = 1; i <= numPrims; i++) { + string primName = llGetLinkName(i); + llOwnerSay("DEBUG: Prim " + (string)i + " name: '" + primName + "'"); + } + + // Trigger rescan and test displays + llOwnerSay("DEBUG: Triggering XyzzyText rescan"); + llMessageLinked(LINK_SET, RESCAN_LINKSET, "", ""); + + llSleep(1.0); + llOwnerSay("DEBUG: Sending test text to banks"); + llMessageLinked(LINK_SET, DISPLAY_STRING, "TEST0", "0"); + llMessageLinked(LINK_SET, DISPLAY_STRING, "TEST1", "1"); + llMessageLinked(LINK_SET, DISPLAY_STRING, "TEST2", "2"); + } +} diff --git a/images/title.png b/images/title.png new file mode 100644 index 0000000000000000000000000000000000000000..d802db98e996fb6c90256667094396d80684ddff GIT binary patch literal 194577 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[\\]^_`"; + gCharIndex += "abcdefghijklmnopqrstuvwxyz{|}~"; + gCharIndex += "\n\n\n\n\n"; +} + +vector GetGridOffset(integer index) { + // Calculate the offset needed to display this character. + integer Row = index / 10; + integer Col = index % 10; + + // Return the offset in the texture. + return <-0.45 + 0.1 * Col, 0.45 - 0.1 * Row, 0.0>; +} + +ShowChars(integer link,vector grid_offset1, vector grid_offset2, vector grid_offset3, vector grid_offset4, vector grid_offset5) { + // Set the primitive textures directly. + + // <-0.256, 0, 0> + // <0, 0, 0> + // <0.130, 0, 0> + // <0, 0, 0> + // <-0.74, 0, 0> + + llSetLinkPrimitiveParamsFast( link,[ + PRIM_TEXTURE, FACE_1, (string)gFontTexture, <0.126, 0.1, 0>, grid_offset1 + <0.037, 0, 0>, 0.0, + PRIM_TEXTURE, FACE_2, (string)gFontTexture, <0.05, 0.1, 0>, grid_offset2, 0.0, + PRIM_TEXTURE, FACE_3, (string)gFontTexture, <-0.74, 0.1, 0>, grid_offset3 - <0.244, 0, 0>, 0.0, + PRIM_TEXTURE, FACE_4, (string)gFontTexture, <0.05, 0.1, 0>, grid_offset4, 0.0, + PRIM_TEXTURE, FACE_5, (string)gFontTexture, <0.126, 0.1, 0>, grid_offset5 - <0.037, 0, 0>, 0.0 + ]); +} + +RenderString(integer link, string str) { + // Get the grid positions for each pair of characters. + vector GridOffset1 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 0, 0)) ); + vector GridOffset2 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 1, 1)) ); + vector GridOffset3 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 2, 2)) ); + vector GridOffset4 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 3, 3)) ); + vector GridOffset5 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 4, 4)) ); + + // Use these grid positions to display the correct textures/offsets. + ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5); +} + +RenderWithEffects(integer link, string str) { + // Get the grid positions for each pair of characters. + vector GridOffset1 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 0, 0)) ); + vector GridOffset2 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 1, 1)) ); + vector GridOffset3 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 2, 2)) ); + vector GridOffset4 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 3, 3)) ); + vector GridOffset5 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 4, 4)) ); + + // First set the alpha to the lowest possible. + llSetLinkAlpha(link,0.05, ALL_SIDES); + + // Use these grid positions to display the correct textures/offsets. + ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5); // Now turn up the alpha until it is at full strength. + float Alpha = 0.10; + for (; Alpha <= 1.0; Alpha += 0.05) + llSetLinkAlpha(link,Alpha, ALL_SIDES); + // See if we want to fade out as well. + if (gCellHoldDelay < 0.0) + // No, bail out. (Just keep showing the string at full strength). + return; + // Hold the text for a while. + llSleep(gCellHoldDelay); + // Now fade out. + for (Alpha = 0.95; Alpha >= 0.05; Alpha -= 0.05) + llSetLinkAlpha(link,Alpha, ALL_SIDES); + // Make the text transparent to fully hide it. + llSetLinkTexture(link,TRANSPARENT, ALL_SIDES); +} + +integer RenderExtended(integer link, string str, integer render) { + // Look for escape sequences. + integer length = 0; + list Parsed = llParseString2List(str, [], (list)ESCAPE_SEQUENCE); + integer ParsedLen = llGetListLength(Parsed); + + // Create a list of index values to work with. + list Indices; + // We start with room for 5 indices. + integer IndicesLeft = 5; + + string Token; + integer Clipped; + integer LastWasEscapeSequence = FALSE; + // Work from left to right. + integer i = 0; + for (; i < ParsedLen && IndicesLeft > 0; ++i) { + Token = llList2String(Parsed, i); + + // If this is an escape sequence, just set the flag and move on. + if (Token == ESCAPE_SEQUENCE) { + LastWasEscapeSequence = TRUE; + } + else { // Token != ESCAPE_SEQUENCE + // Otherwise this is a normal token. Check its length. + Clipped = FALSE; + integer TokenLength = llStringLength(Token); + // Clip if necessary. + if (TokenLength > IndicesLeft) { + TokenLength = llStringLength(Token = llGetSubString(Token, 0, IndicesLeft - 1)); + IndicesLeft = 0; + Clipped = TRUE; + } + else + IndicesLeft -= TokenLength; + + // Was the previous token an escape sequence? + if (LastWasEscapeSequence) { + // Yes, the first character is an escape character, the rest are normal. + length += 2 + TokenLength; + if(render) + { + // This is the extended character. + Indices += (llSubStringIndex(EXTENDED_INDEX, llGetSubString(Token, 0, 0)) + 95); + + // These are the normal characters. + integer j = 1; + for (; j < TokenLength; ++j) + { + Indices += llSubStringIndex(gCharIndex, llGetSubString(Token, j, j)); + } + } + } + else { // Normal string. + // Just add the characters normally. + length += TokenLength; + if(render) + { + integer j = 0; + for (; j < TokenLength; ++j) + { + Indices += llSubStringIndex(gCharIndex, llGetSubString(Token, j, j)); + } + } + } + + // Unset this flag, since this was not an escape sequence. + LastWasEscapeSequence = FALSE; + } + } + + // Use the indices to create grid positions. + if(render) + { + vector GridOffset1 = GetGridOffset( llList2Integer(Indices, 0) ); + vector GridOffset2 = GetGridOffset( llList2Integer(Indices, 1) ); + vector GridOffset3 = GetGridOffset( llList2Integer(Indices, 2) ); + vector GridOffset4 = GetGridOffset( llList2Integer(Indices, 3) ); + vector GridOffset5 = GetGridOffset( llList2Integer(Indices, 4) ); + + // Use these grid positions to display the correct textures/offsets. + ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5); + } + return length; +} + +integer ConvertIndex(integer index) { + // This converts from an ASCII based index to our indexing scheme. + if (index >= 32) // ' ' or higher + index -= 32; + else { // index < 32 + // Quick bounds check. + if (index > 15) + index = 15; + + index += 94; // extended characters + } + + return index; +} + + + +PassToRender(integer render,string message, integer bank) +{ +// float time; + integer extendedlen = 0; + integer link; + integer i = 0; + integer msgLen = llStringLength(message); + string TextToRender; + integer num_slaves=llGetListLength(gSlaveNames); + string slave_name; //avoids unnecessary casts, keeping it as a string + + + //get the bank offset and length + integer bank_offset=llList2Integer(gBankingData, (bank * BANK_STRIDE)); + integer bank_length=llList2Integer(gBankingData, (bank * BANK_STRIDE) + 1); + integer bank_highest_dirty=llList2Integer(gBankingData, (bank * BANK_STRIDE) + 2); + + integer x = 0; + for (;x < msgLen;x = x + 5) + { + + if (i >= bank_length) //we don't want to run off the end of the bank + { + //set the dirty to max, and bail out, we're done + gBankingData=llListReplaceList(gBankingData, (list)bank_length, (bank * BANK_STRIDE) + 2, (bank * BANK_STRIDE) + 2); + return; + } + + link = unpack(gXyTextPrims,(i + bank_offset)); + TextToRender = llGetSubString(message, x, x + 15); + + if(gSlaveRegistered && (link % (num_slaves + 1))) + { + slave_name=llList2String(gSlaveNames, (link % (num_slaves + 1)) - 1); + if (render == 1) + llMessageLinked(LINK_THIS, SLAVE_DISPLAY, TextToRender, (key)((string)link + "," + slave_name)); + if (render == 2) + { + //time = llGetAndResetTime(); + if(llSubStringIndex(TextToRender,"\e") > x) + extendedlen = 5; + else + extendedlen = RenderExtended(link,TextToRender,0); + if (extendedlen > 5) + { + x += extendedlen - 5; + } + llMessageLinked(LINK_THIS, SLAVE_DISPLAY_EXTENDED, TextToRender, (key)((string)link + "," + slave_name)); + // llOwnerSay((string)llGetAndResetTime()); + } + //sorry, no fade effect with slave + } + else + { + if (render == 1) + RenderString(link,TextToRender); + if (render == 2) + { + extendedlen = RenderExtended(link,TextToRender,1); + if (extendedlen > 5) + { + x += extendedlen - 5; + } + + } + if (render == 3) + RenderWithEffects(link,TextToRender); + } + ++i; + } + + if (bank_highest_dirty==0) + bank_highest_dirty=bank_length; + + integer current_highest_dirty=i; + while (i < bank_highest_dirty) + { + link = unpack(gXyTextPrims,(i + bank_offset)); + + if(gSlaveRegistered && (link % (num_slaves+1) != 0)) + { + slave_name=llList2String(gSlaveNames, (link % (num_slaves + 1)) - 1); + llMessageLinked(LINK_THIS, SLAVE_DISPLAY, " ", (key)((string)link + "," + slave_name)); + //sorry, no fade effect with slave + } + else + { + RenderString(link," "); + } + ++i; + } + gBankingData=llListReplaceList(gBankingData, (list)current_highest_dirty, (bank * BANK_STRIDE) + 2, (bank * BANK_STRIDE) + 2); +} + +// Bitwise Voodoo by Gigs Taggart and optimized by Strife Onizuka +list gXyTextPrims; + + +integer get_number_of_prims() +{//ignores avatars. + integer a = llGetNumberOfPrims(); + //Mono tweak + vector size = llGetAgentSize(llGetLinkKey(a)); + while(size.z > 0) + { + --a; + size = llGetAgentSize(llGetLinkKey(a)); + } + return a; +} + +//functions to pack 8-bit shorts into ints +list pack_and_insert(list in_list, integer pos, integer value) +{ +// //figure out the bitpack position +// integer pack = pos & 3; //4 bytes per int +// pos=pos >> 2; +// integer shifted = value << (pack << 3); +// integer old_value = llList2Integer(in_list, pos); +// shifted = old_value | shifted; +// in_list = llListReplaceList(in_list, (list)shifted, pos, pos); +// return in_list; + //Safe optimized version + integer index = pos >> 2; + return llListReplaceList(in_list, (list)(llList2Integer(in_list, index) | (value << ((pos & 3) << 3))), index, index); +} + +integer unpack(list in_list, integer pos) +{ + return (llList2Integer(in_list, pos >> 2) >> ((pos & 3) << 3)) & 0x000000FF;//unsigned +// return (llList2Integer(in_list, pos >> 2) << (((~pos) & 3) << 3)) >> 24;//signed +} + +change_color(vector color) +{ + integer num_prims=llGetListLength(gXyTextPrims) << 2; + + integer i = 0; + + for (; i<=num_prims; ++i) + { + integer link = unpack(gXyTextPrims,i); + if (!link) + return; + + llSetLinkPrimitiveParamsFast( link,[ + PRIM_COLOR, FACE_1, color, 1.0, + PRIM_COLOR, FACE_2, color, 1.0, + PRIM_COLOR, FACE_3, color, 1.0, + PRIM_COLOR, FACE_4, color, 1.0, + PRIM_COLOR, FACE_5, color, 1.0 + ]); + } +} + +change_line_color(integer bank, vector color) +{ + + //get the bank offset and length + integer i = llList2Integer(gBankingData, (bank * BANK_STRIDE)); + integer bank_end = i + llList2Integer(gBankingData, (bank * BANK_STRIDE) + 1); + + for (; i < bank_end; ++i) + { + integer link = unpack(gXyTextPrims,i); + if (!link) + return; + + llSetLinkPrimitiveParamsFast( link,[ + PRIM_COLOR, FACE_1, color, 1.0, + PRIM_COLOR, FACE_2, color, 1.0, + PRIM_COLOR, FACE_3, color, 1.0, + PRIM_COLOR, FACE_4, color, 1.0, + PRIM_COLOR, FACE_5, color, 1.0 + ]); + } +} + + +init() +{ + integer num_prims=get_number_of_prims(); + string link_name; + integer bank=0; + integer prims_pointer=0; //"pointer" to the next entry to be used in the gXyTextPrims list. + + list temp_bank = []; + integer temp_bank_stride=2; + + //FIXME: font texture might should be per-bank + llMessageLinked(LINK_THIS, SET_FONT_TEXTURE, "", gFontTexture); + + // moving this before the prim scan so that the slaves properly configure themseves before + // any requests to display + llMessageLinked(LINK_THIS, SLAVE_RESET, "" , null_key); + + gXyTextPrims=[]; + integer x=0; + for (;x<64;++x) + { + gXyTextPrims = (gXyTextPrims = []) + gXyTextPrims + 0; //we need to pad out the list to make it easier to add things in any order later + } + + gBankingData = []; + @loop; + { + //loop over all prims, looking for ones in the current bank + for(x=0;x<=num_prims;++x) + { + link_name=llGetLinkName(x); + list tmp = llParseString2List(link_name, (list)"-", []); + if(llList2String(tmp,0) == "xyzzytext") + { + if (llList2Integer(tmp,1) == bank) + { + temp_bank += llList2Integer(tmp,2) + (list)x; + } + } + + } + + if (temp_bank != []) + { + //sort the current bank + temp_bank = llListSort(temp_bank, temp_bank_stride, TRUE); + + integer temp_len = llGetListLength(temp_bank); + + //store metadata + gBankingData += [prims_pointer, temp_len/temp_bank_stride, 0]; + + //repack the bank into the prim list + for (x = 0; x < temp_len; x += temp_bank_stride) + { + gXyTextPrims = pack_and_insert(gXyTextPrims, prims_pointer, llList2Integer(temp_bank, x + 1)); + ++prims_pointer; + } + ++bank; + temp_bank=[]; + jump loop; + } + } + + //llOwnerSay((string)llGetFreeMemory()); +} + + +default { + state_entry() { + // Initialize the character index. + ResetCharIndex(); + init(); + } + + on_rez(integer num) + { + llResetScript(); + } + + link_message(integer sender, integer channel, string data, key id) { + if (id==null_key) + id="0"; + + if (channel == DISPLAY_STRING) { + PassToRender(1,data, (integer)((string)id)); + } + else if (channel == DISPLAY_EXTENDED) { + PassToRender(2,data, (integer)((string)id)); + } + else if (channel == REMAP_INDICES) { + // Parse the message, splitting it up into index values. + list Parsed = llCSV2List(data); + integer i = 0; + // Go through the list and swap each pair of indices. + for (; i < llGetListLength(Parsed); i += 2) { + integer Index1 = ConvertIndex( llList2Integer(Parsed, i) ); + integer Index2 = ConvertIndex( llList2Integer(Parsed, i + 1) ); + + // Swap these index values. + string Value1 = llGetSubString(gCharIndex, Index1, Index1); + string Value2 = llGetSubString(gCharIndex, Index2, Index2); + + gCharIndex = llDeleteSubString(gCharIndex, Index1, Index1); + gCharIndex = llInsertString(gCharIndex, Index1, Value2); + + gCharIndex = llDeleteSubString(gCharIndex, Index2, Index2); + gCharIndex = llInsertString(gCharIndex, Index2, Value1); + } + } + else if (channel == RESCAN_LINKSET) + { + init(); + } + else if (channel == RESET_INDICES) { + // Restore the character index back to default settings. + ResetCharIndex(); + } + else if (channel == SET_FADE_OPTIONS) { + // Change the channel we listen to for cell commands, the + // starting character position to extract from, and + // special effect attributes. + list Parsed = llCSV2List(data); + gCellUseFading = (integer) llList2String(Parsed, 0); + gCellHoldDelay = (float) llList2String(Parsed, 1); + } + else if (channel == SET_FONT_TEXTURE) { + // Use the new texture instead of the current one. + gFontTexture = id; + } + else if (channel == SET_COLOR) { + change_color((vector)data); + } + else if (channel == SET_LINE_COLOR) { + change_line_color((integer)((string)id), (vector)data); + } + else if (channel == REGISTER_SLAVE) + { + if(!~llListFindList(gSlaveNames, (list)data)) + {//isn't registered yet + gSlaveNames += data; + gSlaveRegistered=TRUE; + //llOwnerSay((string)llGetListLength(gSlaveNames) + " Slave(s) Recognized: " + data); + } +// else +// {//it already exists +// llOwnerSay((string)llGetListLength(gSlaveNames) + " Slave, Existing Slave Recognized: " + data); +// } + llMessageLinked(LINK_THIS, SLAVE_RECOGNIZED, data , null_key); + } + } + + + changed(integer change) + { + if(change&CHANGED_INVENTORY) + { + if(gSlaveRegistered) + { + //by using negative indexes they don't need to be adjusted when an entry is deleted. + integer x = ~llGetListLength(gSlaveNames); + while(++x) + { + if (!~llGetInventoryType(llList2String(gSlaveNames, x))) + { + //llOwnerSay("Slave Removed: " + llList2String(gSlaveNames, x)); + gSlaveNames = llDeleteSubList(gSlaveNames, x, x); + } + } + gSlaveRegistered = !(gSlaveNames == []); + } + } + } +} + diff --git a/xytext_master_clean.lsl b/xytext_master_clean.lsl new file mode 100644 index 0000000..5c1c9a6 --- /dev/null +++ b/xytext_master_clean.lsl @@ -0,0 +1,521 @@ +//////////////////////////////////////////// +// XyzzyText v2.1 Script (Set Line Color) by Huney Jewell +// Modified to listen directly to scoreboard channel +// +//////////////////////////////////////////// + +/////////////// CONSTANTS /////////////////// +// XyText Message Map. +integer DISPLAY_STRING = 204000; +integer DISPLAY_EXTENDED = 204001; +integer REMAP_INDICES = 204002; +integer RESET_INDICES = 204003; +integer SET_FADE_OPTIONS = 204004; +integer SET_FONT_TEXTURE = 204005; +integer SET_LINE_COLOR = 204006; +integer SET_COLOR = 204007; +integer RESCAN_LINKSET = 204008; + +//internal API +integer REGISTER_SLAVE = 205000; +integer SLAVE_RECOGNIZED = 205001; +integer SLAVE_DISPLAY = 205003; +integer SLAVE_DISPLAY_EXTENDED = 205004; +integer SLAVE_RESET = 205005; + +// Communication channel from scoreboard +integer LEADERBOARD_CHANNEL = -12346; + +// This is an extended character escape sequence. +string ESCAPE_SEQUENCE = "\\e"; + +// This is used to get an index for the extended character. +string EXTENDED_INDEX = "12345"; + +// Face numbers. +integer FACE_1 = 3; +integer FACE_2 = 7; +integer FACE_3 = 4; +integer FACE_4 = 6; +integer FACE_5 = 1; + +// Used to hide the text after a fade-out. +key TRANSPARENT = "701917a8-d614-471f-13dd-5f4644e36e3c"; +key null_key = NULL_KEY; +///////////// END CONSTANTS //////////////// + +///////////// GLOBAL VARIABLES /////////////// +// This is the key of the font we are displaying. +key gFontTexture = "b2e7394f-5e54-aa12-6e1c-ef327b6bed9e"; +// All displayable characters. Default to ASCII order. +string gCharIndex; + +// This is whether or not to use the fade in/out special effect. +integer gCellUseFading = FALSE; +// This is how long to display the text before fading out (if using +// fading special effect). +// Note: < 0 means don't fade out. +float gCellHoldDelay = 1.0; + +integer gSlaveRegistered; +list gSlaveNames; + +integer BANK_STRIDE=3; //offset, length, highest_dirty +list gBankingData; + +list gXyTextPrims; //rather than make it generic, we just reuse this from the original script + +////////////////////////////////////////////////////////////// +// *** IMPORTANT: SET THIS FOR EACH XYZZYTEXT OBJECT *** +// +// Bank 0 = LEFT display (set MY_BANK = 0;) +// Bank 1 = MIDDLE display (set MY_BANK = 1;) +// Bank 2 = RIGHT display (set MY_BANK = 2;) +// +////////////////////////////////////////////////////////////// +integer MY_BANK = 1; // ← CHANGE THIS NUMBER FOR EACH OBJECT! + +/////////// END GLOBAL VARIABLES //////////// + +ResetCharIndex() { + gCharIndex = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`"; + gCharIndex += "abcdefghijklmnopqrstuvwxyz{|}~"; + gCharIndex += "\\n\\n\\n\\n\\n"; +} + +vector GetGridOffset(integer index) { + // Calculate the offset needed to display this character. + integer Row = index / 10; + integer Col = index % 10; + + // Return the offset in the texture. + return <-0.45 + 0.1 * Col, 0.45 - 0.1 * Row, 0.0>; +} + +ShowChars(integer link,vector grid_offset1, vector grid_offset2, vector grid_offset3, vector grid_offset4, vector grid_offset5) { + // Set the primitive textures directly. + + llSetLinkPrimitiveParamsFast( link,[ + PRIM_TEXTURE, FACE_1, (string)gFontTexture, <0.126, 0.1, 0>, grid_offset1 + <0.037, 0, 0>, 0.0, + PRIM_TEXTURE, FACE_2, (string)gFontTexture, <0.05, 0.1, 0>, grid_offset2, 0.0, + PRIM_TEXTURE, FACE_3, (string)gFontTexture, <-0.74, 0.1, 0>, grid_offset3 - <0.244, 0, 0>, 0.0, + PRIM_TEXTURE, FACE_4, (string)gFontTexture, <0.05, 0.1, 0>, grid_offset4, 0.0, + PRIM_TEXTURE, FACE_5, (string)gFontTexture, <0.126, 0.1, 0>, grid_offset5 - <0.037, 0, 0>, 0.0 + ]); +} + +RenderString(integer link, string str) { + // Get the grid positions for each pair of characters. + vector GridOffset1 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 0, 0)) ); + vector GridOffset2 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 1, 1)) ); + vector GridOffset3 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 2, 2)) ); + vector GridOffset4 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 3, 3)) ); + vector GridOffset5 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 4, 4)) ); + + // Use these grid positions to display the correct textures/offsets. + ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5); +} + +RenderWithEffects(integer link, string str) { + // Get the grid positions for each pair of characters. + vector GridOffset1 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 0, 0)) ); + vector GridOffset2 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 1, 1)) ); + vector GridOffset3 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 2, 2)) ); + vector GridOffset4 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 3, 3)) ); + vector GridOffset5 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 4, 4)) ); + + // First set the alpha to the lowest possible. + llSetLinkAlpha(link,0.05, ALL_SIDES); + + // Use these grid positions to display the correct textures/offsets. + ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5); // Now turn up the alpha until it is at full strength. + float Alpha = 0.10; + for (; Alpha <= 1.0; Alpha += 0.05) + llSetLinkAlpha(link,Alpha, ALL_SIDES); + // See if we want to fade out as well. + if (gCellHoldDelay < 0.0) + // No, bail out. (Just keep showing the string at full strength). + return; + // Hold the text for a while. + llSleep(gCellHoldDelay); + // Now fade out. + for (Alpha = 0.95; Alpha >= 0.05; Alpha -= 0.05) + llSetLinkAlpha(link,Alpha, ALL_SIDES); + // Make the text transparent to fully hide it. + llSetLinkTexture(link,TRANSPARENT, ALL_SIDES); +} + +integer RenderExtended(integer link, string str, integer render) { + // Look for escape sequences. + integer length = 0; + list Parsed = llParseString2List(str, [], (list)ESCAPE_SEQUENCE); + integer ParsedLen = llGetListLength(Parsed); + + // Create a list of index values to work with. + list Indices; + // We start with room for 5 indices. + integer IndicesLeft = 5; + + string Token; + integer Clipped; + integer LastWasEscapeSequence = FALSE; + // Work from left to right. + integer i = 0; + for (; i < ParsedLen && IndicesLeft > 0; ++i) { + Token = llList2String(Parsed, i); + + // If this is an escape sequence, just set the flag and move on. + if (Token == ESCAPE_SEQUENCE) { + LastWasEscapeSequence = TRUE; + } + else { // Token != ESCAPE_SEQUENCE + // Otherwise this is a normal token. Check its length. + Clipped = FALSE; + integer TokenLength = llStringLength(Token); + // Clip if necessary. + if (TokenLength > IndicesLeft) { + TokenLength = llStringLength(Token = llGetSubString(Token, 0, IndicesLeft - 1)); + IndicesLeft = 0; + Clipped = TRUE; + } + else + IndicesLeft -= TokenLength; + + // Was the previous token an escape sequence? + if (LastWasEscapeSequence) { + // Yes, the first character is an escape character, the rest are normal. + length += 2 + TokenLength; + if(render) + { + // This is the extended character. + Indices += (llSubStringIndex(EXTENDED_INDEX, llGetSubString(Token, 0, 0)) + 95); + + // These are the normal characters. + integer j = 1; + for(; j < TokenLength; ++j) { + Indices += llSubStringIndex(gCharIndex, llGetSubString(Token, j, j)); + } + } + LastWasEscapeSequence = FALSE; + } + else { + // Nope, just normal characters. + length += TokenLength; + if(render) + { + // Just add the characters normally. + integer j = 0; + for(; j < TokenLength; ++j) { + Indices += llSubStringIndex(gCharIndex, llGetSubString(Token, j, j)); + } + } + } + + // Bail out if this was a clipped token. + if (Clipped) + i = ParsedLen; + } + } + + if(render) { + // Make sure we have 5 indices. + integer IndicesCount = llGetListLength(Indices); + for (; IndicesCount < 5; ++IndicesCount) { + Indices += (llSubStringIndex(gCharIndex, " ")); + } + + // Use the indices to create grid positions. + vector GridOffset1 = GetGridOffset( llList2Integer(Indices, 0) ); + vector GridOffset2 = GetGridOffset( llList2Integer(Indices, 1) ); + vector GridOffset3 = GetGridOffset( llList2Integer(Indices, 2) ); + vector GridOffset4 = GetGridOffset( llList2Integer(Indices, 3) ); + vector GridOffset5 = GetGridOffset( llList2Integer(Indices, 4) ); + + // Use these grid positions to display the correct textures/offsets. + ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5); + } + return length; +} + +integer ConvertIndex(integer index) { + // This function is used to convert from an ASCII based index to our + // internal representation. + if (index >= 32) + // ASCII character, subtract 32. + return index - 32; + else if (index == 10) + // Newline character. + return 94; + else + // Everything else is a space. + return 0; +} + +PassToRender(integer render_type, string message, integer bank) { + if(bank != MY_BANK) { + // This message is not for our bank, ignore it + return; + } + + list lines = llParseString2List(message, ["\n"], []); + integer line_count = llGetListLength(lines); + + //get the bank offset and length + integer i = llList2Integer(gBankingData, (bank * BANK_STRIDE)); + integer bank_end = i + llList2Integer(gBankingData, (bank * BANK_STRIDE) + 1); + + for(; i < bank_end && (i - llList2Integer(gBankingData, (bank * BANK_STRIDE))) < line_count; ++i) { + integer link = unpack(gXyTextPrims, i); + if(link) { + string line = llList2String(lines, i - llList2Integer(gBankingData, (bank * BANK_STRIDE))); + + if(render_type == 1) { + RenderString(link, line); + } else if(render_type == 2) { + RenderExtended(link, line, TRUE); + } + } + } +} + +integer get_number_of_prims() +{//ignores avatars. + integer a = llGetNumberOfPrims(); + //Mono tweak + vector size = llGetAgentSize(llGetLinkKey(a)); + while(size.z > 0) + { + --a; + size = llGetAgentSize(llGetLinkKey(a)); + } + return a; +} + +//functions to pack 8-bit shorts into ints +list pack_and_insert(list in_list, integer pos, integer value) +{ + //Safe optimized version + integer index = pos >> 2; + return llListReplaceList(in_list, (list)(llList2Integer(in_list, index) | (value << ((pos & 3) << 3))), index, index); +} + +integer unpack(list in_list, integer pos) +{ + return (llList2Integer(in_list, pos >> 2) >> ((pos & 3) << 3)) & 0x000000FF;//unsigned +} + +change_color(vector color) +{ + integer num_prims=llGetListLength(gXyTextPrims) << 2; + + integer i = 0; + + for (; i<=num_prims; ++i) + { + integer link = unpack(gXyTextPrims,i); + if (!link) + return; + + llSetLinkPrimitiveParamsFast( link,[ + PRIM_COLOR, FACE_1, color, 1.0, + PRIM_COLOR, FACE_2, color, 1.0, + PRIM_COLOR, FACE_3, color, 1.0, + PRIM_COLOR, FACE_4, color, 1.0, + PRIM_COLOR, FACE_5, color, 1.0 + ]); + } +} + +change_line_color(integer bank, vector color) +{ + + //get the bank offset and length + integer i = llList2Integer(gBankingData, (bank * BANK_STRIDE)); + integer bank_end = i + llList2Integer(gBankingData, (bank * BANK_STRIDE) + 1); + + for (; i < bank_end; ++i) + { + integer link = unpack(gXyTextPrims,i); + if (!link) + return; + + llSetLinkPrimitiveParamsFast( link,[ + PRIM_COLOR, FACE_1, color, 1.0, + PRIM_COLOR, FACE_2, color, 1.0, + PRIM_COLOR, FACE_3, color, 1.0, + PRIM_COLOR, FACE_4, color, 1.0, + PRIM_COLOR, FACE_5, color, 1.0 + ]); + } +} + + +init() +{ + integer num_prims=get_number_of_prims(); + string link_name; + integer prims_pointer=0; + + list temp_bank = []; + integer temp_bank_stride=2; + + //FIXME: font texture might should be per-bank + llMessageLinked(LINK_THIS, SET_FONT_TEXTURE, "", gFontTexture); + + // moving this before the prim scan so that the slaves properly configure themseves before + // any requests to display + llMessageLinked(LINK_THIS, SLAVE_RESET, "" , null_key); + + gXyTextPrims=[]; + integer x=0; + for (;x<64;++x) + { + gXyTextPrims = (gXyTextPrims = []) + gXyTextPrims + 0; //we need to pad out the list to make it easier to add things in any order later + } + + gBankingData = []; + + // Only look for prims that match MY_BANK + for(x=0;x<=num_prims;++x) + { + link_name=llGetLinkName(x); + + list tmp = llParseString2List(link_name, (list)"-", []); + if(llList2String(tmp,0) == "xyzzytext") + { + integer prim_bank = llList2Integer(tmp,1); + integer prim_position = llList2Integer(tmp,2); + + if (prim_bank == MY_BANK) + { + temp_bank += prim_position + (list)x; + } + } + } + + if (temp_bank != []) + { + //sort the current bank by position + temp_bank = llListSort(temp_bank, temp_bank_stride, TRUE); + + integer temp_len = llGetListLength(temp_bank); + + //store metadata for MY_BANK at position MY_BANK in the banking data + while(llGetListLength(gBankingData) <= (MY_BANK * BANK_STRIDE + 2)) { + gBankingData += [0, 0, 0]; // pad the list + } + + gBankingData = llListReplaceList(gBankingData, [prims_pointer, temp_len/temp_bank_stride, 0], + MY_BANK * BANK_STRIDE, MY_BANK * BANK_STRIDE + 2); + + //repack the bank into the prim list + for (x = 0; x < temp_len; x += temp_bank_stride) + { + integer link_num = llList2Integer(temp_bank, x + 1); + gXyTextPrims = pack_and_insert(gXyTextPrims, prims_pointer, link_num); + ++prims_pointer; + } + } + + llOwnerSay("XyzzyText Bank " + (string)MY_BANK + " ready with " + (string)prims_pointer + " prims"); +} + + +default { + state_entry() { + // Initialize the character index. + ResetCharIndex(); + + // Listen for messages from scoreboard + llListen(LEADERBOARD_CHANNEL, "", "", ""); + + init(); + } + + on_rez(integer num) + { + llResetScript(); + } + + listen(integer channel, string name, key id, string message) { + if (channel == LEADERBOARD_CHANNEL) { + if (MY_BANK == 0 && llSubStringIndex(message, "LEFT_TEXT|") == 0) { + // This is bank 0 (left), process LEFT_TEXT messages + string leftText = llGetSubString(message, 10, -1); + PassToRender(1, leftText, 0); + + } else if (MY_BANK == 1 && llSubStringIndex(message, "MIDDLE_TEXT|") == 0) { + // This is bank 1 (middle), process MIDDLE_TEXT messages + string middleText = llGetSubString(message, 12, -1); + PassToRender(1, middleText, 1); + + } else if (MY_BANK == 2 && llSubStringIndex(message, "RIGHT_TEXT|") == 0) { + // This is bank 2 (right), process RIGHT_TEXT messages + string rightText = llGetSubString(message, 11, -1); + PassToRender(1, rightText, 2); + + } else if (message == "CLEAR_LEADERBOARD") { + // Clear display for this bank + PassToRender(1, " ", MY_BANK); + } + } + } + + link_message(integer sender, integer channel, string data, key id) { + if (id==null_key) + id="0"; + + if (channel == DISPLAY_STRING) { + PassToRender(1,data, (integer)((string)id)); + } + else if (channel == DISPLAY_EXTENDED) { + PassToRender(2,data, (integer)((string)id)); + } + else if (channel == REMAP_INDICES) { + // Parse the message, splitting it up into index values. + list Parsed = llCSV2List(data); + integer i = 0; + // Go through the list and swap each pair of indices. + for (; i < llGetListLength(Parsed); i += 2) { + integer Index1 = ConvertIndex( llList2Integer(Parsed, i) ); + integer Index2 = ConvertIndex( llList2Integer(Parsed, i + 1) ); + + // Swap these index values. + string Value1 = llGetSubString(gCharIndex, Index1, Index1); + string Value2 = llGetSubString(gCharIndex, Index2, Index2); + + gCharIndex = llDeleteSubString(gCharIndex, Index1, Index1); + gCharIndex = llInsertString(gCharIndex, Index1, Value2); + + gCharIndex = llDeleteSubString(gCharIndex, Index2, Index2); + gCharIndex = llInsertString(gCharIndex, Index2, Value1); + } + } + else if (channel == RESCAN_LINKSET) + { + init(); + } + else if (channel == RESET_INDICES) { + // Restore the character index back to default settings. + ResetCharIndex(); + } + else if (channel == SET_FADE_OPTIONS) { + list Parsed = llCSV2List(data); + gCellUseFading = llList2Integer(Parsed, 0); + gCellHoldDelay = llList2Float(Parsed, 1); + } + else if (channel == SET_FONT_TEXTURE) { + gFontTexture = id; + } + else if (channel == SET_LINE_COLOR) { + change_line_color((integer)data, (vector)((string)id)); + } + else if (channel == SET_COLOR) { + change_color((vector)data); + } + else if (channel == REGISTER_SLAVE) { + gSlaveNames += data; + llMessageLinked(sender, SLAVE_RECOGNIZED, "", ""); + } + } +} diff --git a/xytext_master_with_listener.lsl b/xytext_master_with_listener.lsl new file mode 100644 index 0000000..b682774 --- /dev/null +++ b/xytext_master_with_listener.lsl @@ -0,0 +1,540 @@ +//////////////////////////////////////////// +// XyzzyText v2.1 Script (Set Line Color) by Huney Jewell +// Modified to listen directly to scoreboard channel +// +//////////////////////////////////////////// + +/////////////// CONSTANTS /////////////////// +// XyText Message Map. +integer DISPLAY_STRING = 204000; +integer DISPLAY_EXTENDED = 204001; +integer REMAP_INDICES = 204002; +integer RESET_INDICES = 204003; +integer SET_FADE_OPTIONS = 204004; +integer SET_FONT_TEXTURE = 204005; +integer SET_LINE_COLOR = 204006; +integer SET_COLOR = 204007; +integer RESCAN_LINKSET = 204008; + +//internal API +integer REGISTER_SLAVE = 205000; +integer SLAVE_RECOGNIZED = 205001; +integer SLAVE_DISPLAY = 205003; +integer SLAVE_DISPLAY_EXTENDED = 205004; +integer SLAVE_RESET = 205005; + +// Communication channel from scoreboard +integer LEADERBOARD_CHANNEL = -12346; + +// This is an extended character escape sequence. +string ESCAPE_SEQUENCE = "\\e"; + +// This is used to get an index for the extended character. +string EXTENDED_INDEX = "12345"; + +// Face numbers. +integer FACE_1 = 3; +integer FACE_2 = 7; +integer FACE_3 = 4; +integer FACE_4 = 6; +integer FACE_5 = 1; + +// Used to hide the text after a fade-out. +key TRANSPARENT = "701917a8-d614-471f-13dd-5f4644e36e3c"; +key null_key = NULL_KEY; +///////////// END CONSTANTS //////////////// + +///////////// GLOBAL VARIABLES /////////////// +// This is the key of the font we are displaying. +key gFontTexture = "b2e7394f-5e54-aa12-6e1c-ef327b6bed9e"; +// All displayable characters. Default to ASCII order. +string gCharIndex; + +// This is whether or not to use the fade in/out special effect. +integer gCellUseFading = FALSE; +// This is how long to display the text before fading out (if using +// fading special effect). +// Note: < 0 means don't fade out. +float gCellHoldDelay = 1.0; + +integer gSlaveRegistered; +list gSlaveNames; + +integer BANK_STRIDE=3; //offset, length, highest_dirty +list gBankingData; + +list gXyTextPrims; //rather than make it generic, we just reuse this from the original script + +// Bank configuration - SET THIS FOR EACH OBJECT +integer MY_BANK = 1; // Change this: 0 for left, 1 for middle, 2 for right + +/////////// END GLOBAL VARIABLES //////////// + +ResetCharIndex() { + gCharIndex = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`"; + gCharIndex += "abcdefghijklmnopqrstuvwxyz{|}~"; + gCharIndex += "\\n\\n\\n\\n\\n"; +} + +vector GetGridOffset(integer index) { + // Calculate the offset needed to display this character. + integer Row = index / 10; + integer Col = index % 10; + + // Return the offset in the texture. + return <-0.45 + 0.1 * Col, 0.45 - 0.1 * Row, 0.0>; +} + +ShowChars(integer link,vector grid_offset1, vector grid_offset2, vector grid_offset3, vector grid_offset4, vector grid_offset5) { + // Set the primitive textures directly. + + // <-0.256, 0, 0> + // <0, 0, 0> + // <0.130, 0, 0> + // <0, 0, 0> + // <-0.74, 0, 0> + + llSetLinkPrimitiveParamsFast( link,[ + PRIM_TEXTURE, FACE_1, (string)gFontTexture, <0.126, 0.1, 0>, grid_offset1 + <0.037, 0, 0>, 0.0, + PRIM_TEXTURE, FACE_2, (string)gFontTexture, <0.05, 0.1, 0>, grid_offset2, 0.0, + PRIM_TEXTURE, FACE_3, (string)gFontTexture, <-0.74, 0.1, 0>, grid_offset3 - <0.244, 0, 0>, 0.0, + PRIM_TEXTURE, FACE_4, (string)gFontTexture, <0.05, 0.1, 0>, grid_offset4, 0.0, + PRIM_TEXTURE, FACE_5, (string)gFontTexture, <0.126, 0.1, 0>, grid_offset5 - <0.037, 0, 0>, 0.0 + ]); +} + +RenderString(integer link, string str) { + // Get the grid positions for each pair of characters. + vector GridOffset1 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 0, 0)) ); + vector GridOffset2 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 1, 1)) ); + vector GridOffset3 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 2, 2)) ); + vector GridOffset4 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 3, 3)) ); + vector GridOffset5 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 4, 4)) ); + + // Use these grid positions to display the correct textures/offsets. + ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5); +} + +RenderWithEffects(integer link, string str) { + // Get the grid positions for each pair of characters. + vector GridOffset1 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 0, 0)) ); + vector GridOffset2 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 1, 1)) ); + vector GridOffset3 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 2, 2)) ); + vector GridOffset4 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 3, 3)) ); + vector GridOffset5 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 4, 4)) ); + + // First set the alpha to the lowest possible. + llSetLinkAlpha(link,0.05, ALL_SIDES); + + // Use these grid positions to display the correct textures/offsets. + ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5); // Now turn up the alpha until it is at full strength. + float Alpha = 0.10; + for (; Alpha <= 1.0; Alpha += 0.05) + llSetLinkAlpha(link,Alpha, ALL_SIDES); + // See if we want to fade out as well. + if (gCellHoldDelay < 0.0) + // No, bail out. (Just keep showing the string at full strength). + return; + // Hold the text for a while. + llSleep(gCellHoldDelay); + // Now fade out. + for (Alpha = 0.95; Alpha >= 0.05; Alpha -= 0.05) + llSetLinkAlpha(link,Alpha, ALL_SIDES); + // Make the text transparent to fully hide it. + llSetLinkTexture(link,TRANSPARENT, ALL_SIDES); +} + +integer RenderExtended(integer link, string str, integer render) { + // Look for escape sequences. + integer length = 0; + list Parsed = llParseString2List(str, [], (list)ESCAPE_SEQUENCE); + integer ParsedLen = llGetListLength(Parsed); + + // Create a list of index values to work with. + list Indices; + // We start with room for 5 indices. + integer IndicesLeft = 5; + + string Token; + integer Clipped; + integer LastWasEscapeSequence = FALSE; + // Work from left to right. + integer i = 0; + for (; i < ParsedLen && IndicesLeft > 0; ++i) { + Token = llList2String(Parsed, i); + + // If this is an escape sequence, just set the flag and move on. + if (Token == ESCAPE_SEQUENCE) { + LastWasEscapeSequence = TRUE; + } + else { // Token != ESCAPE_SEQUENCE + // Otherwise this is a normal token. Check its length. + Clipped = FALSE; + integer TokenLength = llStringLength(Token); + // Clip if necessary. + if (TokenLength > IndicesLeft) { + TokenLength = llStringLength(Token = llGetSubString(Token, 0, IndicesLeft - 1)); + IndicesLeft = 0; + Clipped = TRUE; + } + else + IndicesLeft -= TokenLength; + + // Was the previous token an escape sequence? + if (LastWasEscapeSequence) { + // Yes, the first character is an escape character, the rest are normal. + length += 2 + TokenLength; + if(render) + { + // This is the extended character. + Indices += (llSubStringIndex(EXTENDED_INDEX, llGetSubString(Token, 0, 0)) + 95); + + // These are the normal characters. + integer j = 1; + for(; j < TokenLength; ++j) { + Indices += llSubStringIndex(gCharIndex, llGetSubString(Token, j, j)); + } + } + LastWasEscapeSequence = FALSE; + } + else { + // Nope, just normal characters. + length += TokenLength; + if(render) + { + // Just add the characters normally. + integer j = 0; + for(; j < TokenLength; ++j) { + Indices += llSubStringIndex(gCharIndex, llGetSubString(Token, j, j)); + } + } + } + + // Bail out if this was a clipped token. + if (Clipped) + i = ParsedLen; + } + } + + if(render) { + // Make sure we have 5 indices. + integer IndicesCount = llGetListLength(Indices); + for (; IndicesCount < 5; ++IndicesCount) { + Indices += (llSubStringIndex(gCharIndex, " ")); + } + + // Use the indices to create grid positions. + vector GridOffset1 = GetGridOffset( llList2Integer(Indices, 0) ); + vector GridOffset2 = GetGridOffset( llList2Integer(Indices, 1) ); + vector GridOffset3 = GetGridOffset( llList2Integer(Indices, 2) ); + vector GridOffset4 = GetGridOffset( llList2Integer(Indices, 3) ); + vector GridOffset5 = GetGridOffset( llList2Integer(Indices, 4) ); + + // Use these grid positions to display the correct textures/offsets. + ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5); + } + return length; +} + +integer ConvertIndex(integer index) { + // This function is used to convert from an ASCII based index to our + // internal representation. + if (index >= 32) + // ASCII character, subtract 32. + return index - 32; + else if (index == 10) + // Newline character. + return 94; + else + // Everything else is a space. + return 0; +} + +PassToRender(integer render_type, string message, integer bank) { + if(bank != MY_BANK) { + // This message is not for our bank, ignore it + return; + } + + llOwnerSay("DEBUG: Bank " + (string)MY_BANK + " received message: " + message); + + list lines = llParseString2List(message, ["\n"], []); + integer line_count = llGetListLength(lines); + + //get the bank offset and length + integer i = llList2Integer(gBankingData, (bank * BANK_STRIDE)); + integer bank_end = i + llList2Integer(gBankingData, (bank * BANK_STRIDE) + 1); + + for(; i < bank_end && (i - llList2Integer(gBankingData, (bank * BANK_STRIDE))) < line_count; ++i) { + integer link = unpack(gXyTextPrims, i); + if(link) { + string line = llList2String(lines, i - llList2Integer(gBankingData, (bank * BANK_STRIDE))); + + if(render_type == 1) { + RenderString(link, line); + } else if(render_type == 2) { + RenderExtended(link, line, TRUE); + } + } + } +} + +integer get_number_of_prims() +{//ignores avatars. + integer a = llGetNumberOfPrims(); + //Mono tweak + vector size = llGetAgentSize(llGetLinkKey(a)); + while(size.z > 0) + { + --a; + size = llGetAgentSize(llGetLinkKey(a)); + } + return a; +} + +//functions to pack 8-bit shorts into ints +list pack_and_insert(list in_list, integer pos, integer value) +{ + //Safe optimized version + integer index = pos >> 2; + return llListReplaceList(in_list, (list)(llList2Integer(in_list, index) | (value << ((pos & 3) << 3))), index, index); +} + +integer unpack(list in_list, integer pos) +{ + return (llList2Integer(in_list, pos >> 2) >> ((pos & 3) << 3)) & 0x000000FF;//unsigned +} + +change_color(vector color) +{ + integer num_prims=llGetListLength(gXyTextPrims) << 2; + + integer i = 0; + + for (; i<=num_prims; ++i) + { + integer link = unpack(gXyTextPrims,i); + if (!link) + return; + + llSetLinkPrimitiveParamsFast( link,[ + PRIM_COLOR, FACE_1, color, 1.0, + PRIM_COLOR, FACE_2, color, 1.0, + PRIM_COLOR, FACE_3, color, 1.0, + PRIM_COLOR, FACE_4, color, 1.0, + PRIM_COLOR, FACE_5, color, 1.0 + ]); + } +} + +change_line_color(integer bank, vector color) +{ + + //get the bank offset and length + integer i = llList2Integer(gBankingData, (bank * BANK_STRIDE)); + integer bank_end = i + llList2Integer(gBankingData, (bank * BANK_STRIDE) + 1); + + for (; i < bank_end; ++i) + { + integer link = unpack(gXyTextPrims,i); + if (!link) + return; + + llSetLinkPrimitiveParamsFast( link,[ + PRIM_COLOR, FACE_1, color, 1.0, + PRIM_COLOR, FACE_2, color, 1.0, + PRIM_COLOR, FACE_3, color, 1.0, + PRIM_COLOR, FACE_4, color, 1.0, + PRIM_COLOR, FACE_5, color, 1.0 + ]); + } +} + + +init() +{ + integer num_prims=get_number_of_prims(); + string link_name; + integer prims_pointer=0; + + list temp_bank = []; + integer temp_bank_stride=2; + + //FIXME: font texture might should be per-bank + llMessageLinked(LINK_THIS, SET_FONT_TEXTURE, "", gFontTexture); + + // moving this before the prim scan so that the slaves properly configure themseves before + // any requests to display + llMessageLinked(LINK_THIS, SLAVE_RESET, "" , null_key); + + gXyTextPrims=[]; + integer x=0; + for (;x<64;++x) + { + gXyTextPrims = (gXyTextPrims = []) + gXyTextPrims + 0; //we need to pad out the list to make it easier to add things in any order later + } + + gBankingData = []; + + // Only look for prims that match MY_BANK + llOwnerSay("DEBUG: Scanning " + (string)num_prims + " prims for bank " + (string)MY_BANK); + + for(x=0;x<=num_prims;++x) + { + link_name=llGetLinkName(x); + llOwnerSay("DEBUG: Prim " + (string)x + " name: '" + link_name + "'"); + + list tmp = llParseString2List(link_name, (list)"-", []); + if(llList2String(tmp,0) == "xyzzytext") + { + integer prim_bank = llList2Integer(tmp,1); + integer prim_position = llList2Integer(tmp,2); + + llOwnerSay("DEBUG: Found xyzzytext prim - bank: " + (string)prim_bank + ", position: " + (string)prim_position); + + if (prim_bank == MY_BANK) + { + llOwnerSay("DEBUG: Adding prim " + (string)x + " to bank " + (string)MY_BANK); + temp_bank += prim_position + (list)x; + } + } + } + + if (temp_bank != []) + { + llOwnerSay("DEBUG: Found " + (string)(llGetListLength(temp_bank)/temp_bank_stride) + " prims for bank " + (string)MY_BANK); + + //sort the current bank by position + temp_bank = llListSort(temp_bank, temp_bank_stride, TRUE); + + integer temp_len = llGetListLength(temp_bank); + + //store metadata for MY_BANK at position MY_BANK in the banking data + while(llGetListLength(gBankingData) <= (MY_BANK * BANK_STRIDE + 2)) { + gBankingData += [0, 0, 0]; // pad the list + } + + gBankingData = llListReplaceList(gBankingData, [prims_pointer, temp_len/temp_bank_stride, 0], + MY_BANK * BANK_STRIDE, MY_BANK * BANK_STRIDE + 2); + + //repack the bank into the prim list + for (x = 0; x < temp_len; x += temp_bank_stride) + { + integer link_num = llList2Integer(temp_bank, x + 1); + llOwnerSay("DEBUG: Packing prim " + (string)link_num + " at position " + (string)prims_pointer); + gXyTextPrims = pack_and_insert(gXyTextPrims, prims_pointer, link_num); + ++prims_pointer; + } + } else { + llOwnerSay("DEBUG: No prims found for bank " + (string)MY_BANK); + } + + llOwnerSay("XyzzyText initialized for bank " + (string)MY_BANK + " with " + (string)prims_pointer + " prims"); +} + + +default { + state_entry() { + // Initialize the character index. + ResetCharIndex(); + + // Listen for messages from scoreboard + llListen(LEADERBOARD_CHANNEL, "", "", ""); + llOwnerSay("XyzzyText Bank " + (string)MY_BANK + " ready - listening on channel " + (string)LEADERBOARD_CHANNEL); + + init(); + } + + on_rez(integer num) + { + llResetScript(); + } + + listen(integer channel, string name, key id, string message) { + if (channel == LEADERBOARD_CHANNEL) { + llOwnerSay("DEBUG: Bank " + (string)MY_BANK + " heard: " + message); + + if (MY_BANK == 0 && llSubStringIndex(message, "LEFT_TEXT|") == 0) { + // This is bank 0 (left), process LEFT_TEXT messages + string leftText = llGetSubString(message, 10, -1); + llOwnerSay("DEBUG: Bank 0 processing LEFT text: " + leftText); + PassToRender(1, leftText, 0); + + } else if (MY_BANK == 1 && llSubStringIndex(message, "MIDDLE_TEXT|") == 0) { + // This is bank 1 (middle), process MIDDLE_TEXT messages + string middleText = llGetSubString(message, 12, -1); + llOwnerSay("DEBUG: Bank 1 processing MIDDLE text: " + middleText); + PassToRender(1, middleText, 1); + + } else if (MY_BANK == 2 && llSubStringIndex(message, "RIGHT_TEXT|") == 0) { + // This is bank 2 (right), process RIGHT_TEXT messages + string rightText = llGetSubString(message, 11, -1); + llOwnerSay("DEBUG: Bank 2 processing RIGHT text: " + rightText); + PassToRender(1, rightText, 2); + + } else if (message == "CLEAR_LEADERBOARD") { + // Clear display for this bank + llOwnerSay("DEBUG: Bank " + (string)MY_BANK + " clearing display"); + PassToRender(1, " ", MY_BANK); + } + } + } + + link_message(integer sender, integer channel, string data, key id) { + if (id==null_key) + id="0"; + + if (channel == DISPLAY_STRING) { + PassToRender(1,data, (integer)((string)id)); + } + else if (channel == DISPLAY_EXTENDED) { + PassToRender(2,data, (integer)((string)id)); + } + else if (channel == REMAP_INDICES) { + // Parse the message, splitting it up into index values. + list Parsed = llCSV2List(data); + integer i = 0; + // Go through the list and swap each pair of indices. + for (; i < llGetListLength(Parsed); i += 2) { + integer Index1 = ConvertIndex( llList2Integer(Parsed, i) ); + integer Index2 = ConvertIndex( llList2Integer(Parsed, i + 1) ); + + // Swap these index values. + string Value1 = llGetSubString(gCharIndex, Index1, Index1); + string Value2 = llGetSubString(gCharIndex, Index2, Index2); + + gCharIndex = llDeleteSubString(gCharIndex, Index1, Index1); + gCharIndex = llInsertString(gCharIndex, Index1, Value2); + + gCharIndex = llDeleteSubString(gCharIndex, Index2, Index2); + gCharIndex = llInsertString(gCharIndex, Index2, Value1); + } + } + else if (channel == RESCAN_LINKSET) + { + init(); + } + else if (channel == RESET_INDICES) { + // Restore the character index back to default settings. + ResetCharIndex(); + } + else if (channel == SET_FADE_OPTIONS) { + list Parsed = llCSV2List(data); + gCellUseFading = llList2Integer(Parsed, 0); + gCellHoldDelay = llList2Float(Parsed, 1); + } + else if (channel == SET_FONT_TEXTURE) { + gFontTexture = id; + } + else if (channel == SET_LINE_COLOR) { + change_line_color((integer)data, (vector)((string)id)); + } + else if (channel == SET_COLOR) { + change_color((vector)data); + } + else if (channel == REGISTER_SLAVE) { + gSlaveNames += data; + llMessageLinked(sender, SLAVE_RECOGNIZED, "", ""); + } + } +} diff --git a/xytext_slave.lsl b/xytext_slave.lsl new file mode 100644 index 0000000..92e7b0c --- /dev/null +++ b/xytext_slave.lsl @@ -0,0 +1,281 @@ +//////////////////////////////////////////// +// XyText v2.0 SLAVE Script (5 Face, Single Texture) +// +// Modified by Thraxis Epsilon and Gigs Taggart 5/2007 +// Rewrite to allow one-script-per-object operation +// +// Modified by Kermitt Quirk 19/01/2006 +// To add support for 5 face prim instead of 3 +// +// Originally Written by Xylor Baysklef +// +// +//////////////////////////////////////////// + + +integer REMAP_INDICES = 204002; +integer RESET_INDICES = 204003; + +//internal API +integer REGISTER_SLAVE = 205000; +integer SLAVE_RECOGNIZED = 205001; +integer SLAVE_DISPLAY = 205003; +integer SET_FONT_TEXTURE = 204005; + +integer SLAVE_DISPLAY_EXTENDED = 205004; +integer SLAVE_RESET = 205005; + + +// This is an extended character escape sequence. +string ESCAPE_SEQUENCE = "\e"; + +// This is used to get an index for the extended character. +string EXTENDED_INDEX = "12345"; + +// Face numbers. +integer FACE_1 = 3; +integer FACE_2 = 7; +integer FACE_3 = 4; +integer FACE_4 = 6; +integer FACE_5 = 1; + + +///////////// GLOBAL VARIABLES /////////////// +// This is the key of the font we are displaying. +key gFontTexture = "b2e7394f-5e54-aa12-6e1c-ef327b6bed9e"; +// All displayable characters. Default to ASCII order. +string gCharIndex; + +integer gActive; //if we are recognized, this is true +/////////// END GLOBAL VARIABLES //////////// + +ResetCharIndex() { + gCharIndex = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`"; + gCharIndex += "abcdefghijklmnopqrstuvwxyz{|}~"; + gCharIndex += "\n\n\n\n\n"; +} + +vector GetGridOffset(integer index) { + // Calculate the offset needed to display this character. + integer Row = index / 10; + integer Col = index % 10; + + // Return the offset in the texture. + return <-0.45 + 0.1 * Col, 0.45 - 0.1 * Row, 0.0>; +} + +ShowChars(integer link,vector grid_offset1, vector grid_offset2, vector grid_offset3, vector grid_offset4, vector grid_offset5) { + // Set the primitive textures directly. + + // <-0.256, 0, 0> + // <0, 0, 0> + // <0.130, 0, 0> + // <0, 0, 0> + // <-0.74, 0, 0> + + llSetLinkPrimitiveParamsFast( link,[ + PRIM_TEXTURE, FACE_1, (string)gFontTexture, <0.126, 0.1, 0>, grid_offset1 + <0.037, 0, 0>, 0.0, + PRIM_TEXTURE, FACE_2, (string)gFontTexture, <0.05, 0.1, 0>, grid_offset2, 0.0, + PRIM_TEXTURE, FACE_3, (string)gFontTexture, <-0.74, 0.1, 0>, grid_offset3 - <0.244, 0, 0>, 0.0, + PRIM_TEXTURE, FACE_4, (string)gFontTexture, <0.05, 0.1, 0>, grid_offset4, 0.0, + PRIM_TEXTURE, FACE_5, (string)gFontTexture, <0.126, 0.1, 0>, grid_offset5 - <0.037, 0, 0>, 0.0 + ]); +} + +RenderString(integer link, string str) { + // Get the grid positions for each pair of characters. + vector GridOffset1 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 0, 0)) ); + vector GridOffset2 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 1, 1)) ); + vector GridOffset3 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 2, 2)) ); + vector GridOffset4 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 3, 3)) ); + vector GridOffset5 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 4, 4)) ); + + // Use these grid positions to display the correct textures/offsets. + ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5); +} + +RenderExtended(integer link, string str) { + // Look for escape sequences. + list Parsed = llParseString2List(str, [], [ESCAPE_SEQUENCE]); + integer ParsedLen = llGetListLength(Parsed); + + // Create a list of index values to work with. + list Indices; + // We start with room for 5 indices. + integer IndicesLeft = 5; + + integer i = 0; + string Token; + integer Clipped; + integer LastWasEscapeSequence = FALSE; + // Work from left to right. + for (; i < ParsedLen && IndicesLeft > 0; ++i) { + Token = llList2String(Parsed, i); + + // If this is an escape sequence, just set the flag and move on. + if (Token == ESCAPE_SEQUENCE) { + LastWasEscapeSequence = TRUE; + } + else { // Token != ESCAPE_SEQUENCE + // Otherwise this is a normal token. Check its length. + Clipped = FALSE; + integer TokenLength = llStringLength(Token); + // Clip if necessary. + if (TokenLength > IndicesLeft) { + Token = llGetSubString(Token, 0, IndicesLeft - 1); + TokenLength = llStringLength(Token); + IndicesLeft = 0; + Clipped = TRUE; + } + else + IndicesLeft -= TokenLength; + + // Was the previous token an escape sequence? + if (LastWasEscapeSequence) { + // Yes, the first character is an escape character, the rest are normal. + + // This is the extended character. + Indices += (llSubStringIndex(EXTENDED_INDEX, llGetSubString(Token, 0, 0)) + 95); + + // These are the normal characters. + integer j = 1; + for (; j < TokenLength; ++j) + Indices += llSubStringIndex(gCharIndex, llGetSubString(Token, j, j)); + } + else { // Normal string. + // Just add the characters normally. + integer j; + for (j = 0; j < TokenLength; ++j) + Indices += llSubStringIndex(gCharIndex, llGetSubString(Token, j, j)); + } + + // Unset this flag, since this was not an escape sequence. + LastWasEscapeSequence = FALSE; + } + } + + // Use the indices to create grid positions. + vector GridOffset1 = GetGridOffset( llList2Integer(Indices, 0) ); + vector GridOffset2 = GetGridOffset( llList2Integer(Indices, 1) ); + vector GridOffset3 = GetGridOffset( llList2Integer(Indices, 2) ); + vector GridOffset4 = GetGridOffset( llList2Integer(Indices, 3) ); + vector GridOffset5 = GetGridOffset( llList2Integer(Indices, 4) ); + + // Use these grid positions to display the correct textures/offsets. + ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5); +} + +integer ConvertIndex(integer index) { + // This converts from an ASCII based index to our indexing scheme. + if (index >= 32) // ' ' or higher + index -= 32; + else { // index < 32 + // Quick bounds check. + if (index > 15) + index = 15; + + index += 94; // extended characters + } + + return index; +} + + +default +{ + state_entry() + { + // Initialize the character index. + ResetCharIndex(); + llMessageLinked(LINK_THIS, REGISTER_SLAVE, llGetScriptName() , NULL_KEY); + } + + on_rez(integer num) + { + llResetScript(); + } + + link_message(integer sender, integer channel, string data, key id) + { + + if (channel == SLAVE_RECOGNIZED) + { + if (data == llGetScriptName()) + { + gActive=TRUE; + } + return; + } + + if (channel == SLAVE_DISPLAY) + { + if (!gActive) + return; + + list params=llCSV2List((string)id); + if (llList2String(params, 1) != llGetScriptName()) + return; + + + RenderString(llList2Integer(params, 0),data); + return; + } + + if (channel == SLAVE_DISPLAY_EXTENDED) + { + if (!gActive) + return; + + list params=llCSV2List((string)id); + if (llList2String(params, 1) != llGetScriptName()) + return; + + RenderExtended(llList2Integer(params, 0),data); + } + + if (channel == SET_FONT_TEXTURE) + { + gFontTexture = id; + return; + } + + if (channel == REMAP_INDICES) { + // Parse the message, splitting it up into index values. + list Parsed = llCSV2List(data); + integer i; + // Go through the list and swap each pair of indices. + for (i = 0; i < llGetListLength(Parsed); i += 2) { + integer Index1 = ConvertIndex( llList2Integer(Parsed, i) ); + integer Index2 = ConvertIndex( llList2Integer(Parsed, i + 1) ); + + // Swap these index values. + string Value1 = llGetSubString(gCharIndex, Index1, Index1); + string Value2 = llGetSubString(gCharIndex, Index2, Index2); + + gCharIndex = llDeleteSubString(gCharIndex, Index1, Index1); + gCharIndex = llInsertString(gCharIndex, Index1, Value2); + + gCharIndex = llDeleteSubString(gCharIndex, Index2, Index2); + gCharIndex = llInsertString(gCharIndex, Index2, Value1); + } + return; + } + if (channel == RESET_INDICES) { + // Restore the character index back to default settings. + ResetCharIndex(); + return; + } + + + if (channel == SLAVE_RESET) + { + ResetCharIndex(); + gActive=FALSE; + llMessageLinked(LINK_THIS, REGISTER_SLAVE, llGetScriptName() , NULL_KEY); + } + + } + + +} +