feat: implement blinking #1 rank highlight and add authenticated global leaderboard wipe functionality
This commit is contained in:
parent
1297b99e2c
commit
0974d19f12
4 changed files with 91 additions and 9 deletions
|
|
@ -1,6 +1,10 @@
|
||||||
#include "Peril_Constants.lsl"
|
#include "Peril_Constants.lsl"
|
||||||
|
|
||||||
string leftText = "";
|
string leftText = "";
|
||||||
|
string firstName = "";
|
||||||
|
integer blinkState = 0;
|
||||||
|
integer canBlink = 0;
|
||||||
|
|
||||||
|
|
||||||
// Distribute text to the FURWARE "Leaderboard" boxes
|
// Distribute text to the FURWARE "Leaderboard" boxes
|
||||||
distributeFullText(string text) {
|
distributeFullText(string text) {
|
||||||
|
|
@ -10,7 +14,33 @@ distributeFullText(string text) {
|
||||||
if (llGetListLength(parts) >= 3) {
|
if (llGetListLength(parts) >= 3) {
|
||||||
// Distribute each column to its virtual box
|
// Distribute each column to its virtual box
|
||||||
llMessageLinked(LINK_SET, 0, llList2String(parts, 0), (key)"fw_data:LB_Rank");
|
llMessageLinked(LINK_SET, 0, llList2String(parts, 0), (key)"fw_data:LB_Rank");
|
||||||
llMessageLinked(LINK_SET, 0, llList2String(parts, 1), (key)"fw_data:LB_Name");
|
|
||||||
|
// Distribute Name column (Split first line for blinking)
|
||||||
|
string nameText = llList2String(parts, 1);
|
||||||
|
integer firstLineEnd = llSubStringIndex(nameText, "\n");
|
||||||
|
if (firstLineEnd != -1) {
|
||||||
|
firstName = llGetSubString(nameText, 0, firstLineEnd - 1);
|
||||||
|
string remainingNames = llGetSubString(nameText, firstLineEnd + 1, -1);
|
||||||
|
llMessageLinked(LINK_SET, 0, firstName, (key)"fw_data:LB_Name_Top");
|
||||||
|
llMessageLinked(LINK_SET, 0, remainingNames, (key)"fw_data:LB_Name");
|
||||||
|
} else {
|
||||||
|
firstName = nameText;
|
||||||
|
llMessageLinked(LINK_SET, 0, firstName, (key)"fw_data:LB_Name_Top");
|
||||||
|
llMessageLinked(LINK_SET, 0, "", (key)"fw_data:LB_Name");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we should blink (#1 spot on first page only)
|
||||||
|
integer offset = (integer)llList2String(parts, 5);
|
||||||
|
if (offset == 0) {
|
||||||
|
canBlink = TRUE;
|
||||||
|
llSetTimerEvent(0.5);
|
||||||
|
} else {
|
||||||
|
canBlink = FALSE;
|
||||||
|
llSetTimerEvent(0.0);
|
||||||
|
// Ensure name is visible on non-blinking pages
|
||||||
|
llMessageLinked(LINK_SET, 0, firstName, (key)"fw_data:LB_Name_Top");
|
||||||
|
}
|
||||||
|
|
||||||
llMessageLinked(LINK_SET, 0, llList2String(parts, 2), (key)"fw_data:LB_WL");
|
llMessageLinked(LINK_SET, 0, llList2String(parts, 2), (key)"fw_data:LB_WL");
|
||||||
|
|
||||||
// Route Navigation Arrows to dedicated button boxes
|
// Route Navigation Arrows to dedicated button boxes
|
||||||
|
|
@ -41,8 +71,13 @@ default {
|
||||||
|
|
||||||
// Registering virtual columns + Navigation buttons
|
// Registering virtual columns + Navigation buttons
|
||||||
// Coordinates: x, y, width, height (0-indexed)
|
// Coordinates: x, y, width, height (0-indexed)
|
||||||
|
// border=lr added to create vertical separators between columns
|
||||||
llMessageLinked(LINK_SET, 0, "", (key)"fw_addbox:LB_Rank:Leaderboard:0,1,4,10:");
|
llMessageLinked(LINK_SET, 0, "", (key)"fw_addbox:LB_Rank:Leaderboard:0,1,4,10:");
|
||||||
llMessageLinked(LINK_SET, 0, "", (key)"fw_addbox:LB_Name:Leaderboard:4,1,20,10:");
|
|
||||||
|
// Split Name into Top (for blinking) and Body
|
||||||
|
llMessageLinked(LINK_SET, 0, "", (key)"fw_addbox:LB_Name_Top:Leaderboard:4,1,20,1:border=lr");
|
||||||
|
llMessageLinked(LINK_SET, 0, "", (key)"fw_addbox:LB_Name:Leaderboard:4,2,20,9:border=lr");
|
||||||
|
|
||||||
llMessageLinked(LINK_SET, 0, "", (key)"fw_addbox:LB_WL:Leaderboard:24,1,8,10:");
|
llMessageLinked(LINK_SET, 0, "", (key)"fw_addbox:LB_WL:Leaderboard:24,1,8,10:");
|
||||||
|
|
||||||
// Navigation Row (Shifted down to Y=11)
|
// Navigation Row (Shifted down to Y=11)
|
||||||
|
|
@ -58,6 +93,22 @@ default {
|
||||||
|
|
||||||
// Trigger Leaderboard Manager to download from KVP Database
|
// Trigger Leaderboard Manager to download from KVP Database
|
||||||
llMessageLinked(LINK_SET, MSG_RESET_LEADERBOARD, "START_SYNC", NULL_KEY);
|
llMessageLinked(LINK_SET, MSG_RESET_LEADERBOARD, "START_SYNC", NULL_KEY);
|
||||||
|
|
||||||
|
// Start Blink Timer (0.5s intervals)
|
||||||
|
llSetTimerEvent(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
timer() {
|
||||||
|
if (!canBlink) {
|
||||||
|
llSetTimerEvent(0.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
blinkState = !blinkState;
|
||||||
|
if (blinkState) {
|
||||||
|
llMessageLinked(LINK_SET, 0, firstName, (key)"fw_data:LB_Name_Top");
|
||||||
|
} else {
|
||||||
|
llMessageLinked(LINK_SET, 0, "", (key)"fw_data:LB_Name_Top");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
touch_start(integer _n) {
|
touch_start(integer _n) {
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,8 @@ startUpdateSequence(string pName, string pResult) {
|
||||||
}
|
}
|
||||||
|
|
||||||
default {
|
default {
|
||||||
|
on_rez(integer _p) { llResetScript(); }
|
||||||
|
|
||||||
state_entry() {
|
state_entry() {
|
||||||
REPORT_MEMORY();
|
REPORT_MEMORY();
|
||||||
dbg("⏳ [Leaderboard] Startup: Handshake link active.");
|
dbg("⏳ [Leaderboard] Startup: Handshake link active.");
|
||||||
|
|
@ -343,7 +345,7 @@ default {
|
||||||
}
|
}
|
||||||
string _p = " "; if (_offset > 0) _p = "[ < PREV ]";
|
string _p = " "; if (_offset > 0) _p = "[ < PREV ]";
|
||||||
string _n = " "; if (_offset + 10 < _globalTotal) _n = "[ NEXT > ]";
|
string _n = " "; if (_offset + 10 < _globalTotal) _n = "[ NEXT > ]";
|
||||||
llMessageLinked(LINK_SET, MSG_DISPLAY_LEADERBOARD, "COLUMNS|" + _rankCol + "|" + _nameCol + "|" + _statsCol + "|" + _p + "|" + _n, NULL_KEY);
|
llMessageLinked(LINK_SET, MSG_DISPLAY_LEADERBOARD, "COLUMNS|" + _rankCol + "|" + _nameCol + "|" + _statsCol + "|" + _p + "|" + _n + "|" + (string)_offset, NULL_KEY);
|
||||||
}
|
}
|
||||||
else if (num == MSG_LB_PAGE_NEXT) {
|
else if (num == MSG_LB_PAGE_NEXT) {
|
||||||
integer _maxEntries = llGetListLength(leaderboardData) / 3;
|
integer _maxEntries = llGetListLength(leaderboardData) / 3;
|
||||||
|
|
@ -367,6 +369,18 @@ default {
|
||||||
if (str == "START_SYNC") {
|
if (str == "START_SYNC") {
|
||||||
loadLBPage(1);
|
loadLBPage(1);
|
||||||
}
|
}
|
||||||
|
else if (str == "WIPE" || str == "HARD_RESET") {
|
||||||
|
if (id != (key)GLOBAL_ADMIN) {
|
||||||
|
llOwnerSay("🚫 [Security] Unauthorized WIPE attempt blocked from: " + (string)id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Soft Wipe: Clear all shards to empty in world datastore
|
||||||
|
integer _i;
|
||||||
|
for (_i = 1; _i <= MAX_LB_PAGES; _i++) {
|
||||||
|
llUpdateKeyValue(LB_KEY_PREFIX + (string)_i, "", FALSE, "");
|
||||||
|
}
|
||||||
|
dbg("🚫 [Leaderboard Manager] GLOBAL WIPE: All 10 datastore shards have been set to empty.");
|
||||||
|
}
|
||||||
else if (str == "DEBUG_GENERATE" && llGetOwner() == llGetCreator()) {
|
else if (str == "DEBUG_GENERATE" && llGetOwner() == llGetCreator()) {
|
||||||
generateShardedData();
|
generateShardedData();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1127,15 +1127,30 @@ default {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (msg == "Reset Leaderboard") {
|
if (msg == "Reset Leaderboard") {
|
||||||
// CHANGED: Send to scoreboard, which will handle leaderboard reset
|
llDialog(id, "⚠️ WARNING: This will PERMANENTLY WIPE the World Ranking database (all 10 shards). Are you sure?", ["YES, WIPE LB", "NO, CANCEL"], DIALOG_CHANNEL);
|
||||||
llMessageLinked(LINK_SCOREBOARD, MSG_RESET_LEADERBOARD, "", NULL_KEY);
|
return;
|
||||||
dbg("🏆 Leaderboard scores reset - game wins cleared!");
|
}
|
||||||
|
if (msg == "YES, WIPE LB") {
|
||||||
|
if (id != (key)GLOBAL_ADMIN) {
|
||||||
|
llRegionSayTo(id, 0, "🚫 Access Denied: Only the Global Admin can perform this action.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
llMessageLinked(LINK_SCOREBOARD, MSG_RESET_LEADERBOARD, "WIPE", id); // Use 'id' to pass user key
|
||||||
|
llOwnerSay("🏆 GLOBAL LEADERBOARD WIPE confirmed and executed.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (msg == "Reset All") {
|
if (msg == "Reset All") {
|
||||||
|
llDialog(id, "⚠️ WARNING: This will factory reset the game AND permanently wipe the leaderboard. Are you sure?", ["YES, RESET ALL", "NO, CANCEL"], DIALOG_CHANNEL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (msg == "YES, RESET ALL") {
|
||||||
|
if (id != (key)GLOBAL_ADMIN) {
|
||||||
|
llRegionSayTo(id, 0, "🚫 Access Denied: Only the Global Admin can perform this action.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
resetGame();
|
resetGame();
|
||||||
llMessageLinked(LINK_SCOREBOARD, MSG_RESET_LEADERBOARD, "", NULL_KEY);
|
llMessageLinked(LINK_SCOREBOARD, MSG_RESET_LEADERBOARD, "WIPE", id); // Use 'id' for security check
|
||||||
dbg("🔄 Complete reset - game and leaderboard cleared!");
|
llOwnerSay("🔄 FULL RESET confirmed and executed.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (msg == "Memory Stats") {
|
if (msg == "Memory Stats") {
|
||||||
|
|
|
||||||
|
|
@ -190,10 +190,12 @@ key EXPERIENCE_ID = "06926390-26e6-11f1-a452-0242ac110003"; // Final Girlz I.N.C
|
||||||
#define DELAY_CONFETTI_TICK 0.2 // Confetti particle interval (0.2s)
|
#define DELAY_CONFETTI_TICK 0.2 // Confetti particle interval (0.2s)
|
||||||
#define DELAY_CONFETTI_PREP 0.5 // Confetti preparation delay (0.5s)
|
#define DELAY_CONFETTI_PREP 0.5 // Confetti preparation delay (0.5s)
|
||||||
#define DELAY_FLOAT_UPDATE 0.1 // Floater status update delay (0.1s)
|
#define DELAY_FLOAT_UPDATE 0.1 // Floater status update delay (0.1s)
|
||||||
|
|
||||||
// --- Game Timing Settings (Originals relocated here) ---
|
// --- Game Timing Settings (Originals relocated here) ---
|
||||||
#define BOT_PICK_DELAY 2.0 // Bot picking decision time (2.0s)
|
#define BOT_PICK_DELAY 2.0 // Bot picking decision time (2.0s)
|
||||||
#define HUMAN_PICK_DELAY 1.0 // Human picking buffer (1.0s)
|
#define HUMAN_PICK_DELAY 1.0 // Human picking buffer (1.0s)
|
||||||
#define DIALOG_DELAY 1.5 // Base dialog presentation delay (1.5s)
|
#define DIALOG_DELAY 1.5 // Base dialog presentation delay (1.5s)
|
||||||
#define STATUS_DISPLAY_TIME 8.0 // How long status text stays on display (8.0s)
|
#define STATUS_DISPLAY_TIME 8.0 // How long status text stays on display (8.0s)
|
||||||
#define BOT_RESPONSE_DELAY 1.5 // Bot response timing (1.5s)
|
#define BOT_RESPONSE_DELAY 1.5 // Bot response timing (1.5s)
|
||||||
|
|
||||||
|
// --- Security ---
|
||||||
|
#define GLOBAL_ADMIN "3e01527d-a9ff-4776-b2b8-918ab622f70f"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue