some floater and scoreboard fixes
This commit is contained in:
parent
f06108d99a
commit
b28970ea8e
6 changed files with 156 additions and 70 deletions
|
|
@ -31,10 +31,6 @@ integer BOT_COMMAND_CHANNEL;
|
||||||
// Channel initialization function
|
// Channel initialization function
|
||||||
initializeChannels() {
|
initializeChannels() {
|
||||||
BOT_COMMAND_CHANNEL = calculateChannel(5); // ~-77500 range to match Main.lsl
|
BOT_COMMAND_CHANNEL = calculateChannel(5); // ~-77500 range to match Main.lsl
|
||||||
|
|
||||||
// Report channel to owner for debugging
|
|
||||||
llOwnerSay("🔧 [Bot Manager] Dynamic channel initialized:");
|
|
||||||
llOwnerSay(" Bot Command: " + (string)BOT_COMMAND_CHANNEL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configuration
|
// Configuration
|
||||||
|
|
@ -197,20 +193,15 @@ doBotRoll(string botName, integer diceMax) {
|
||||||
|
|
||||||
default {
|
default {
|
||||||
state_entry() {
|
state_entry() {
|
||||||
// Initialize dynamic channels
|
|
||||||
initializeChannels();
|
initializeChannels();
|
||||||
LISTEN_CHANNEL = BOT_COMMAND_CHANNEL;
|
LISTEN_CHANNEL = BOT_COMMAND_CHANNEL;
|
||||||
|
|
||||||
// Clean up any existing listeners
|
|
||||||
if (listenHandle != -1) {
|
if (listenHandle != -1) {
|
||||||
llListenRemove(listenHandle);
|
llListenRemove(listenHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up managed listener with dynamic channel
|
|
||||||
listenHandle = llListen(LISTEN_CHANNEL, "", NULL_KEY, "");
|
listenHandle = llListen(LISTEN_CHANNEL, "", NULL_KEY, "");
|
||||||
llOwnerSay("[Bot Manager] Ready and listening on channel " + (string)LISTEN_CHANNEL);
|
llOwnerSay("🤖 Bot Manager ready!");
|
||||||
llOwnerSay("[Bot Manager] My key: " + (string)llGetKey());
|
|
||||||
llOwnerSay("[Bot Manager] My position: " + (string)llGetPos());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
link_message(integer sender, integer num, string str, key id) {
|
link_message(integer sender, integer num, string str, key id) {
|
||||||
|
|
|
||||||
|
|
@ -39,13 +39,6 @@ integer FLOATER_BASE_CHANNEL;
|
||||||
// Channel initialization function
|
// Channel initialization function
|
||||||
initializeChannels() {
|
initializeChannels() {
|
||||||
FLOATER_BASE_CHANNEL = calculateChannel(9); // ~-86000 range base for floaters
|
FLOATER_BASE_CHANNEL = calculateChannel(9); // ~-86000 range base for floaters
|
||||||
|
|
||||||
// Report channel to owner for debugging
|
|
||||||
llOwnerSay("🔧 [Floater Manager] Dynamic channels initialized:");
|
|
||||||
llOwnerSay(" Floater Base: " + (string)FLOATER_BASE_CHANNEL);
|
|
||||||
llOwnerSay(" Player 0 channel: " + (string)(FLOATER_BASE_CHANNEL + 0));
|
|
||||||
llOwnerSay(" Player 1 channel: " + (string)(FLOATER_BASE_CHANNEL + 1));
|
|
||||||
llOwnerSay(" Player 9 channel: " + (string)(FLOATER_BASE_CHANNEL + 9));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maximum number of players allowed in the game
|
// Maximum number of players allowed in the game
|
||||||
|
|
@ -108,12 +101,8 @@ string getNameFromKey(key id) {
|
||||||
// Main event handler
|
// Main event handler
|
||||||
default {
|
default {
|
||||||
state_entry() {
|
state_entry() {
|
||||||
// Initialize dynamic channels
|
|
||||||
initializeChannels();
|
initializeChannels();
|
||||||
|
|
||||||
// Verify channel consistency with Main Controller
|
|
||||||
llOwnerSay("📦 Floater Manager ready!");
|
llOwnerSay("📦 Floater Manager ready!");
|
||||||
llOwnerSay("📦 Using FLOATER_BASE_CHANNEL: " + (string)FLOATER_BASE_CHANNEL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
link_message(integer sender, integer num, string str, key id) {
|
link_message(integer sender, integer num, string str, key id) {
|
||||||
|
|
@ -139,6 +128,13 @@ default {
|
||||||
list info = llParseString2List(str, ["|"], []);
|
list info = llParseString2List(str, ["|"], []);
|
||||||
string name = llList2String(info, 0);
|
string name = llList2String(info, 0);
|
||||||
key avKey = llList2Key(info, 1);
|
key avKey = llList2Key(info, 1);
|
||||||
|
|
||||||
|
// Check if this player is already registered to prevent duplicate floaters
|
||||||
|
if (llListFindList(players, [avKey]) != -1) {
|
||||||
|
llOwnerSay("⚠️ Player " + name + " is already registered, ignoring duplicate registration");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
names += [name];
|
names += [name];
|
||||||
players += [avKey];
|
players += [avKey];
|
||||||
lives += [3]; // Initialize with 3 lives for new players
|
lives += [3]; // Initialize with 3 lives for new players
|
||||||
|
|
@ -268,6 +264,12 @@ default {
|
||||||
string namesStr = llList2String(parts, 3);
|
string namesStr = llList2String(parts, 3);
|
||||||
names = llCSV2List(namesStr);
|
names = llCSV2List(namesStr);
|
||||||
|
|
||||||
|
// Sync players list if available (5th part)
|
||||||
|
if (llGetListLength(parts) >= 5) {
|
||||||
|
string playersStr = llList2String(parts, 4);
|
||||||
|
players = llCSV2List(playersStr);
|
||||||
|
}
|
||||||
|
|
||||||
// After synchronizing the game state, update all existing floats so
|
// After synchronizing the game state, update all existing floats so
|
||||||
// they reflect the current peril status. Without this, floats
|
// they reflect the current peril status. Without this, floats
|
||||||
// created in previous rounds may continue to display an old
|
// created in previous rounds may continue to display an old
|
||||||
|
|
|
||||||
|
|
@ -281,10 +281,6 @@ syncStateToMain() {
|
||||||
default {
|
default {
|
||||||
state_entry() {
|
state_entry() {
|
||||||
llOwnerSay("🎯 Game Manager ready!");
|
llOwnerSay("🎯 Game Manager ready!");
|
||||||
|
|
||||||
// Reset game on startup to ensure clean state when core logic is updated
|
|
||||||
llOwnerSay("🔄 [Game Manager] Requesting game reset on startup...");
|
|
||||||
llMessageLinked(LINK_SET, -99998, "REQUEST_GAME_RESET", NULL_KEY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
link_message(integer sender, integer num, string str, key id) {
|
link_message(integer sender, integer num, string str, key id) {
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,8 @@ integer MSG_TOGGLE_READY = 202;
|
||||||
integer MSG_QUERY_READY_STATE = 210;
|
integer MSG_QUERY_READY_STATE = 210;
|
||||||
integer MSG_READY_STATE_RESULT = 211;
|
integer MSG_READY_STATE_RESULT = 211;
|
||||||
integer MSG_CLEANUP_ALL_FLOATERS = 212;
|
integer MSG_CLEANUP_ALL_FLOATERS = 212;
|
||||||
|
integer MSG_QUERY_OWNER_STATUS = 213;
|
||||||
|
integer MSG_OWNER_STATUS_RESULT = 214;
|
||||||
integer MSG_SHOW_ROLL_DIALOG = 301;
|
integer MSG_SHOW_ROLL_DIALOG = 301;
|
||||||
integer MSG_GET_CURRENT_DIALOG = 302;
|
integer MSG_GET_CURRENT_DIALOG = 302;
|
||||||
integer MSG_PLAYER_WON = 551;
|
integer MSG_PLAYER_WON = 551;
|
||||||
|
|
@ -176,10 +178,6 @@ initializeChannels() {
|
||||||
rollDialogChannel = ROLLDIALOG_CHANNEL;
|
rollDialogChannel = ROLLDIALOG_CHANNEL;
|
||||||
DIALOG_CHANNEL = MAIN_DIALOG_CHANNEL;
|
DIALOG_CHANNEL = MAIN_DIALOG_CHANNEL;
|
||||||
|
|
||||||
llOwnerSay("🔧 [Main Controller] Channels initialized for external communication:");
|
|
||||||
llOwnerSay(" Dialog: " + (string)MAIN_DIALOG_CHANNEL);
|
|
||||||
llOwnerSay(" Roll: " + (string)ROLLDIALOG_CHANNEL);
|
|
||||||
llOwnerSay(" Floater Base: " + (string)FLOATER_BASE_CHANNEL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up listen handles
|
// Clean up listen handles
|
||||||
|
|
@ -274,7 +272,7 @@ updateHelpers() {
|
||||||
checkMemoryUsage("updateHelpers_after_picks_processing");
|
checkMemoryUsage("updateHelpers_after_picks_processing");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send core game state to internal scripts
|
// Send core game state to internal scripts (include players list for floater management)
|
||||||
string syncMessage = llList2CSV(lives) + "~" + picksDataStr + "~" + perilForSync + "~" + llList2CSV(names) + "~" + llList2CSV(players);
|
string syncMessage = llList2CSV(lives) + "~" + picksDataStr + "~" + perilForSync + "~" + llList2CSV(names) + "~" + llList2CSV(players);
|
||||||
llMessageLinked(LINK_SET, MSG_SYNC_GAME_STATE, syncMessage, NULL_KEY);
|
llMessageLinked(LINK_SET, MSG_SYNC_GAME_STATE, syncMessage, NULL_KEY);
|
||||||
|
|
||||||
|
|
@ -319,8 +317,15 @@ updateFloatingText() {
|
||||||
resetGame() {
|
resetGame() {
|
||||||
cleanupListeners();
|
cleanupListeners();
|
||||||
|
|
||||||
|
// Only clean up channels that actually have active floaters
|
||||||
integer i;
|
integer i;
|
||||||
for (i = 0; i < MAX_PLAYERS; i++) {
|
for (i = 0; i < llGetListLength(floaterChannels); i++) {
|
||||||
|
integer ch = llList2Integer(floaterChannels, i);
|
||||||
|
llMessageLinked(LINK_SET, MSG_CLEANUP_FLOAT, (string)ch, NULL_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also send a few cleanup messages to common channel ranges in case of orphaned floaters
|
||||||
|
for (i = 0; i < llGetListLength(names); i++) {
|
||||||
integer ch = FLOATER_BASE_CHANNEL + i;
|
integer ch = FLOATER_BASE_CHANNEL + i;
|
||||||
llMessageLinked(LINK_SET, MSG_CLEANUP_FLOAT, (string)ch, NULL_KEY);
|
llMessageLinked(LINK_SET, MSG_CLEANUP_FLOAT, (string)ch, NULL_KEY);
|
||||||
}
|
}
|
||||||
|
|
@ -364,8 +369,6 @@ resetGame() {
|
||||||
default {
|
default {
|
||||||
state_entry() {
|
state_entry() {
|
||||||
llOwnerSay("🎮 Main Controller ready! (Linkset Version)");
|
llOwnerSay("🎮 Main Controller ready! (Linkset Version)");
|
||||||
llOwnerSay("🎮 Main Controller key: " + (string)llGetKey());
|
|
||||||
llOwnerSay("🎮 Main Controller position: " + (string)llGetPos());
|
|
||||||
|
|
||||||
// Initialize lockout system
|
// Initialize lockout system
|
||||||
gameOwner = llGetOwner();
|
gameOwner = llGetOwner();
|
||||||
|
|
@ -375,10 +378,8 @@ default {
|
||||||
initializeChannels();
|
initializeChannels();
|
||||||
|
|
||||||
// Reset the game on startup to ensure clean state
|
// Reset the game on startup to ensure clean state
|
||||||
llOwnerSay("🔄 Resetting game state on startup...");
|
|
||||||
resetGame();
|
resetGame();
|
||||||
|
|
||||||
llOwnerSay("📡 Linkset communication active - no discovery needed!");
|
|
||||||
llOwnerSay("✅ Main Controller initialization complete!");
|
llOwnerSay("✅ Main Controller initialization complete!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -690,6 +691,9 @@ default {
|
||||||
perilPlayer = newPerilPlayer;
|
perilPlayer = newPerilPlayer;
|
||||||
names = newNames;
|
names = newNames;
|
||||||
|
|
||||||
|
// Update scoreboard and other helpers with the new game state
|
||||||
|
updateHelpers();
|
||||||
|
|
||||||
integer allPicksEmpty = TRUE;
|
integer allPicksEmpty = TRUE;
|
||||||
integer i;
|
integer i;
|
||||||
for (i = 0; i < llGetListLength(newPicksData) && allPicksEmpty; i++) {
|
for (i = 0; i < llGetListLength(newPicksData) && allPicksEmpty; i++) {
|
||||||
|
|
@ -766,6 +770,45 @@ default {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle owner status queries
|
||||||
|
if (num == MSG_QUERY_OWNER_STATUS) {
|
||||||
|
list queryParts = llParseString2List(str, ["|"], []);
|
||||||
|
string ownerName;
|
||||||
|
integer requestID = 0;
|
||||||
|
|
||||||
|
if (llGetListLength(queryParts) >= 2) {
|
||||||
|
ownerName = llList2String(queryParts, 0);
|
||||||
|
requestID = (integer)llList2String(queryParts, 1);
|
||||||
|
} else {
|
||||||
|
ownerName = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if owner is registered
|
||||||
|
integer ownerIdx = llListFindList(players, [id]);
|
||||||
|
integer isRegistered = (ownerIdx != -1);
|
||||||
|
integer isPending = (llListFindList(pendingRegistrations, [id]) != -1);
|
||||||
|
integer isStarter = FALSE;
|
||||||
|
|
||||||
|
if (isRegistered) {
|
||||||
|
// Calculate starter status if registered
|
||||||
|
isStarter = TRUE;
|
||||||
|
integer k;
|
||||||
|
for (k = 0; k < ownerIdx && isStarter; k++) {
|
||||||
|
string existingName = llList2String(names, k);
|
||||||
|
if (llSubStringIndex(existingName, "Bot") != 0) {
|
||||||
|
isStarter = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ownerIdx == 0) {
|
||||||
|
isStarter = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string result = ownerName + "|" + (string)isRegistered + "|" + (string)isPending + "|" + (string)isStarter + "|" + (string)requestID;
|
||||||
|
llMessageLinked(LINK_SET, MSG_OWNER_STATUS_RESULT, result, id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle aggressive floater cleanup
|
// Handle aggressive floater cleanup
|
||||||
if (num == MSG_CLEANUP_ALL_FLOATERS) {
|
if (num == MSG_CLEANUP_ALL_FLOATERS) {
|
||||||
integer i;
|
integer i;
|
||||||
|
|
@ -906,19 +949,9 @@ default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle owner choice menu
|
// Handle owner choice menu - "Join Game" is handled by Player_DialogHandler
|
||||||
if (id == llGetOwner()) {
|
if (id == llGetOwner()) {
|
||||||
if (msg == "Join Game") {
|
if (msg == "Owner Menu") {
|
||||||
// Owner wants to join as a player
|
|
||||||
string ownerName = getPlayerName(id);
|
|
||||||
pendingRegistrations += [id];
|
|
||||||
llMessageLinked(LINK_SET, MSG_REGISTER_PLAYER, ownerName + "|" + (string)id, NULL_KEY);
|
|
||||||
|
|
||||||
// After registration, they'll get the appropriate player menu
|
|
||||||
// The registration handler will call updateHelpers() and show menu
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (msg == "Owner Menu") {
|
|
||||||
// Owner wants admin functions without joining - use admin targetType
|
// Owner wants admin functions without joining - use admin targetType
|
||||||
llMessageLinked(LINK_SET, MSG_SHOW_MENU, "admin|0", id);
|
llMessageLinked(LINK_SET, MSG_SHOW_MENU, "admin|0", id);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,8 @@ integer MSG_TOGGLE_READY = 202;
|
||||||
integer MSG_QUERY_READY_STATE = 210;
|
integer MSG_QUERY_READY_STATE = 210;
|
||||||
integer MSG_READY_STATE_RESULT = 211;
|
integer MSG_READY_STATE_RESULT = 211;
|
||||||
integer MSG_CLEANUP_ALL_FLOATERS = 212;
|
integer MSG_CLEANUP_ALL_FLOATERS = 212;
|
||||||
|
integer MSG_QUERY_OWNER_STATUS = 213;
|
||||||
|
integer MSG_OWNER_STATUS_RESULT = 214;
|
||||||
integer MSG_GET_CURRENT_DIALOG = 302;
|
integer MSG_GET_CURRENT_DIALOG = 302;
|
||||||
|
|
||||||
// Categorized owner menu system
|
// Categorized owner menu system
|
||||||
|
|
@ -155,9 +157,15 @@ showReadyLeaveMenu(key id, integer isStarter, integer isOwner) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate unique request ID and store pending menu state
|
// Generate unique request ID and store pending menu state
|
||||||
|
// New requests always override previous ones for the same player
|
||||||
currentRequestID++;
|
currentRequestID++;
|
||||||
if (currentRequestID > 1000000) currentRequestID = 1; // Prevent overflow
|
if (currentRequestID > 1000000) currentRequestID = 1; // Prevent overflow
|
||||||
|
|
||||||
|
// If there's a pending request for a different player, warn about it but proceed
|
||||||
|
if (pendingMenuPlayer != NULL_KEY && pendingMenuPlayer != id) {
|
||||||
|
llOwnerSay("⚠️ [Debug] Overriding pending request for " + (string)pendingMenuPlayer + " with new request for " + (string)id);
|
||||||
|
}
|
||||||
|
|
||||||
pendingMenuPlayer = id;
|
pendingMenuPlayer = id;
|
||||||
pendingMenuIsStarter = isStarter;
|
pendingMenuIsStarter = isStarter;
|
||||||
pendingMenuIsOwner = isOwner;
|
pendingMenuIsOwner = isOwner;
|
||||||
|
|
@ -337,6 +345,9 @@ default {
|
||||||
if (targetType == "owner") {
|
if (targetType == "owner") {
|
||||||
// Both starter and non-starter owners get ready/leave menu with Owner button
|
// Both starter and non-starter owners get ready/leave menu with Owner button
|
||||||
showReadyLeaveMenu(id, isStarter, TRUE);
|
showReadyLeaveMenu(id, isStarter, TRUE);
|
||||||
|
} else if (targetType == "registered_owner") {
|
||||||
|
// Registered owner gets ready/leave menu with Owner button
|
||||||
|
showReadyLeaveMenu(id, isStarter, TRUE);
|
||||||
} else if (targetType == "player") {
|
} else if (targetType == "player") {
|
||||||
showReadyLeaveMenu(id, isStarter, FALSE);
|
showReadyLeaveMenu(id, isStarter, FALSE);
|
||||||
} else if (targetType == "admin") {
|
} else if (targetType == "admin") {
|
||||||
|
|
@ -363,7 +374,7 @@ default {
|
||||||
}
|
}
|
||||||
|
|
||||||
showReadyLeaveMenuWithState(pendingMenuPlayer, pendingMenuIsStarter, pendingMenuIsOwner, isReady, isBot);
|
showReadyLeaveMenuWithState(pendingMenuPlayer, pendingMenuIsStarter, pendingMenuIsOwner, isReady, isBot);
|
||||||
// Reset pending state
|
// Reset pending state ONLY after successfully showing the dialog
|
||||||
pendingMenuPlayer = NULL_KEY;
|
pendingMenuPlayer = NULL_KEY;
|
||||||
pendingMenuRequestID = 0;
|
pendingMenuRequestID = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -421,6 +432,57 @@ default {
|
||||||
showPickListMenu(id);
|
showPickListMenu(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (num == MSG_OWNER_STATUS_RESULT) {
|
||||||
|
// Parse owner status response and show appropriate menu
|
||||||
|
list parts = llParseString2List(str, ["|"], []);
|
||||||
|
if (llGetListLength(parts) >= 5) {
|
||||||
|
string ownerName = llList2String(parts, 0);
|
||||||
|
integer isRegistered = (integer)llList2String(parts, 1);
|
||||||
|
integer isPending = (integer)llList2String(parts, 2);
|
||||||
|
integer isStarter = (integer)llList2String(parts, 3);
|
||||||
|
integer responseRequestID = (integer)llList2String(parts, 4);
|
||||||
|
|
||||||
|
// Validate that this response matches our pending request
|
||||||
|
if (pendingMenuPlayer == id && responseRequestID == pendingMenuRequestID) {
|
||||||
|
// Check for timeout
|
||||||
|
if ((llGetTime() - pendingMenuTimestamp) > MENU_REQUEST_TIMEOUT) {
|
||||||
|
llOwnerSay("⏰ Owner status query timed out, ignoring response");
|
||||||
|
pendingMenuPlayer = NULL_KEY;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decide which menu to show based on registration status
|
||||||
|
if (isRegistered) {
|
||||||
|
// Owner is registered - show ready/leave menu with Owner button
|
||||||
|
llOwnerSay("🔍 [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");
|
||||||
|
|
||||||
|
// DON'T reset pending state here - showReadyLeaveMenu needs it!
|
||||||
|
// The ready state handler will reset it when the dialog is shown
|
||||||
|
showReadyLeaveMenu(id, isStarter, TRUE);
|
||||||
|
llOwnerSay("🔍 [Debug] showReadyLeaveMenu call completed");
|
||||||
|
} else if (isPending) {
|
||||||
|
llRegionSayTo(id, 0, "⏳ Registration already in progress for " + ownerName);
|
||||||
|
// Reset pending state for non-registered responses
|
||||||
|
pendingMenuPlayer = NULL_KEY;
|
||||||
|
pendingMenuRequestID = 0;
|
||||||
|
} else {
|
||||||
|
// Owner is not registered - show join/admin choice menu
|
||||||
|
list options = ["Join Game", "Owner Menu"];
|
||||||
|
string menuText = "👑 Owner Options:\n\n🎮 Join Game - Register as a player\n🔧 Owner Menu - Admin functions without joining";
|
||||||
|
llDialog(id, menuText, options, DIALOG_CHANNEL);
|
||||||
|
// Reset pending state for non-registered responses
|
||||||
|
pendingMenuPlayer = NULL_KEY;
|
||||||
|
pendingMenuRequestID = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
llOwnerSay("⚠️ Owner status response mismatch - ignoring");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
llOwnerSay("⚠️ Invalid owner status result format - expected 5 parts, got " + (string)llGetListLength(parts));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
listen(integer channel, string name, key id, string msg) {
|
listen(integer channel, string name, key id, string msg) {
|
||||||
|
|
@ -474,9 +536,22 @@ default {
|
||||||
showOwnerMenu(id);
|
showOwnerMenu(id);
|
||||||
}
|
}
|
||||||
else if (msg == "⬅️ Back to Game") {
|
else if (msg == "⬅️ Back to Game") {
|
||||||
// Return to the owner's ready/leave menu
|
// Intelligently determine what menu to show based on owner's registration status
|
||||||
// Need to determine if owner is starter
|
if (id == gameOwner) {
|
||||||
llMessageLinked(LINK_SET, MSG_SHOW_MENU, "owner|1", id); // Assume starter for now, will be corrected by main controller
|
// Query the Main Controller about the owner's registration status
|
||||||
|
string ownerName = getPlayerName(id);
|
||||||
|
// Generate unique request ID for tracking
|
||||||
|
currentRequestID++;
|
||||||
|
if (currentRequestID > 1000000) currentRequestID = 1;
|
||||||
|
|
||||||
|
// Store pending owner query state
|
||||||
|
pendingMenuPlayer = id;
|
||||||
|
pendingMenuRequestID = currentRequestID;
|
||||||
|
pendingMenuTimestamp = llGetTime();
|
||||||
|
|
||||||
|
string queryData = ownerName + "|" + (string)currentRequestID;
|
||||||
|
llMessageLinked(LINK_SET, MSG_QUERY_OWNER_STATUS, queryData, id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Owner joins the game: register and rez a float for them
|
// Owner joins the game: register and rez a float for them
|
||||||
else if (msg == "Join Game") {
|
else if (msg == "Join Game") {
|
||||||
|
|
|
||||||
|
|
@ -287,8 +287,7 @@ default {
|
||||||
llSay(0, "⚡ PLOT TWIST! " + newPeril + " picked " + resultStr + " (rolled on d" + (string)diceType + ") and is now in ULTIMATE PERIL! ⚡");
|
llSay(0, "⚡ PLOT TWIST! " + newPeril + " picked " + resultStr + " (rolled on d" + (string)diceType + ") and is now in ULTIMATE PERIL! ⚡");
|
||||||
perilPlayer = newPeril;
|
perilPlayer = newPeril;
|
||||||
|
|
||||||
// Send Plot Twist status to scoreboard
|
// Plot Twist status will be sent by Main Controller via link messages
|
||||||
llRegionSay(SCOREBOARD_CHANNEL_1, "GAME_STATUS|Plot Twist");
|
|
||||||
// Add delay to let status display before next phase
|
// Add delay to let status display before next phase
|
||||||
llSleep(2.0);
|
llSleep(2.0);
|
||||||
|
|
||||||
|
|
@ -300,14 +299,8 @@ default {
|
||||||
integer currentLives = llList2Integer(lives, pidx);
|
integer currentLives = llList2Integer(lives, pidx);
|
||||||
lives = llListReplaceList(lives, [currentLives - 1], pidx, pidx);
|
lives = llListReplaceList(lives, [currentLives - 1], pidx, pidx);
|
||||||
|
|
||||||
// Immediately send updated heart count to scoreboard
|
// Player update will be sent by Main Controller via sync message and updateHelpers()
|
||||||
integer newLives = currentLives - 1;
|
llOwnerSay("💗 Player lives updated: " + perilPlayer + " now has " + (string)(currentLives - 1) + " lives");
|
||||||
key perilKey = NULL_KEY; // We don't have player keys in this module, use NULL_KEY
|
|
||||||
if (pidx < llGetListLength(names)) {
|
|
||||||
string updateMsg = "PLAYER_UPDATE|" + perilPlayer + "|" + (string)newLives + "|" + (string)perilKey;
|
|
||||||
llRegionSay(SCOREBOARD_CHANNEL_1, updateMsg);
|
|
||||||
llOwnerSay("💗 Immediate scoreboard update: " + perilPlayer + " now has " + (string)newLives + " lives");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if peril player picked the rolled number
|
// Check if peril player picked the rolled number
|
||||||
list perilPicks = getPicksFor(perilPlayer);
|
list perilPicks = getPicksFor(perilPlayer);
|
||||||
|
|
@ -315,14 +308,12 @@ default {
|
||||||
|
|
||||||
if (perilPickedIt) {
|
if (perilPickedIt) {
|
||||||
llSay(0, "🩸 DIRECT HIT! " + perilPlayer + " picked their own doom - the d" + (string)diceType + " landed on " + resultStr + "! 🩸");
|
llSay(0, "🩸 DIRECT HIT! " + perilPlayer + " picked their own doom - the d" + (string)diceType + " landed on " + resultStr + "! 🩸");
|
||||||
// Send Direct Hit status to scoreboard
|
// Direct Hit status will be sent by Main Controller via link messages
|
||||||
llRegionSay(SCOREBOARD_CHANNEL_1, "GAME_STATUS|Direct Hit");
|
|
||||||
// Add delay to let status display before next phase
|
// Add delay to let status display before next phase
|
||||||
llSleep(2.0);
|
llSleep(2.0);
|
||||||
} else {
|
} else {
|
||||||
llSay(0, "🩸 NO SHIELD! Nobody picked " + resultStr + " - " + perilPlayer + " takes the hit from the d" + (string)diceType + "! 🩸");
|
llSay(0, "🩸 NO SHIELD! Nobody picked " + resultStr + " - " + perilPlayer + " takes the hit from the d" + (string)diceType + "! 🩸");
|
||||||
// Send No Shield status to scoreboard
|
// No Shield status will be sent by Main Controller via link messages
|
||||||
llRegionSay(SCOREBOARD_CHANNEL_1, "GAME_STATUS|No Shield");
|
|
||||||
// Add delay to let status display before next phase
|
// Add delay to let status display before next phase
|
||||||
llSleep(2.0);
|
llSleep(2.0);
|
||||||
}
|
}
|
||||||
|
|
@ -331,10 +322,8 @@ default {
|
||||||
|
|
||||||
// Check for elimination
|
// Check for elimination
|
||||||
if (currentLives - 1 <= 0) {
|
if (currentLives - 1 <= 0) {
|
||||||
// Show 0 hearts on scoreboard before elimination message
|
// Player elimination will be handled by Main Controller via sync and elimination messages
|
||||||
string eliminationUpdateMsg = "PLAYER_UPDATE|" + perilPlayer + "|0|" + (string)NULL_KEY;
|
llOwnerSay("💀 Elimination detected: " + perilPlayer + " has 0 hearts remaining");
|
||||||
llRegionSay(SCOREBOARD_CHANNEL_1, eliminationUpdateMsg);
|
|
||||||
llOwnerSay("💀 Elimination update: " + perilPlayer + " now shows 0 hearts");
|
|
||||||
|
|
||||||
llSay(0, "🐻 PUNISHMENT TIME! " + perilPlayer + " has been ELIMINATED!");
|
llSay(0, "🐻 PUNISHMENT TIME! " + perilPlayer + " has been ELIMINATED!");
|
||||||
// Remove eliminated player (send message to main controller)
|
// Remove eliminated player (send message to main controller)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue