added rules
This commit is contained in:
parent
63b100efa0
commit
d53a557e43
4 changed files with 271 additions and 24 deletions
271
GAME_RULES.md
Normal file
271
GAME_RULES.md
Normal file
|
|
@ -0,0 +1,271 @@
|
||||||
|
# 🎲 **PERIL DICE GAME - OFFICIAL RULES**
|
||||||
|
|
||||||
|
*Original concept by **Noose the Bunny** (djmusica28) in Second Life*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 **OBJECTIVE**
|
||||||
|
Be the last player standing! Survive the deadly dice rolls while others fall to elimination. Only one can claim **Ultimate Victory**!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ **SETUP**
|
||||||
|
|
||||||
|
### **Players**
|
||||||
|
- **2-10 players** can join the game
|
||||||
|
- **Bots available** for testing and variety
|
||||||
|
- **Owner participation** - game owner can play too!
|
||||||
|
|
||||||
|
### **Starting Conditions**
|
||||||
|
- Each player begins with **3 lives** ❤️❤️❤️
|
||||||
|
- One player is randomly selected as the **Peril Player** 🎯
|
||||||
|
- Dice type automatically chosen based on player count
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎮 **GAMEPLAY PHASES**
|
||||||
|
|
||||||
|
### **1️⃣ Ready Phase**
|
||||||
|
- All players (except game starter) must mark themselves **"Ready"**
|
||||||
|
- Game starter can begin once everyone is prepared
|
||||||
|
- No joining allowed once the killing game begins! 🚫
|
||||||
|
|
||||||
|
### **2️⃣ Number Picking Phase**
|
||||||
|
Players pick numbers based on the **Peril Player's remaining lives**:
|
||||||
|
|
||||||
|
| Peril Player's Lives | Numbers Each Player Must Pick |
|
||||||
|
|---------------------|-------------------------------|
|
||||||
|
| ❤️❤️❤️ (3 lives) | **1 number** |
|
||||||
|
| ❤️❤️ (2 lives) | **2 numbers** |
|
||||||
|
| ❤️ (1 life) | **3 numbers** |
|
||||||
|
|
||||||
|
**Picking Order:**
|
||||||
|
1. **Peril Player** picks first
|
||||||
|
2. All other players pick in sequence
|
||||||
|
3. **No duplicate picks** - each number can only be chosen once per round
|
||||||
|
|
||||||
|
### **3️⃣ Dice Rolling Phase**
|
||||||
|
- **Peril Player** rolls the dice
|
||||||
|
- Result determines everyone's fate!
|
||||||
|
- Roll is displayed on the game board for all to see
|
||||||
|
|
||||||
|
### **4️⃣ Resolution Phase**
|
||||||
|
Three possible outcomes based on the dice roll:
|
||||||
|
|
||||||
|
#### 🔄 **PLOT TWIST!**
|
||||||
|
- Someone **OTHER than the Peril Player** picked the rolled number
|
||||||
|
- **That player becomes the new Peril Player**
|
||||||
|
- No lives lost this round
|
||||||
|
- Game continues with new Peril Player
|
||||||
|
|
||||||
|
#### 🩸 **DIRECT HIT!**
|
||||||
|
- The **Peril Player picked their own rolled number**
|
||||||
|
- Peril Player **loses 1 life** ❤️ → 💔
|
||||||
|
- If they survive, they remain the Peril Player for next round
|
||||||
|
|
||||||
|
#### 🩸 **NO SHIELD!**
|
||||||
|
- **Nobody picked the rolled number**
|
||||||
|
- Peril Player **loses 1 life** ❤️ → 💔
|
||||||
|
- No protection from other players' picks
|
||||||
|
|
||||||
|
### **5️⃣ Elimination**
|
||||||
|
- Players with **0 lives** are eliminated from the game 💀
|
||||||
|
- Eliminated players cannot return
|
||||||
|
- Game continues with remaining survivors
|
||||||
|
|
||||||
|
### **6️⃣ Victory**
|
||||||
|
- **Last player standing wins!** 🏆
|
||||||
|
- Victory celebration with confetti effects! ✨
|
||||||
|
- Winner's name recorded on the leaderboard
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎲 **DICE SCALING SYSTEM**
|
||||||
|
|
||||||
|
The game automatically selects appropriate dice to ensure fair gameplay:
|
||||||
|
|
||||||
|
| Number of Players | Dice Type | Total Numbers Available |
|
||||||
|
|------------------|-----------|----------------------|
|
||||||
|
| 1-2 players | **d6** | 6 numbers (1-6) |
|
||||||
|
| 3-4 players | **d12** | 12 numbers (1-12) |
|
||||||
|
| 5-6 players | **d20** | 20 numbers (1-20) |
|
||||||
|
| 7-10 players | **d30** | 30 numbers (1-30) |
|
||||||
|
|
||||||
|
*This ensures at least 3 numbers per player are always available*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎭 **DRAMATIC ANNOUNCEMENTS**
|
||||||
|
|
||||||
|
The game features thematic messaging for maximum immersion:
|
||||||
|
|
||||||
|
- **"💀 [Player] has entered the deadly game! Welcome to your potential doom! 💀"**
|
||||||
|
- **"⚔️ [Player] steels themselves for the deadly challenge ahead! ⚔️"**
|
||||||
|
- **"🏃 [Player] loses their nerve and backs away from the challenge! 🏃"**
|
||||||
|
- **"⚡ THE KILLING GAME BEGINS! ⚡"**
|
||||||
|
- **"✨ ULTIMATE VICTORY! [Player] is the Ultimate Survivor! ✨"**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 **STRATEGY TIPS**
|
||||||
|
|
||||||
|
### **As a Regular Player:**
|
||||||
|
- **Pick popular numbers** (5, 6, 7) to increase chances of causing Plot Twists
|
||||||
|
- **Avoid number 1** - statistically less likely on higher dice
|
||||||
|
- **Watch the Peril Player's lives** - affects how many numbers you must pick
|
||||||
|
|
||||||
|
### **As the Peril Player:**
|
||||||
|
- **Avoid common/popular numbers** that others might pick
|
||||||
|
- **Pick edge numbers** (1, maximum die value) for better survival odds
|
||||||
|
- **Remember**: The more lives you have, the fewer numbers others pick (easier to avoid)
|
||||||
|
|
||||||
|
### **Advanced Tactics:**
|
||||||
|
- **Psychological warfare** - discuss picks to influence others
|
||||||
|
- **Alliance forming** - temporary cooperation to eliminate threats
|
||||||
|
- **Risk assessment** - calculate odds based on remaining numbers
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏆 **WINNING CONDITIONS**
|
||||||
|
|
||||||
|
### **Individual Victory:**
|
||||||
|
- Be the **last player with lives remaining**
|
||||||
|
- Achieve **Ultimate Survivor** status
|
||||||
|
- Earn a permanent record on the leaderboard
|
||||||
|
|
||||||
|
### **Leaderboard System:**
|
||||||
|
- **Wins** and **losses** tracked across all games
|
||||||
|
- **Persistent records** saved between sessions
|
||||||
|
- **Top players** displayed for bragging rights
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🤖 **BOT PLAYERS**
|
||||||
|
|
||||||
|
- **AI opponents** available for practice and testing
|
||||||
|
- **Always ready** - no need to mark bots as ready
|
||||||
|
- **Intelligent picking** - avoid already chosen numbers
|
||||||
|
- **Auto-rolling** when selected as Peril Player
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ **IMPORTANT RULES**
|
||||||
|
|
||||||
|
### **No Take-Backs:**
|
||||||
|
- Once numbers are picked, they cannot be changed
|
||||||
|
- Dice rolls are final - no re-rolls
|
||||||
|
|
||||||
|
### **Fair Play:**
|
||||||
|
- No joining games in progress
|
||||||
|
- All players must participate actively
|
||||||
|
- Owner can moderate and manage the game
|
||||||
|
|
||||||
|
### **Technical Rules:**
|
||||||
|
- Game supports up to **10 players maximum**
|
||||||
|
- **10-minute timeout** on dialog responses
|
||||||
|
- Automatic game reset if inactive too long
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎊 **GAME VARIATIONS**
|
||||||
|
|
||||||
|
While the core rules remain the same, consider these optional variations:
|
||||||
|
|
||||||
|
### **Speed Peril:**
|
||||||
|
- Reduce dialog timeout to 2 minutes for faster gameplay
|
||||||
|
|
||||||
|
### **High Stakes:**
|
||||||
|
- Start with only 2 lives instead of 3
|
||||||
|
|
||||||
|
### **Team Peril:**
|
||||||
|
- Players form alliances (unofficial - for roleplay only)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 **QUICK REFERENCE**
|
||||||
|
|
||||||
|
**🎯 Peril Player Picks:** Always go first
|
||||||
|
**📊 Pick Count:** 4 minus Peril Player's current lives
|
||||||
|
**🎲 Dice Roll:** Determines round outcome
|
||||||
|
**💔 Life Loss:** Direct Hit or No Shield scenarios
|
||||||
|
**🔄 Plot Twist:** New Peril Player selected
|
||||||
|
**🏆 Victory:** Last survivor standing
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎮 **HOW TO PLAY (STEP BY STEP)**
|
||||||
|
|
||||||
|
### **For Game Owner:**
|
||||||
|
1. **Touch the game controller** to access owner menu
|
||||||
|
2. **Add Test Players** if desired for practice
|
||||||
|
3. **Join the game yourself** (optional)
|
||||||
|
4. **Start Game** when all players are ready
|
||||||
|
|
||||||
|
### **For Players:**
|
||||||
|
1. **Touch the game controller** to join
|
||||||
|
2. **Mark yourself "Ready"** when prepared to play
|
||||||
|
3. **Wait for game to begin**
|
||||||
|
4. **Pick your numbers** when prompted (follow on-screen instructions)
|
||||||
|
5. **Roll dice** if you're the Peril Player
|
||||||
|
6. **Survive and repeat** until victory or elimination!
|
||||||
|
|
||||||
|
### **Dialog System:**
|
||||||
|
- **Touch controller anytime** to recover lost dialogs
|
||||||
|
- **Follow button prompts** in dialog boxes
|
||||||
|
- **Time limit:** 10 minutes to respond to dialogs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 **TROUBLESHOOTING**
|
||||||
|
|
||||||
|
### **Lost Dialog Box:**
|
||||||
|
- Touch the game controller to recover your dialog
|
||||||
|
|
||||||
|
### **Game Stuck:**
|
||||||
|
- Owner can access troubleshooting menu
|
||||||
|
- "Reset Game" restarts current game
|
||||||
|
- "Reset All" clears everything including leaderboard
|
||||||
|
|
||||||
|
### **Can't Join Game:**
|
||||||
|
- Game may be in progress (no joining mid-game)
|
||||||
|
- Maximum 10 players may be reached
|
||||||
|
- Check if you're already registered
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📈 **STATISTICS & RECORDS**
|
||||||
|
|
||||||
|
### **Individual Stats:**
|
||||||
|
- **Games Won:** Total victories achieved
|
||||||
|
- **Games Lost:** Total eliminations suffered
|
||||||
|
- **Win Rate:** Percentage of games won
|
||||||
|
|
||||||
|
### **Leaderboard Features:**
|
||||||
|
- **Persistent tracking** across all gaming sessions
|
||||||
|
- **Top 10 players** displayed publicly
|
||||||
|
- **Separate reset options** for games vs. leaderboard
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎪 **SOCIAL FEATURES**
|
||||||
|
|
||||||
|
### **Spectating:**
|
||||||
|
- Non-players can watch the action unfold
|
||||||
|
- Real-time visual scoreboard shows all player status
|
||||||
|
- Dramatic announcements keep everyone engaged
|
||||||
|
|
||||||
|
### **Community Events:**
|
||||||
|
- **Tournament play** with multiple rounds
|
||||||
|
- **Theme nights** with special rules
|
||||||
|
- **Betting pools** on outcomes (unofficial)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Master these rules and you'll be ready to enter the deadly world of Peril Dice! May luck and strategy guide you to Ultimate Victory!* 🎲✨
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Version:** 2.6.0
|
||||||
|
**Last Updated:** August 9, 2025
|
||||||
|
**Game System:** Production Ready - Enhanced Multi-Instance Support
|
||||||
|
**Credits:** Original concept by Noose the Bunny (djmusica28), Automated system implementation
|
||||||
|
|
@ -158,7 +158,6 @@ default {
|
||||||
}
|
}
|
||||||
names = llCSV2List(llList2String(parts, 3));
|
names = llCSV2List(llList2String(parts, 3));
|
||||||
|
|
||||||
llOwnerSay("🔄 Calculator synced: lives=" + (string)llGetListLength(lives) + ", picks=" + (string)llGetListLength(picksData) + ", names=" + (string)llGetListLength(names) + ", peril=" + perilPlayer);
|
|
||||||
}
|
}
|
||||||
else if (num == MSG_SYNC_PICKQUEUE) {
|
else if (num == MSG_SYNC_PICKQUEUE) {
|
||||||
pickQueue = llCSV2List(str);
|
pickQueue = llCSV2List(str);
|
||||||
|
|
|
||||||
|
|
@ -306,23 +306,17 @@ initListeners() {
|
||||||
}
|
}
|
||||||
|
|
||||||
resetGame() {
|
resetGame() {
|
||||||
llOwnerSay("🧼 Debug - Starting resetGame(), players: " + (string)llGetListLength(players) + ", tracked channels: " + llList2CSV(floaterChannels));
|
|
||||||
|
|
||||||
// Clean up listeners first
|
// Clean up listeners first
|
||||||
cleanupListeners();
|
cleanupListeners();
|
||||||
|
|
||||||
// UNIVERSAL CLEANUP: Always clean ALL possible floater channels regardless of tracked state
|
// UNIVERSAL CLEANUP: Always clean ALL possible floater channels regardless of tracked state
|
||||||
// This ensures cleanup works even after script resets destroy tracking data
|
// This ensures cleanup works even after script resets destroy tracking data
|
||||||
llOwnerSay("🧼 Debug - Universal floater cleanup (0-" + (string)(MAX_PLAYERS-1) + ")");
|
|
||||||
integer i;
|
integer i;
|
||||||
for (i = 0; i < MAX_PLAYERS; i++) {
|
for (i = 0; i < MAX_PLAYERS; i++) {
|
||||||
integer ch = FLOATER_BASE_CHANNEL + i;
|
integer ch = FLOATER_BASE_CHANNEL + i;
|
||||||
llOwnerSay("🧼 Debug - Cleaning universal channel " + (string)i + ": " + (string)ch);
|
|
||||||
llMessageLinked(LINK_SET, MSG_CLEANUP_FLOAT, (string)ch, NULL_KEY);
|
llMessageLinked(LINK_SET, MSG_CLEANUP_FLOAT, (string)ch, NULL_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
llOwnerSay("🧼 Debug - Universal cleanup complete, waiting for floater processing...");
|
|
||||||
|
|
||||||
// Give floater cleanup time to process BEFORE clearing state
|
// Give floater cleanup time to process BEFORE clearing state
|
||||||
llSleep(2.0);
|
llSleep(2.0);
|
||||||
|
|
||||||
|
|
@ -366,8 +360,6 @@ resetGame() {
|
||||||
initListeners();
|
initListeners();
|
||||||
|
|
||||||
updateHelpers();
|
updateHelpers();
|
||||||
|
|
||||||
llOwnerSay("🧼 Debug - resetGame() complete");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// continueCurrentRound() removed - handled by Game Manager
|
// continueCurrentRound() removed - handled by Game Manager
|
||||||
|
|
|
||||||
|
|
@ -259,7 +259,6 @@ default {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num == MSG_SHOW_MENU) {
|
if (num == MSG_SHOW_MENU) {
|
||||||
llOwnerSay("📨 Received MSG_SHOW_MENU with: " + str);
|
|
||||||
list args = llParseString2List(str, ["|"], []);
|
list args = llParseString2List(str, ["|"], []);
|
||||||
if (llGetListLength(args) < 2) {
|
if (llGetListLength(args) < 2) {
|
||||||
llOwnerSay("⚠️ Invalid message format: " + str);
|
llOwnerSay("⚠️ Invalid message format: " + str);
|
||||||
|
|
@ -269,10 +268,8 @@ default {
|
||||||
integer isStarter = (integer)llList2String(args, 1);
|
integer isStarter = (integer)llList2String(args, 1);
|
||||||
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
|
||||||
llOwnerSay("DEBUG: Owner menu request - isStarter=" + (string)isStarter + ", calling showReadyLeaveMenu");
|
|
||||||
showReadyLeaveMenu(id, isStarter, TRUE);
|
showReadyLeaveMenu(id, isStarter, TRUE);
|
||||||
} else if (targetType == "player") {
|
} else if (targetType == "player") {
|
||||||
llOwnerSay("DEBUG: Player menu request - isStarter=" + (string)isStarter + ", calling showReadyLeaveMenu");
|
|
||||||
showReadyLeaveMenu(id, isStarter, FALSE);
|
showReadyLeaveMenu(id, isStarter, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -285,9 +282,6 @@ default {
|
||||||
integer isBot = (integer)llList2String(parts, 2);
|
integer isBot = (integer)llList2String(parts, 2);
|
||||||
integer responseRequestID = (integer)llList2String(parts, 3);
|
integer responseRequestID = (integer)llList2String(parts, 3);
|
||||||
|
|
||||||
llOwnerSay("DEBUG: Ready state result for " + playerName + ": ready=" + (string)isReady + ", bot=" + (string)isBot + ", requestID=" + (string)responseRequestID);
|
|
||||||
llOwnerSay("DEBUG: Pending menu - ID=" + (string)pendingMenuPlayer + ", expectedRequestID=" + (string)pendingMenuRequestID + ", starter=" + (string)pendingMenuIsStarter + ", owner=" + (string)pendingMenuIsOwner);
|
|
||||||
|
|
||||||
// Validate that this response matches our pending request
|
// Validate that this response matches our pending request
|
||||||
if (pendingMenuPlayer == id && responseRequestID == pendingMenuRequestID) {
|
if (pendingMenuPlayer == id && responseRequestID == pendingMenuRequestID) {
|
||||||
// Check for timeout
|
// Check for timeout
|
||||||
|
|
@ -297,19 +291,10 @@ default {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
llOwnerSay("DEBUG: Valid response - showing menu");
|
|
||||||
showReadyLeaveMenuWithState(pendingMenuPlayer, pendingMenuIsStarter, pendingMenuIsOwner, isReady, isBot);
|
showReadyLeaveMenuWithState(pendingMenuPlayer, pendingMenuIsStarter, pendingMenuIsOwner, isReady, isBot);
|
||||||
// Reset pending state
|
// Reset pending state
|
||||||
pendingMenuPlayer = NULL_KEY;
|
pendingMenuPlayer = NULL_KEY;
|
||||||
pendingMenuRequestID = 0;
|
pendingMenuRequestID = 0;
|
||||||
} else {
|
|
||||||
// Log the mismatch for debugging
|
|
||||||
if (pendingMenuPlayer != id) {
|
|
||||||
llOwnerSay("DEBUG: Player mismatch: expected " + (string)pendingMenuPlayer + ", got " + (string)id);
|
|
||||||
}
|
|
||||||
if (responseRequestID != pendingMenuRequestID) {
|
|
||||||
llOwnerSay("DEBUG: Request ID mismatch: expected " + (string)pendingMenuRequestID + ", got " + (string)responseRequestID + " (ignoring stale response)");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
llOwnerSay("⚠️ Invalid ready state result format - expected 4 parts, got " + (string)llGetListLength(parts));
|
llOwnerSay("⚠️ Invalid ready state result format - expected 4 parts, got " + (string)llGetListLength(parts));
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue