Initial commit: Enhanced IRC bot with duck hunt game
- Added hunt/feed duck mechanics (80% hunt, 20% feed) - Implemented persistent scoring system - Added channel control commands (\!stopducks/\!startducks) - Enhanced duck hunt with wrong action penalties - Organized bot structure with botmain.js as main file - Added comprehensive documentation (README.md) - Included 17 plugins with various games and utilities 🦆 Duck Hunt Features: - Hunt ducks with \!shoot/\!bang (80% of spawns) - Feed ducks with \!feed (20% of spawns) - Persistent scores saved to JSON - Channel-specific controls for #bakedbeans - Reaction time tracking and special achievements 🎮 Other Games: - Casino games (slots, coinflip, hi-lo, scratch cards) - Multiplayer games (pigs, zombie dice, quiplash) - Text generation (babble, conspiracy, drunk historian) - Interactive features (story writing, emojify, combos) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
commit
a3ed25f8dd
39 changed files with 12360 additions and 0 deletions
668
plugins/pigsmp_plugin_fixed.js
Normal file
668
plugins/pigsmp_plugin_fixed.js
Normal file
|
|
@ -0,0 +1,668 @@
|
|||
// plugins/pigsmp.js - Pass the Pigs Multiplayer game plugin
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
init(bot) {
|
||||
console.log('Pass the Pigs Multiplayer plugin initialized');
|
||||
this.bot = bot;
|
||||
|
||||
// Persistent player statistics (saved to file)
|
||||
this.playerStats = new Map(); // nick -> { bestScore, totalGames, totalRolls, jackpots, name }
|
||||
|
||||
// Current game scores (reset each game)
|
||||
this.gameScores = new Map(); // nick -> { currentScore, rollCount, eliminated }
|
||||
|
||||
// Game state with multiplayer support
|
||||
this.gameState = {
|
||||
phase: 'idle', // 'idle', 'joining', 'active'
|
||||
players: [],
|
||||
joinTimer: null,
|
||||
startTime: null,
|
||||
currentPlayer: 0,
|
||||
turnScore: 0,
|
||||
channel: null,
|
||||
joinTimeLimit: 60000, // 60 seconds
|
||||
warningTime: 50000 // Warning at 50 seconds (10 sec left sluts)
|
||||
};
|
||||
|
||||
// Set up score file path
|
||||
this.scoresFile = path.join(__dirname, 'pigsmp_scores.json');
|
||||
|
||||
// Load existing scores
|
||||
this.loadScores();
|
||||
},
|
||||
|
||||
cleanup(bot) {
|
||||
console.log('Pass the Pigs Multiplayer plugin cleaned up');
|
||||
// Clear any timers
|
||||
if (this.gameState.joinTimer) {
|
||||
clearTimeout(this.gameState.joinTimer);
|
||||
}
|
||||
// Save scores before cleanup
|
||||
this.saveScores();
|
||||
// Clear any active games on cleanup
|
||||
this.resetGameState();
|
||||
// Clear game scores
|
||||
if (this.gameScores) {
|
||||
this.gameScores.clear();
|
||||
}
|
||||
},
|
||||
|
||||
// Reset game state to idle
|
||||
resetGameState() {
|
||||
if (this.gameState.joinTimer) {
|
||||
clearTimeout(this.gameState.joinTimer);
|
||||
}
|
||||
this.gameState = {
|
||||
phase: 'idle',
|
||||
players: [],
|
||||
joinTimer: null,
|
||||
startTime: null,
|
||||
currentPlayer: 0,
|
||||
turnScore: 0,
|
||||
channel: null,
|
||||
joinTimeLimit: 30000,
|
||||
warningTime: 25000
|
||||
};
|
||||
},
|
||||
|
||||
// Load scores from file
|
||||
loadScores() {
|
||||
try {
|
||||
if (fs.existsSync(this.scoresFile)) {
|
||||
const data = fs.readFileSync(this.scoresFile, 'utf8');
|
||||
const scoresObject = JSON.parse(data);
|
||||
|
||||
// Convert back to Map
|
||||
this.playerStats = new Map(Object.entries(scoresObject));
|
||||
console.log(`🐷 Loaded ${this.playerStats.size} pig multiplayer player stats from ${this.scoresFile}`);
|
||||
|
||||
// Log top 3 players if any exist
|
||||
if (this.playerStats.size > 0) {
|
||||
const topPlayers = Array.from(this.playerStats.values())
|
||||
.sort((a, b) => b.bestScore - a.bestScore)
|
||||
.slice(0, 3);
|
||||
console.log('🏆 Top players:', topPlayers.map(p => `${p.name}(${p.bestScore})`).join(', '));
|
||||
}
|
||||
} else {
|
||||
console.log(`🐷 No existing multiplayer scores file found, starting fresh`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`❌ Error loading pig multiplayer scores:`, error);
|
||||
this.playerStats = new Map(); // Reset to empty if load fails
|
||||
}
|
||||
},
|
||||
|
||||
// Save scores to file
|
||||
saveScores() {
|
||||
try {
|
||||
// Convert Map to plain object for JSON serialization
|
||||
const scoresObject = Object.fromEntries(this.playerStats);
|
||||
const data = JSON.stringify(scoresObject, null, 2);
|
||||
|
||||
fs.writeFileSync(this.scoresFile, data, 'utf8');
|
||||
console.log(`💾 Saved ${this.playerStats.size} pig multiplayer player stats to ${this.scoresFile}`);
|
||||
} catch (error) {
|
||||
console.error(`❌ Error saving pig multiplayer scores:`, error);
|
||||
}
|
||||
},
|
||||
|
||||
// Update a player's persistent stats and save to file
|
||||
updatePlayerStats(nick, updates) {
|
||||
// Ensure playerStats Map exists
|
||||
if (!this.playerStats) {
|
||||
this.playerStats = new Map();
|
||||
}
|
||||
|
||||
if (!this.playerStats.has(nick)) {
|
||||
this.playerStats.set(nick, {
|
||||
bestScore: 0,
|
||||
totalGames: 0,
|
||||
totalRolls: 0,
|
||||
jackpots: 0,
|
||||
name: nick
|
||||
});
|
||||
}
|
||||
|
||||
const player = this.playerStats.get(nick);
|
||||
Object.assign(player, updates);
|
||||
|
||||
// Save to file after each update
|
||||
this.saveScores();
|
||||
},
|
||||
|
||||
// Initialize player for current game
|
||||
initGamePlayer(nick) {
|
||||
// Ensure gameScores Map exists
|
||||
if (!this.gameScores) {
|
||||
this.gameScores = new Map();
|
||||
}
|
||||
|
||||
if (!this.gameScores.has(nick)) {
|
||||
this.gameScores.set(nick, {
|
||||
currentScore: 0,
|
||||
rollCount: 0,
|
||||
eliminated: false
|
||||
});
|
||||
} else {
|
||||
// Reset for new game
|
||||
this.gameScores.set(nick, {
|
||||
currentScore: 0,
|
||||
rollCount: 0,
|
||||
eliminated: false
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize persistent stats if new player
|
||||
if (!this.playerStats.has(nick)) {
|
||||
this.updatePlayerStats(nick, {
|
||||
bestScore: 0,
|
||||
totalGames: 0,
|
||||
totalRolls: 0,
|
||||
jackpots: 0,
|
||||
name: nick
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// Start the join timer
|
||||
startJoinTimer(target) {
|
||||
this.gameState.startTime = Date.now();
|
||||
|
||||
// Set warning timer (25 seconds)
|
||||
setTimeout(() => {
|
||||
if (this.gameState.phase === 'joining') {
|
||||
this.bot.say(target, '⏰ 10 seconds left to join the pig game! Join you sluts!');
|
||||
}
|
||||
}, this.gameState.warningTime);
|
||||
|
||||
// Set game start timer (30 seconds)
|
||||
this.gameState.joinTimer = setTimeout(() => {
|
||||
this.startGame(target);
|
||||
}, this.gameState.joinTimeLimit);
|
||||
},
|
||||
|
||||
// Start the actual game
|
||||
startGame(target) {
|
||||
if (this.gameState.players.length < 2) {
|
||||
this.bot.say(target, '😞 Nobody else joined the pig game. Game cancelled.');
|
||||
this.resetGameState();
|
||||
this.gameScores.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize all players
|
||||
this.gameState.players.forEach(nick => {
|
||||
this.initGamePlayer(nick);
|
||||
});
|
||||
|
||||
// Start the game
|
||||
this.gameState.phase = 'active';
|
||||
this.gameState.currentPlayer = 0;
|
||||
this.gameState.turnScore = 0;
|
||||
|
||||
const playerList = this.gameState.players.join(' vs ');
|
||||
this.bot.say(target, `🎮 Game starting! ${playerList} - ${this.gameState.players[0]} goes first!`);
|
||||
},
|
||||
|
||||
// Pass the Pigs game simulation with reduced difficulty
|
||||
rollPigs() {
|
||||
// Actual probabilities from 11,954 sample study
|
||||
const positions = [
|
||||
{ name: 'Side (no dot)', points: 0, weight: 34.9 },
|
||||
{ name: 'Side (dot)', points: 0, weight: 30.2 },
|
||||
{ name: 'Razorback', points: 5, weight: 22.4 },
|
||||
{ name: 'Trotter', points: 5, weight: 8.8 },
|
||||
{ name: 'Snouter', points: 10, weight: 3.0 },
|
||||
{ name: 'Leaning Jowler', points: 15, weight: 0.61 }
|
||||
];
|
||||
|
||||
const rollPig = () => {
|
||||
const totalWeight = positions.reduce((sum, pos) => sum + pos.weight, 0);
|
||||
let random = Math.random() * totalWeight;
|
||||
|
||||
for (const position of positions) {
|
||||
random -= position.weight;
|
||||
if (random <= 0) {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
return positions[0]; // fallback
|
||||
};
|
||||
|
||||
const pig1 = rollPig();
|
||||
const pig2 = rollPig();
|
||||
|
||||
// Check for touching conditions first (increased probability for more difficulty)
|
||||
if (Math.random() < 0.035) { // 3.5% chance of touching (was 1.5%)
|
||||
if (Math.random() < 0.25) { // 25% of touches are Piggyback
|
||||
return { result: 'Piggyback', points: -9999, description: '🐷📚 Piggyback! ELIMINATED!' };
|
||||
} else { // 75% are Makin' Bacon/Oinker
|
||||
return { result: 'Makin\' Bacon', points: -999, description: '🥓 Makin\' Bacon! Lose ALL points!' };
|
||||
}
|
||||
}
|
||||
|
||||
// Handle side positions (Sider vs Pig Out)
|
||||
const pig1IsSide = pig1.name.startsWith('Side');
|
||||
const pig2IsSide = pig2.name.startsWith('Side');
|
||||
|
||||
if (pig1IsSide && pig2IsSide) {
|
||||
// Both on sides - reduced chance of opposite sides (Pig Out)
|
||||
const pig1Dot = pig1.name.includes('dot');
|
||||
const pig2Dot = pig2.name.includes('dot');
|
||||
|
||||
// Reduced bias toward opposite sides for better gameplay
|
||||
const oppositeRoll = Math.random();
|
||||
if (oppositeRoll < 0.35) { // 35% chance of opposite sides when both are siders
|
||||
return { result: 'Pig Out', points: 0, description: '💥 Pig Out! Turn ends!' };
|
||||
} else {
|
||||
return { result: 'Sider', points: 1, description: '🐷 Sider' };
|
||||
}
|
||||
}
|
||||
|
||||
// If only one pig is on its side, that pig scores nothing
|
||||
if (pig1IsSide && !pig2IsSide) {
|
||||
return {
|
||||
result: pig2.name,
|
||||
points: pig2.points,
|
||||
description: `🐷 ${pig2.name} (${pig2.points})`
|
||||
};
|
||||
}
|
||||
|
||||
if (pig2IsSide && !pig1IsSide) {
|
||||
return {
|
||||
result: pig1.name,
|
||||
points: pig1.points,
|
||||
description: `🐷 ${pig1.name} (${pig1.points})`
|
||||
};
|
||||
}
|
||||
|
||||
// Neither pig is on its side - normal scoring
|
||||
if (pig1.name === pig2.name) {
|
||||
// Double combinations - sum doubled (quadruple individual)
|
||||
const doublePoints = (pig1.points + pig2.points) * 2;
|
||||
switch (pig1.name) {
|
||||
case 'Razorback':
|
||||
return { result: 'Double Razorback', points: doublePoints, description: '🐷🐷 Double Razorback (20)' };
|
||||
case 'Trotter':
|
||||
return { result: 'Double Trotter', points: doublePoints, description: '🐷🐷 Double Trotter (20)' };
|
||||
case 'Snouter':
|
||||
return { result: 'Double Snouter', points: doublePoints, description: '🐷🐷 Double Snouter (40)' };
|
||||
case 'Leaning Jowler':
|
||||
return { result: 'Double Leaning Jowler', points: doublePoints, description: '🐷🐷 Double Leaning Jowler (60)' };
|
||||
}
|
||||
}
|
||||
|
||||
// Mixed combination - sum of individual scores
|
||||
const totalPoints = pig1.points + pig2.points;
|
||||
return {
|
||||
result: 'Mixed Combo',
|
||||
points: totalPoints,
|
||||
description: `🐷 ${pig1.name} + ${pig2.name} (${totalPoints})`
|
||||
};
|
||||
},
|
||||
|
||||
// Turn management for multiplayer pig game
|
||||
nextTurn(target) {
|
||||
// Find next non-eliminated player
|
||||
let attempts = 0;
|
||||
const maxAttempts = this.gameState.players.length;
|
||||
|
||||
do {
|
||||
this.gameState.currentPlayer = (this.gameState.currentPlayer + 1) % this.gameState.players.length;
|
||||
attempts++;
|
||||
|
||||
if (attempts >= maxAttempts) {
|
||||
// All players eliminated somehow - shouldn't happen but safety check
|
||||
this.bot.say(target, '🚨 All players eliminated! Game ending.');
|
||||
this.endGame(target);
|
||||
return;
|
||||
}
|
||||
} while (this.gameScores.get(this.gameState.players[this.gameState.currentPlayer])?.eliminated);
|
||||
|
||||
const nextPlayer = this.gameState.players[this.gameState.currentPlayer];
|
||||
this.bot.say(target, `🎲 ${nextPlayer}'s turn!`);
|
||||
},
|
||||
|
||||
endGame(target) {
|
||||
// Ensure gameScores exists before processing
|
||||
if (!this.gameScores) {
|
||||
this.gameScores = new Map();
|
||||
}
|
||||
|
||||
// Save final scores to persistent stats and update records
|
||||
this.gameState.players.forEach(playerName => {
|
||||
const gameScore = this.gameScores.get(playerName);
|
||||
const playerStats = this.playerStats.get(playerName);
|
||||
|
||||
if (gameScore && playerStats) {
|
||||
const updates = {
|
||||
totalGames: playerStats.totalGames + 1,
|
||||
totalRolls: playerStats.totalRolls + gameScore.rollCount
|
||||
};
|
||||
|
||||
// Update best score if this game was better
|
||||
if (gameScore.currentScore > playerStats.bestScore) {
|
||||
updates.bestScore = gameScore.currentScore;
|
||||
this.bot.say(target, `🏆 ${playerName} set a new personal best: ${gameScore.currentScore} points!`);
|
||||
}
|
||||
|
||||
this.updatePlayerStats(playerName, updates);
|
||||
console.log(`🐷 Saved game stats for ${playerName}: score=${gameScore.currentScore}, rolls=${gameScore.rollCount}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Clear current game data
|
||||
this.gameScores.clear();
|
||||
|
||||
this.bot.say(target, '🏁 Game ended! Use !pigs to start new game.');
|
||||
this.resetGameState();
|
||||
},
|
||||
|
||||
commands: [
|
||||
{
|
||||
name: 'pigs',
|
||||
description: 'Start or join a multiplayer Pass the Pigs game',
|
||||
execute: function(context, bot) {
|
||||
const plugin = module.exports;
|
||||
const target = context.replyTo;
|
||||
const from = context.nick;
|
||||
const to = context.channel || context.replyTo;
|
||||
|
||||
// Only allow channel play for multiplayer games
|
||||
if (!context.channel) {
|
||||
bot.say(target, 'Multiplayer pig games can only be played in channels!');
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle different game phases
|
||||
switch (plugin.gameState.phase) {
|
||||
case 'idle':
|
||||
// Start new game and join timer
|
||||
plugin.gameState.phase = 'joining';
|
||||
plugin.gameState.players = [from];
|
||||
plugin.gameState.channel = to;
|
||||
|
||||
bot.say(target, `🐷 ${from} started a pig game! Others have 60 seconds to join with !pigs`);
|
||||
plugin.startJoinTimer(target);
|
||||
break;
|
||||
|
||||
case 'joining':
|
||||
// Player wants to join during countdown
|
||||
if (plugin.gameState.players.includes(from)) {
|
||||
bot.say(target, `${from}: You're already in the game!`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin.gameState.players.length >= 6) { // Max 6 players
|
||||
bot.say(target, `${from}: Game is full! (Max 6 players)`);
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.gameState.players.push(from);
|
||||
bot.say(target, `🐷 ${from} joined! (${plugin.gameState.players.length} players)`);
|
||||
break;
|
||||
|
||||
case 'active':
|
||||
// Game is running - handle roll
|
||||
if (!plugin.gameState.players.includes(from)) {
|
||||
bot.say(target, `${from}: You're not in the current game!`);
|
||||
return;
|
||||
}
|
||||
|
||||
const currentPlayerName = plugin.gameState.players[plugin.gameState.currentPlayer];
|
||||
if (from !== currentPlayerName) {
|
||||
bot.say(target, `${from}: It's ${currentPlayerName}'s turn!`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if current player is eliminated
|
||||
const playerGame = plugin.gameScores.get(from);
|
||||
if (playerGame.eliminated) {
|
||||
bot.say(target, `${from}: You are eliminated!`);
|
||||
plugin.endGame(target);
|
||||
return;
|
||||
}
|
||||
|
||||
// Roll the pigs!
|
||||
const roll = plugin.rollPigs();
|
||||
|
||||
// Update roll count
|
||||
playerGame.rollCount++;
|
||||
|
||||
let endTurn = false;
|
||||
let endGame = false;
|
||||
|
||||
if (roll.points === -9999) {
|
||||
// Piggyback - eliminate player
|
||||
playerGame.eliminated = true;
|
||||
bot.say(target, `${from}: ${roll.description}`);
|
||||
|
||||
// Check if only one player left
|
||||
const activePlayers = plugin.gameState.players.filter(p =>
|
||||
!plugin.gameScores.get(p)?.eliminated
|
||||
);
|
||||
|
||||
if (activePlayers.length <= 1) {
|
||||
if (activePlayers.length === 1) {
|
||||
bot.say(target, `🎉 ${activePlayers[0]} wins by elimination! 🎉`);
|
||||
}
|
||||
endGame = true;
|
||||
} else {
|
||||
endTurn = true;
|
||||
}
|
||||
} else if (roll.points === -999) {
|
||||
// Makin' Bacon - lose all points and end turn
|
||||
const lostPoints = playerGame.currentScore;
|
||||
playerGame.currentScore = 0;
|
||||
plugin.gameState.turnScore = 0;
|
||||
bot.say(target, `${from}: ${roll.description} Lost ${lostPoints} game points!`);
|
||||
endTurn = true;
|
||||
} else if (roll.points === 0) {
|
||||
// Pig Out - lose turn score and end turn
|
||||
const lostTurn = plugin.gameState.turnScore;
|
||||
plugin.gameState.turnScore = 0;
|
||||
bot.say(target, `${from}: ${roll.description} Lost ${lostTurn} turn points!`);
|
||||
endTurn = true;
|
||||
} else {
|
||||
// Normal scoring - add to turn score
|
||||
plugin.gameState.turnScore += roll.points;
|
||||
|
||||
const potentialTotal = playerGame.currentScore + plugin.gameState.turnScore;
|
||||
|
||||
// Send detailed roll info as notice to the player (NO public message for normal rolls)
|
||||
let detailMsg = `Your roll: ${roll.description} | Turn: ${plugin.gameState.turnScore} | Game Total: ${playerGame.currentScore}`;
|
||||
if (potentialTotal >= 100) {
|
||||
detailMsg += ` | Can win!`;
|
||||
}
|
||||
bot.notice(from, detailMsg);
|
||||
console.log(`Sending notice to ${from}: ${detailMsg}`);
|
||||
}
|
||||
|
||||
if (endGame) {
|
||||
plugin.endGame(target);
|
||||
} else if (endTurn) {
|
||||
plugin.nextTurn(target);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: 'bank',
|
||||
description: 'Bank your turn points in multiplayer Pass the Pigs',
|
||||
execute: function(context, bot) {
|
||||
const plugin = module.exports;
|
||||
const target = context.replyTo;
|
||||
const from = context.nick;
|
||||
|
||||
if (plugin.gameState.phase !== 'active' || !plugin.gameState.players.includes(from)) {
|
||||
bot.say(target, `${from}: You're not in an active pig game!`);
|
||||
return;
|
||||
}
|
||||
|
||||
const currentPlayerName = plugin.gameState.players[plugin.gameState.currentPlayer];
|
||||
if (from !== currentPlayerName) {
|
||||
bot.say(target, `${from}: It's ${currentPlayerName}'s turn!`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin.gameState.turnScore === 0) {
|
||||
bot.say(target, `${from}: No points to bank!`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Bank the points
|
||||
const playerGame = plugin.gameScores.get(from);
|
||||
const newTotal = playerGame.currentScore + plugin.gameState.turnScore;
|
||||
|
||||
playerGame.currentScore = newTotal;
|
||||
|
||||
bot.say(target, `${from}: Banked ${plugin.gameState.turnScore} points! Game Total: ${newTotal}`);
|
||||
|
||||
// Check for win
|
||||
if (newTotal >= 100) {
|
||||
bot.say(target, `🎉 ${from} WINS with ${newTotal} points! 🎉`);
|
||||
plugin.endGame(target);
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.gameState.turnScore = 0;
|
||||
plugin.nextTurn(target);
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: 'quitpigs',
|
||||
description: 'Quit the current multiplayer pig game',
|
||||
execute: function(context, bot) {
|
||||
const plugin = module.exports;
|
||||
const target = context.replyTo;
|
||||
const from = context.nick;
|
||||
|
||||
if (plugin.gameState.phase === 'idle') {
|
||||
bot.say(target, `${from}: No pig game to quit!`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!plugin.gameState.players.includes(from)) {
|
||||
bot.say(target, `${from}: You're not in the current game!`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove player from game
|
||||
plugin.gameState.players = plugin.gameState.players.filter(p => p !== from);
|
||||
bot.say(target, `${from} quit the pig game!`);
|
||||
|
||||
// Check if game should continue
|
||||
if (plugin.gameState.phase === 'joining') {
|
||||
if (plugin.gameState.players.length === 0) {
|
||||
bot.say(target, 'Game cancelled - no players left.');
|
||||
plugin.resetGameState();
|
||||
}
|
||||
} else if (plugin.gameState.phase === 'active') {
|
||||
if (plugin.gameState.players.length <= 1) {
|
||||
if (plugin.gameState.players.length === 1) {
|
||||
bot.say(target, `${plugin.gameState.players[0]} wins by forfeit!`);
|
||||
}
|
||||
plugin.endGame(target);
|
||||
} else {
|
||||
// Adjust current player if needed
|
||||
if (plugin.gameState.currentPlayer >= plugin.gameState.players.length) {
|
||||
plugin.gameState.currentPlayer = 0;
|
||||
}
|
||||
plugin.nextTurn(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: 'toppigs',
|
||||
description: 'Show top multiplayer pig players',
|
||||
execute: function(context, bot) {
|
||||
const plugin = module.exports;
|
||||
const target = context.replyTo;
|
||||
|
||||
if (plugin.playerStats.size === 0) {
|
||||
bot.say(target, 'No multiplayer pig scores recorded yet! Use !pigs to start playing.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert to array and sort by best score
|
||||
const sortedScores = Array.from(plugin.playerStats.values())
|
||||
.sort((a, b) => b.bestScore - a.bestScore)
|
||||
.slice(0, 5); // Top 5
|
||||
|
||||
bot.say(target, '🏆 Top Multiplayer Pig Players:');
|
||||
|
||||
sortedScores.forEach((player, index) => {
|
||||
const rank = index + 1;
|
||||
const trophy = rank === 1 ? '🥇' : rank === 2 ? '🥈' : rank === 3 ? '🥉' : `${rank}.`;
|
||||
bot.say(target, `${trophy} ${player.name}: Best ${player.bestScore} pts (${player.totalGames} games, ${player.totalRolls} rolls)`);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: 'pigstatus',
|
||||
description: 'Show current multiplayer pig game status',
|
||||
execute: function(context, bot) {
|
||||
const plugin = module.exports;
|
||||
const target = context.replyTo;
|
||||
|
||||
if (plugin.gameState.phase === 'idle') {
|
||||
bot.say(target, 'No active multiplayer pig game. Use !pigs to start one!');
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin.gameState.phase === 'joining') {
|
||||
const timeLeft = Math.ceil((plugin.gameState.joinTimeLimit - (Date.now() - plugin.gameState.startTime)) / 1000);
|
||||
bot.say(target, `🐷 Joining phase: ${plugin.gameState.players.join(', ')} (${timeLeft}s left)`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin.gameState.phase === 'active') {
|
||||
const currentPlayer = plugin.gameState.players[plugin.gameState.currentPlayer];
|
||||
let statusMsg = `🎮 Active game: `;
|
||||
|
||||
plugin.gameState.players.forEach((player, i) => {
|
||||
const gameScore = plugin.gameScores.get(player);
|
||||
if (i > 0) statusMsg += ' vs ';
|
||||
statusMsg += `${player}(${gameScore.currentScore})`;
|
||||
if (gameScore.eliminated) statusMsg += '[OUT]';
|
||||
});
|
||||
|
||||
bot.say(target, statusMsg);
|
||||
bot.say(target, `🎲 ${currentPlayer}'s turn | Turn score: ${plugin.gameState.turnScore}`);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: 'resetpigs',
|
||||
description: 'Reset all multiplayer pig scores (admin command)',
|
||||
execute: function(context, bot) {
|
||||
const plugin = module.exports;
|
||||
const target = context.replyTo;
|
||||
const from = context.nick;
|
||||
|
||||
// Simple admin check - you can customize this list
|
||||
const adminNicks = ['admin', 'owner', 'cancerbot', 'megasconed']; // Add your admin nicks here
|
||||
|
||||
if (!adminNicks.includes(from)) {
|
||||
bot.say(target, `${from}: Access denied - admin only command`);
|
||||
return;
|
||||
}
|
||||
|
||||
const playerCount = plugin.playerStats.size;
|
||||
plugin.playerStats.clear();
|
||||
plugin.saveScores();
|
||||
|
||||
bot.say(target, `🗑️ ${from}: Reset ${playerCount} multiplayer pig player stats`);
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue