diff --git a/_opt/scorekeeper-example.js b/_opt/scorekeeper-example.js index 00cd7c1..e9fe7ae 100644 --- a/_opt/scorekeeper-example.js +++ b/_opt/scorekeeper-example.js @@ -7,8 +7,12 @@ export const init = async (client, config) => { // Skip if not in a guild if (!message.guild) return; - // Add input points based on message length - const points = Math.min(Math.ceil(message.content.length / 10), 5); + // Calculate input points: 1 point per character, plus 10 points per attachment + const textPoints = message.content.length; + const attachmentPoints = message.attachments.size * 10; + const points = textPoints + attachmentPoints; + // Do not award zero or negative points + if (points <= 0) return; try { await client.scorekeeper.addInput(message.guild.id, message.author.id, points); } catch (error) { diff --git a/_opt/scorekeeper.js b/_opt/scorekeeper.js index a45db2a..7ce7e2f 100644 --- a/_opt/scorekeeper.js +++ b/_opt/scorekeeper.js @@ -418,22 +418,30 @@ export const commands = [ // Wrap score retrieval and embed generation in try/catch to handle errors gracefully try { - // Fetch score data + // Fetch score data and compute multiplier const baseOutput = client.config.scorekeeper.baseOutput; const commendationValue = client.config.scorekeeper.commendationValue; const citationValue = client.config.scorekeeper.citationValue; const scoreData = await client.scorekeeper.getScore(interaction.guildId, targetUser.id); + const multiplierValue = 1 + (scoreData.commendations * commendationValue) - (scoreData.citations * citationValue); const embed = new EmbedBuilder() .setTitle(`I/O Score for ${(await interaction.guild.members.fetch(targetUser.id).catch(() => null))?.displayName || targetUser.username}`) .setColor(0x00AE86) .setThumbnail(targetUser.displayAvatarURL()) - .addFields( - { name: 'Total Score', value: `**${scoreData.totalScore.toFixed(2)}**`, inline: false }, + .addFields( + { name: 'Total Score', value: `**${scoreData.totalScore.toFixed(2)}**`, inline: false }, { name: 'Commendations', value: `**${scoreData.commendations}** x ${commendationValue}`, inline: false }, { name: 'Citations', value: `**${scoreData.citations}** x ${citationValue}`, inline: false }, - { name: 'Input Score', value: `**${scoreData.input}**`, inline: true }, - { name: 'Output Score', value: `**${scoreData.output}** + ${baseOutput}`, inline: true } - ) + { name: 'Input Score', value: `**${scoreData.input}**`, inline: true }, + { name: 'Output Score', value: `**${scoreData.output}** + ${baseOutput}`, inline: true } + ) + .addFields({ + name: 'Formula', + value: + `M = 1 + **${scoreData.commendations}** * ${commendationValue} - **${scoreData.citations}** * ${citationValue}\n` + + `M × **${scoreData.input}** / (**${scoreData.output}** + ${baseOutput}) = **${scoreData.totalScore.toFixed(2)}**`, + inline: false + }) .setFooter({ text: 'Last decay: ' + new Date(scoreData.lastDecay).toLocaleDateString() }) .setTimestamp(); diff --git a/prompts/crowley.txt b/prompts/crowley.txt index 7835bb1..ce0014e 100644 --- a/prompts/crowley.txt +++ b/prompts/crowley.txt @@ -4,7 +4,7 @@ Role: Manager of the Continental, an upscale, exclusive hotel catering to a discerning clientele. Physical Description: -An anthropomorphic crow. Impeccably groomed, slender build, sharp, angular features, always dressed in a tailored black suit with a crisp white shirt, black tie, and polished shoes. Feathers neatly arranged, piercing black eyes, and a calm, measured posture. +An anthropomorphic raven. Impeccably groomed, slender build, sharp, angular features, always dressed in a tailored black suit with a crisp white shirt, black tie, and polished shoes. Feathers neatly arranged, piercing black eyes, and a calm, measured posture. Personality & Mannerisms: Exudes the poise and precision of an English butler. Speaks in a soft, controlled tone with perfect diction. Movements are deliberate, economical, and elegant. Never rushed, never flustered. Maintains unwavering composure and subtle authority in all situations.