updated to useing preprocesser in firestorm, saveing space in memory, changed to new experience database
This commit is contained in:
parent
991b478e01
commit
5c3eb15c16
7 changed files with 387 additions and 175 deletions
138
Experience_Admin_HUD.lsl
Normal file
138
Experience_Admin_HUD.lsl
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
// ============================================================================
|
||||||
|
// Experience Admin HUD
|
||||||
|
// ============================================================================
|
||||||
|
// Instructions:
|
||||||
|
// 1. Create a new box, put this script inside.
|
||||||
|
// 2. DO NOT FORGET to check "Use Experience" and select Final Girlz I.N.C!
|
||||||
|
// 3. Attach it to your HUD or click it if it's rezzed.
|
||||||
|
//
|
||||||
|
// Commands (type in local chat):
|
||||||
|
// /99 keys - Lists all keys currently in the entire database
|
||||||
|
// /99 get [Key] - Reads and displays the data inside a specific key
|
||||||
|
// /99 del [Key] - Deletes a specific key from the database
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
key requestKeys;
|
||||||
|
key requestRead;
|
||||||
|
key requestDelete;
|
||||||
|
key requestWrite;
|
||||||
|
key lastUser;
|
||||||
|
string pendingSetKey;
|
||||||
|
string pendingSetValue;
|
||||||
|
|
||||||
|
default {
|
||||||
|
state_entry() {
|
||||||
|
lastUser = llGetOwner();
|
||||||
|
llRegionSayTo(lastUser, 0, "🔧 Experience Admin Terminal Ready.");
|
||||||
|
llRegionSayTo(lastUser, 0, "💬 Type commands in local chat:");
|
||||||
|
llRegionSayTo(lastUser, 0, " /99 keys");
|
||||||
|
llRegionSayTo(lastUser, 0, " /99 get key_name");
|
||||||
|
llRegionSayTo(lastUser, 0, " /99 set key_name=Hello World");
|
||||||
|
llRegionSayTo(lastUser, 0, " /99 del key_name");
|
||||||
|
llListen(99, "", NULL_KEY, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
listen(integer channel, string name, key id, string msg) {
|
||||||
|
// SECURITY CHECK: Strictly whitelist authorized Admin usernames!
|
||||||
|
string uname = llStringTrim(llToLower(llGetUsername(id)), STRING_TRIM);
|
||||||
|
if (id != llGetOwner() && uname != "djmusica28" && uname != "finalgirlzbot") {
|
||||||
|
llRegionSayTo(id, 0, "❌ Access Denied: You are not on the authorized Administrator whitelist for this database.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastUser = id;
|
||||||
|
msg = llStringTrim(msg, STRING_TRIM);
|
||||||
|
|
||||||
|
if (msg == "keys") {
|
||||||
|
llRegionSayTo(lastUser, 0, "🔍 Requesting list of database keys (up to 100)...");
|
||||||
|
requestKeys = llKeysKeyValue(0, 100);
|
||||||
|
}
|
||||||
|
else if (llGetSubString(msg, 0, 3) == "get ") {
|
||||||
|
string targetKey = llStringTrim(llGetSubString(msg, 4, -1), STRING_TRIM);
|
||||||
|
llRegionSayTo(lastUser, 0, "🔍 Reading key: " + targetKey + "...");
|
||||||
|
requestRead = llReadKeyValue(targetKey);
|
||||||
|
}
|
||||||
|
else if (llGetSubString(msg, 0, 3) == "set ") {
|
||||||
|
string payload = llStringTrim(llGetSubString(msg, 4, -1), STRING_TRIM);
|
||||||
|
integer equalSign = llSubStringIndex(payload, "=");
|
||||||
|
if (equalSign != -1) {
|
||||||
|
pendingSetKey = llStringTrim(llGetSubString(payload, 0, equalSign - 1), STRING_TRIM);
|
||||||
|
pendingSetValue = llStringTrim(llGetSubString(payload, equalSign + 1, -1), STRING_TRIM);
|
||||||
|
llRegionSayTo(lastUser, 0, "💾 Writing key: " + pendingSetKey + "...");
|
||||||
|
requestWrite = llUpdateKeyValue(pendingSetKey, pendingSetValue, FALSE, "");
|
||||||
|
} else {
|
||||||
|
llRegionSayTo(lastUser, 0, "❌ Format: /99 set key=value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (llGetSubString(msg, 0, 3) == "del ") {
|
||||||
|
string targetKey = llStringTrim(llGetSubString(msg, 4, -1), STRING_TRIM);
|
||||||
|
llRegionSayTo(lastUser, 0, "🗑️ Deleting key: " + targetKey + "...");
|
||||||
|
requestDelete = llDeleteKeyValue(targetKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dataserver(key queryid, string data) {
|
||||||
|
// llKeysKeyValue returns data as CSV:
|
||||||
|
// Success: 1,keyname1,keyname2...
|
||||||
|
// Failure: 0,error_code
|
||||||
|
if (queryid == requestKeys) {
|
||||||
|
list result = llCSV2List(data);
|
||||||
|
if (llList2Integer(result, 0) == 1) {
|
||||||
|
// Success
|
||||||
|
integer numKeys = llGetListLength(result) - 1;
|
||||||
|
llRegionSayTo(lastUser, 0, "✅ Found " + (string)numKeys + " keys in database:");
|
||||||
|
|
||||||
|
integer i;
|
||||||
|
for(i = 1; i < llGetListLength(result); i++) {
|
||||||
|
llRegionSayTo(lastUser, 0, " 🔑 " + llList2String(result, i));
|
||||||
|
}
|
||||||
|
} else if (llList2Integer(result, 1) == 3) {
|
||||||
|
llRegionSayTo(lastUser, 0, "📭 The database is completely empty! No keys exist.");
|
||||||
|
} else {
|
||||||
|
llRegionSayTo(lastUser, 0, "❌ Failed to read keys (Error " + llList2String(result, 1) + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// llReadKeyValue returns data as: status,value
|
||||||
|
else if (queryid == requestRead) {
|
||||||
|
integer comma = llSubStringIndex(data, ",");
|
||||||
|
string status = llGetSubString(data, 0, comma - 1);
|
||||||
|
string val = llGetSubString(data, comma + 1, -1);
|
||||||
|
|
||||||
|
if (status == "1") {
|
||||||
|
llRegionSayTo(lastUser, 0, "📄 Content:\n" + val);
|
||||||
|
} else if (status == "3") {
|
||||||
|
llRegionSayTo(lastUser, 0, "❌ That key doesn't exist!");
|
||||||
|
} else {
|
||||||
|
llRegionSayTo(lastUser, 0, "❌ Read failed (Status: " + status + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// llDeleteKeyValue dataserver logic
|
||||||
|
else if (queryid == requestDelete) {
|
||||||
|
integer comma = llSubStringIndex(data, ",");
|
||||||
|
string status = llGetSubString(data, 0, comma - 1);
|
||||||
|
|
||||||
|
if (status == "1") {
|
||||||
|
llRegionSayTo(lastUser, 0, "✅ Key successfully deleted!");
|
||||||
|
} else if (status == "3") {
|
||||||
|
llRegionSayTo(lastUser, 0, "❌ Key didn't exist to delete.");
|
||||||
|
} else {
|
||||||
|
llRegionSayTo(lastUser, 0, "❌ Delete failed (Status: " + status + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write logic
|
||||||
|
else if (queryid == requestWrite) {
|
||||||
|
integer comma = llSubStringIndex(data, ",");
|
||||||
|
string status = llGetSubString(data, 0, comma - 1);
|
||||||
|
if (status == "1") {
|
||||||
|
llRegionSayTo(lastUser, 0, "✅ Key saved successfully!");
|
||||||
|
} else if (status == "3") {
|
||||||
|
// Key didn't exist to update, manually create it!
|
||||||
|
requestWrite = llCreateKeyValue(pendingSetKey, pendingSetValue);
|
||||||
|
} else {
|
||||||
|
llRegionSayTo(lastUser, 0, "❌ Write failed (Status: " + status + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
166
Game_Manager.lsl
166
Game_Manager.lsl
|
|
@ -92,7 +92,15 @@ reportMemoryUsage(string scriptName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verbose logging control - toggled by owner
|
// Verbose logging control - toggled by owner
|
||||||
|
#define DEBUG_LOGS 0 // Set to 1 to enable logs, 0 to STRIP from memory completely
|
||||||
|
#if DEBUG_LOGS
|
||||||
|
#define dbg(msg) dbg(msg)
|
||||||
integer VERBOSE_LOGGING = FALSE;
|
integer VERBOSE_LOGGING = FALSE;
|
||||||
|
#else
|
||||||
|
#define dbg(msg)
|
||||||
|
#define VERBOSE_LOGGING 0
|
||||||
|
#endif
|
||||||
|
// Original VERBOSE_LOGGING definition removed
|
||||||
|
|
||||||
// Message constants
|
// Message constants
|
||||||
#define MSG_SHOW_DIALOG 101
|
#define MSG_SHOW_DIALOG 101
|
||||||
|
|
@ -118,30 +126,30 @@ continueCurrentRound() {
|
||||||
if (continuePlayerIdx != -1 && continuePlayerIdx < llGetListLength(lives)) {
|
if (continuePlayerIdx != -1 && continuePlayerIdx < llGetListLength(lives)) {
|
||||||
integer continuePlayerLives = llList2Integer(lives, continuePlayerIdx);
|
integer continuePlayerLives = llList2Integer(lives, continuePlayerIdx);
|
||||||
if (continuePlayerLives <= 0) {
|
if (continuePlayerLives <= 0) {
|
||||||
llOwnerSay("🛑 [Game Manager] continueCurrentRound: Found eliminated player " + continueName + " with " + (string)continuePlayerLives + " lives - aborting round start");
|
dbg("🛑 [Game Manager] continueCurrentRound: Found eliminated player " + continueName + " with " + (string)continuePlayerLives + " lives - aborting round start");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (perilPlayer == "" || perilPlayer == "NONE") {
|
if (perilPlayer == "" || perilPlayer == "NONE") {
|
||||||
llOwnerSay("🛑 [Game Manager] continueCurrentRound: Invalid peril player (" + perilPlayer + ") - aborting round start");
|
dbg("🛑 [Game Manager] continueCurrentRound: Invalid peril player (" + perilPlayer + ") - aborting round start");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify peril player exists and has lives
|
// Verify peril player exists and has lives
|
||||||
integer perilIdx = llListFindList(names, [perilPlayer]);
|
integer perilIdx = llListFindList(names, [perilPlayer]);
|
||||||
if (perilIdx == -1) {
|
if (perilIdx == -1) {
|
||||||
llOwnerSay("🛑 [Game Manager] continueCurrentRound: Peril player " + perilPlayer + " not found in names list - aborting round start");
|
dbg("🛑 [Game Manager] continueCurrentRound: Peril player " + perilPlayer + " not found in names list - aborting round start");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (perilIdx >= llGetListLength(lives)) {
|
if (perilIdx >= llGetListLength(lives)) {
|
||||||
llOwnerSay("🛑 [Game Manager] continueCurrentRound: Peril player " + perilPlayer + " index out of bounds - aborting round start");
|
dbg("🛑 [Game Manager] continueCurrentRound: Peril player " + perilPlayer + " index out of bounds - aborting round start");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
integer perilLives = llList2Integer(lives, perilIdx);
|
integer perilLives = llList2Integer(lives, perilIdx);
|
||||||
if (perilLives <= 0) {
|
if (perilLives <= 0) {
|
||||||
llOwnerSay("🛑 [Game Manager] continueCurrentRound: Peril player " + perilPlayer + " has " + (string)perilLives + " lives - aborting round start");
|
dbg("🛑 [Game Manager] continueCurrentRound: Peril player " + perilPlayer + " has " + (string)perilLives + " lives - aborting round start");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,7 +157,7 @@ continueCurrentRound() {
|
||||||
// globalPickedNumbers will be cleared when first player picks
|
// globalPickedNumbers will be cleared when first player picks
|
||||||
picksData = [];
|
picksData = [];
|
||||||
|
|
||||||
llOwnerSay("🔄 [Game Manager] continueCurrentRound: All validation passed, starting fresh round with " + (string)llGetListLength(names) + " players");
|
dbg("🔄 [Game Manager] continueCurrentRound: All validation passed, starting fresh round with " + (string)llGetListLength(names) + " players");
|
||||||
|
|
||||||
// Set round as started for the new round
|
// Set round as started for the new round
|
||||||
roundStarted = TRUE;
|
roundStarted = TRUE;
|
||||||
|
|
@ -165,7 +173,7 @@ continueCurrentRound() {
|
||||||
}
|
}
|
||||||
currentPickerIdx = 0;
|
currentPickerIdx = 0;
|
||||||
|
|
||||||
llOwnerSay("🎯 [Game Manager] Pick queue created: " + llList2CSV(pickQueue) + ", requesting dice type");
|
dbg("🎯 [Game Manager] Pick queue created: " + llList2CSV(pickQueue) + ", requesting dice type");
|
||||||
|
|
||||||
// Request dice type directly from Calculator for the new round
|
// Request dice type directly from Calculator for the new round
|
||||||
llMessageLinked(LINK_SET, MSG_GET_DICE_TYPE, (string)llGetListLength(names), NULL_KEY);
|
llMessageLinked(LINK_SET, MSG_GET_DICE_TYPE, (string)llGetListLength(names), NULL_KEY);
|
||||||
|
|
@ -176,12 +184,12 @@ continueCurrentRound() {
|
||||||
startNextRound() {
|
startNextRound() {
|
||||||
// Prevent multiple calls to start round
|
// Prevent multiple calls to start round
|
||||||
if (roundStarted) {
|
if (roundStarted) {
|
||||||
llOwnerSay("⚠️ Round already started, ignoring duplicate start request");
|
dbg("⚠️ Round already started, ignoring duplicate start request");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (llGetListLength(names) < 2) {
|
if (llGetListLength(names) < 2) {
|
||||||
llOwnerSay("⚠️ Need at least 2 players to start the game.");
|
dbg("⚠️ Need at least 2 players to start the game.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -200,7 +208,7 @@ startNextRound() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
llOwnerSay("🎯 Game Manager starting new round...");
|
dbg("🎯 Game Manager starting new round...");
|
||||||
|
|
||||||
// Set roundStarted immediately to prevent duplicate calls
|
// Set roundStarted immediately to prevent duplicate calls
|
||||||
roundStarted = TRUE;
|
roundStarted = TRUE;
|
||||||
|
|
@ -216,7 +224,7 @@ startNextRound() {
|
||||||
llMessageLinked(12, 3005, perilPlayer, NULL_KEY); // MSG_UPDATE_PERIL_PLAYER
|
llMessageLinked(12, 3005, perilPlayer, NULL_KEY); // MSG_UPDATE_PERIL_PLAYER
|
||||||
|
|
||||||
// Sync state to floater manager first, then update floaters to show new peril player immediately
|
// Sync state to floater manager first, then update floaters to show new peril player immediately
|
||||||
llOwnerSay("🔄 [Game Manager] Syncing state and updating floaters for new peril player: " + perilPlayer);
|
dbg("🔄 [Game Manager] Syncing state and updating floaters for new peril player: " + perilPlayer);
|
||||||
syncStateToMain(); // Sync the peril player to all modules first
|
syncStateToMain(); // Sync the peril player to all modules first
|
||||||
llSleep(0.1); // Brief delay to ensure sync propagates
|
llSleep(0.1); // Brief delay to ensure sync propagates
|
||||||
integer startJ;
|
integer startJ;
|
||||||
|
|
@ -230,7 +238,7 @@ startNextRound() {
|
||||||
// globalPickedNumbers will be cleared when first player picks
|
// globalPickedNumbers will be cleared when first player picks
|
||||||
|
|
||||||
// Create pick queue with peril player first
|
// Create pick queue with peril player first
|
||||||
llOwnerSay("🎯 Debug - Creating pickQueue. names: " + llList2CSV(names) + ", perilPlayer: " + perilPlayer);
|
dbg("🎯 Debug - Creating pickQueue. names: " + llList2CSV(names) + ", perilPlayer: " + perilPlayer);
|
||||||
pickQueue = [perilPlayer];
|
pickQueue = [perilPlayer];
|
||||||
integer k;
|
integer k;
|
||||||
for (k = 0; k < llGetListLength(names); k++) {
|
for (k = 0; k < llGetListLength(names); k++) {
|
||||||
|
|
@ -240,11 +248,11 @@ startNextRound() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentPickerIdx = 0;
|
currentPickerIdx = 0;
|
||||||
llOwnerSay("🎯 Debug - Created pickQueue: " + llList2CSV(pickQueue) + ", currentPickerIdx: " + (string)currentPickerIdx);
|
dbg("🎯 Debug - Created pickQueue: " + llList2CSV(pickQueue) + ", currentPickerIdx: " + (string)currentPickerIdx);
|
||||||
|
|
||||||
// Request dice type for this round
|
// Request dice type for this round
|
||||||
llMessageLinked(LINK_SET, MSG_GET_DICE_TYPE, (string)llGetListLength(names), NULL_KEY);
|
llMessageLinked(LINK_SET, MSG_GET_DICE_TYPE, (string)llGetListLength(names), NULL_KEY);
|
||||||
llOwnerSay("🎯 Game Manager round setup complete, requesting dice type...");
|
dbg("🎯 Game Manager round setup complete, requesting dice type...");
|
||||||
}
|
}
|
||||||
|
|
||||||
showNextPickerDialog() {
|
showNextPickerDialog() {
|
||||||
|
|
@ -254,40 +262,40 @@ showNextPickerDialog() {
|
||||||
// Clear globalPickedNumbers if this is the first picker of a new round
|
// Clear globalPickedNumbers if this is the first picker of a new round
|
||||||
if (currentPickerIdx == 0 && llGetListLength(picksData) == 0) {
|
if (currentPickerIdx == 0 && llGetListLength(picksData) == 0) {
|
||||||
globalPickedNumbers = [];
|
globalPickedNumbers = [];
|
||||||
llOwnerSay("🔄 [Game Manager] Cleared globalPickedNumbers at start of new round");
|
dbg("🔄 [Game Manager] Cleared globalPickedNumbers at start of new round");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (diceType <= 0) {
|
if (diceType <= 0) {
|
||||||
llOwnerSay("❌ Cannot show picker dialog: diceType not set (" + (string)diceType + ")");
|
dbg("❌ Cannot show picker dialog: diceType not set (" + (string)diceType + ")");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentPickerIdx >= llGetListLength(pickQueue)) {
|
if (currentPickerIdx >= llGetListLength(pickQueue)) {
|
||||||
llOwnerSay("❌ Cannot show picker dialog: currentPickerIdx (" + (string)currentPickerIdx + ") >= pickQueue length (" + (string)llGetListLength(pickQueue) + ")");
|
dbg("❌ Cannot show picker dialog: currentPickerIdx (" + (string)currentPickerIdx + ") >= pickQueue length (" + (string)llGetListLength(pickQueue) + ")");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string firstName = llList2String(pickQueue, currentPickerIdx);
|
string firstName = llList2String(pickQueue, currentPickerIdx);
|
||||||
if (firstName == "") {
|
if (firstName == "") {
|
||||||
llOwnerSay("❌ Cannot show picker dialog: empty player name at index " + (string)currentPickerIdx);
|
dbg("❌ Cannot show picker dialog: empty player name at index " + (string)currentPickerIdx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CRITICAL: Verify this player is still alive and in the game
|
// CRITICAL: Verify this player is still alive and in the game
|
||||||
integer showPlayerIdx = llListFindList(names, [firstName]);
|
integer showPlayerIdx = llListFindList(names, [firstName]);
|
||||||
if (showPlayerIdx == -1) {
|
if (showPlayerIdx == -1) {
|
||||||
llOwnerSay("❌ Cannot show picker dialog: player " + firstName + " not found in current game");
|
dbg("❌ Cannot show picker dialog: player " + firstName + " not found in current game");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showPlayerIdx >= llGetListLength(lives)) {
|
if (showPlayerIdx >= llGetListLength(lives)) {
|
||||||
llOwnerSay("❌ Cannot show picker dialog: player " + firstName + " index out of bounds for lives list");
|
dbg("❌ Cannot show picker dialog: player " + firstName + " index out of bounds for lives list");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
integer showPlayerLives = llList2Integer(lives, showPlayerIdx);
|
integer showPlayerLives = llList2Integer(lives, showPlayerIdx);
|
||||||
if (showPlayerLives <= 0) {
|
if (showPlayerLives <= 0) {
|
||||||
llOwnerSay("❌ Cannot show picker dialog: player " + firstName + " has been eliminated (" + (string)showPlayerLives + " lives)");
|
dbg("❌ Cannot show picker dialog: player " + firstName + " has been eliminated (" + (string)showPlayerLives + " lives)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -299,7 +307,7 @@ showNextPickerDialog() {
|
||||||
string existingPicks = llGetSubString(llList2String(picksData, showIdx), llStringLength(firstName) + 1, -1);
|
string existingPicks = llGetSubString(llList2String(picksData, showIdx), llStringLength(firstName) + 1, -1);
|
||||||
if (existingPicks != "") {
|
if (existingPicks != "") {
|
||||||
alreadyHasPicks = TRUE;
|
alreadyHasPicks = TRUE;
|
||||||
llOwnerSay("🎯 Game Manager: " + firstName + " already has picks (" + existingPicks + "), advancing to next player");
|
dbg("🎯 Game Manager: " + firstName + " already has picks (" + existingPicks + "), advancing to next player");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -319,7 +327,7 @@ showNextPickerDialog() {
|
||||||
|
|
||||||
integer nameIdx = llListFindList(names, [firstName]);
|
integer nameIdx = llListFindList(names, [firstName]);
|
||||||
if (nameIdx == -1) {
|
if (nameIdx == -1) {
|
||||||
llOwnerSay("❌ Cannot show picker dialog: player " + firstName + " not found in names list");
|
dbg("❌ Cannot show picker dialog: player " + firstName + " not found in names list");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -337,7 +345,7 @@ showNextPickerDialog() {
|
||||||
string existingBotPicks = llGetSubString(llList2String(picksData, showJ), llStringLength(firstName) + 1, -1);
|
string existingBotPicks = llGetSubString(llList2String(picksData, showJ), llStringLength(firstName) + 1, -1);
|
||||||
if (existingBotPicks != "") {
|
if (existingBotPicks != "") {
|
||||||
botAlreadyHasPicks = TRUE;
|
botAlreadyHasPicks = TRUE;
|
||||||
llOwnerSay("⚠️ [Game Manager] Bot " + firstName + " already has picks, skipping bot command: " + existingBotPicks);
|
dbg("⚠️ [Game Manager] Bot " + firstName + " already has picks, skipping bot command: " + existingBotPicks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -354,9 +362,9 @@ showNextPickerDialog() {
|
||||||
list showCompleteAvoidList = buildCompleteAvoidanceList();
|
list showCompleteAvoidList = buildCompleteAvoidanceList();
|
||||||
string showAvoidListStr = llList2CSV(showCompleteAvoidList);
|
string showAvoidListStr = llList2CSV(showCompleteAvoidList);
|
||||||
string botCommand = "BOT_PICK:" + firstName + ":" + (string)showPicksNeeded + ":" + (string)diceType + ":" + showAvoidListStr;
|
string botCommand = "BOT_PICK:" + firstName + ":" + (string)showPicksNeeded + ":" + (string)diceType + ":" + showAvoidListStr;
|
||||||
llOwnerSay("🎯 [Game Manager] Sending bot command with complete avoid list (" + (string)llGetListLength(showCompleteAvoidList) + " numbers): " + showAvoidListStr);
|
dbg("🎯 [Game Manager] Sending bot command with complete avoid list (" + (string)llGetListLength(showCompleteAvoidList) + " numbers): " + showAvoidListStr);
|
||||||
llMessageLinked(LINK_SET, -9999, botCommand, NULL_KEY);
|
llMessageLinked(LINK_SET, -9999, botCommand, NULL_KEY);
|
||||||
llOwnerSay("🤖 " + firstName + " is automatically picking " + (string)showPicksNeeded + " numbers...");
|
dbg("🤖 " + firstName + " is automatically picking " + (string)showPicksNeeded + " numbers...");
|
||||||
} else {
|
} else {
|
||||||
// Bot already has picks, advance to next player immediately
|
// Bot already has picks, advance to next player immediately
|
||||||
currentPickerIdx++;
|
currentPickerIdx++;
|
||||||
|
|
@ -382,7 +390,7 @@ showNextPickerDialog() {
|
||||||
string humanAvoidListStr = llList2CSV(humanCompleteAvoidList);
|
string humanAvoidListStr = llList2CSV(humanCompleteAvoidList);
|
||||||
string dialogPayload = firstName + "|" + (string)diceType + "|" + (string)humanPicksNeeded + "|" + humanAvoidListStr;
|
string dialogPayload = firstName + "|" + (string)diceType + "|" + (string)humanPicksNeeded + "|" + humanAvoidListStr;
|
||||||
|
|
||||||
llOwnerSay("🎯 Showing pick dialog for " + firstName);
|
dbg("🎯 Showing pick dialog for " + firstName);
|
||||||
llSleep(0.5); // Brief delay to prevent spam
|
llSleep(0.5); // Brief delay to prevent spam
|
||||||
|
|
||||||
// Send dialog request through Player_RegistrationManager (it has the correct player keys)
|
// Send dialog request through Player_RegistrationManager (it has the correct player keys)
|
||||||
|
|
@ -403,7 +411,7 @@ syncStateToMain() {
|
||||||
default {
|
default {
|
||||||
state_entry() {
|
state_entry() {
|
||||||
reportMemoryUsage("Game Manager");
|
reportMemoryUsage("Game Manager");
|
||||||
llOwnerSay("🎯 Game Manager initializing...");
|
dbg("🎯 Game Manager initializing...");
|
||||||
|
|
||||||
// Initialize/reset all game state variables
|
// Initialize/reset all game state variables
|
||||||
players = [];
|
players = [];
|
||||||
|
|
@ -424,12 +432,12 @@ default {
|
||||||
lastBotPickMessage = "";
|
lastBotPickMessage = "";
|
||||||
lastProcessTime = 0;
|
lastProcessTime = 0;
|
||||||
|
|
||||||
llOwnerSay("🎯 Game Manager ready!");
|
dbg("🎯 Game Manager ready!");
|
||||||
}
|
}
|
||||||
|
|
||||||
on_rez(integer start_param) {
|
on_rez(integer start_param) {
|
||||||
reportMemoryUsage("Game Manager");
|
reportMemoryUsage("Game Manager");
|
||||||
llOwnerSay("🔄 Game Manager rezzed - reinitializing...");
|
dbg("🔄 Game Manager rezzed - reinitializing...");
|
||||||
|
|
||||||
// Reset all game state variables on rez
|
// Reset all game state variables on rez
|
||||||
players = [];
|
players = [];
|
||||||
|
|
@ -450,7 +458,7 @@ default {
|
||||||
lastBotPickMessage = "";
|
lastBotPickMessage = "";
|
||||||
lastProcessTime = 0;
|
lastProcessTime = 0;
|
||||||
|
|
||||||
llOwnerSay("✅ Game Manager reset complete after rez!");
|
dbg("✅ Game Manager reset complete after rez!");
|
||||||
}
|
}
|
||||||
|
|
||||||
link_message(integer sender, integer num, string str, key id) {
|
link_message(integer sender, integer num, string str, key id) {
|
||||||
|
|
@ -528,7 +536,7 @@ default {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (livesChanged && newPerilPlayer != "" && newPerilPlayer != "NONE" && roundStarted && allPicksEmpty) {
|
if (livesChanged && newPerilPlayer != "" && newPerilPlayer != "NONE" && roundStarted && allPicksEmpty) {
|
||||||
llOwnerSay("🎯 Post-roll state update detected - continuing round");
|
dbg("🎯 Post-roll state update detected - continuing round");
|
||||||
continueCurrentRound();
|
continueCurrentRound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -538,21 +546,21 @@ default {
|
||||||
|
|
||||||
// Receive legacy game state updates from main controller (simplified version)
|
// Receive legacy game state updates from main controller (simplified version)
|
||||||
if (num == 9071) {
|
if (num == 9071) {
|
||||||
llOwnerSay("🔧 [Game Manager] Received sync: " + str);
|
dbg("🔧 [Game Manager] Received sync: " + str);
|
||||||
list parts = llParseString2List(str, ["~"], []);
|
list parts = llParseString2List(str, ["~"], []);
|
||||||
llOwnerSay("🔧 [Game Manager] Parsed into " + (string)llGetListLength(parts) + " parts");
|
dbg("🔧 [Game Manager] Parsed into " + (string)llGetListLength(parts) + " parts");
|
||||||
|
|
||||||
// MEMORY OPTIMIZED: Skip heavy validation that causes sync rejections
|
// MEMORY OPTIMIZED: Skip heavy validation that causes sync rejections
|
||||||
// Trust that Main Controller sends valid data
|
// Trust that Main Controller sends valid data
|
||||||
|
|
||||||
// Handle special RESET sync message
|
// Handle special RESET sync message
|
||||||
if (llGetListLength(parts) >= 5 && llList2String(parts, 0) == "RESET") {
|
if (llGetListLength(parts) >= 5 && llList2String(parts, 0) == "RESET") {
|
||||||
llOwnerSay("🔄 [Game Manager] Received reset sync - ignoring during reset");
|
dbg("🔄 [Game Manager] Received reset sync - ignoring during reset");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (llGetListLength(parts) < 4) {
|
if (llGetListLength(parts) < 4) {
|
||||||
llOwnerSay("⚠️ [Game Manager] Incomplete sync message received, parts: " + (string)llGetListLength(parts) + " - IGNORING");
|
dbg("⚠️ [Game Manager] Incomplete sync message received, parts: " + (string)llGetListLength(parts) + " - IGNORING");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|
@ -588,14 +596,14 @@ default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
llOwnerSay("🎯 [Game Manager] Updated: " + (string)llGetListLength(names) + " players (minimal parsing)");
|
dbg("🎯 [Game Manager] Updated: " + (string)llGetListLength(names) + " players (minimal parsing)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update peril player
|
// Update peril player
|
||||||
string receivedPerilPlayer = llList2String(parts, 2);
|
string receivedPerilPlayer = llList2String(parts, 2);
|
||||||
if (receivedPerilPlayer != "NONE" && receivedPerilPlayer != "") {
|
if (receivedPerilPlayer != "NONE" && receivedPerilPlayer != "") {
|
||||||
perilPlayer = receivedPerilPlayer;
|
perilPlayer = receivedPerilPlayer;
|
||||||
llOwnerSay("🎯 [Game Manager] Peril player updated to: " + perilPlayer);
|
dbg("🎯 [Game Manager] Peril player updated to: " + perilPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MEMORY OPTIMIZED: Skip all other complex processing
|
// MEMORY OPTIMIZED: Skip all other complex processing
|
||||||
|
|
@ -608,26 +616,26 @@ default {
|
||||||
list newPickQueue = llCSV2List(str);
|
list newPickQueue = llCSV2List(str);
|
||||||
string senderStr = (string)sender;
|
string senderStr = (string)sender;
|
||||||
string queueLenStr = (string)llGetListLength(newPickQueue);
|
string queueLenStr = (string)llGetListLength(newPickQueue);
|
||||||
llOwnerSay("🔍 [Game Manager] Received pickQueue sync from sender " + senderStr + ": '" + str + "' (" + queueLenStr + " items)");
|
dbg("🔍 [Game Manager] Received pickQueue sync from sender " + senderStr + ": '" + str + "' (" + queueLenStr + " items)");
|
||||||
|
|
||||||
// STRONGEST PROTECTION: Never accept empty pickQueues during any active round
|
// STRONGEST PROTECTION: Never accept empty pickQueues during any active round
|
||||||
if (roundStarted && llGetListLength(pickQueue) > 0 && (str == "" || llGetListLength(newPickQueue) == 0)) {
|
if (roundStarted && llGetListLength(pickQueue) > 0 && (str == "" || llGetListLength(newPickQueue) == 0)) {
|
||||||
llOwnerSay("🔍 [Game Manager] REJECTING empty/invalid pickQueue sync during active round - keeping: " + llList2CSV(pickQueue));
|
dbg("🔍 [Game Manager] REJECTING empty/invalid pickQueue sync during active round - keeping: " + llList2CSV(pickQueue));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Additional protection: Don't accept pickQueue syncs if we just created a valid one
|
// Additional protection: Don't accept pickQueue syncs if we just created a valid one
|
||||||
if (llGetListLength(pickQueue) > 0 && (str == "" || llGetListLength(newPickQueue) == 0)) {
|
if (llGetListLength(pickQueue) > 0 && (str == "" || llGetListLength(newPickQueue) == 0)) {
|
||||||
llOwnerSay("🔍 [Game Manager] REJECTING empty pickQueue sync - keeping valid queue: " + llList2CSV(pickQueue));
|
dbg("🔍 [Game Manager] REJECTING empty pickQueue sync - keeping valid queue: " + llList2CSV(pickQueue));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only accept valid non-empty pickQueues
|
// Only accept valid non-empty pickQueues
|
||||||
if (llGetListLength(newPickQueue) > 0) {
|
if (llGetListLength(newPickQueue) > 0) {
|
||||||
pickQueue = newPickQueue;
|
pickQueue = newPickQueue;
|
||||||
llOwnerSay("🔍 [Game Manager] pickQueue updated to: " + llList2CSV(pickQueue));
|
dbg("🔍 [Game Manager] pickQueue updated to: " + llList2CSV(pickQueue));
|
||||||
} else {
|
} else {
|
||||||
llOwnerSay("🔍 [Game Manager] Ignoring invalid pickQueue sync - keeping current: " + llList2CSV(pickQueue));
|
dbg("🔍 [Game Manager] Ignoring invalid pickQueue sync - keeping current: " + llList2CSV(pickQueue));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -636,13 +644,13 @@ default {
|
||||||
if (num == MSG_DICE_TYPE_RESULT) {
|
if (num == MSG_DICE_TYPE_RESULT) {
|
||||||
// Prevent duplicate processing of dice type results
|
// Prevent duplicate processing of dice type results
|
||||||
if (diceTypeProcessed) {
|
if (diceTypeProcessed) {
|
||||||
llOwnerSay("🎲 Ignoring duplicate dice type result: " + str);
|
dbg("🎲 Ignoring duplicate dice type result: " + str);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
diceType = (integer)str;
|
diceType = (integer)str;
|
||||||
diceTypeProcessed = TRUE;
|
diceTypeProcessed = TRUE;
|
||||||
llOwnerSay("🎲 Game Manager received dice type: d" + str + " from Calculator");
|
dbg("🎲 Game Manager received dice type: d" + str + " from Calculator");
|
||||||
llSleep(0.3); // Brief delay
|
llSleep(0.3); // Brief delay
|
||||||
|
|
||||||
// Start dialog if round has been started and we have a queue
|
// Start dialog if round has been started and we have a queue
|
||||||
|
|
@ -662,7 +670,7 @@ default {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!alreadyHasPicks) {
|
if (!alreadyHasPicks) {
|
||||||
llOwnerSay("🎯 Starting picks for " + currentPlayerName);
|
dbg("🎯 Starting picks for " + currentPlayerName);
|
||||||
llSleep(0.5);
|
llSleep(0.5);
|
||||||
showNextPickerDialog();
|
showNextPickerDialog();
|
||||||
}
|
}
|
||||||
|
|
@ -679,7 +687,7 @@ default {
|
||||||
string playerName = llList2String(parts, 1);
|
string playerName = llList2String(parts, 1);
|
||||||
string picksStr = llList2String(parts, 2);
|
string picksStr = llList2String(parts, 2);
|
||||||
|
|
||||||
llOwnerSay("👤 HUMAN: " + playerName + " picking " + picksStr + " (global has: " + llList2CSV(globalPickedNumbers) + ")");
|
dbg("👤 HUMAN: " + playerName + " picking " + picksStr + " (global has: " + llList2CSV(globalPickedNumbers) + ")");
|
||||||
|
|
||||||
// Check if this player already has picks to prevent duplicate processing
|
// Check if this player already has picks to prevent duplicate processing
|
||||||
integer alreadyHasPicks = FALSE;
|
integer alreadyHasPicks = FALSE;
|
||||||
|
|
@ -689,7 +697,7 @@ default {
|
||||||
if (llSubStringIndex(llList2String(picksData, m), playerName + "|") == 0) {
|
if (llSubStringIndex(llList2String(picksData, m), playerName + "|") == 0) {
|
||||||
string existingPicks = llGetSubString(llList2String(picksData, m), llStringLength(playerName) + 1, -1);
|
string existingPicks = llGetSubString(llList2String(picksData, m), llStringLength(playerName) + 1, -1);
|
||||||
if (existingPicks != "") {
|
if (existingPicks != "") {
|
||||||
llOwnerSay("⚠️ [Game Manager] " + playerName + " already has picks: " + existingPicks + ", ignoring duplicate HUMAN_PICKED");
|
dbg("⚠️ [Game Manager] " + playerName + " already has picks: " + existingPicks + ", ignoring duplicate HUMAN_PICKED");
|
||||||
alreadyHasPicks = TRUE;
|
alreadyHasPicks = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -706,7 +714,7 @@ default {
|
||||||
list duplicatePicks = [];
|
list duplicatePicks = [];
|
||||||
integer i;
|
integer i;
|
||||||
|
|
||||||
llOwnerSay("🔍 [Game Manager] Validating " + playerName + "'s picks against complete avoid list (" + (string)llGetListLength(completeAvoidList) + " numbers): " + llList2CSV(completeAvoidList));
|
dbg("🔍 [Game Manager] Validating " + playerName + "'s picks against complete avoid list (" + (string)llGetListLength(completeAvoidList) + " numbers): " + llList2CSV(completeAvoidList));
|
||||||
|
|
||||||
for (i = 0; i < llGetListLength(newPicks); i++) {
|
for (i = 0; i < llGetListLength(newPicks); i++) {
|
||||||
string pick = llStringTrim(llList2String(newPicks, i), STRING_TRIM);
|
string pick = llStringTrim(llList2String(newPicks, i), STRING_TRIM);
|
||||||
|
|
@ -721,7 +729,7 @@ default {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (llGetListLength(duplicatePicks) > 0) {
|
if (llGetListLength(duplicatePicks) > 0) {
|
||||||
llOwnerSay("❌ DUPLICATE PICKS REJECTED: " + playerName + " tried to pick: " + llList2CSV(duplicatePicks));
|
dbg("❌ DUPLICATE PICKS REJECTED: " + playerName + " tried to pick: " + llList2CSV(duplicatePicks));
|
||||||
integer idx = llListFindList(names, [playerName]);
|
integer idx = llListFindList(names, [playerName]);
|
||||||
if (idx != -1) {
|
if (idx != -1) {
|
||||||
llRegionSayTo(llList2Key(players, idx), 0, "❌ Some picks were already taken. Please pick again.");
|
llRegionSayTo(llList2Key(players, idx), 0, "❌ Some picks were already taken. Please pick again.");
|
||||||
|
|
@ -736,7 +744,7 @@ default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Re-show the dialog with updated globally picked numbers
|
// Re-show the dialog with updated globally picked numbers
|
||||||
llOwnerSay("⚠️ [Game Manager] Re-showing pick dialog for " + playerName + " with updated picks");
|
dbg("⚠️ [Game Manager] Re-showing pick dialog for " + playerName + " with updated picks");
|
||||||
|
|
||||||
// Calculate picks needed based on peril player's lives
|
// Calculate picks needed based on peril player's lives
|
||||||
integer perilIdx = llListFindList(names, [perilPlayer]);
|
integer perilIdx = llListFindList(names, [perilPlayer]);
|
||||||
|
|
@ -771,7 +779,7 @@ default {
|
||||||
} else {
|
} else {
|
||||||
picksData = llListReplaceList(picksData, [newEntry], picksIdx, picksIdx);
|
picksData = llListReplaceList(picksData, [newEntry], picksIdx, picksIdx);
|
||||||
}
|
}
|
||||||
llOwnerSay("🟢 " + playerName + " picks saved: " + picksStr);
|
dbg("🟢 " + playerName + " picks saved: " + picksStr);
|
||||||
|
|
||||||
llSay(0, "🎯 " + playerName + " stakes their life on numbers: " + picksStr + " 🎲");
|
llSay(0, "🎯 " + playerName + " stakes their life on numbers: " + picksStr + " 🎲");
|
||||||
|
|
||||||
|
|
@ -797,19 +805,19 @@ default {
|
||||||
currentPickerIdx++;
|
currentPickerIdx++;
|
||||||
|
|
||||||
if (currentPickerIdx < llGetListLength(pickQueue)) {
|
if (currentPickerIdx < llGetListLength(pickQueue)) {
|
||||||
llOwnerSay("🔍 [Game Manager] More players in queue, showing next dialog");
|
dbg("🔍 [Game Manager] More players in queue, showing next dialog");
|
||||||
showNextPickerDialog();
|
showNextPickerDialog();
|
||||||
} else {
|
} else {
|
||||||
// All picked, show roll dialog
|
// All picked, show roll dialog
|
||||||
llOwnerSay("🎯 [Game Manager] All players have picked! Showing roll dialog to " + perilPlayer);
|
dbg("🎯 [Game Manager] All players have picked! Showing roll dialog to " + perilPlayer);
|
||||||
|
|
||||||
// CRITICAL: Sync the updated picks data to all modules before roll phase
|
// CRITICAL: Sync the updated picks data to all modules before roll phase
|
||||||
llOwnerSay("🔄 [Game Manager] Syncing final picks data before roll phase...");
|
dbg("🔄 [Game Manager] Syncing final picks data before roll phase...");
|
||||||
syncStateToMain();
|
syncStateToMain();
|
||||||
llSleep(1.0); // Longer delay to ensure sync propagates to all modules
|
llSleep(1.0); // Longer delay to ensure sync propagates to all modules
|
||||||
|
|
||||||
// Send roll dialog through Player_RegistrationManager
|
// Send roll dialog through Player_RegistrationManager
|
||||||
llOwnerSay("🎯 [Game Manager] Sending roll dialog request for: " + perilPlayer);
|
dbg("🎯 [Game Manager] Sending roll dialog request for: " + perilPlayer);
|
||||||
string rollRequest = "SHOW_ROLL_DIALOG|" + perilPlayer + "|" + perilPlayer;
|
string rollRequest = "SHOW_ROLL_DIALOG|" + perilPlayer + "|" + perilPlayer;
|
||||||
llMessageLinked(LINK_SET, MSG_DIALOG_FORWARD_REQUEST, rollRequest, NULL_KEY);
|
llMessageLinked(LINK_SET, MSG_DIALOG_FORWARD_REQUEST, rollRequest, NULL_KEY);
|
||||||
}
|
}
|
||||||
|
|
@ -820,13 +828,13 @@ default {
|
||||||
|
|
||||||
// Handle bot picks
|
// Handle bot picks
|
||||||
if (num == -9997 && llSubStringIndex(str, "BOT_PICKED:") == 0) {
|
if (num == -9997 && llSubStringIndex(str, "BOT_PICKED:") == 0) {
|
||||||
llOwnerSay("🔍 [Game Manager] BOT_PICKED message received: " + str);
|
dbg("🔍 [Game Manager] BOT_PICKED message received: " + str);
|
||||||
list parts = llParseString2List(str, [":"], []);
|
list parts = llParseString2List(str, [":"], []);
|
||||||
if (llGetListLength(parts) >= 3) {
|
if (llGetListLength(parts) >= 3) {
|
||||||
string playerName = llList2String(parts, 1);
|
string playerName = llList2String(parts, 1);
|
||||||
string picksStr = llList2String(parts, 2);
|
string picksStr = llList2String(parts, 2);
|
||||||
|
|
||||||
llOwnerSay("🤖 BOT: " + playerName + " picking " + picksStr + " (global had: " + llList2CSV(globalPickedNumbers) + ")");
|
dbg("🤖 BOT: " + playerName + " picking " + picksStr + " (global had: " + llList2CSV(globalPickedNumbers) + ")");
|
||||||
|
|
||||||
// Check if this bot has already made picks this round to prevent duplicates
|
// Check if this bot has already made picks this round to prevent duplicates
|
||||||
integer existingPicksIdx = -1;
|
integer existingPicksIdx = -1;
|
||||||
|
|
@ -835,7 +843,7 @@ default {
|
||||||
if (llSubStringIndex(llList2String(picksData, m), playerName + "|") == 0) {
|
if (llSubStringIndex(llList2String(picksData, m), playerName + "|") == 0) {
|
||||||
string existingPicks = llGetSubString(llList2String(picksData, m), llStringLength(playerName) + 1, -1);
|
string existingPicks = llGetSubString(llList2String(picksData, m), llStringLength(playerName) + 1, -1);
|
||||||
if (existingPicks != "") {
|
if (existingPicks != "") {
|
||||||
llOwnerSay("⚠️ [Game Manager] Ignoring duplicate BOT_PICKED for " + playerName + " (already has picks: " + existingPicks + ")");
|
dbg("⚠️ [Game Manager] Ignoring duplicate BOT_PICKED for " + playerName + " (already has picks: " + existingPicks + ")");
|
||||||
|
|
||||||
// IMPORTANT: Even though this is a duplicate, check if all players have now picked
|
// IMPORTANT: Even though this is a duplicate, check if all players have now picked
|
||||||
// Count how many players have picks
|
// Count how many players have picks
|
||||||
|
|
@ -857,15 +865,15 @@ default {
|
||||||
|
|
||||||
// If all players have picks, advance to roll phase
|
// If all players have picks, advance to roll phase
|
||||||
if (playersWithPicks >= llGetListLength(names)) {
|
if (playersWithPicks >= llGetListLength(names)) {
|
||||||
llOwnerSay("🎯 [Game Manager] All players have picks! Moving to roll phase...");
|
dbg("🎯 [Game Manager] All players have picks! Moving to roll phase...");
|
||||||
|
|
||||||
// CRITICAL: Sync the updated picks data to all modules before roll phase
|
// CRITICAL: Sync the updated picks data to all modules before roll phase
|
||||||
llOwnerSay("🔄 [Game Manager] Syncing final picks data before roll phase...");
|
dbg("🔄 [Game Manager] Syncing final picks data before roll phase...");
|
||||||
syncStateToMain();
|
syncStateToMain();
|
||||||
llSleep(1.0); // Longer delay to ensure sync propagates to all modules
|
llSleep(1.0); // Longer delay to ensure sync propagates to all modules
|
||||||
|
|
||||||
// Force close any active number picker dialogs
|
// Force close any active number picker dialogs
|
||||||
llOwnerSay("🚫 [Game Manager] Sending CLOSE_ALL_DIALOGS command");
|
dbg("🚫 [Game Manager] Sending CLOSE_ALL_DIALOGS command");
|
||||||
llMessageLinked(LINK_SET, -9999, "CLOSE_ALL_DIALOGS", NULL_KEY);
|
llMessageLinked(LINK_SET, -9999, "CLOSE_ALL_DIALOGS", NULL_KEY);
|
||||||
|
|
||||||
// Send roll dialog through Player_RegistrationManager
|
// Send roll dialog through Player_RegistrationManager
|
||||||
|
|
@ -881,8 +889,8 @@ default {
|
||||||
|
|
||||||
// VALIDATE: Check for duplicate picks before saving
|
// VALIDATE: Check for duplicate picks before saving
|
||||||
if (picksStr != "" && llListFindList(globalPickedNumbers, [picksStr]) != -1) {
|
if (picksStr != "" && llListFindList(globalPickedNumbers, [picksStr]) != -1) {
|
||||||
llOwnerSay("❌ [Game Manager] Bot " + playerName + " tried to pick duplicate number: " + picksStr + " - REJECTING");
|
dbg("❌ [Game Manager] Bot " + playerName + " tried to pick duplicate number: " + picksStr + " - REJECTING");
|
||||||
llOwnerSay("🙄 [Game Manager] Sending new pick command to Bot Manager for " + playerName);
|
dbg("🙄 [Game Manager] Sending new pick command to Bot Manager for " + playerName);
|
||||||
|
|
||||||
// Calculate picks needed for bot retry
|
// Calculate picks needed for bot retry
|
||||||
integer perilIdx = llListFindList(names, [perilPlayer]);
|
integer perilIdx = llListFindList(names, [perilPlayer]);
|
||||||
|
|
@ -896,14 +904,14 @@ default {
|
||||||
list completeAvoidList = buildCompleteAvoidanceList();
|
list completeAvoidList = buildCompleteAvoidanceList();
|
||||||
string avoidListStr = llList2CSV(completeAvoidList);
|
string avoidListStr = llList2CSV(completeAvoidList);
|
||||||
string botCommand = "BOT_PICK:" + playerName + ":" + (string)picksNeeded + ":" + (string)diceType + ":" + avoidListStr;
|
string botCommand = "BOT_PICK:" + playerName + ":" + (string)picksNeeded + ":" + (string)diceType + ":" + avoidListStr;
|
||||||
llOwnerSay("🎯 [Game Manager] Sending retry bot command with complete avoid list (" + (string)llGetListLength(completeAvoidList) + " numbers): " + avoidListStr);
|
dbg("🎯 [Game Manager] Sending retry bot command with complete avoid list (" + (string)llGetListLength(completeAvoidList) + " numbers): " + avoidListStr);
|
||||||
llMessageLinked(LINK_SET, -9999, botCommand, NULL_KEY);
|
llMessageLinked(LINK_SET, -9999, botCommand, NULL_KEY);
|
||||||
return; // Don't save this pick
|
return; // Don't save this pick
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update picks data
|
// Update picks data
|
||||||
integer idx = llListFindList(names, [playerName]);
|
integer idx = llListFindList(names, [playerName]);
|
||||||
llOwnerSay("🔧 [Game Manager] Looking for bot " + playerName + " in names list: " + llList2CSV(names) + " (idx: " + (string)idx + ")");
|
dbg("🔧 [Game Manager] Looking for bot " + playerName + " in names list: " + llList2CSV(names) + " (idx: " + (string)idx + ")");
|
||||||
if (idx != -1) {
|
if (idx != -1) {
|
||||||
integer picksIdx = -1;
|
integer picksIdx = -1;
|
||||||
integer k;
|
integer k;
|
||||||
|
|
@ -963,19 +971,19 @@ default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
llOwnerSay("🔍 [Game Manager] Bot pick complete - players with picks: " + (string)playersWithPicks + "/" + (string)llGetListLength(names));
|
dbg("🔍 [Game Manager] Bot pick complete - players with picks: " + (string)playersWithPicks + "/" + (string)llGetListLength(names));
|
||||||
|
|
||||||
// If all players have picks, advance to roll phase
|
// If all players have picks, advance to roll phase
|
||||||
if (playersWithPicks >= llGetListLength(names)) {
|
if (playersWithPicks >= llGetListLength(names)) {
|
||||||
llOwnerSay("🎯 [Game Manager] All players have picks! Moving to roll phase...");
|
dbg("🎯 [Game Manager] All players have picks! Moving to roll phase...");
|
||||||
|
|
||||||
// CRITICAL: Sync the updated picks data to all modules before roll phase
|
// CRITICAL: Sync the updated picks data to all modules before roll phase
|
||||||
llOwnerSay("🔄 [Game Manager] Syncing final picks data before roll phase...");
|
dbg("🔄 [Game Manager] Syncing final picks data before roll phase...");
|
||||||
syncStateToMain();
|
syncStateToMain();
|
||||||
llSleep(0.2); // Brief delay to ensure sync propagates
|
llSleep(0.2); // Brief delay to ensure sync propagates
|
||||||
|
|
||||||
// Force close any active number picker dialogs
|
// Force close any active number picker dialogs
|
||||||
llOwnerSay("🚫 [Game Manager] Sending CLOSE_ALL_DIALOGS command");
|
dbg("🚫 [Game Manager] Sending CLOSE_ALL_DIALOGS command");
|
||||||
llMessageLinked(LINK_SET, -9999, "CLOSE_ALL_DIALOGS", NULL_KEY);
|
llMessageLinked(LINK_SET, -9999, "CLOSE_ALL_DIALOGS", NULL_KEY);
|
||||||
|
|
||||||
// Send roll dialog through Player_RegistrationManager
|
// Send roll dialog through Player_RegistrationManager
|
||||||
|
|
@ -995,12 +1003,12 @@ default {
|
||||||
|
|
||||||
// Handle continue round requests from Main Controller
|
// Handle continue round requests from Main Controller
|
||||||
if (num == MSG_CONTINUE_ROUND) {
|
if (num == MSG_CONTINUE_ROUND) {
|
||||||
llOwnerSay("🎯 [Game Manager] Received continue round request with peril player: '" + str + "'");
|
dbg("🎯 [Game Manager] Received continue round request with peril player: '" + str + "'");
|
||||||
|
|
||||||
// Update peril player from the continue message if provided
|
// Update peril player from the continue message if provided
|
||||||
if (str != "" && str != "NONE") {
|
if (str != "" && str != "NONE") {
|
||||||
perilPlayer = str;
|
perilPlayer = str;
|
||||||
llOwnerSay("🎯 [Game Manager] Updated peril player to: " + perilPlayer);
|
dbg("🎯 [Game Manager] Updated peril player to: " + perilPlayer);
|
||||||
|
|
||||||
// Reset round state and continue with existing peril player
|
// Reset round state and continue with existing peril player
|
||||||
roundStarted = FALSE;
|
roundStarted = FALSE;
|
||||||
|
|
@ -1012,7 +1020,7 @@ default {
|
||||||
continueCurrentRound();
|
continueCurrentRound();
|
||||||
} else {
|
} else {
|
||||||
// Empty peril player means this is initial game start - use startNextRound()
|
// Empty peril player means this is initial game start - use startNextRound()
|
||||||
llOwnerSay("🎯 [Game Manager] Empty peril player - starting initial game round");
|
dbg("🎯 [Game Manager] Empty peril player - starting initial game round");
|
||||||
|
|
||||||
// Reset round state
|
// Reset round state
|
||||||
roundStarted = FALSE;
|
roundStarted = FALSE;
|
||||||
|
|
@ -1030,11 +1038,13 @@ default {
|
||||||
if (num == 9011 && llSubStringIndex(str, "VERBOSE_LOGGING|") == 0) {
|
if (num == 9011 && llSubStringIndex(str, "VERBOSE_LOGGING|") == 0) {
|
||||||
list parts = llParseString2List(str, ["|"], []);
|
list parts = llParseString2List(str, ["|"], []);
|
||||||
if (llGetListLength(parts) >= 2) {
|
if (llGetListLength(parts) >= 2) {
|
||||||
|
#if DEBUG_LOGS
|
||||||
VERBOSE_LOGGING = (integer)llList2String(parts, 1);
|
VERBOSE_LOGGING = (integer)llList2String(parts, 1);
|
||||||
|
#endif
|
||||||
if (VERBOSE_LOGGING) {
|
if (VERBOSE_LOGGING) {
|
||||||
llOwnerSay("🔍 [Game Manager] Verbose logging ON");
|
dbg("🔍 [Game Manager] Verbose logging ON");
|
||||||
} else {
|
} else {
|
||||||
llOwnerSay("🔍 [Game Manager] Verbose logging OFF");
|
dbg("🔍 [Game Manager] Verbose logging OFF");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -1051,13 +1061,13 @@ default {
|
||||||
diceTypeProcessed = FALSE; // Reset for new game
|
diceTypeProcessed = FALSE; // Reset for new game
|
||||||
roundContinueInProgress = FALSE; // Reset protection flag
|
roundContinueInProgress = FALSE; // Reset protection flag
|
||||||
lastSyncProcessTime = 0; // Reset sync timing
|
lastSyncProcessTime = 0; // Reset sync timing
|
||||||
llOwnerSay("🎯 Game Manager reset - ready for new game!");
|
dbg("🎯 Game Manager reset - ready for new game!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle emergency state reset (for when game gets stuck)
|
// Handle emergency state reset (for when game gets stuck)
|
||||||
if (num == -99998 && str == "EMERGENCY_RESET") {
|
if (num == -99998 && str == "EMERGENCY_RESET") {
|
||||||
llOwnerSay("🚨 [Game Manager] Emergency reset triggered!");
|
dbg("🚨 [Game Manager] Emergency reset triggered!");
|
||||||
roundStarted = FALSE;
|
roundStarted = FALSE;
|
||||||
perilPlayer = "";
|
perilPlayer = "";
|
||||||
currentPickerIdx = 0;
|
currentPickerIdx = 0;
|
||||||
|
|
@ -1065,7 +1075,7 @@ default {
|
||||||
diceTypeProcessed = FALSE;
|
diceTypeProcessed = FALSE;
|
||||||
roundContinueInProgress = FALSE;
|
roundContinueInProgress = FALSE;
|
||||||
lastSyncProcessTime = 0; // Reset sync timing
|
lastSyncProcessTime = 0; // Reset sync timing
|
||||||
llOwnerSay("🔒 [Game Manager] Emergency state reset complete");
|
dbg("🔒 [Game Manager] Emergency state reset complete");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,15 @@
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
// Verbose logging control
|
// Verbose logging control
|
||||||
integer VERBOSE_LOGGING = FALSE; // Global flag for verbose debug logs - DISABLED to save memory
|
#define DEBUG_LOGS 0 // Set to 1 to enable, 0 to STRIP all logs from memory
|
||||||
|
|
||||||
|
#if DEBUG_LOGS
|
||||||
|
#define dbg(msg) llOwnerSay(msg)
|
||||||
|
integer VERBOSE_LOGGING = FALSE;
|
||||||
|
#else
|
||||||
|
#define dbg(msg)
|
||||||
|
#define VERBOSE_LOGGING 0
|
||||||
|
#endif
|
||||||
#define MSG_TOGGLE_VERBOSE_LOGS 9998 // Message to toggle verbose logging
|
#define MSG_TOGGLE_VERBOSE_LOGS 9998 // Message to toggle verbose logging
|
||||||
|
|
||||||
// Message constants for link communication
|
// Message constants for link communication
|
||||||
|
|
@ -919,7 +927,11 @@ updatePlayerDisplay(string playerName, integer lives, string profileUUID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
default {
|
default {
|
||||||
|
on_rez(integer start_param) {
|
||||||
|
llResetScript(); // Fixes Z-fighting and alignment glitches on rez
|
||||||
|
}
|
||||||
state_entry() {
|
state_entry() {
|
||||||
|
llListen(1, "", llGetOwner(), ""); // Listen on channel 1 for local owner testing commands
|
||||||
reportMemoryUsage("Scoreboard Manager");
|
reportMemoryUsage("Scoreboard Manager");
|
||||||
if (VERBOSE_LOGGING) {
|
if (VERBOSE_LOGGING) {
|
||||||
llOwnerSay("📈 Scoreboard Manager ready! (Linkset Version)");
|
llOwnerSay("📈 Scoreboard Manager ready! (Linkset Version)");
|
||||||
|
|
@ -938,6 +950,8 @@ default {
|
||||||
|
|
||||||
// Load persistent leaderboard data from KVP Experience database
|
// Load persistent leaderboard data from KVP Experience database
|
||||||
loadLeaderboardData();
|
loadLeaderboardData();
|
||||||
|
// Set a timer to passively auto-refresh the global scoreboard every 5 minutes
|
||||||
|
llSetTimerEvent(300.0);
|
||||||
// NOTE: generateLeaderboardText() will be triggered by dataserver automatically when data arrives
|
// NOTE: generateLeaderboardText() will be triggered by dataserver automatically when data arrives
|
||||||
// No need to generate it randomly before data arrives
|
// No need to generate it randomly before data arrives
|
||||||
|
|
||||||
|
|
@ -954,6 +968,7 @@ default {
|
||||||
|
|
||||||
link_message(integer sender, integer num, string str, key id) {
|
link_message(integer sender, integer num, string str, key id) {
|
||||||
// Handle verbose logging toggle
|
// Handle verbose logging toggle
|
||||||
|
#if DEBUG_LOGS
|
||||||
if (num == MSG_TOGGLE_VERBOSE_LOGS) {
|
if (num == MSG_TOGGLE_VERBOSE_LOGS) {
|
||||||
VERBOSE_LOGGING = !VERBOSE_LOGGING;
|
VERBOSE_LOGGING = !VERBOSE_LOGGING;
|
||||||
if (VERBOSE_LOGGING) {
|
if (VERBOSE_LOGGING) {
|
||||||
|
|
@ -963,6 +978,7 @@ default {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Only listen to messages from the main controller (link 1)
|
// Only listen to messages from the main controller (link 1)
|
||||||
if (sender != 1) return;
|
if (sender != 1) return;
|
||||||
|
|
@ -1124,7 +1140,7 @@ default {
|
||||||
string status = llGetSubString(data, 0, comma - 1);
|
string status = llGetSubString(data, 0, comma - 1);
|
||||||
string val = llGetSubString(data, comma + 1, -1);
|
string val = llGetSubString(data, comma + 1, -1);
|
||||||
|
|
||||||
if (status == "0") {
|
if (status == "1") {
|
||||||
leaderboardNames = [];
|
leaderboardNames = [];
|
||||||
leaderboardWins = [];
|
leaderboardWins = [];
|
||||||
leaderboardLosses = [];
|
leaderboardLosses = [];
|
||||||
|
|
@ -1165,7 +1181,7 @@ default {
|
||||||
if (status == "3") {
|
if (status == "3") {
|
||||||
// Update failed because key didn't exist yet! Create it.
|
// Update failed because key didn't exist yet! Create it.
|
||||||
llCreateKeyValue("Peril_LB_Top50", pendingSerialize);
|
llCreateKeyValue("Peril_LB_Top50", pendingSerialize);
|
||||||
} else if (status == "0") {
|
} else if (status == "1") {
|
||||||
if (VERBOSE_LOGGING) {
|
if (VERBOSE_LOGGING) {
|
||||||
llOwnerSay("✅ Global scoreboard synced successfully.");
|
llOwnerSay("✅ Global scoreboard synced successfully.");
|
||||||
}
|
}
|
||||||
|
|
@ -1183,4 +1199,32 @@ default {
|
||||||
llOwnerSay(" HTTP requests pending: " + (string)(llGetListLength(httpRequests) / 2));
|
llOwnerSay(" HTTP requests pending: " + (string)(llGetListLength(httpRequests) / 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timer() {
|
||||||
|
if (VERBOSE_LOGGING) {
|
||||||
|
llOwnerSay("⏱️ Auto-refreshing Global Scoreboard Data...");
|
||||||
|
}
|
||||||
|
loadLeaderboardData();
|
||||||
|
}
|
||||||
|
|
||||||
|
listen(integer channel, string name, key id, string message) {
|
||||||
|
string msg = llToLower(llStringTrim(message, STRING_TRIM));
|
||||||
|
if (msg == "testx") {
|
||||||
|
llOwnerSay("Testing X overlays on all 10 player slots...");
|
||||||
|
integer i;
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
integer overlayIdx = getOverlayPrimLink(i);
|
||||||
|
if (overlayIdx >= FIRST_OVERLAY_PRIM && overlayIdx <= LAST_OVERLAY_PRIM) {
|
||||||
|
llSetLinkPrimitiveParamsFast(overlayIdx, [
|
||||||
|
PRIM_TEXTURE, ALL_SIDES, TEXTURE_ELIMINATED_X, <1,1,0>, <0,0,0>, 0.0,
|
||||||
|
PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (msg == "clearx") {
|
||||||
|
llOwnerSay("Refreshing display to clear test X overlays...");
|
||||||
|
refreshPlayerDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,9 @@ distributeToBank(string text, list linkNumbers) {
|
||||||
}
|
}
|
||||||
|
|
||||||
default {
|
default {
|
||||||
|
on_rez(integer start_param) {
|
||||||
|
llResetScript(); // Fixes Z-fighting and alignment glitches on rez
|
||||||
|
}
|
||||||
state_entry() {
|
state_entry() {
|
||||||
if (VERBOSE_LOGGING) {
|
if (VERBOSE_LOGGING) {
|
||||||
llOwnerSay("📋 Leaderboard Communication Script ready! (Linkset Version)");
|
llOwnerSay("📋 Leaderboard Communication Script ready! (Linkset Version)");
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,13 @@ string getPlayerName(key id) {
|
||||||
// LINKSET COMMUNICATION CONSTANTS
|
// LINKSET COMMUNICATION CONSTANTS
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
|
#define DEBUG_LOGS 0 // Set to 1 to enable logs, 0 to STRIP them from bytecode and recover memory
|
||||||
|
#if DEBUG_LOGS
|
||||||
|
#define dbg(msg) dbg(msg)
|
||||||
|
#else
|
||||||
|
#define dbg(msg)
|
||||||
|
#endif
|
||||||
|
|
||||||
// Target link numbers (UPDATED after overlay prim insertion)
|
// Target link numbers (UPDATED after overlay prim insertion)
|
||||||
#define SCOREBOARD_LINK 12 // Scoreboard manager cube
|
#define SCOREBOARD_LINK 12 // Scoreboard manager cube
|
||||||
#define LEADERBOARD_LINK 35 // Leaderboard manager (first XyzzyText prim)
|
#define LEADERBOARD_LINK 35 // Leaderboard manager (first XyzzyText prim)
|
||||||
|
|
@ -343,7 +350,7 @@ resetGame() {
|
||||||
llMessageLinked(SCOREBOARD_LINK, MSG_UPDATE_WINNER, "", NULL_KEY); // Clear winner glow
|
llMessageLinked(SCOREBOARD_LINK, MSG_UPDATE_WINNER, "", NULL_KEY); // Clear winner glow
|
||||||
llMessageLinked(DICE_LINK, MSG_CLEAR_DICE, "", NULL_KEY);
|
llMessageLinked(DICE_LINK, MSG_CLEAR_DICE, "", NULL_KEY);
|
||||||
|
|
||||||
llOwnerSay("🎮 Game reset! All state cleared (including scoreboard).");
|
dbg("🎮 Game reset! All state cleared (including scoreboard).");
|
||||||
|
|
||||||
statusTimer = 0;
|
statusTimer = 0;
|
||||||
lastStatus = "";
|
lastStatus = "";
|
||||||
|
|
@ -365,7 +372,7 @@ resetGame() {
|
||||||
default {
|
default {
|
||||||
state_entry() {
|
state_entry() {
|
||||||
reportMemoryUsage("Main Controller");
|
reportMemoryUsage("Main Controller");
|
||||||
llOwnerSay("🎮 Main Controller ready! (Linkset Version)");
|
dbg("🎮 Main Controller ready! (Linkset Version)");
|
||||||
|
|
||||||
// Initialize lockout system
|
// Initialize lockout system
|
||||||
gameOwner = llGetOwner();
|
gameOwner = llGetOwner();
|
||||||
|
|
@ -377,12 +384,12 @@ default {
|
||||||
// Reset the game on startup to ensure clean state
|
// Reset the game on startup to ensure clean state
|
||||||
resetGame();
|
resetGame();
|
||||||
|
|
||||||
llOwnerSay("✅ Main Controller initialization complete!");
|
dbg("✅ Main Controller initialization complete!");
|
||||||
}
|
}
|
||||||
|
|
||||||
on_rez(integer start_param) {
|
on_rez(integer start_param) {
|
||||||
reportMemoryUsage("Main Controller");
|
reportMemoryUsage("Main Controller");
|
||||||
llOwnerSay("🔄 Main Controller rezzed - resetting game state...");
|
dbg("🔄 Main Controller rezzed - resetting game state...");
|
||||||
|
|
||||||
// Re-initialize lockout system
|
// Re-initialize lockout system
|
||||||
gameOwner = llGetOwner();
|
gameOwner = llGetOwner();
|
||||||
|
|
@ -394,7 +401,7 @@ default {
|
||||||
// Reset the game to ensure clean state when rezzed
|
// Reset the game to ensure clean state when rezzed
|
||||||
resetGame();
|
resetGame();
|
||||||
|
|
||||||
llOwnerSay("✅ Main Controller reset complete after rez!");
|
dbg("✅ Main Controller reset complete after rez!");
|
||||||
}
|
}
|
||||||
|
|
||||||
touch_start(integer total_number) {
|
touch_start(integer total_number) {
|
||||||
|
|
@ -475,11 +482,11 @@ default {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toucher == llGetOwner()) {
|
if (toucher == llGetOwner()) {
|
||||||
llOwnerSay("🔍 [DEBUG] Owner touched - idx: " + (string)idx + ", players list: " + llList2CSV(players));
|
dbg("🔍 [DEBUG] Owner touched - idx: " + (string)idx + ", players list: " + llList2CSV(players));
|
||||||
if (idx == -1) {
|
if (idx == -1) {
|
||||||
// Owner is not in game - show join/admin choice
|
// Owner is not in game - show join/admin choice
|
||||||
if (llListFindList(pendingRegistrations, [toucher]) != -1) {
|
if (llListFindList(pendingRegistrations, [toucher]) != -1) {
|
||||||
llOwnerSay("⏳ Registration already in progress for " + getPlayerName(toucher));
|
dbg("⏳ Registration already in progress for " + getPlayerName(toucher));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -521,7 +528,7 @@ default {
|
||||||
string playerName = getPlayerName(toucher);
|
string playerName = getPlayerName(toucher);
|
||||||
if (playerName != "") {
|
if (playerName != "") {
|
||||||
if (llListFindList(pendingRegistrations, [toucher]) != -1) {
|
if (llListFindList(pendingRegistrations, [toucher]) != -1) {
|
||||||
llOwnerSay("⏳ Registration already in progress for " + playerName);
|
dbg("⏳ Registration already in progress for " + playerName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -538,7 +545,7 @@ default {
|
||||||
}
|
}
|
||||||
llMessageLinked(LINK_SET, MSG_SHOW_MENU, "player|" + (string)isStarter, toucher);
|
llMessageLinked(LINK_SET, MSG_SHOW_MENU, "player|" + (string)isStarter, toucher);
|
||||||
} else {
|
} else {
|
||||||
llOwnerSay("⚠️ Could not get name for toucher: " + (string)toucher);
|
dbg("⚠️ Could not get name for toucher: " + (string)toucher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -567,8 +574,8 @@ default {
|
||||||
integer existingPlayerIdx = llListFindList(players, [id]);
|
integer existingPlayerIdx = llListFindList(players, [id]);
|
||||||
|
|
||||||
if (existingPlayerIdx != -1) {
|
if (existingPlayerIdx != -1) {
|
||||||
llOwnerSay("⚠️ [Main Controller] DUPLICATE PLAYER KEY DETECTED - Player: " + newName + " (" + (string)id + ") already exists!");
|
dbg("⚠️ [Main Controller] DUPLICATE PLAYER KEY DETECTED - Player: " + newName + " (" + (string)id + ") already exists!");
|
||||||
llOwnerSay("⚠️ [Main Controller] Players list length: " + (string)llGetListLength(players) + ", Names list length: " + (string)llGetListLength(names));
|
dbg("⚠️ [Main Controller] Players list length: " + (string)llGetListLength(players) + ", Names list length: " + (string)llGetListLength(names));
|
||||||
return; // Skip adding duplicate
|
return; // Skip adding duplicate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -585,8 +592,8 @@ default {
|
||||||
}
|
}
|
||||||
|
|
||||||
// That's it! Player_RegistrationManager already sent sync and scoreboard updates
|
// That's it! Player_RegistrationManager already sent sync and scoreboard updates
|
||||||
llOwnerSay("✅ Player added to master lists: " + newName + " (" + (string)llGetFreeMemory() + " bytes free)");
|
dbg("✅ Player added to master lists: " + newName + " (" + (string)llGetFreeMemory() + " bytes free)");
|
||||||
llOwnerSay("🔍 [DEBUG] Updated lists - Players: " + (string)llGetListLength(players) + ", Names: " + (string)llGetListLength(names));
|
dbg("🔍 [DEBUG] Updated lists - Players: " + (string)llGetListLength(players) + ", Names: " + (string)llGetListLength(names));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -625,7 +632,7 @@ default {
|
||||||
// SEND WINNER GLOW to scoreboard and trigger floater update
|
// SEND WINNER GLOW to scoreboard and trigger floater update
|
||||||
llMessageLinked(SCOREBOARD_LINK, MSG_UPDATE_WINNER, potentialWinner, NULL_KEY);
|
llMessageLinked(SCOREBOARD_LINK, MSG_UPDATE_WINNER, potentialWinner, NULL_KEY);
|
||||||
llMessageLinked(LINK_SET, MSG_UPDATE_FLOAT, potentialWinner, NULL_KEY); // Update winner's floater
|
llMessageLinked(LINK_SET, MSG_UPDATE_FLOAT, potentialWinner, NULL_KEY); // Update winner's floater
|
||||||
llOwnerSay("🏆 [Main Controller] Pre-victory winner glow sent for: " + potentialWinner);
|
dbg("🏆 [Main Controller] Pre-victory winner glow sent for: " + potentialWinner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -718,7 +725,7 @@ default {
|
||||||
|
|
||||||
// ENHANCED: Give eliminated player's floater time to show eliminated status
|
// ENHANCED: Give eliminated player's floater time to show eliminated status
|
||||||
// before declaring victory and cleaning up
|
// before declaring victory and cleaning up
|
||||||
llOwnerSay("⏳ [Main Controller] Final elimination detected - allowing display time before victory");
|
dbg("⏳ [Main Controller] Final elimination detected - allowing display time before victory");
|
||||||
llSleep(2.0); // Give final eliminated player time to show red eliminated status
|
llSleep(2.0); // Give final eliminated player time to show red eliminated status
|
||||||
|
|
||||||
// CRITICAL: Set victory flag immediately to prevent sync processing
|
// CRITICAL: Set victory flag immediately to prevent sync processing
|
||||||
|
|
@ -750,7 +757,7 @@ default {
|
||||||
llMessageLinked(SCOREBOARD_LINK, MSG_GAME_WON, winner, NULL_KEY);
|
llMessageLinked(SCOREBOARD_LINK, MSG_GAME_WON, winner, NULL_KEY);
|
||||||
|
|
||||||
// Use timer instead of llSleep to avoid immediate reset
|
// Use timer instead of llSleep to avoid immediate reset
|
||||||
llOwnerSay("🏆 [Main Controller] Winner glow applied - starting victory delay timer");
|
dbg("🏆 [Main Controller] Winner glow applied - starting victory delay timer");
|
||||||
victoryDelayTimer = llGetUnixTime();
|
victoryDelayTimer = llGetUnixTime();
|
||||||
currentTimerMode = TIMER_VICTORY_DELAY;
|
currentTimerMode = TIMER_VICTORY_DELAY;
|
||||||
llSetTimerEvent(1.0); // Check every second
|
llSetTimerEvent(1.0); // Check every second
|
||||||
|
|
@ -800,7 +807,7 @@ default {
|
||||||
|
|
||||||
// Handle emergency reset for stuck games
|
// Handle emergency reset for stuck games
|
||||||
if (num == -99998 && str == "EMERGENCY_RESET") {
|
if (num == -99998 && str == "EMERGENCY_RESET") {
|
||||||
llOwnerSay("🚨 [Main Controller] Emergency reset triggered - sending emergency reset to all scripts");
|
dbg("🚨 [Main Controller] Emergency reset triggered - sending emergency reset to all scripts");
|
||||||
// Signal all scripts to emergency reset
|
// Signal all scripts to emergency reset
|
||||||
llMessageLinked(LINK_SET, -99998, "EMERGENCY_RESET", NULL_KEY);
|
llMessageLinked(LINK_SET, -99998, "EMERGENCY_RESET", NULL_KEY);
|
||||||
llSleep(0.5);
|
llSleep(0.5);
|
||||||
|
|
@ -857,7 +864,7 @@ default {
|
||||||
integer idx = llListFindList(names, [playerName]);
|
integer idx = llListFindList(names, [playerName]);
|
||||||
if (idx != -1) {
|
if (idx != -1) {
|
||||||
if (llSubStringIndex(playerName, "Bot") == 0) {
|
if (llSubStringIndex(playerName, "Bot") == 0) {
|
||||||
llOwnerSay("🤖 Bots are always ready and cannot change state");
|
dbg("🤖 Bots are always ready and cannot change state");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -971,12 +978,12 @@ default {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newPerilPlayer != "") {
|
if (newPerilPlayer != "") {
|
||||||
llOwnerSay("🎯 [Main Controller] Peril player left - assigning new peril player: " + newPerilPlayer);
|
dbg("🎯 [Main Controller] Peril player left - assigning new peril player: " + newPerilPlayer);
|
||||||
perilPlayer = newPerilPlayer;
|
perilPlayer = newPerilPlayer;
|
||||||
// Send peril player update to scoreboard for glow effect
|
// Send peril player update to scoreboard for glow effect
|
||||||
llMessageLinked(SCOREBOARD_LINK, 3005, newPerilPlayer, NULL_KEY); // MSG_UPDATE_PERIL_PLAYER
|
llMessageLinked(SCOREBOARD_LINK, 3005, newPerilPlayer, NULL_KEY); // MSG_UPDATE_PERIL_PLAYER
|
||||||
} else {
|
} else {
|
||||||
llOwnerSay("⚠️ [Main Controller] No valid peril player candidates found after player left!");
|
dbg("⚠️ [Main Controller] No valid peril player candidates found after player left!");
|
||||||
perilPlayer = "NONE";
|
perilPlayer = "NONE";
|
||||||
// Clear peril player glow on scoreboard
|
// Clear peril player glow on scoreboard
|
||||||
llMessageLinked(SCOREBOARD_LINK, MSG_UPDATE_PERIL_PLAYER, "", NULL_KEY);
|
llMessageLinked(SCOREBOARD_LINK, MSG_UPDATE_PERIL_PLAYER, "", NULL_KEY);
|
||||||
|
|
@ -1006,7 +1013,7 @@ default {
|
||||||
|
|
||||||
// Check if we should reset the game (no players left)
|
// Check if we should reset the game (no players left)
|
||||||
if (llGetListLength(names) == 0) {
|
if (llGetListLength(names) == 0) {
|
||||||
llOwnerSay("🔄 [Main Controller] All players left - resetting game");
|
dbg("🔄 [Main Controller] All players left - resetting game");
|
||||||
// Force clear any remaining game state before reset
|
// Force clear any remaining game state before reset
|
||||||
roundStarted = FALSE;
|
roundStarted = FALSE;
|
||||||
gameStarting = FALSE;
|
gameStarting = FALSE;
|
||||||
|
|
@ -1018,7 +1025,7 @@ default {
|
||||||
|
|
||||||
// Skip updateHelpers to prevent memory crashes during player removal
|
// Skip updateHelpers to prevent memory crashes during player removal
|
||||||
// Scoreboard was already updated with MSG_REMOVE_PLAYER above
|
// Scoreboard was already updated with MSG_REMOVE_PLAYER above
|
||||||
llOwnerSay("✅ [Main Controller] Synchronized removal of " + leavingName);
|
dbg("✅ [Main Controller] Synchronized removal of " + leavingName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -1029,7 +1036,7 @@ default {
|
||||||
if (id == gameOwner && str == "LOCK_GAME") {
|
if (id == gameOwner && str == "LOCK_GAME") {
|
||||||
isLocked = TRUE;
|
isLocked = TRUE;
|
||||||
updateFloatingText();
|
updateFloatingText();
|
||||||
llOwnerSay("🔒 [Main Controller] Game has been LOCKED - Floating text updated");
|
dbg("🔒 [Main Controller] Game has been LOCKED - Floating text updated");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1038,7 +1045,7 @@ default {
|
||||||
if (id == gameOwner && str == "UNLOCK_GAME") {
|
if (id == gameOwner && str == "UNLOCK_GAME") {
|
||||||
isLocked = FALSE;
|
isLocked = FALSE;
|
||||||
updateFloatingText();
|
updateFloatingText();
|
||||||
llOwnerSay("🔓 [Main Controller] Game has been UNLOCKED - Floating text updated");
|
dbg("🔓 [Main Controller] Game has been UNLOCKED - Floating text updated");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1059,13 +1066,13 @@ default {
|
||||||
// Handle memory monitor messages
|
// Handle memory monitor messages
|
||||||
if (num == MSG_EMERGENCY_CLEANUP) {
|
if (num == MSG_EMERGENCY_CLEANUP) {
|
||||||
// Removed emergencyMemoryCleanup call to save memory
|
// Removed emergencyMemoryCleanup call to save memory
|
||||||
llOwnerSay("Emergency cleanup disabled to prevent crashes");
|
dbg("Emergency cleanup disabled to prevent crashes");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle reset requests from other scripts (like Game_Manager)
|
// Handle reset requests from other scripts (like Game_Manager)
|
||||||
if (num == -99998 && str == "REQUEST_GAME_RESET") {
|
if (num == -99998 && str == "REQUEST_GAME_RESET") {
|
||||||
llOwnerSay("🔄 [Main Controller] Reset requested by " + (string)sender + ", executing...");
|
dbg("🔄 [Main Controller] Reset requested by " + (string)sender + ", executing...");
|
||||||
resetGame();
|
resetGame();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1076,7 +1083,7 @@ default {
|
||||||
if (channel == rollDialogChannel) {
|
if (channel == rollDialogChannel) {
|
||||||
if (msg == "Start Next Round" || msg == "BEGIN KILLING GAME") {
|
if (msg == "Start Next Round" || msg == "BEGIN KILLING GAME") {
|
||||||
if (roundStarted) {
|
if (roundStarted) {
|
||||||
llOwnerSay("⚠️ Round already in progress, ignoring duplicate round start from roll dialog");
|
dbg("⚠️ Round already in progress, ignoring duplicate round start from roll dialog");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1124,23 +1131,23 @@ default {
|
||||||
if (msg == "Reset Leaderboard") {
|
if (msg == "Reset Leaderboard") {
|
||||||
// CHANGED: Send to scoreboard, which will handle leaderboard reset
|
// CHANGED: Send to scoreboard, which will handle leaderboard reset
|
||||||
llMessageLinked(SCOREBOARD_LINK, MSG_RESET_LEADERBOARD, "", NULL_KEY);
|
llMessageLinked(SCOREBOARD_LINK, MSG_RESET_LEADERBOARD, "", NULL_KEY);
|
||||||
llOwnerSay("🏆 Leaderboard scores reset - game wins cleared!");
|
dbg("🏆 Leaderboard scores reset - game wins cleared!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (msg == "Reset All") {
|
if (msg == "Reset All") {
|
||||||
resetGame();
|
resetGame();
|
||||||
llMessageLinked(SCOREBOARD_LINK, MSG_RESET_LEADERBOARD, "", NULL_KEY);
|
llMessageLinked(SCOREBOARD_LINK, MSG_RESET_LEADERBOARD, "", NULL_KEY);
|
||||||
llOwnerSay("🔄 Complete reset - game and leaderboard cleared!");
|
dbg("🔄 Complete reset - game and leaderboard cleared!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (msg == "Memory Stats") {
|
if (msg == "Memory Stats") {
|
||||||
// Removed reportMemoryStats call to save memory
|
// Removed reportMemoryStats call to save memory
|
||||||
llOwnerSay("Memory stats reporting disabled to prevent crashes");
|
dbg("Memory stats reporting disabled to prevent crashes");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (msg == "Add Test Player") {
|
if (msg == "Add Test Player") {
|
||||||
if (llGetListLength(players) >= MAX_PLAYERS) {
|
if (llGetListLength(players) >= MAX_PLAYERS) {
|
||||||
llOwnerSay("⚠️ Cannot add test player; the game is full (max " + (string)MAX_PLAYERS + ").");
|
dbg("⚠️ Cannot add test player; the game is full (max " + (string)MAX_PLAYERS + ").");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1161,11 +1168,11 @@ default {
|
||||||
|
|
||||||
// Don't show menu immediately - let the player touch the board again
|
// Don't show menu immediately - let the player touch the board again
|
||||||
// This avoids timing issues where the menu is shown before registration completes
|
// This avoids timing issues where the menu is shown before registration completes
|
||||||
llOwnerSay("✅ " + testName + " registration sent - touch the board again to refresh menu");
|
dbg("✅ " + testName + " registration sent - touch the board again to refresh menu");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (msg == "Force Floaters") {
|
if (msg == "Force Floaters") {
|
||||||
llOwnerSay("🔧 Forcing floater creation for all " + (string)llGetListLength(names) + " players...");
|
dbg("🔧 Forcing floater creation for all " + (string)llGetListLength(names) + " players...");
|
||||||
integer i;
|
integer i;
|
||||||
for (i = 0; i < llGetListLength(names); i++) {
|
for (i = 0; i < llGetListLength(names); i++) {
|
||||||
string playerName = llList2String(names, i);
|
string playerName = llList2String(names, i);
|
||||||
|
|
@ -1173,7 +1180,7 @@ default {
|
||||||
llMessageLinked(LINK_SET, MSG_REZ_FLOAT, playerName, playerKey);
|
llMessageLinked(LINK_SET, MSG_REZ_FLOAT, playerName, playerKey);
|
||||||
llSleep(0.3);
|
llSleep(0.3);
|
||||||
}
|
}
|
||||||
llOwnerSay("✅ Floater creation requests sent for all players!");
|
dbg("✅ Floater creation requests sent for all players!");
|
||||||
|
|
||||||
// After forcing floaters, show appropriate menu based on owner registration status
|
// After forcing floaters, show appropriate menu based on owner registration status
|
||||||
integer ownerIdx = llListFindList(players, [llGetOwner()]);
|
integer ownerIdx = llListFindList(players, [llGetOwner()]);
|
||||||
|
|
@ -1205,7 +1212,7 @@ default {
|
||||||
integer playerCount = llGetListLength(players);
|
integer playerCount = llGetListLength(players);
|
||||||
integer nameCount = llGetListLength(names);
|
integer nameCount = llGetListLength(names);
|
||||||
if (playerCount < 2) {
|
if (playerCount < 2) {
|
||||||
llOwnerSay("⚠️ Need at least 2 players to start the game.");
|
dbg("⚠️ Need at least 2 players to start the game.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1220,7 +1227,7 @@ default {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (starterName == "") {
|
if (starterName == "") {
|
||||||
llOwnerSay("⚠️ Only the game starter can start the game.");
|
dbg("⚠️ Only the game starter can start the game.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1236,7 +1243,7 @@ default {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (llGetListLength(notReadyPlayers) > 0) {
|
if (llGetListLength(notReadyPlayers) > 0) {
|
||||||
llOwnerSay("⚠️ Cannot start game. These players are not ready: " + llList2CSV(notReadyPlayers));
|
dbg("⚠️ Cannot start game. These players are not ready: " + llList2CSV(notReadyPlayers));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1269,7 +1276,7 @@ default {
|
||||||
lastStatus = "";
|
lastStatus = "";
|
||||||
// CHANGED: Use link message instead of llRegionSay
|
// CHANGED: Use link message instead of llRegionSay
|
||||||
llMessageLinked(SCOREBOARD_LINK, MSG_GAME_STATUS, "Title", NULL_KEY);
|
llMessageLinked(SCOREBOARD_LINK, MSG_GAME_STATUS, "Title", NULL_KEY);
|
||||||
llOwnerSay("📢 Status cleared - reverted to Title");
|
dbg("📢 Status cleared - reverted to Title");
|
||||||
currentTimerMode = TIMER_IDLE;
|
currentTimerMode = TIMER_IDLE;
|
||||||
llSetTimerEvent(0);
|
llSetTimerEvent(0);
|
||||||
}
|
}
|
||||||
|
|
@ -1278,7 +1285,7 @@ default {
|
||||||
if (victoryDelayTimer > 0) {
|
if (victoryDelayTimer > 0) {
|
||||||
integer elapsed = llGetUnixTime() - victoryDelayTimer;
|
integer elapsed = llGetUnixTime() - victoryDelayTimer;
|
||||||
if (elapsed >= (integer)(STATUS_DISPLAY_TIME * 3.0)) { // 24 seconds
|
if (elapsed >= (integer)(STATUS_DISPLAY_TIME * 3.0)) { // 24 seconds
|
||||||
llOwnerSay("🏆 [Main Controller] Victory display time complete - executing game reset");
|
dbg("🏆 [Main Controller] Victory display time complete - executing game reset");
|
||||||
victoryDelayTimer = 0;
|
victoryDelayTimer = 0;
|
||||||
currentTimerMode = TIMER_IDLE;
|
currentTimerMode = TIMER_IDLE;
|
||||||
llSetTimerEvent(0);
|
llSetTimerEvent(0);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,10 @@
|
||||||
|
#define DEBUG_LOGS 0 // Set to 1 to enable logs, 0 to STRIP from memory completely
|
||||||
|
#if DEBUG_LOGS
|
||||||
|
#define dbg(msg) dbg(msg)
|
||||||
|
#else
|
||||||
|
#define dbg(msg)
|
||||||
|
#endif
|
||||||
|
|
||||||
// === Dialog Handler (Owner & Player) with unified Ready/Leave menu and join support ===
|
// === Dialog Handler (Owner & Player) with unified Ready/Leave menu and join support ===
|
||||||
|
|
||||||
// Helper function to get display name with fallback to username
|
// Helper function to get display name with fallback to username
|
||||||
|
|
@ -51,11 +58,11 @@ initializeChannels() {
|
||||||
DICE_DATA_CHANNEL = calculateChannel(8); // ~-85000 range
|
DICE_DATA_CHANNEL = calculateChannel(8); // ~-85000 range
|
||||||
|
|
||||||
// Report channel to owner for debugging
|
// Report channel to owner for debugging
|
||||||
llOwnerSay("🔧 [Owner/Player Dialog] Dynamic channels initialized:");
|
dbg("🔧 [Owner/Player Dialog] Dynamic channels initialized:");
|
||||||
llOwnerSay(" Main Dialog: " + (string)MAIN_DIALOG_CHANNEL);
|
dbg(" Main Dialog: " + (string)MAIN_DIALOG_CHANNEL);
|
||||||
llOwnerSay(" Scoreboard: " + (string)SCOREBOARD_DATA_CHANNEL);
|
dbg(" Scoreboard: " + (string)SCOREBOARD_DATA_CHANNEL);
|
||||||
llOwnerSay(" Leaderboard: " + (string)LEADERBOARD_DATA_CHANNEL);
|
dbg(" Leaderboard: " + (string)LEADERBOARD_DATA_CHANNEL);
|
||||||
llOwnerSay(" Dice: " + (string)DICE_DATA_CHANNEL);
|
dbg(" Dice: " + (string)DICE_DATA_CHANNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
integer DIALOG_CHANNEL; // Legacy variable, will be set dynamically
|
integer DIALOG_CHANNEL; // Legacy variable, will be set dynamically
|
||||||
|
|
@ -165,7 +172,7 @@ showTroubleshootingMenu(key id) {
|
||||||
showReadyLeaveMenu(key id, integer isStarter, integer isOwner) {
|
showReadyLeaveMenu(key id, integer isStarter, integer isOwner) {
|
||||||
// Check for timeout of previous request
|
// Check for timeout of previous request
|
||||||
if (pendingMenuPlayer != NULL_KEY && (llGetTime() - pendingMenuTimestamp) > MENU_REQUEST_TIMEOUT) {
|
if (pendingMenuPlayer != NULL_KEY && (llGetTime() - pendingMenuTimestamp) > MENU_REQUEST_TIMEOUT) {
|
||||||
llOwnerSay("⏰ Previous menu request timed out, clearing pending state");
|
dbg("⏰ Previous menu request timed out, clearing pending state");
|
||||||
pendingMenuPlayer = NULL_KEY;
|
pendingMenuPlayer = NULL_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,7 +183,7 @@ showReadyLeaveMenu(key id, integer isStarter, integer isOwner) {
|
||||||
|
|
||||||
// If there's a pending request for a different player, warn about it but proceed
|
// If there's a pending request for a different player, warn about it but proceed
|
||||||
if (pendingMenuPlayer != NULL_KEY && pendingMenuPlayer != id) {
|
if (pendingMenuPlayer != NULL_KEY && pendingMenuPlayer != id) {
|
||||||
llOwnerSay("⚠️ [Debug] Overriding pending request for " + (string)pendingMenuPlayer + " with new request for " + (string)id);
|
dbg("⚠️ [Debug] Overriding pending request for " + (string)pendingMenuPlayer + " with new request for " + (string)id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pendingMenuPlayer = id;
|
pendingMenuPlayer = id;
|
||||||
|
|
@ -291,7 +298,7 @@ showKickPlayerMenu(key id, list playerNames) {
|
||||||
string buttonLabel = "👢 " + kickDisplayName;
|
string buttonLabel = "👢 " + kickDisplayName;
|
||||||
|
|
||||||
// Debug: Check button length
|
// Debug: Check button length
|
||||||
llOwnerSay("🔍 Debug kick button: '" + buttonLabel + "' = " + (string)llStringLength(buttonLabel) + " chars");
|
dbg("🔍 Debug kick button: '" + buttonLabel + "' = " + (string)llStringLength(buttonLabel) + " chars");
|
||||||
|
|
||||||
kickOptions += [buttonLabel];
|
kickOptions += [buttonLabel];
|
||||||
kickDisplayNames += [buttonLabel]; // Store the full button label
|
kickDisplayNames += [buttonLabel]; // Store the full button label
|
||||||
|
|
@ -363,14 +370,14 @@ default {
|
||||||
leaderboardHandle = llListen(LEADERBOARD_DATA_CHANNEL, "", "", "");
|
leaderboardHandle = llListen(LEADERBOARD_DATA_CHANNEL, "", "", "");
|
||||||
diceHandle = llListen(DICE_DATA_CHANNEL, "", "", "");
|
diceHandle = llListen(DICE_DATA_CHANNEL, "", "", "");
|
||||||
|
|
||||||
llOwnerSay("🎭 Owner and Player Dialog Handler ready with lockout system!");
|
dbg("🎭 Owner and Player Dialog Handler ready with lockout system!");
|
||||||
llOwnerSay("🔓 Game is UNLOCKED - All players can access menus");
|
dbg("🔓 Game is UNLOCKED - All players can access menus");
|
||||||
}
|
}
|
||||||
|
|
||||||
on_rez(integer start_param) {
|
on_rez(integer start_param) {
|
||||||
reportMemoryUsage("🎭 Player Dialog");
|
reportMemoryUsage("🎭 Player Dialog");
|
||||||
|
|
||||||
llOwnerSay("🔄 Player Dialog Handler rezzed - reinitializing...");
|
dbg("🔄 Player Dialog Handler rezzed - reinitializing...");
|
||||||
|
|
||||||
// Re-initialize dynamic channels
|
// Re-initialize dynamic channels
|
||||||
initializeChannels();
|
initializeChannels();
|
||||||
|
|
@ -408,7 +415,7 @@ default {
|
||||||
leaderboardHandle = llListen(LEADERBOARD_DATA_CHANNEL, "", "", "");
|
leaderboardHandle = llListen(LEADERBOARD_DATA_CHANNEL, "", "", "");
|
||||||
diceHandle = llListen(DICE_DATA_CHANNEL, "", "", "");
|
diceHandle = llListen(DICE_DATA_CHANNEL, "", "", "");
|
||||||
|
|
||||||
llOwnerSay("✅ Player Dialog Handler reset complete after rez!");
|
dbg("✅ Player Dialog Handler reset complete after rez!");
|
||||||
}
|
}
|
||||||
|
|
||||||
link_message(integer sender, integer num, string str, key id) {
|
link_message(integer sender, integer num, string str, key id) {
|
||||||
|
|
@ -424,14 +431,14 @@ default {
|
||||||
currentPickList = [];
|
currentPickList = [];
|
||||||
currentPickTarget = "";
|
currentPickTarget = "";
|
||||||
currentPickLimit = 3;
|
currentPickLimit = 3;
|
||||||
llOwnerSay("🎭 Owner and Player Dialog Handler reset!");
|
dbg("🎭 Owner and Player Dialog Handler reset!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num == MSG_SHOW_MENU) {
|
if (num == MSG_SHOW_MENU) {
|
||||||
list args = llParseString2List(str, ["|"], []);
|
list args = llParseString2List(str, ["|"], []);
|
||||||
if (llGetListLength(args) < 2) {
|
if (llGetListLength(args) < 2) {
|
||||||
llOwnerSay("⚠️ Invalid message format: " + str);
|
dbg("⚠️ Invalid message format: " + str);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
string targetType = llList2String(args, 0);
|
string targetType = llList2String(args, 0);
|
||||||
|
|
@ -468,7 +475,7 @@ default {
|
||||||
if (pendingMenuPlayer == id && responseRequestID == pendingMenuRequestID) {
|
if (pendingMenuPlayer == id && responseRequestID == pendingMenuRequestID) {
|
||||||
// Check for timeout
|
// Check for timeout
|
||||||
if ((llGetTime() - pendingMenuTimestamp) > MENU_REQUEST_TIMEOUT) {
|
if ((llGetTime() - pendingMenuTimestamp) > MENU_REQUEST_TIMEOUT) {
|
||||||
llOwnerSay("⏰ Menu request timed out, ignoring response");
|
dbg("⏰ Menu request timed out, ignoring response");
|
||||||
pendingMenuPlayer = NULL_KEY;
|
pendingMenuPlayer = NULL_KEY;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -479,20 +486,20 @@ default {
|
||||||
pendingMenuRequestID = 0;
|
pendingMenuRequestID = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
llOwnerSay("⚠️ Invalid ready state result format - expected 4 parts, got " + (string)llGetListLength(parts));
|
dbg("⚠️ Invalid ready state result format - expected 4 parts, got " + (string)llGetListLength(parts));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (num == MSG_PLAYER_LIST_RESULT) {
|
else if (num == MSG_PLAYER_LIST_RESULT) {
|
||||||
list playerNames = llParseString2List(str, [","], []);
|
list playerNames = llParseString2List(str, [","], []);
|
||||||
llOwnerSay("📋 Fetching list of players for pick management...");
|
dbg("📋 Fetching list of players for pick management...");
|
||||||
showPickManageMenu(id, playerNames);
|
showPickManageMenu(id, playerNames);
|
||||||
}
|
}
|
||||||
// Handle player list result for kick functionality
|
// Handle player list result for kick functionality
|
||||||
else if (num == 8009) {
|
else if (num == 8009) {
|
||||||
llOwnerSay("🔍 [Dialog Handler] Received kick player list string: '" + str + "'");
|
dbg("🔍 [Dialog Handler] Received kick player list string: '" + str + "'");
|
||||||
list rawNames = llParseString2List(str, [","], []);
|
list rawNames = llParseString2List(str, [","], []);
|
||||||
llOwnerSay("🔍 [Dialog Handler] Raw parsed into " + (string)llGetListLength(rawNames) + " names: " + llList2CSV(rawNames));
|
dbg("🔍 [Dialog Handler] Raw parsed into " + (string)llGetListLength(rawNames) + " names: " + llList2CSV(rawNames));
|
||||||
|
|
||||||
// Filter out any command strings that might have gotten mixed in
|
// Filter out any command strings that might have gotten mixed in
|
||||||
list playerNames = [];
|
list playerNames = [];
|
||||||
|
|
@ -506,11 +513,11 @@ default {
|
||||||
llSubStringIndex(name, "MSG_") != 0) {
|
llSubStringIndex(name, "MSG_") != 0) {
|
||||||
playerNames += [name];
|
playerNames += [name];
|
||||||
} else {
|
} else {
|
||||||
llOwnerSay("⚠️ [Dialog Handler] Filtered out invalid name: '" + name + "'");
|
dbg("⚠️ [Dialog Handler] Filtered out invalid name: '" + name + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
llOwnerSay("🔍 [Dialog Handler] Filtered to " + (string)llGetListLength(playerNames) + " valid names: " + llList2CSV(playerNames));
|
dbg("🔍 [Dialog Handler] Filtered to " + (string)llGetListLength(playerNames) + " valid names: " + llList2CSV(playerNames));
|
||||||
showKickPlayerMenu(id, playerNames);
|
showKickPlayerMenu(id, playerNames);
|
||||||
}
|
}
|
||||||
else if (num == MSG_PICK_LIST_RESULT) {
|
else if (num == MSG_PICK_LIST_RESULT) {
|
||||||
|
|
@ -518,11 +525,11 @@ default {
|
||||||
string returnedName = llList2String(parts, 0);
|
string returnedName = llList2String(parts, 0);
|
||||||
string picks = llList2String(parts, 1);
|
string picks = llList2String(parts, 1);
|
||||||
if (llStringTrim(returnedName, STRING_TRIM) == llStringTrim(currentPickTarget, STRING_TRIM)) {
|
if (llStringTrim(returnedName, STRING_TRIM) == llStringTrim(currentPickTarget, STRING_TRIM)) {
|
||||||
llOwnerSay("✅ Matched pick list for: " + returnedName);
|
dbg("✅ Matched pick list for: " + returnedName);
|
||||||
currentPickList = llCSV2List(picks);
|
currentPickList = llCSV2List(picks);
|
||||||
llMessageLinked(LINK_THIS, MSG_LIFE_LOOKUP, currentPickTarget, id);
|
llMessageLinked(LINK_THIS, MSG_LIFE_LOOKUP, currentPickTarget, id);
|
||||||
} else {
|
} else {
|
||||||
llOwnerSay("❌ Name mismatch: got " + returnedName + " but expected " + currentPickTarget);
|
dbg("❌ Name mismatch: got " + returnedName + " but expected " + currentPickTarget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (num == MSG_LIFE_LOOKUP) {
|
else if (num == MSG_LIFE_LOOKUP) {
|
||||||
|
|
@ -546,7 +553,7 @@ default {
|
||||||
if (pendingMenuPlayer == id && responseRequestID == pendingMenuRequestID) {
|
if (pendingMenuPlayer == id && responseRequestID == pendingMenuRequestID) {
|
||||||
// Check for timeout
|
// Check for timeout
|
||||||
if ((llGetTime() - pendingMenuTimestamp) > MENU_REQUEST_TIMEOUT) {
|
if ((llGetTime() - pendingMenuTimestamp) > MENU_REQUEST_TIMEOUT) {
|
||||||
llOwnerSay("⏰ Owner status query timed out, ignoring response");
|
dbg("⏰ Owner status query timed out, ignoring response");
|
||||||
pendingMenuPlayer = NULL_KEY;
|
pendingMenuPlayer = NULL_KEY;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -554,13 +561,13 @@ default {
|
||||||
// Decide which menu to show based on registration status
|
// Decide which menu to show based on registration status
|
||||||
if (isRegistered) {
|
if (isRegistered) {
|
||||||
// Owner is registered - show ready/leave menu with Owner button
|
// Owner is registered - show ready/leave menu with Owner button
|
||||||
llOwnerSay("🔍 [Debug] Owner is registered, isStarter=" + (string)isStarter + ", showing ready/leave menu");
|
dbg("🔍 [Debug] Owner is registered, isStarter=" + (string)isStarter + ", showing ready/leave menu");
|
||||||
llOwnerSay("🔍 [Debug] About to call showReadyLeaveMenu with id=" + (string)id + ", isStarter=" + (string)isStarter + ", isOwner=TRUE");
|
dbg("🔍 [Debug] About to call showReadyLeaveMenu with id=" + (string)id + ", isStarter=" + (string)isStarter + ", isOwner=TRUE");
|
||||||
|
|
||||||
// DON'T reset pending state here - showReadyLeaveMenu needs it!
|
// DON'T reset pending state here - showReadyLeaveMenu needs it!
|
||||||
// The ready state handler will reset it when the dialog is shown
|
// The ready state handler will reset it when the dialog is shown
|
||||||
showReadyLeaveMenu(id, isStarter, TRUE);
|
showReadyLeaveMenu(id, isStarter, TRUE);
|
||||||
llOwnerSay("🔍 [Debug] showReadyLeaveMenu call completed");
|
dbg("🔍 [Debug] showReadyLeaveMenu call completed");
|
||||||
} else if (isPending) {
|
} else if (isPending) {
|
||||||
llRegionSayTo(id, 0, "⏳ Registration already in progress for " + ownerName);
|
llRegionSayTo(id, 0, "⏳ Registration already in progress for " + ownerName);
|
||||||
// Reset pending state for non-registered responses
|
// Reset pending state for non-registered responses
|
||||||
|
|
@ -576,10 +583,10 @@ default {
|
||||||
pendingMenuRequestID = 0;
|
pendingMenuRequestID = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
llOwnerSay("⚠️ Owner status response mismatch - ignoring");
|
dbg("⚠️ Owner status response mismatch - ignoring");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
llOwnerSay("⚠️ Invalid owner status result format - expected 5 parts, got " + (string)llGetListLength(parts));
|
dbg("⚠️ Invalid owner status result format - expected 5 parts, got " + (string)llGetListLength(parts));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -603,7 +610,7 @@ default {
|
||||||
isLocked = TRUE;
|
isLocked = TRUE;
|
||||||
// Notify Main Controller to update floating text
|
// Notify Main Controller to update floating text
|
||||||
llMessageLinked(LINK_SET, 9001, "LOCK_GAME", id);
|
llMessageLinked(LINK_SET, 9001, "LOCK_GAME", id);
|
||||||
llOwnerSay("🔒 Game has been LOCKED - Only owner can access any features");
|
dbg("🔒 Game has been LOCKED - Only owner can access any features");
|
||||||
llSay(0, "🔒 Game has been locked by the owner. Only the owner can access any features.");
|
llSay(0, "🔒 Game has been locked by the owner. Only the owner can access any features.");
|
||||||
showOwnerMenu(id); // Refresh the owner menu
|
showOwnerMenu(id); // Refresh the owner menu
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -615,7 +622,7 @@ default {
|
||||||
isLocked = FALSE;
|
isLocked = FALSE;
|
||||||
// Notify Main Controller to update floating text
|
// Notify Main Controller to update floating text
|
||||||
llMessageLinked(LINK_SET, 9002, "UNLOCK_GAME", id);
|
llMessageLinked(LINK_SET, 9002, "UNLOCK_GAME", id);
|
||||||
llOwnerSay("🔓 Game has been UNLOCKED - All players can access menus");
|
dbg("🔓 Game has been UNLOCKED - All players can access menus");
|
||||||
llSay(0, "🔓 Game has been unlocked by the owner. All features are now available.");
|
llSay(0, "🔓 Game has been unlocked by the owner. All features are now available.");
|
||||||
showOwnerMenu(id); // Refresh the owner menu
|
showOwnerMenu(id); // Refresh the owner menu
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -676,25 +683,25 @@ default {
|
||||||
}
|
}
|
||||||
else if (msg == "Cleanup Floaters") {
|
else if (msg == "Cleanup Floaters") {
|
||||||
// Universal floater cleanup that works even after script resets
|
// Universal floater cleanup that works even after script resets
|
||||||
llOwnerSay("🧩 Force cleaning ALL possible floater channels...");
|
dbg("🧩 Force cleaning ALL possible floater channels...");
|
||||||
llMessageLinked(LINK_SET, MSG_CLEANUP_ALL_FLOATERS, "", NULL_KEY);
|
llMessageLinked(LINK_SET, MSG_CLEANUP_ALL_FLOATERS, "", NULL_KEY);
|
||||||
}
|
}
|
||||||
else if (msg == "Force Floaters") {
|
else if (msg == "Force Floaters") {
|
||||||
// Force creation of floaters for all registered players - send as dialog response to Main Controller
|
// Force creation of floaters for all registered players - send as dialog response to Main Controller
|
||||||
llOwnerSay("🔧 Requesting floater creation for all registered players...");
|
dbg("🔧 Requesting floater creation for all registered players...");
|
||||||
// This will be handled by Main Controller's dialog listener
|
// This will be handled by Main Controller's dialog listener
|
||||||
// No need to forward via link_message - the Main Controller is already listening on DIALOG_CHANNEL
|
// No need to forward via link_message - the Main Controller is already listening on DIALOG_CHANNEL
|
||||||
}
|
}
|
||||||
else if (msg == "🔍 Toggle Verbose Logs") {
|
else if (msg == "🔍 Toggle Verbose Logs") {
|
||||||
// Toggle verbose logging system-wide
|
// Toggle verbose logging system-wide
|
||||||
llOwnerSay("🔍 Toggling verbose logging system-wide...");
|
dbg("🔍 Toggling verbose logging system-wide...");
|
||||||
llMessageLinked(LINK_SET, 9010, "TOGGLE_VERBOSE_LOGS", id);
|
llMessageLinked(LINK_SET, 9010, "TOGGLE_VERBOSE_LOGS", id);
|
||||||
// Return to troubleshooting menu after toggling
|
// Return to troubleshooting menu after toggling
|
||||||
showTroubleshootingMenu(id);
|
showTroubleshootingMenu(id);
|
||||||
}
|
}
|
||||||
else if (msg == "🔄 Check for Updates") {
|
else if (msg == "🔄 Check for Updates") {
|
||||||
// Trigger update check via Update_Receiver script
|
// Trigger update check via Update_Receiver script
|
||||||
llOwnerSay("🔄 Checking GitHub for Peril Dice updates...");
|
dbg("🔄 Checking GitHub for Peril Dice updates...");
|
||||||
llMessageLinked(LINK_SET, 2100, "CHECK_UPDATES_REQUEST", id);
|
llMessageLinked(LINK_SET, 2100, "CHECK_UPDATES_REQUEST", id);
|
||||||
// Return to troubleshooting menu
|
// Return to troubleshooting menu
|
||||||
showTroubleshootingMenu(id);
|
showTroubleshootingMenu(id);
|
||||||
|
|
@ -704,7 +711,7 @@ default {
|
||||||
}
|
}
|
||||||
else if (llSubStringIndex(msg, "🛠 ") == 0) {
|
else if (llSubStringIndex(msg, "🛠 ") == 0) {
|
||||||
currentPickTarget = llStringTrim(llDeleteSubString(msg, 0, 1), STRING_TRIM);
|
currentPickTarget = llStringTrim(llDeleteSubString(msg, 0, 1), STRING_TRIM);
|
||||||
llOwnerSay("🎯 Pick target set to: " + currentPickTarget);
|
dbg("🎯 Pick target set to: " + currentPickTarget);
|
||||||
currentPickList = [];
|
currentPickList = [];
|
||||||
llMessageLinked(LINK_THIS, 206, currentPickTarget, id);
|
llMessageLinked(LINK_THIS, 206, currentPickTarget, id);
|
||||||
}
|
}
|
||||||
|
|
@ -731,7 +738,7 @@ default {
|
||||||
// Send kick message to Controller_MessageHandler (not sync channel 107!)
|
// Send kick message to Controller_MessageHandler (not sync channel 107!)
|
||||||
llMessageLinked(LINK_SET, 8007, "KICK_PLAYER|" + playerToKick + "|" + (string)id, NULL_KEY);
|
llMessageLinked(LINK_SET, 8007, "KICK_PLAYER|" + playerToKick + "|" + (string)id, NULL_KEY);
|
||||||
} else {
|
} else {
|
||||||
llOwnerSay("⚠️ Could not find original name for kick selection: " + msg);
|
dbg("⚠️ Could not find original name for kick selection: " + msg);
|
||||||
}
|
}
|
||||||
// Return to player management menu
|
// Return to player management menu
|
||||||
showPlayerManagementMenu(id);
|
showPlayerManagementMenu(id);
|
||||||
|
|
@ -739,19 +746,19 @@ default {
|
||||||
// Forward numeric picks to the game logic
|
// Forward numeric picks to the game logic
|
||||||
else if ((integer)msg > 0) {
|
else if ((integer)msg > 0) {
|
||||||
if (llGetListLength(currentPickList) >= currentPickLimit) {
|
if (llGetListLength(currentPickList) >= currentPickLimit) {
|
||||||
llOwnerSay("⚠️ Reached pick limit of " + (string)currentPickLimit + " for " + currentPickTarget);
|
dbg("⚠️ Reached pick limit of " + (string)currentPickLimit + " for " + currentPickTarget);
|
||||||
showPickListMenu(id);
|
showPickListMenu(id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (llListFindList(currentPickList, [msg]) != -1) {
|
if (llListFindList(currentPickList, [msg]) != -1) {
|
||||||
llOwnerSay("⚠️ Pick already exists: " + msg);
|
dbg("⚠️ Pick already exists: " + msg);
|
||||||
showPickListMenu(id);
|
showPickListMenu(id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
integer i;
|
integer i;
|
||||||
for (i = 0; i < llGetListLength(currentPickList); i++) {
|
for (i = 0; i < llGetListLength(currentPickList); i++) {
|
||||||
if (llList2String(currentPickList, i) == msg) {
|
if (llList2String(currentPickList, i) == msg) {
|
||||||
llOwnerSay("⚠️ Duplicate pick detected.");
|
dbg("⚠️ Duplicate pick detected.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -779,9 +786,9 @@ default {
|
||||||
// Store display info: [type, offset, rotation, ...]
|
// Store display info: [type, offset, rotation, ...]
|
||||||
foundDisplays += [object_type, offset, rel_rot];
|
foundDisplays += [object_type, offset, rel_rot];
|
||||||
|
|
||||||
llOwnerSay("✅ Found " + object_type + " display at position " + (string)object_pos);
|
dbg("✅ Found " + object_type + " display at position " + (string)object_pos);
|
||||||
llOwnerSay(" Config: " + object_type + "_offset=" + (string)offset);
|
dbg(" Config: " + object_type + "_offset=" + (string)offset);
|
||||||
llOwnerSay(" Rotation: " + object_type + "_rotation=" + (string)rel_rot);
|
dbg(" Rotation: " + object_type + "_rotation=" + (string)rel_rot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Note: Automatic auto-config requests are now handled by Controller_Discovery.lsl
|
// Note: Automatic auto-config requests are now handled by Controller_Discovery.lsl
|
||||||
|
|
@ -795,18 +802,18 @@ default {
|
||||||
integer numDisplays = llGetListLength(foundDisplays) / 3; // 3 items per display (type, offset, rotation)
|
integer numDisplays = llGetListLength(foundDisplays) / 3; // 3 items per display (type, offset, rotation)
|
||||||
|
|
||||||
if (numDisplays == 0) {
|
if (numDisplays == 0) {
|
||||||
llOwnerSay("\n⚠️ No follower displays found within 20 meters.");
|
dbg("\n⚠️ No follower displays found within 20 meters.");
|
||||||
llOwnerSay("📝 Make sure your displays have the follower script and are close enough.");
|
dbg("📝 Make sure your displays have the follower script and are close enough.");
|
||||||
llOwnerSay("🔄 Check that they use the same dynamic channel system as this controller.");
|
dbg("🔄 Check that they use the same dynamic channel system as this controller.");
|
||||||
} else {
|
} else {
|
||||||
llOwnerSay("\n🎉 Position scan complete! Found " + (string)numDisplays + " display(s).");
|
dbg("\n🎉 Position scan complete! Found " + (string)numDisplays + " display(s).");
|
||||||
llOwnerSay("\n📄 CONFIG UPDATE METHODS:");
|
dbg("\n📄 CONFIG UPDATE METHODS:");
|
||||||
llOwnerSay("1️⃣ MANUAL: Copy the config lines above to each display's 'config' notecard");
|
dbg("1️⃣ MANUAL: Copy the config lines above to each display's 'config' notecard");
|
||||||
llOwnerSay("2️⃣ AUTOMATIC: The displays should move to their new positions automatically!");
|
dbg("2️⃣ AUTOMATIC: The displays should move to their new positions automatically!");
|
||||||
llOwnerSay("\n📆 The new positions are now saved and will be remembered when objects are rezzed.");
|
dbg("\n📆 The new positions are now saved and will be remembered when objects are rezzed.");
|
||||||
|
|
||||||
// Send position update commands to displays (future enhancement)
|
// Send position update commands to displays (future enhancement)
|
||||||
llOwnerSay("🔄 Broadcasting position updates to all found displays...");
|
dbg("🔄 Broadcasting position updates to all found displays...");
|
||||||
|
|
||||||
// Broadcast updates to each found display
|
// Broadcast updates to each found display
|
||||||
integer i;
|
integer i;
|
||||||
|
|
@ -822,18 +829,18 @@ default {
|
||||||
else if (displayType == "dice") updateChannel = DICE_DATA_CHANNEL;
|
else if (displayType == "dice") updateChannel = DICE_DATA_CHANNEL;
|
||||||
else {
|
else {
|
||||||
// Skip unknown display types
|
// Skip unknown display types
|
||||||
llOwnerSay("⚠️ Unknown display type: " + displayType);
|
dbg("⚠️ Unknown display type: " + displayType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only send update if we found a valid channel
|
// Only send update if we found a valid channel
|
||||||
if (displayType == "scoreboard" || displayType == "leaderboard" || displayType == "dice") {
|
if (displayType == "scoreboard" || displayType == "leaderboard" || displayType == "dice") {
|
||||||
string updateMsg = "POSITION_UPDATE|" + displayType + "|" + (string)displayOffset + "|" + (string)displayRotation;
|
string updateMsg = "POSITION_UPDATE|" + displayType + "|" + (string)displayOffset + "|" + (string)displayRotation;
|
||||||
llRegionSay(updateChannel, updateMsg);
|
llRegionSay(updateChannel, updateMsg);
|
||||||
llOwnerSay("✅ Sent position update to " + displayType + " display");
|
dbg("✅ Sent position update to " + displayType + " display");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
llOwnerSay("\n✨ Position reset complete! Your displays should now be in the correct positions.");
|
dbg("\n✨ Position reset complete! Your displays should now be in the correct positions.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,9 @@ displayDiceText(string text) {
|
||||||
}
|
}
|
||||||
|
|
||||||
default {
|
default {
|
||||||
|
on_rez(integer start_param) {
|
||||||
|
llResetScript(); // Fixes Z-fighting and alignment glitches on rez
|
||||||
|
}
|
||||||
state_entry() {
|
state_entry() {
|
||||||
if (VERBOSE_LOGGING) {
|
if (VERBOSE_LOGGING) {
|
||||||
llOwnerSay("🎲 Dice Display Bridge ready! (Linkset Version)");
|
llOwnerSay("🎲 Dice Display Bridge ready! (Linkset Version)");
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue