Peril_Dice/Game_Calculator.lsl

204 lines
7.2 KiB
Text
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "peril/Peril_Constants.lsl"
// === Game Calculator Module (Max 10 players) ===
// Calculates dice types, pick requirements, and other game mechanics
// This version chooses a dice size based on the number of players,
// ensuring at least three numbers are available per player.
list lives;
list picksData;
string perilPlayer;
list names;
list pickQueue;
// List of supported dice sizes; ensure the last entry can accommodate 10 players × 3 picks = 30
#define STANDARD_DICE [6, 12, 20, 30]
// Determine which die to use based on player count.
// Each player should have at least 3 numbers available to choose from.
integer getDiceType(integer playerCount) {
integer minimumSides = playerCount * 3;
integer i;
for (i = 0; i < llGetListLength(STANDARD_DICE); i++) {
integer sides = llList2Integer(STANDARD_DICE, i);
if (sides >= minimumSides) {
return sides;
}
}
// If no predefined die has enough sides, return the largest supported die (d30)
return llList2Integer(STANDARD_DICE, llGetListLength(STANDARD_DICE) - 1);
}
// Determine how many picks a player should make based on the peril player's lives
integer getPicksRequiredFromName(string name) {
integer nameIdx = llListFindList(names, [name]);
if (nameIdx == -1) {
integer j;
for (j = 0; j < llGetListLength(names); j++) {
string checkName = llList2String(names, j);
if (llSubStringIndex(checkName, name) != -1) {
nameIdx = j;
j = llGetListLength(names);
}
}
}
if (nameIdx == -1) return 0;
integer lifeCount = (integer)llList2String(lives, nameIdx);
// Pick count = 4 - peril player's lives (3 lives=1 pick, 2 lives=2 picks, 1 life=3 picks)
return 4 - lifeCount;
}
// Find the index of a player in the pickQueue by name
integer getPickerIndex(string name) {
return llListFindList(pickQueue, [name]);
}
// Serialize the current game state for syncing with other scripts
string serializeGameState() {
return llList2CSV(lives) + "~" + llList2CSV(picksData) + "~" + perilPlayer + "~" + llList2CSV(names);
}
// Show a pick management dialog for the owner.
// LSL does not support a void return type, so this returns an integer which is ignored.
integer showPickManager(string player, key id) {
string searchName = player;
if (llSubStringIndex(searchName, "~") != -1) {
list parts = llParseString2List(searchName, ["~"], []);
searchName = llList2String(parts, 1);
}
integer searchIdx = llListFindList(names, [searchName]);
if (searchIdx == -1) {
integer k;
for (k = 0; k < llGetListLength(names); k++) {
string matchName = llList2String(names, k);
if (llSubStringIndex(matchName, searchName) != -1) {
searchIdx = k;
k = llGetListLength(names);
}
}
if (searchIdx == -1) {
return 0;
}
}
integer maxPicks = getPicksRequiredFromName(llList2String(names, searchIdx));
string currentData = llList2String(picksData, searchIdx);
list dataParts = llParseString2List(currentData, ["|"], []);
list currentPicks = [];
if (llGetListLength(dataParts) > 1) {
currentPicks = llParseString2List(llList2String(dataParts, 1), [","], []);
}
list buttons = [];
integer buttonIdx;
for (buttonIdx = 1; buttonIdx <= 6; buttonIdx++) {
string numStr = (string)buttonIdx;
if (llListFindList(currentPicks, [numStr]) != -1) {
buttons += ["❌ " + numStr];
} else if (llGetListLength(currentPicks) < maxPicks) {
buttons += ["➕ " + numStr];
}
}
return 0;
}
default {
state_entry() {
REPORT_MEMORY();
// Initialize/reset all state variables
lives = [];
picksData = [];
perilPlayer = "";
names = [];
pickQueue = [];
dbg("🧮 [Calculator] Game Calculator ready!");
}
on_rez(integer start_param) {
REPORT_MEMORY();
// Reset all state variables on rez
lives = [];
picksData = [];
perilPlayer = "";
names = [];
pickQueue = [];
}
link_message(integer sender, integer num, string str, key id) {
// Handle full reset from main controller
if (num == MSG_RESET_ALL && str == "FULL_RESET") {
// Reset helper state
lives = [];
picksData = [];
perilPlayer = "";
names = [];
pickQueue = [];
dbg("🧮 [Calculator] Calculator Module reset!");
return;
}
if (num == MSG_SYNC_GAME_STATE) {
list parts = llParseString2List(str, ["~"], []);
// Handle special RESET sync message
if (llGetListLength(parts) >= 5 && llList2String(parts, 0) == "RESET") {
dbg("🧮 [Calculator] 🔄 Received reset sync - ignoring during reset");
return;
}
if (llGetListLength(parts) < 4) {
dbg("🧮 [Calculator] ⚠️ Incomplete sync message received, parts: " + (string)llGetListLength(parts));
dbg("🧮 [Calculator] ⚠️ Incomplete game state received.");
return;
}
lives = llCSV2List(llList2String(parts, 0));
// Use ^ delimiter for picksData to avoid comma conflicts
string picksDataStr = llList2String(parts, 1);
if (picksDataStr == "" || picksDataStr == "EMPTY") {
picksData = [];
} else {
picksData = llParseString2List(picksDataStr, ["^"], []);
}
string receivedPeril = llList2String(parts, 2);
if (receivedPeril == "NONE") {
perilPlayer = "";
} else {
perilPlayer = receivedPeril;
}
names = llCSV2List(llList2String(parts, 3));
}
else if (num == MSG_SYNC_PICKQUEUE) {
pickQueue = llCSV2List(str);
}
else if (num == MSG_GET_DICE_TYPE) {
integer playerCount = (integer)str;
dbg("🧮 [Calculator] 📈 Calculating dice type for " + (string)playerCount + " players");
integer result = getDiceType(playerCount);
// Send result only to the requester (sender), not broadcast to everyone
llMessageLinked(sender, MSG_DICE_TYPE_RESULT, (string)result, NULL_KEY);
}
else if (num == MSG_GET_PICKS_REQUIRED) {
integer result = getPicksRequiredFromName(str);
llMessageLinked(LINK_THIS, MSG_GET_PICKS_REQUIRED, (string)result, NULL_KEY);
}
else if (num == MSG_GET_PICKER_INDEX) {
integer result = getPickerIndex(str);
llMessageLinked(LINK_THIS, MSG_GET_PICKER_INDEX, (string)result, NULL_KEY);
}
else if (num == MSG_SERIALIZE_GAME_STATE) {
llMessageLinked(LINK_THIS, MSG_SERIALIZE_GAME_STATE, serializeGameState(), NULL_KEY);
}
else if (num == MSG_OWNER_PICK_MANAGER) {
dbg("🧮 [Calculator] 📨 MSG 206 received for: " + str + " from: " + (string)id);
showPickManager(str, id);
}
}
}